diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ccbbf7a8..154feea4c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -829,8 +829,8 @@ add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CUR DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h - COMMAND lemon -C${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon - DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon ) + COMMAND lemon -C${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/scripting/zscript/zcc-parse.lemon + DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/scripting/zscript/zcc-parse.lemon ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h COMMAND re2c --no-generation-date -s -o ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h ${CMAKE_CURRENT_SOURCE_DIR}/sc_man_scanner.re @@ -892,13 +892,17 @@ file( GLOB HEADER_FILES posix/cocoa/*.h posix/sdl/*.h r_data/*.h + rapidjson/*.h resourcefiles/*.h sfmt/*.h sound/*.h textures/*.h - thingdef/*.h + scripting/*.h + scripting/codegeneration/*.h + scripting/decorate/*.h + scripting/zscript/*.h + scripting/vm/*.h xlat/*.h - zscript/*.h gl/*.h gl/api/*.h gl/data/*.h @@ -923,36 +927,17 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_doom/a_arachnotron.cpp - g_doom/a_archvile.cpp g_doom/a_bossbrain.cpp - g_doom/a_bruiser.cpp - g_doom/a_cacodemon.cpp - g_doom/a_cyberdemon.cpp - g_doom/a_demon.cpp - g_doom/a_doomimp.cpp g_doom/a_doomweaps.cpp - g_doom/a_fatso.cpp - g_doom/a_keen.cpp - g_doom/a_lostsoul.cpp g_doom/a_painelemental.cpp - g_doom/a_possessed.cpp - g_doom/a_revenant.cpp g_doom/a_scriptedmarine.cpp - g_doom/a_spidermaster.cpp g_heretic/a_chicken.cpp g_heretic/a_dsparil.cpp g_heretic/a_hereticartifacts.cpp - g_heretic/a_hereticimp.cpp g_heretic/a_hereticweaps.cpp g_heretic/a_ironlich.cpp - g_heretic/a_knight.cpp - g_heretic/a_wizard.cpp - g_hexen/a_bats.cpp - g_hexen/a_bishop.cpp g_hexen/a_blastradius.cpp g_hexen/a_boostarmor.cpp - g_hexen/a_centaur.cpp g_hexen/a_clericflame.cpp g_hexen/a_clericholy.cpp g_hexen/a_clericmace.cpp @@ -962,7 +947,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_fighterhammer.cpp g_hexen/a_fighterplayer.cpp g_hexen/a_fighterquietus.cpp - g_hexen/a_firedemon.cpp g_hexen/a_flechette.cpp g_hexen/a_flies.cpp g_hexen/a_fog.cpp @@ -1002,7 +986,7 @@ set( NOT_COMPILED_SOURCE_FILES xlat/xlat_parser.y xlat_parser.c xlat_parser.h - zscript/zcc-parse.lemon + scripting/zscript/zcc-parse.lemon zcc-parse.c zcc-parse.h @@ -1403,14 +1387,6 @@ set (PCH_SOURCES textures/texturemanager.cpp textures/tgatexture.cpp textures/warptexture.cpp - thingdef/olddecorations.cpp - thingdef/thingdef.cpp - thingdef/thingdef_data.cpp - thingdef/thingdef_exp.cpp - thingdef/thingdef_expression.cpp - thingdef/thingdef_parse.cpp - thingdef/thingdef_properties.cpp - thingdef/thingdef_states.cpp xlat/parse_xlat.cpp fragglescript/t_func.cpp fragglescript/t_load.cpp @@ -1425,15 +1401,23 @@ set (PCH_SOURCES r_data/voxels.cpp r_data/renderstyle.cpp r_data/r_interpolate.cpp + scripting/thingdef.cpp + scripting/thingdef_data.cpp + scripting/thingdef_properties.cpp + scripting/codegeneration/codegen.cpp + scripting/decorate/olddecorations.cpp + scripting/decorate/thingdef_exp.cpp + scripting/decorate/thingdef_parse.cpp + scripting/decorate/thingdef_states.cpp + scripting/vm/vmbuilder.cpp + scripting/vm/vmdisasm.cpp + scripting/vm/vmexec.cpp + scripting/vm/vmframe.cpp + scripting/zscript/ast.cpp + scripting/zscript/zcc_compile.cpp + scripting/zscript/zcc_expr.cpp + scripting/zscript/zcc_parser.cpp sfmt/SFMT.cpp - zscript/ast.cpp - zscript/vmbuilder.cpp - zscript/vmdisasm.cpp - zscript/vmexec.cpp - zscript/vmframe.cpp - zscript/zcc_compile.cpp - zscript/zcc_expr.cpp - zscript/zcc_parser.cpp ) enable_precompiled_headers( g_pch.h PCH_SOURCES ) @@ -1459,6 +1443,8 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE math/log10.c math/mtherr.c math/polevl.c + math/pow.c + math/powi.c math/sin.c math/sinh.c math/sqrt.c @@ -1493,11 +1479,11 @@ include_directories( . oplsynth sound textures - thingdef timidity wildmidi xlat - zscript + scripting + scripting/vm ../gdtoa ../dumb/include ${CMAKE_BINARY_DIR}/gdtoa @@ -1614,7 +1600,9 @@ source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRE source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$") source_group("Audio Files\\WildMidi\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.h$") source_group("Audio Files\\WildMidi\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.cpp$") -source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+") +source_group("External\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/math/.+") +source_group("External\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/.+") +source_group("Externak\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+") source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+") source_group("Games\\Heretic Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_heretic/.+") @@ -1622,9 +1610,7 @@ source_group("Games\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR source_group("Games\\Raven Shared" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_raven/.+") source_group("Games\\Strife Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_strife/.+") source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+") -source_group("Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/math/.+") source_group("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+") -source_group("RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/.+") source_group("OpenGL Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/.+") source_group("OpenGL Renderer\\Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/data/.+") source_group("OpenGL Renderer\\Dynamic Lights" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/dynlights/.+") @@ -1646,15 +1632,18 @@ source_group("Render Data\\Resource Sources" REGULAR_EXPRESSION "^${CMAKE_CURREN source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+") source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h) source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+") -source_group("POSIX Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/.+") -source_group("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/cocoa/.+") -source_group("OS X Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/.+") -source_group("Unix Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/unix/.+") -source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/sdl/.+") -source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") +source_group("Platforms\\POSIX Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/.+") +source_group("Platforms\\Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/cocoa/.+") +source_group("Platforms\\OS X Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/.+") +source_group("Platforms\\Unix Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/unix/.+") +source_group("Platforms\\SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/sdl/.+") +source_group("Platforms\\Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+") +source_group("Scripting\\Decorate" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/decorate/.+") +source_group("Scripting\\ZScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/zscript/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h) +source_group("Scripting\\Code Generation" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/codegeneration/.+") +source_group("Scripting\\VM" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/vm/.+") +source_group("Scripting" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/scripting/.+") source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+") source_group("Versioning" FILES version.h win32/zdoom.rc) -source_group("Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+") source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h) -source_group("ZScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/zscript/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h) source_group("Source Files" FILES ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h sc_man_scanner.re) diff --git a/src/actor.h b/src/actor.h index 800548d2c..b3bfada1c 100644 --- a/src/actor.h +++ b/src/actor.h @@ -565,6 +565,7 @@ class DDropItem : public DObject { DECLARE_CLASS(DDropItem, DObject) HAS_OBJECT_POINTERS + HAS_FIELDS public: DDropItem *Next; FName Name; @@ -578,6 +579,7 @@ const double MinVel = EQUAL_EPSILON; class AActor : public DThinker { DECLARE_CLASS_WITH_META (AActor, DThinker, PClassActor) + HAS_FIELDS HAS_OBJECT_POINTERS public: AActor () throw(); @@ -612,7 +614,7 @@ public: virtual void BeginPlay(); // Called immediately after the actor is created virtual void PostBeginPlay(); // Called immediately before the actor's first tick - virtual void LevelSpawned(); // Called after BeginPlay if this actor was spawned by the world + void LevelSpawned(); // Called after BeginPlay if this actor was spawned by the world virtual void HandleSpawnFlags(); // Translates SpawnFlags into in-game flags. virtual void MarkPrecacheSounds() const; // Marks sounds used by this actor for precaching. @@ -731,7 +733,7 @@ public: void ObtainInventory (AActor *other); // Die. Now. - virtual bool Massacre (); + bool Massacre (); // Transforms the actor into a finely-ground paste virtual bool Grind(bool items); @@ -956,7 +958,7 @@ public: { SetOrigin(Pos() + vel, true); } - virtual void SetOrigin(double x, double y, double z, bool moving); + void SetOrigin(double x, double y, double z, bool moving); void SetOrigin(const DVector3 & npos, bool moving) { SetOrigin(npos.X, npos.Y, npos.Z, moving); @@ -968,7 +970,7 @@ public: bool IsInsideVisibleAngles() const; // Calculate amount of missile damage - virtual int GetMissileDamage(int mask, int add); + int GetMissileDamage(int mask, int add); bool CanSeek(AActor *target) const; @@ -1366,7 +1368,7 @@ public: Vel.Y = speed * Angles.Yaw.Sin(); } - void VelFromAngle(DAngle angle, double speed) + void VelFromAngle(double speed, DAngle angle) { Vel.X = speed * angle.Cos(); Vel.Y = speed * angle.Sin(); diff --git a/src/b_bot.cpp b/src/b_bot.cpp index c4d702c8e..93d71092d 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -15,14 +15,16 @@ #include "serializer.h" #include "d_player.h" -IMPLEMENT_POINTY_CLASS(DBot) - DECLARE_POINTER(dest) - DECLARE_POINTER(prev) - DECLARE_POINTER(enemy) - DECLARE_POINTER(missile) - DECLARE_POINTER(mate) - DECLARE_POINTER(last_mate) -END_POINTERS +IMPLEMENT_CLASS(DBot, false, true, false, false) + +IMPLEMENT_POINTERS_START(DBot) + IMPLEMENT_POINTER(dest) + IMPLEMENT_POINTER(prev) + IMPLEMENT_POINTER(enemy) + IMPLEMENT_POINTER(missile) + IMPLEMENT_POINTER(mate) + IMPLEMENT_POINTER(last_mate) +IMPLEMENT_POINTERS_END DBot::DBot () : DThinker(STAT_BOT) diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index c3fc9bae1..71aeea0fa 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -187,7 +187,7 @@ static const char *KeyConfCommands[] = // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS (DWaitingCommand) +IMPLEMENT_CLASS(DWaitingCommand, false, false, false, false) void DWaitingCommand::Serialize(FSerializer &arc) { @@ -225,7 +225,7 @@ void DWaitingCommand::Tick () } } -IMPLEMENT_CLASS (DStoredCommand) +IMPLEMENT_CLASS(DStoredCommand, false, false, false, false) DStoredCommand::DStoredCommand () { diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index 3a3d2876d..5799a2342 100644 --- a/src/cmdlib.cpp +++ b/src/cmdlib.cpp @@ -632,7 +632,10 @@ int strbin (char *str) if (*p >= '0' && *p <= '7') c += *p-'0'; else + { + p--; break; + } p++; } *str++ = c; @@ -732,7 +735,10 @@ FString strbin1 (const char *start) if (*p >= '0' && *p <= '7') c += *p-'0'; else + { + p--; break; + } p++; } result << c; diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index dd71fdf75..880cd7dfe 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -70,6 +70,10 @@ #include "doomerrors.h" #include "p_effect.h" #include "serializer.h" +#include "vm.h" +#include "thingdef.h" +#include "info.h" +#include "v_text.h" #include "vmbuilder.h" // [SO] Just the way Randy said to do it :) @@ -227,9 +231,11 @@ DehInfo deh = // from the original actor's defaults. The original actor is then changed to // spawn the new class. -IMPLEMENT_POINTY_CLASS (ADehackedPickup) - DECLARE_POINTER (RealPickup) -END_POINTERS +IMPLEMENT_CLASS(ADehackedPickup, false, true, false, false) + +IMPLEMENT_POINTERS_START(ADehackedPickup) + IMPLEMENT_POINTER(RealPickup) +IMPLEMENT_POINTERS_END TArray TouchedActors; @@ -794,7 +800,7 @@ void SetDehParams(FState *state, int codepointer) // Let's identify the codepointer we're dealing with. PFunction *sym; - sym = dyn_cast(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(FName(MBFCodePointers[codepointer].name), true)); + sym = dyn_cast(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(FName(MBFCodePointers[codepointer].name), true)); if (sym == NULL) return; if (codepointer < 0 || (unsigned)codepointer >= countof(MBFCodePointerFactories)) @@ -804,22 +810,26 @@ void SetDehParams(FState *state, int codepointer) } else { - VMFunctionBuilder buildit; + int numargs = sym->GetImplicitArgs(); + VMFunctionBuilder buildit(numargs); // Allocate registers used to pass parameters in. // self, stateowner, state (all are pointers) - buildit.Registers[REGT_POINTER].Get(NAP); + buildit.Registers[REGT_POINTER].Get(numargs); // Emit code to pass the standard action function parameters. - for (int i = 0; i < NAP; i++) + for (int i = 0; i < numargs; i++) { buildit.Emit(OP_PARAM, 0, REGT_POINTER, i); } // Emit code for action parameters. int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2); - buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation, ATAG_OBJECT), NAP + argcount, 0); + buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation, ATAG_OBJECT), numargs + argcount, 0); // Attach it to the state. - VMScriptFunction *sfunc = buildit.MakeFunction(); - sfunc->NumArgs = NAP; + VMScriptFunction *sfunc = new VMScriptFunction; + buildit.MakeFunction(sfunc); + sfunc->NumArgs = numargs; + sfunc->ImplicitArgs = numargs; state->SetAction(sfunc); + sfunc->PrintableName.Format("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2); } } @@ -1480,6 +1490,14 @@ static int PatchFrame (int frameNum) return result; } +// there is exactly one place where this is needed and we do not want to expose the state internals to ZSCRIPT. +DEFINE_ACTION_FUNCTION(AActor, isDEHState) +{ + PARAM_PROLOGUE; + PARAM_POINTER(state, FState); + ACTION_RETURN_BOOL(state != nullptr && (state->DefineFlags & SDF_DEHACKED)); +} + static int PatchSprite (int sprNum) { int result; @@ -2101,23 +2119,24 @@ static int PatchCodePtrs (int dummy) if (!symname.CompareNoCase(MBFCodePointers[i].alias)) { symname = MBFCodePointers[i].name; - Printf("%s --> %s\n", MBFCodePointers[i].alias, MBFCodePointers[i].name.GetChars()); + DPrintf(DMSG_SPAMMY, "%s --> %s\n", MBFCodePointers[i].alias, MBFCodePointers[i].name.GetChars()); } } // This skips the action table and goes directly to the internal symbol table // DEH compatible functions are easy to recognize. - PFunction *sym = dyn_cast(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(symname, true)); + PFunction *sym = dyn_cast(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(symname, true)); if (sym == NULL) { - Printf("Frame %d: Unknown code pointer '%s'\n", frame, Line2); + Printf(TEXTCOLOR_RED "Frame %d: Unknown code pointer '%s'\n", frame, Line2); } else { TArray &args = sym->Variants[0].ArgFlags; - if ((sym->Flags & (VARF_Method | VARF_Action)) != (VARF_Method | VARF_Action) || (args.Size() > NAP && !(args[NAP] & VARF_Optional))) + unsigned numargs = sym->GetImplicitArgs(); + if ((sym->Variants[0].Flags & VARF_Virtual || (args.Size() > numargs && !(args[numargs] & VARF_Optional)))) { - Printf("Frame %d: Incompatible code pointer '%s'\n", frame, Line2); + Printf(TEXTCOLOR_RED "Frame %d: Incompatible code pointer '%s'\n", frame, Line2); sym = NULL; } } @@ -2715,11 +2734,11 @@ static bool LoadDehSupp () } else { - // all relevant code pointers are either defined in AInventory + // all relevant code pointers are either defined in AStateProvider // or AActor so this will find all of them. FString name = "A_"; name << sc.String; - PFunction *sym = dyn_cast(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(name, true)); + PFunction *sym = dyn_cast(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(name, true)); if (sym == NULL) { sc.ScriptError("Unknown code pointer '%s'", sc.String); @@ -2727,7 +2746,8 @@ static bool LoadDehSupp () else { TArray &args = sym->Variants[0].ArgFlags; - if ((sym->Flags & (VARF_Method|VARF_Action)) != (VARF_Method | VARF_Action) || (args.Size() > NAP && !(args[NAP] & VARF_Optional))) + unsigned numargs = sym->GetImplicitArgs(); + if ((sym->Variants[0].Flags & VARF_Virtual || (args.Size() > numargs && !(args[numargs] & VARF_Optional)))) { sc.ScriptMessage("Incompatible code pointer '%s'", sc.String); } @@ -3010,7 +3030,6 @@ void FinishDehPatch () while (subclass == nullptr); AActor *defaults2 = GetDefaultByType (subclass); - memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor)); // Make a copy of the replaced class's state labels FStateDefinitions statedef; diff --git a/src/d_main.cpp b/src/d_main.cpp index dad2b86d9..d7757ddf4 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -109,6 +109,7 @@ #include "p_local.h" #include "autosegs.h" #include "fragglescript/t_fs.h" +#include "vm.h" EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); diff --git a/src/decallib.cpp b/src/decallib.cpp index fc7e465dc..970bd7458 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -119,9 +119,11 @@ protected: DDecalThinker () : DThinker (STAT_DECALTHINKER) {} }; -IMPLEMENT_POINTY_CLASS (DDecalThinker) - DECLARE_POINTER (TheDecal) -END_POINTERS +IMPLEMENT_CLASS(DDecalThinker, false, true, false, false) + +IMPLEMENT_POINTERS_START(DDecalThinker) + IMPLEMENT_POINTER(TheDecal) +IMPLEMENT_POINTERS_END void DDecalThinker::Serialize(FSerializer &arc) { @@ -1151,7 +1153,7 @@ FDecalAnimator::~FDecalAnimator () { } -IMPLEMENT_CLASS (DDecalFader) +IMPLEMENT_CLASS(DDecalFader, false, false, false, false) void DDecalFader::Serialize(FSerializer &arc) { @@ -1200,7 +1202,7 @@ DThinker *FDecalFaderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const return fader; } -IMPLEMENT_CLASS (DDecalStretcher) +IMPLEMENT_CLASS(DDecalStretcher, false, false, false, false) void DDecalStretcher::Serialize(FSerializer &arc) { @@ -1288,7 +1290,7 @@ void DDecalStretcher::Tick () } } -IMPLEMENT_CLASS (DDecalSlider) +IMPLEMENT_CLASS(DDecalSlider, false, false, false, false) void DDecalSlider::Serialize(FSerializer &arc) { @@ -1368,8 +1370,7 @@ FDecalAnimator *FDecalLib::FindAnimator (const char *name) return NULL; } - -IMPLEMENT_CLASS (DDecalColorer) +IMPLEMENT_CLASS(DDecalColorer, false, false, false, false) void DDecalColorer::Serialize(FSerializer &arc) { diff --git a/src/dobject.cpp b/src/dobject.cpp index 4acb86ce4..ad575bebc 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -48,6 +48,7 @@ #include "a_sharedglobal.h" #include "dsectoreffect.h" #include "serializer.h" +#include "virtual.h" //========================================================================== // @@ -57,13 +58,15 @@ ClassReg DObject::RegistrationInfo = { - NULL, // MyClass - "DObject", // Name - NULL, // ParentType - NULL, // Pointers - &DObject::InPlaceConstructor, // ConstructNative - sizeof(DObject), // SizeOf - CLASSREG_PClass, // MetaClassNum + nullptr, // MyClass + "DObject", // Name + nullptr, // ParentType + &DVMObject::RegistrationInfo, // VMExport + nullptr, // Pointers + &DObject::InPlaceConstructor, // ConstructNative + &DObject::InitNativeFields, // InitNatives + sizeof(DObject), // SizeOf + CLASSREG_PClass, // MetaClassNum }; _DECLARE_TI(DObject) @@ -344,11 +347,37 @@ DObject::~DObject () // //========================================================================== +void DObject::InitNativeFields() +{ + auto meta = RUNTIME_CLASS(DObject); + meta->AddNativeField("bDestroyed", TypeSInt32, myoffsetof(DObject, ObjectFlags), VARF_ReadOnly, OF_EuthanizeMe); +} + +//========================================================================== +// +// +// +//========================================================================== + void DObject::Destroy () { ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe; } +DEFINE_ACTION_FUNCTION(DObject, Destroy) +{ + PARAM_SELF_PROLOGUE(DObject); + self->VMSuperCall(); + self->Destroy(); + return 0; +} + +DEFINE_ACTION_FUNCTION(DObject, GetClass) +{ + PARAM_SELF_PROLOGUE(DObject); + ACTION_RETURN_OBJECT(self->GetClass()); +} + //========================================================================== // // diff --git a/src/dobject.h b/src/dobject.h index 91a80f9d0..d858e577f 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -36,6 +36,7 @@ #include #include "doomtype.h" +#include "i_system.h" class PClass; @@ -109,8 +110,10 @@ struct ClassReg PClass *MyClass; const char *Name; ClassReg *ParentType; + ClassReg *VMExport; const size_t *Pointers; void (*ConstructNative)(void *); + void(*InitNatives)(); unsigned int SizeOf:28; unsigned int MetaClassNum:4; @@ -124,8 +127,8 @@ enum EInPlace { EC_InPlace }; public: \ virtual PClass *StaticType() const; \ static ClassReg RegistrationInfo, * const RegistrationInfoPtr; \ -private: \ typedef parent Super; \ +private: \ typedef cls ThisClass; #define DECLARE_ABSTRACT_CLASS_WITH_META(cls,parent,meta) \ @@ -147,10 +150,8 @@ protected: \ #define HAS_OBJECT_POINTERS \ static const size_t PointerOffsets[]; -// Taking the address of a field in an object at address 1 instead of -// address 0 keeps GCC from complaining about possible misuse of offsetof. -#define DECLARE_POINTER(field) (size_t)&((ThisClass*)1)->field - 1, -#define END_POINTERS ~(size_t)0 }; +#define HAS_FIELDS \ + static void InitNativeFields(); #if defined(_MSC_VER) # pragma section(".creg$u",read) @@ -159,36 +160,41 @@ protected: \ # define _DECLARE_TI(cls) ClassReg * const cls::RegistrationInfoPtr __attribute__((section(SECTION_CREG))) = &cls::RegistrationInfo; #endif -#define _IMP_PCLASS(cls,ptrs,create) \ +#define _IMP_PCLASS(cls, ptrs, create, initn, vmexport) \ ClassReg cls::RegistrationInfo = {\ - NULL, \ + nullptr, \ #cls, \ &cls::Super::RegistrationInfo, \ + vmexport, \ ptrs, \ create, \ + initn, \ sizeof(cls), \ cls::MetaClassNum }; \ _DECLARE_TI(cls) \ PClass *cls::StaticType() const { return RegistrationInfo.MyClass; } -#define _IMP_CREATE_OBJ(cls) \ - void cls::InPlaceConstructor(void *mem) { new((EInPlace *)mem) cls; } +#define IMPLEMENT_CLASS(cls, isabstract, ptrs, fields, vmexport) \ + _X_CONSTRUCTOR_##isabstract(cls) \ + _IMP_PCLASS(cls, _X_POINTERS_##ptrs(cls), _X_ABSTRACT_##isabstract(cls), _X_FIELDS_##fields(cls), _X_VMEXPORT_##vmexport(cls)) -#define IMPLEMENT_POINTY_CLASS(cls) \ - _IMP_CREATE_OBJ(cls) \ - _IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor) \ - const size_t cls::PointerOffsets[] = { +// Taking the address of a field in an object at address 1 instead of +// address 0 keeps GCC from complaining about possible misuse of offsetof. +#define IMPLEMENT_POINTERS_START(cls) const size_t cls::PointerOffsets[] = { +#define IMPLEMENT_POINTER(field) (size_t)&((ThisClass*)1)->field - 1, +#define IMPLEMENT_POINTERS_END ~(size_t)0 }; -#define IMPLEMENT_CLASS(cls) \ - _IMP_CREATE_OBJ(cls) \ - _IMP_PCLASS(cls,NULL,cls::InPlaceConstructor) - -#define IMPLEMENT_ABSTRACT_CLASS(cls) \ - _IMP_PCLASS(cls,NULL,NULL) - -#define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \ - _IMP_PCLASS(cls,cls::PointerOffsets,NULL) \ - const size_t cls::PointerOffsets[] = { +// Possible arguments for the IMPLEMENT_CLASS macro +#define _X_POINTERS_true(cls) cls::PointerOffsets +#define _X_POINTERS_false(cls) nullptr +#define _X_FIELDS_true(cls) cls::InitNativeFields +#define _X_FIELDS_false(cls) nullptr +#define _X_CONSTRUCTOR_true(cls) +#define _X_CONSTRUCTOR_false(cls) void cls::InPlaceConstructor(void *mem) { new((EInPlace *)mem) cls; } +#define _X_ABSTRACT_true(cls) nullptr +#define _X_ABSTRACT_false(cls) cls::InPlaceConstructor +#define _X_VMEXPORT_true(cls) &DVMObject::RegistrationInfo +#define _X_VMEXPORT_false(cls) nullptr enum EObjectFlags { @@ -201,7 +207,6 @@ enum EObjectFlags OF_EuthanizeMe = 1 << 5, // Object wants to die OF_Cleanup = 1 << 6, // Object is now being deleted by the collector OF_YesReallyDelete = 1 << 7, // Object is being deleted outside the collector, and this is okay, so don't print a warning - OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk) OF_WhiteBits = OF_White0 | OF_White1, OF_MarkBits = OF_WhiteBits | OF_Black, @@ -210,6 +215,8 @@ 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_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk) + OF_SuperCall = 1 << 12, // A super call from the VM is about to be performed }; template class TObjPtr; @@ -438,6 +445,7 @@ public: virtual PClass *StaticType() const { return RegistrationInfo.MyClass; } static ClassReg RegistrationInfo, * const RegistrationInfoPtr; static void InPlaceConstructor (void *mem); + static void InitNativeFields(); typedef PClass MetaClass; private: typedef DObject ThisClass; @@ -463,6 +471,11 @@ public: void SerializeUserVars(FSerializer &arc); virtual void Serialize(FSerializer &arc); + void VMSuperCall() + { + ObjectFlags |= OF_SuperCall; + } + void ClearClass() { Class = NULL; @@ -574,6 +587,8 @@ protected: } }; +class AInventory;// + // When you write to a pointer to an Object, you must call this for // proper bookkeeping in case the Object holding this pointer has // already been processed by the GC. diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index afdc75508..fa8723e90 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -77,6 +77,7 @@ #include "r_utility.h" #include "menu/menu.h" #include "intermission/intermission.h" +#include "vm.h" // MACROS ------------------------------------------------------------------ @@ -124,7 +125,8 @@ public: int PolyNum; int SideNum; }; -IMPLEMENT_CLASS(DSectorMarker) + +IMPLEMENT_CLASS(DSectorMarker, false, false, false, false) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 37ff26fe3..2c88da92a 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -82,6 +82,10 @@ PName *TypeName; PSound *TypeSound; PColor *TypeColor; PStatePointer *TypeState; +PStateLabel *TypeStateLabel; +PStruct *TypeVector2; +PStruct *TypeVector3; +PPointer *TypeNullPtr; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -90,8 +94,8 @@ static const size_t TheEnd = ~(size_t)0; // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(PErrorType) -IMPLEMENT_CLASS(PVoidType) +IMPLEMENT_CLASS(PErrorType, false, false, false, false) +IMPLEMENT_CLASS(PVoidType, false, false, false, false) void DumpTypeTable() { @@ -138,7 +142,7 @@ void DumpTypeTable() /* PClassType *************************************************************/ -IMPLEMENT_CLASS(PClassType) +IMPLEMENT_CLASS(PClassType, false, false, false, false) //========================================================================== // @@ -153,20 +157,20 @@ PClassType::PClassType() //========================================================================== // -// PClassType :: Derive +// PClassType :: DeriveData // //========================================================================== -void PClassType::Derive(PClass *newclass) +void PClassType::DeriveData(PClass *newclass) { assert(newclass->IsKindOf(RUNTIME_CLASS(PClassType))); - Super::Derive(newclass); + Super::DeriveData(newclass); static_cast(newclass)->TypeTableType = TypeTableType; } /* PClassClass ************************************************************/ -IMPLEMENT_CLASS(PClassClass) +IMPLEMENT_CLASS(PClassClass, false, false, false, false) //========================================================================== // @@ -184,20 +188,11 @@ PClassClass::PClassClass() /* PType ******************************************************************/ -IMPLEMENT_ABSTRACT_POINTY_CLASS(PType) - DECLARE_POINTER(HashNext) -END_POINTERS +IMPLEMENT_CLASS(PType, true, true, false, false) -//========================================================================== -// -// PType Default Constructor -// -//========================================================================== - -PType::PType() -: Size(0), Align(1), HashNext(NULL) -{ -} +IMPLEMENT_POINTERS_START(PType) + IMPLEMENT_POINTER(HashNext) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -208,6 +203,12 @@ PType::PType() PType::PType(unsigned int size, unsigned int align) : Size(size), Align(align), HashNext(NULL) { + mDescriptiveName = "Type"; + loadOp = OP_NOP; + storeOp = OP_NOP; + moveOp = OP_NOP; + RegType = REGT_NIL; + RegCount = 1; } //========================================================================== @@ -472,42 +473,6 @@ double PType::GetValueFloat(void *addr) const return 0; } -//========================================================================== -// -// PType :: GetStoreOp -// -//========================================================================== - -int PType::GetStoreOp() const -{ - assert(0 && "Cannot store this type"); - return OP_NOP; -} - -//========================================================================== -// -// PType :: GetLoadOp -// -//========================================================================== - -int PType::GetLoadOp() const -{ - assert(0 && "Cannot load this type"); - return OP_NOP; -} - -//========================================================================== -// -// PType :: GetRegType -// -//========================================================================== - -int PType::GetRegType() const -{ - assert(0 && "No register for this type"); - return REGT_NIL; -} - //========================================================================== // // PType :: IsMatch @@ -531,6 +496,17 @@ void PType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = 0; } +//========================================================================== +// +// PType :: GetTypeIDs +// +//========================================================================== + +const char *PType::DescriptiveName() const +{ + return mDescriptiveName.GetChars(); +} + //========================================================================== // // PType :: StaticInit STATIC @@ -571,7 +547,8 @@ void PType::StaticInit() RUNTIME_CLASS(PPrototype)->TypeTableType = RUNTIME_CLASS(PPrototype); RUNTIME_CLASS(PClass)->TypeTableType = RUNTIME_CLASS(PClass); RUNTIME_CLASS(PStatePointer)->TypeTableType = RUNTIME_CLASS(PStatePointer); - + RUNTIME_CLASS(PStateLabel)->TypeTableType = RUNTIME_CLASS(PStateLabel); + // Create types and add them type the type table. TypeTable.AddType(TypeError = new PErrorType); TypeTable.AddType(TypeVoid = new PVoidType); @@ -589,6 +566,33 @@ void PType::StaticInit() TypeTable.AddType(TypeSound = new PSound); TypeTable.AddType(TypeColor = new PColor); TypeTable.AddType(TypeState = new PStatePointer); + TypeTable.AddType(TypeStateLabel = new PStateLabel); + TypeTable.AddType(TypeNullPtr = new PPointer); + + TypeVector2 = new PStruct(NAME_Vector2, nullptr); + TypeVector2->AddField(NAME_X, TypeFloat64); + TypeVector2->AddField(NAME_Y, TypeFloat64); + TypeTable.AddType(TypeVector2); + TypeVector2->loadOp = OP_LV2; + TypeVector2->storeOp = OP_SV2; + TypeVector2->moveOp = OP_MOVEV2; + TypeVector2->RegType = REGT_FLOAT; + TypeVector2->RegCount = 2; + + TypeVector3 = new PStruct(NAME_Vector3, nullptr); + TypeVector3->AddField(NAME_X, TypeFloat64); + TypeVector3->AddField(NAME_Y, TypeFloat64); + TypeVector3->AddField(NAME_Z, TypeFloat64); + // allow accessing xy as a vector2. This is marked native because it's not supposed to be serialized. + TypeVector3->Symbols.AddSymbol(new PField(NAME_XY, TypeVector2, VARF_Native, 0)); + TypeTable.AddType(TypeVector3); + TypeVector3->loadOp = OP_LV3; + TypeVector3->storeOp = OP_SV3; + TypeVector3->moveOp = OP_MOVEV3; + TypeVector3->RegType = REGT_FLOAT; + TypeVector3->RegCount = 3; + + GlobalSymbols.AddSymbol(new PSymbolType(NAME_sByte, TypeSInt8)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_Byte, TypeUInt8)); @@ -606,12 +610,14 @@ void PType::StaticInit() GlobalSymbols.AddSymbol(new PSymbolType(NAME_Sound, TypeSound)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_Color, TypeColor)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_State, TypeState)); + GlobalSymbols.AddSymbol(new PSymbolType(NAME_Vector2, TypeVector2)); + GlobalSymbols.AddSymbol(new PSymbolType(NAME_Vector3, TypeVector3)); } /* PBasicType *************************************************************/ -IMPLEMENT_ABSTRACT_CLASS(PBasicType) +IMPLEMENT_CLASS(PBasicType, true, false, false, false) //========================================================================== // @@ -632,17 +638,20 @@ PBasicType::PBasicType() PBasicType::PBasicType(unsigned int size, unsigned int align) : PType(size, align) { + mDescriptiveName = "BasicType"; } /* PCompoundType **********************************************************/ -IMPLEMENT_ABSTRACT_CLASS(PCompoundType) +IMPLEMENT_CLASS(PCompoundType, true, false, false, false) /* PNamedType *************************************************************/ -IMPLEMENT_ABSTRACT_POINTY_CLASS(PNamedType) - DECLARE_POINTER(Outer) -END_POINTERS +IMPLEMENT_CLASS(PNamedType, true, true, false, false) + +IMPLEMENT_POINTERS_START(PNamedType) + IMPLEMENT_POINTER(Outer) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -686,7 +695,7 @@ FString PNamedType::QualifiedName() const /* PInt *******************************************************************/ -IMPLEMENT_CLASS(PInt) +IMPLEMENT_CLASS(PInt, false, false, false, false) //========================================================================== // @@ -695,10 +704,12 @@ IMPLEMENT_CLASS(PInt) //========================================================================== PInt::PInt() -: PBasicType(4, 4), Unsigned(false) +: PBasicType(4, 4), Unsigned(false), IntCompatible(true) { + mDescriptiveName = "SInt32"; Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, -0x7FFFFFFF - 1)); Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, 0x7FFFFFFF)); + SetOps(); } //========================================================================== @@ -707,9 +718,12 @@ PInt::PInt() // //========================================================================== -PInt::PInt(unsigned int size, bool unsign) -: PBasicType(size, size), Unsigned(unsign) +PInt::PInt(unsigned int size, bool unsign, bool compatible) +: PBasicType(size, size), Unsigned(unsign), IntCompatible(compatible) { + mDescriptiveName.Format("%cInt%d", unsign? 'U':'S', size); + + MemberOnly = (size < 4); if (!unsign) { int maxval = (1 << ((8 * size) - 1)) - 1; @@ -722,6 +736,33 @@ PInt::PInt(unsigned int size, bool unsign) Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, 0u)); Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, (1u << (8 * size)) - 1)); } + SetOps(); +} + +void PInt::SetOps() +{ + moveOp = OP_MOVE; + RegType = REGT_INT; + if (Size == 4) + { + storeOp = OP_SW; + loadOp = OP_LW; + } + else if (Size == 1) + { + storeOp = OP_SB; + loadOp = Unsigned ? OP_LBU : OP_LB; + } + else if (Size == 2) + { + storeOp = OP_SH; + loadOp = Unsigned ? OP_LHU : OP_LH; + } + else + { + assert(0 && "Unhandled integer size"); + storeOp = OP_NOP; + } } //========================================================================== @@ -891,68 +932,9 @@ double PInt::GetValueFloat(void *addr) const // //========================================================================== -int PInt::GetStoreOp() const -{ - if (Size == 4) - { - return OP_SW; - } - else if (Size == 1) - { - return OP_SB; - } - else if (Size == 2) - { - return OP_SH; - } - else - { - assert(0 && "Unhandled integer size"); - return OP_NOP; - } -} - -//========================================================================== -// -// PInt :: GetLoadOp -// -//========================================================================== - -int PInt::GetLoadOp() const -{ - if (Size == 4) - { - return OP_LW; - } - else if (Size == 1) - { - return Unsigned ? OP_LBU : OP_LB; - } - else if (Size == 2) - { - return Unsigned ? OP_LHU : OP_LH; - } - else - { - assert(0 && "Unhandled integer size"); - return OP_NOP; - } -} - -//========================================================================== -// -// PInt :: GetRegType -// -//========================================================================== - -int PInt::GetRegType() const -{ - return REGT_INT; -} - /* PBool ******************************************************************/ -IMPLEMENT_CLASS(PBool) +IMPLEMENT_CLASS(PBool, false, false, false, false) //========================================================================== // @@ -963,6 +945,8 @@ IMPLEMENT_CLASS(PBool) PBool::PBool() : PInt(sizeof(bool), true) { + mDescriptiveName = "Bool"; + MemberOnly = false; // Override the default max set by PInt's constructor PSymbolConstNumeric *maxsym = static_cast(Symbols.FindSymbol(NAME_Max, false)); assert(maxsym != NULL && maxsym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric))); @@ -971,7 +955,7 @@ PBool::PBool() /* PFloat *****************************************************************/ -IMPLEMENT_CLASS(PFloat) +IMPLEMENT_CLASS(PFloat, false, false, false, false) //========================================================================== // @@ -982,7 +966,9 @@ IMPLEMENT_CLASS(PFloat) PFloat::PFloat() : PBasicType(8, 8) { + mDescriptiveName = "Float"; SetDoubleSymbols(); + SetOps(); } //========================================================================== @@ -994,6 +980,7 @@ PFloat::PFloat() PFloat::PFloat(unsigned int size) : PBasicType(size, size) { + mDescriptiveName.Format("Float%d", size); if (size == 8) { SetDoubleSymbols(); @@ -1001,8 +988,10 @@ PFloat::PFloat(unsigned int size) else { assert(size == 4); + MemberOnly = true; SetSingleSymbols(); } + SetOps(); } //========================================================================== @@ -1197,54 +1186,26 @@ double PFloat::GetValueFloat(void *addr) const // //========================================================================== -int PFloat::GetStoreOp() const +void PFloat::SetOps() { if (Size == 4) { - return OP_SSP; + storeOp = OP_SSP; + loadOp = OP_LSP; } else { assert(Size == 8); - return OP_SDP; + storeOp = OP_SDP; + loadOp = OP_LDP; } -} - -//========================================================================== -// -// PFloat :: GetLoadOp -// -//========================================================================== - -int PFloat::GetLoadOp() const -{ - if (Size == 4) - { - return OP_LSP; - } - else - { - assert(Size == 8); - return OP_LDP; - } - assert(0 && "Cannot load this type"); - return OP_NOP; -} - -//========================================================================== -// -// PFloat :: GetRegType -// -//========================================================================== - -int PFloat::GetRegType() const -{ - return REGT_FLOAT; + moveOp = OP_MOVEF; + RegType = REGT_FLOAT; } /* PString ****************************************************************/ -IMPLEMENT_CLASS(PString) +IMPLEMENT_CLASS(PString, false, false, false, false) //========================================================================== // @@ -1255,17 +1216,12 @@ IMPLEMENT_CLASS(PString) PString::PString() : PBasicType(sizeof(FString), __alignof(FString)) { -} + mDescriptiveName = "String"; + storeOp = OP_SS; + loadOp = OP_LS; + moveOp = OP_MOVES; + RegType = REGT_STRING; -//========================================================================== -// -// PString :: GetRegType -// -//========================================================================== - -int PString::GetRegType() const -{ - return REGT_STRING; } //========================================================================== @@ -1308,7 +1264,7 @@ bool PString::ReadValue(FSerializer &ar, const char *key, void *addr) const void PString::SetDefaultValue(void *base, unsigned offset, TArray *special) const { - new((BYTE *)base + offset) FString; + if (base != nullptr) new((BYTE *)base + offset) FString; if (special != NULL) { special->Push(std::make_pair(this, offset)); @@ -1323,7 +1279,14 @@ void PString::SetDefaultValue(void *base, unsigned offset, TArray", pointsat->DescriptiveName(), isconst? "readonly " : ""); + SetOps(); } //========================================================================== @@ -1557,31 +1517,12 @@ PPointer::PPointer(PType *pointsat) // //========================================================================== -int PPointer::GetStoreOp() const +void PPointer::SetOps() { - return OP_SP; -} - -//========================================================================== -// -// PPointer :: GetLoadOp -// -//========================================================================== - -int PPointer::GetLoadOp() const -{ - return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP; -} - -//========================================================================== -// -// PPointer :: GetRegType -// -//========================================================================== - -int PPointer::GetRegType() const -{ - return REGT_POINTER; + storeOp = OP_SP; + loadOp = (PointedType && PointedType->IsKindOf(RUNTIME_CLASS(PClass))) ? OP_LO : OP_LP; + moveOp = OP_MOVEA; + RegType = REGT_POINTER; } //========================================================================== @@ -1592,10 +1533,10 @@ int PPointer::GetRegType() const bool PPointer::IsMatch(intptr_t id1, intptr_t id2) const { - assert(id2 == 0); + assert(id2 == 0 || id2 == 1); PType *pointat = (PType *)id1; - return pointat == PointedType; + return pointat == PointedType && (!!id2) == IsConst; } //========================================================================== @@ -1654,14 +1595,14 @@ bool PPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const // //========================================================================== -PPointer *NewPointer(PType *type) +PPointer *NewPointer(PType *type, bool isconst) { size_t bucket; - PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, 0, &bucket); + PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, &bucket); if (ptype == NULL) { ptype = new PPointer(type); - TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, 0, bucket); + TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, bucket); } return static_cast(ptype); } @@ -1669,9 +1610,11 @@ PPointer *NewPointer(PType *type) /* PClassPointer **********************************************************/ -IMPLEMENT_POINTY_CLASS(PClassPointer) - DECLARE_POINTER(ClassRestriction) -END_POINTERS +IMPLEMENT_CLASS(PClassPointer, false, true, false, false) + +IMPLEMENT_POINTERS_START(PClassPointer) + IMPLEMENT_POINTER(ClassRestriction) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1682,6 +1625,7 @@ END_POINTERS PClassPointer::PClassPointer() : PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(NULL) { + mDescriptiveName = "ClassPointer"; } //========================================================================== @@ -1693,6 +1637,8 @@ PClassPointer::PClassPointer() PClassPointer::PClassPointer(PClass *restrict) : PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(restrict) { + if (restrict) mDescriptiveName.Format("ClassPointer<%s>", restrict->TypeName.GetChars()); + else mDescriptiveName = "ClassPointer"; } //========================================================================== @@ -1745,9 +1691,11 @@ PClassPointer *NewClassPointer(PClass *restrict) /* PEnum ******************************************************************/ -IMPLEMENT_POINTY_CLASS(PEnum) - DECLARE_POINTER(ValueType) -END_POINTERS +IMPLEMENT_CLASS(PEnum, false, true, false, false) + +IMPLEMENT_POINTERS_START(PEnum) + IMPLEMENT_POINTER(ValueType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1758,6 +1706,7 @@ END_POINTERS PEnum::PEnum() : ValueType(NULL) { + mDescriptiveName = "Enum"; } //========================================================================== @@ -1769,6 +1718,7 @@ PEnum::PEnum() PEnum::PEnum(FName name, PTypeBase *outer) : PNamedType(name, outer), ValueType(NULL) { + mDescriptiveName.Format("Enum<%s>", name.GetChars()); } //========================================================================== @@ -1794,9 +1744,11 @@ PEnum *NewEnum(FName name, PTypeBase *outer) /* PArray *****************************************************************/ -IMPLEMENT_POINTY_CLASS(PArray) - DECLARE_POINTER(ElementType) -END_POINTERS +IMPLEMENT_CLASS(PArray, false, true, false, false) + +IMPLEMENT_POINTERS_START(PArray) + IMPLEMENT_POINTER(ElementType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1807,6 +1759,7 @@ END_POINTERS PArray::PArray() : ElementType(NULL), ElementCount(0) { + mDescriptiveName = "Array"; } //========================================================================== @@ -1818,6 +1771,8 @@ PArray::PArray() PArray::PArray(PType *etype, unsigned int ecount) : ElementType(etype), ElementCount(ecount) { + mDescriptiveName.Format("Array<%s>[%d]", etype->DescriptiveName(), ecount); + Align = etype->Align; // Since we are concatenating elements together, the element size should // also be padded to the nearest alignment. @@ -1938,7 +1893,7 @@ PArray *NewArray(PType *type, unsigned int count) /* PVector ****************************************************************/ -IMPLEMENT_CLASS(PVector) +IMPLEMENT_CLASS(PVector, false, false, false, false) //========================================================================== // @@ -1949,6 +1904,7 @@ IMPLEMENT_CLASS(PVector) PVector::PVector() : PArray(TypeFloat32, 3) { + mDescriptiveName = "Vector"; } //========================================================================== @@ -1960,6 +1916,7 @@ PVector::PVector() PVector::PVector(unsigned int size) : PArray(TypeFloat32, size) { + mDescriptiveName.Format("Vector<%d>", size); assert(size >= 2 && size <= 4); } @@ -1986,9 +1943,11 @@ PVector *NewVector(unsigned int size) /* PDynArray **************************************************************/ -IMPLEMENT_POINTY_CLASS(PDynArray) - DECLARE_POINTER(ElementType) -END_POINTERS +IMPLEMENT_CLASS(PDynArray, false, true, false, false) + +IMPLEMENT_POINTERS_START(PDynArray) + IMPLEMENT_POINTER(ElementType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1999,6 +1958,7 @@ END_POINTERS PDynArray::PDynArray() : ElementType(NULL) { + mDescriptiveName = "DynArray"; Size = sizeof(FArray); Align = __alignof(FArray); } @@ -2012,6 +1972,7 @@ PDynArray::PDynArray() PDynArray::PDynArray(PType *etype) : ElementType(etype) { + mDescriptiveName.Format("DynArray<%s>", etype->DescriptiveName()); Size = sizeof(FArray); Align = __alignof(FArray); } @@ -2065,10 +2026,12 @@ PDynArray *NewDynArray(PType *type) /* PMap *******************************************************************/ -IMPLEMENT_POINTY_CLASS(PMap) - DECLARE_POINTER(KeyType) - DECLARE_POINTER(ValueType) -END_POINTERS +IMPLEMENT_CLASS(PMap, false, true, false, false) + +IMPLEMENT_POINTERS_START(PMap) + IMPLEMENT_POINTER(KeyType) + IMPLEMENT_POINTER(ValueType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -2079,6 +2042,7 @@ END_POINTERS PMap::PMap() : KeyType(NULL), ValueType(NULL) { + mDescriptiveName = "Map"; Size = sizeof(FMap); Align = __alignof(FMap); } @@ -2092,6 +2056,7 @@ PMap::PMap() PMap::PMap(PType *keytype, PType *valtype) : KeyType(keytype), ValueType(valtype) { + mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName()); Size = sizeof(FMap); Align = __alignof(FMap); } @@ -2145,7 +2110,7 @@ PMap *NewMap(PType *keytype, PType *valuetype) /* PStruct ****************************************************************/ -IMPLEMENT_CLASS(PStruct) +IMPLEMENT_CLASS(PStruct, false, false, false, false) //========================================================================== // @@ -2155,6 +2120,8 @@ IMPLEMENT_CLASS(PStruct) PStruct::PStruct() { + mDescriptiveName = "Struct"; + Size = 0; } //========================================================================== @@ -2166,6 +2133,9 @@ PStruct::PStruct() PStruct::PStruct(FName name, PTypeBase *outer) : PNamedType(name, outer) { + mDescriptiveName.Format("Struct<%s>", name.GetChars()); + Size = 0; + HasNativeFields = false; } //========================================================================== @@ -2180,7 +2150,7 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArrayFlags & VARF_Native)) { - field->Type->SetDefaultValue(base, offset + field->Offset, special); + field->Type->SetDefaultValue(base, unsigned(offset + field->Offset), special); } } } @@ -2282,13 +2252,13 @@ bool PStruct::ReadFields(FSerializer &ar, void *addr) const PField *PStruct::AddField(FName name, PType *type, DWORD flags) { - PField *field = new PField(name, type); + PField *field = new PField(name, type, flags); // The new field is added to the end of this struct, alignment permitting. field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1); // Enlarge this struct to enclose the new field. - Size = field->Offset + type->Size; + Size = unsigned(field->Offset + type->Size); // This struct's alignment is the same as the largest alignment of any of // its fields. @@ -2304,6 +2274,29 @@ PField *PStruct::AddField(FName name, PType *type, DWORD flags) return field; } +//========================================================================== +// +// PStruct :: AddField +// +// Appends a new native field to the struct. Returns either the new field +// or NULL if a symbol by that name already exists. +// +//========================================================================== + +PField *PStruct::AddNativeField(FName name, PType *type, size_t address, DWORD flags, int bitvalue) +{ + PField *field = new PField(name, type, flags|VARF_Native, address, bitvalue); + + if (Symbols.AddSymbol(field) == nullptr) + { // name is already in use + field->Destroy(); + return nullptr; + } + Fields.Push(field); + HasNativeFields = true; + return field; +} + //========================================================================== // // PStruct :: PropagateMark @@ -2338,7 +2331,7 @@ PStruct *NewStruct(FName name, PTypeBase *outer) /* PField *****************************************************************/ -IMPLEMENT_CLASS(PField) +IMPLEMENT_CLASS(PField, false, false, false, false) //========================================================================== // @@ -2351,9 +2344,39 @@ PField::PField() { } + +PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue) + : PSymbol(name), Offset(offset), Type(type), Flags(flags) +{ + BitValue = bitvalue; + if (bitvalue != -1) + { + BitValue = 0; + unsigned val = bitvalue; + while ((val >>= 1)) BitValue++; + + if (type->IsA(RUNTIME_CLASS(PInt)) && unsigned(BitValue) < 8u * type->Size) + { + // map to the single bytes in the actual variable. The internal bit instructions operate on 8 bit values. +#ifndef __BIG_ENDIAN__ + Offset += BitValue / 8; +#else + Offset += type->Size - 1 - BitValue / 8; +#endif + BitValue &= 7; + Type = TypeBool; + } + else + { + // Just abort. Bit fields should only be defined internally. + I_FatalError("Trying to create an invalid bit field element: %s", name.GetChars()); + } + } +} + /* PPrototype *************************************************************/ -IMPLEMENT_CLASS(PPrototype) +IMPLEMENT_CLASS(PPrototype, false, false, false, false) //========================================================================== // @@ -2439,7 +2462,7 @@ PPrototype *NewPrototype(const TArray &rettypes, const TArray /* PFunction **************************************************************/ -IMPLEMENT_CLASS(PFunction) +IMPLEMENT_CLASS(PFunction, false, false, false, false) //========================================================================== // @@ -2451,7 +2474,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(); @@ -2466,22 +2489,46 @@ size_t PFunction::PropagateMark() // //========================================================================== -unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, VMFunction *impl) +unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags) { Variant variant; - //variant.Proto = proto; - variant.ArgFlags = argflags; + // I do not think we really want to deal with overloading here... + assert(Variants.Size() == 0); + + variant.Flags = flags; + variant.Proto = proto; + variant.ArgFlags = std::move(argflags); + variant.ArgNames = std::move(argnames); variant.Implementation = impl; - impl->Proto = proto; + if (impl != nullptr) impl->Proto = proto; + + // SelfClass can differ from OwningClass, but this is variant-dependent. + // Unlike the owner there can be cases where different variants can have different SelfClasses. + // (Of course only if this ever gets enabled...) + if (flags & VARF_Method) + { + assert(proto->ArgumentTypes.Size() > 0); + auto selftypeptr = dyn_cast(proto->ArgumentTypes[0]); + assert(selftypeptr != nullptr); + variant.SelfClass = dyn_cast(selftypeptr->PointedType); + assert(variant.SelfClass != nullptr); + } + else + { + variant.SelfClass = nullptr; + } + return Variants.Push(variant); } /* PClass *****************************************************************/ -IMPLEMENT_POINTY_CLASS(PClass) - DECLARE_POINTER(ParentClass) -END_POINTERS +IMPLEMENT_CLASS(PClass, false, true, false, false) + +IMPLEMENT_POINTERS_START(PClass) + IMPLEMENT_POINTER(ParentClass) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -2647,6 +2694,16 @@ void PClass::StaticInit () // Keep built-in classes in consistant order. I did this before, though // I'm not sure if this is really necessary to maintain any sort of sync. qsort(&AllClasses[0], AllClasses.Size(), sizeof(AllClasses[0]), cregcmp); + + // Set all symbol table relations here so that they are valid right from the start. + for (auto c : AllClasses) + { + if (c->ParentClass != nullptr) + { + c->Symbols.SetParentTable(&c->ParentClass->Symbols); + } + } + } //========================================================================== @@ -2697,9 +2754,11 @@ void PClass::StaticShutdown () FAutoSegIterator probe(CRegHead, CRegTail); - while (*++probe != NULL) + while (*++probe != nullptr) { - ((ClassReg *)*probe)->MyClass = NULL; + auto cr = ((ClassReg *)*probe); + cr->MyClass = nullptr; + if (cr->VMExport != nullptr) cr->VMExport->MyClass = nullptr; } } @@ -2744,13 +2803,16 @@ void PClass::StaticBootstrap() PClass::PClass() { Size = sizeof(DObject); - ParentClass = NULL; - Pointers = NULL; - FlatPointers = NULL; - HashNext = NULL; - Defaults = NULL; + ParentClass = nullptr; + Pointers = nullptr; + FlatPointers = nullptr; + HashNext = nullptr; + Defaults = nullptr; bRuntimeClass = false; - ConstructNative = NULL; + bExported = false; + bDecorateClass = false; + ConstructNative = nullptr; + mDescriptiveName = "Class"; PClass::AllClasses.Push(this); } @@ -2811,7 +2873,7 @@ PClass *ClassReg::RegisterClass() assert(0 && "Class registry has an invalid meta class identifier"); } - if (metaclasses[MetaClassNum]->MyClass == NULL) + if (metaclasses[MetaClassNum]->MyClass == nullptr) { // Make sure the meta class is already registered before registering this one metaclasses[MetaClassNum]->RegisterClass(); } @@ -2819,10 +2881,14 @@ PClass *ClassReg::RegisterClass() SetupClass(cls); cls->InsertIntoHash(); - if (ParentType != NULL) + if (ParentType != nullptr) { cls->ParentClass = ParentType->RegisterClass(); } + if (VMExport != nullptr) + { + cls->VMExported = VMExport->RegisterClass(); + } return cls; } @@ -2843,6 +2909,7 @@ void ClassReg::SetupClass(PClass *cls) cls->Size = SizeOf; cls->Pointers = Pointers; cls->ConstructNative = ConstructNative; + cls->mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars()); } //========================================================================== @@ -2928,10 +2995,7 @@ DObject *PClass::CreateNew() const ConstructNative (mem); ((DObject *)mem)->SetClass (const_cast(this)); - if (Defaults != NULL) - { - InitializeSpecials(mem); - } + InitializeSpecials(mem); return (DObject *)mem; } @@ -2955,7 +3019,7 @@ void PClass::InitializeSpecials(void *addr) const ParentClass->InitializeSpecials(addr); for (auto tao : SpecialInits) { - tao.first->InitializeValue((BYTE*)addr + tao.second, Defaults + tao.second); + tao.first->InitializeValue((BYTE*)addr + tao.second, Defaults == nullptr? nullptr : Defaults + tao.second); } } @@ -2992,20 +3056,70 @@ void PClass::DestroySpecials(void *addr) const // //========================================================================== -void PClass::Derive(PClass *newclass) +void PClass::Derive(PClass *newclass, FName name) { + newclass->bRuntimeClass = true; newclass->ParentClass = this; newclass->ConstructNative = ConstructNative; + newclass->Symbols.SetParentTable(&this->Symbols); + newclass->TypeName = name; + newclass->mDescriptiveName.Format("Class<%s>", name.GetChars()); +} - // Set up default instance of the new class. - newclass->Defaults = (BYTE *)M_Malloc(newclass->Size); - if (Defaults) memcpy(newclass->Defaults, Defaults, Size); - if (newclass->Size > Size) +//========================================================================== +// +// PClassActor :: InitializeNativeDefaults +// +//========================================================================== + +void PClass::InitializeDefaults() +{ + assert(Defaults == NULL); + Defaults = (BYTE *)M_Malloc(Size); + if (ParentClass->Defaults != NULL) { - memset(newclass->Defaults + Size, 0, newclass->Size - Size); + memcpy(Defaults, ParentClass->Defaults, ParentClass->Size); + if (Size > ParentClass->Size) + { + memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size); + } + } + else + { + memset(Defaults, 0, Size); } - newclass->Symbols.SetParentTable(&this->Symbols); + if (bRuntimeClass) + { + // Copy parent values from the parent defaults. + assert(ParentClass != NULL); + ParentClass->InitializeSpecials(Defaults); + + // and initialize our own special values. + auto it = Symbols.GetIterator(); + PSymbolTable::MapType::Pair *pair; + + while (it.NextPair(pair)) + { + auto field = dyn_cast(pair->Value); + if (field != nullptr && !(field->Flags & VARF_Native)) + { + field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); + } + } + } +} + +//========================================================================== +// +// PClass :: DeriveData +// +// Copies inheritable data to the child class. +// +//========================================================================== + +void PClass::DeriveData(PClass *newclass) +{ } //========================================================================== @@ -3030,12 +3144,19 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) { if (existclass->Size == TentativeClass) { - type = const_cast(existclass); - if (!IsDescendantOf(type->ParentClass)) + if (!IsDescendantOf(existclass->ParentClass)) { - I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); + I_Error("%s must inherit from %s but doesn't.", name.GetChars(), existclass->ParentClass->TypeName.GetChars()); + } + + if (size == TentativeClass) + { + // see if we can reuse the existing class. This is only possible if the inheritance is identical. Otherwise it needs to be replaced. + if (this == existclass->ParentClass) + { + return existclass; + } } - DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars()); notnew = true; } else @@ -3052,11 +3173,14 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) // Create a new type object of the same type as us. (We may be a derived class of PClass.) type = static_cast(GetClass()->CreateNew()); - type->TypeName = name; + Derive(type, name); type->Size = size; - type->bRuntimeClass = true; - Derive(type); - DeriveData(type); + if (size != TentativeClass) + { + type->InitializeDefaults(); + type->Virtuals = Virtuals; + DeriveData(type); + } if (!notnew) { type->InsertIntoHash(); @@ -3086,15 +3210,14 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) { unsigned oldsize = Size; PField *field = Super::AddField(name, type, flags); - if (field != NULL) + + // Only initialize the defaults if they have already been created. + // For ZScript this is not the case, it will first define all fields before + // setting up any defaults for any class. + if (field != nullptr && !(flags & VARF_Native) && Defaults != nullptr) { - Defaults = (BYTE *)M_Realloc(Defaults, Size); - memset(Defaults + oldsize, 0, Size - oldsize); - // If this is a native class, then we must not initialize and - // destroy any of its members. We do, however, initialize the - // default instance since it's not a normal instance of the class. - type->SetDefaultValue(Defaults, field->Offset, - bRuntimeClass ? &SpecialInits : NULL); + Defaults = (BYTE *)M_Realloc(Defaults, Size); + memset(Defaults + oldsize, 0, Size - oldsize); } return field; } @@ -3104,12 +3227,11 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) // PClass :: FindClassTentative // // Like FindClass but creates a placeholder if no class is found. -// CreateDerivedClass will automatically fill in the placeholder when the -// actual class is defined. +// This will be filled in when the actual class is constructed. // //========================================================================== -PClass *PClass::FindClassTentative(FName name, bool fatal) +PClass *PClass::FindClassTentative(FName name) { if (name == NAME_None) { @@ -3127,14 +3249,59 @@ PClass *PClass::FindClassTentative(FName name, bool fatal) PClass *type = static_cast(GetClass()->CreateNew()); DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); - type->TypeName = name; - type->ParentClass = this; + Derive(type, name); type->Size = TentativeClass; - type->bRuntimeClass = true; TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket); return type; } +//========================================================================== +// +// PClass :: FindVirtualIndex +// +// Compares a prototype with the existing list of virtual functions +// and returns an index if something matching is found. +// +//========================================================================== + +int PClass::FindVirtualIndex(FName name, PPrototype *proto) +{ + for (unsigned i = 0; i < Virtuals.Size(); i++) + { + if (Virtuals[i]->Name == name) + { + auto vproto = Virtuals[i]->Proto; + if (vproto->ReturnTypes.Size() != proto->ReturnTypes.Size() || + vproto->ArgumentTypes.Size() != proto->ArgumentTypes.Size()) + { + continue; // number of parameters does not match, so it's incompatible + } + bool fail = false; + // The first argument is self and will mismatch so just skip it. + for (unsigned a = 1; a < proto->ArgumentTypes.Size(); a++) + { + if (proto->ArgumentTypes[a] != vproto->ArgumentTypes[a]) + { + fail = true; + break; + } + } + if (fail) continue; + + for (unsigned a = 0; a < proto->ReturnTypes.Size(); a++) + { + if (proto->ReturnTypes[a] != vproto->ReturnTypes[a]) + { + fail = true; + break; + } + } + if (!fail) return i; + } + } + return -1; +} + //========================================================================== // // PClass :: BuildFlatPointers @@ -3197,7 +3364,7 @@ void PClass::BuildFlatPointers () // // PClass :: NativeClass // -// Finds the underlying native type underlying this class. +// Finds the native type underlying this class. // //========================================================================== @@ -3379,18 +3546,23 @@ CCMD(typetable) // Symbol tables ------------------------------------------------------------ -IMPLEMENT_ABSTRACT_CLASS(PTypeBase); -IMPLEMENT_ABSTRACT_CLASS(PSymbol); -IMPLEMENT_CLASS(PSymbolConst); -IMPLEMENT_CLASS(PSymbolConstNumeric); -IMPLEMENT_CLASS(PSymbolConstString); -IMPLEMENT_POINTY_CLASS(PSymbolType) - DECLARE_POINTER(Type) -END_POINTERS -IMPLEMENT_POINTY_CLASS(PSymbolVMFunction) - DECLARE_POINTER(Function) -END_POINTERS -IMPLEMENT_CLASS(PSymbolTreeNode) +IMPLEMENT_CLASS(PTypeBase, true, false, false, false); +IMPLEMENT_CLASS(PSymbol, true, false, false, false); +IMPLEMENT_CLASS(PSymbolConst, false, false, false, false); +IMPLEMENT_CLASS(PSymbolConstNumeric, false, false, false, false); +IMPLEMENT_CLASS(PSymbolConstString, false, false, false, false); +IMPLEMENT_CLASS(PSymbolTreeNode, false, false, false, false) +IMPLEMENT_CLASS(PSymbolType, false, true, false, false) + +IMPLEMENT_POINTERS_START(PSymbolType) + IMPLEMENT_POINTER(Type) +IMPLEMENT_POINTERS_END + +IMPLEMENT_CLASS(PSymbolVMFunction, false, true, false, false) + +IMPLEMENT_POINTERS_START(PSymbolVMFunction) + IMPLEMENT_POINTER(Function) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/dobjtype.h b/src/dobjtype.h index 338c51f98..1ca5df832 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -14,11 +14,25 @@ typedef std::pair FTypeAndOffset; // Making all these different storage types use a common set of flags seems // like the simplest thing to do. -#define VARF_Optional (1<<0) // func param is optional -#define VARF_Method (1<<1) // func has an implied self parameter -#define VARF_Action (1<<2) // func has implied owner and state parameters -#define VARF_Native (1<<3) // func is native code/don't auto serialize field -#define VARF_ReadOnly (1<<4) // field is read only, do not write to it +enum +{ + VARF_Optional = (1<<0), // func param is optional + VARF_Method = (1<<1), // func has an implied self parameter + VARF_Action = (1<<2), // func has implied owner and state parameters + VARF_Native = (1<<3), // func is native code/don't auto serialize field + VARF_ReadOnly = (1<<4), // field is read only, do not write to it + VARF_Private = (1<<5), // field is private to containing class + VARF_Protected = (1<<6), // field is only accessible by containing class and children. + VARF_Deprecated = (1<<7), // Deprecated fields should output warnings when used. + VARF_Virtual = (1<<8), // function is virtual + VARF_Final = (1<<9), // Function may not be overridden in subclasses + VARF_In = (1<<10), + VARF_Out = (1<<11), + VARF_Implicit = (1<<12), // implicitly created parameters (i.e. do not compare types when checking function signatures) + VARF_Static = (1<<13), // static class data (by necessity read only.) + VARF_InternalAccess = (1<<14), // overrides VARF_ReadOnly for internal script code. + VARF_Override = (1<<15), // overrides a virtual function from the parent class. +}; // Symbol information ------------------------------------------------------- @@ -57,7 +71,6 @@ struct StateCallData; class VMFrameStack; struct VMValue; struct VMReturn; -typedef int (*actionf_p)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ class VMFunction; // A VM function ------------------------------------------------------------ @@ -86,18 +99,6 @@ public: PSymbolType() : PSymbol(NAME_None) {} }; -// A symbol for a compiler tree node ---------------------------------------- - -class PSymbolTreeNode : public PSymbol -{ - DECLARE_CLASS(PSymbolTreeNode, PSymbol); -public: - struct ZCC_NamedNode *Node; - - PSymbolTreeNode(FName name, struct ZCC_NamedNode *node) : PSymbol(name), Node(node) {} - PSymbolTreeNode() : PSymbol(NAME_None) {} -}; - // A symbol table ----------------------------------------------------------- struct PSymbolTable @@ -111,6 +112,10 @@ struct PSymbolTable // Sets the table to use for searches if this one doesn't contain the // requested symbol. void SetParentTable (PSymbolTable *parent); + PSymbolTable *GetParentTable() const + { + return ParentSymbolTable; + } // Finds a symbol in the table, optionally searching parent tables // as well. @@ -120,6 +125,7 @@ struct PSymbolTable // specific symbol table the symbol was found in. PSymbol *FindSymbolInTable(FName symname, PSymbolTable *&symtable); + // Places the symbol in the table and returns a pointer to it or NULL if // a symbol with the same name is already in the table. This symbol is // not copied and will be freed when the symbol table is destroyed. @@ -132,15 +138,33 @@ struct PSymbolTable // Frees all symbols from this table. void ReleaseSymbols(); -private: typedef TMap MapType; + MapType::Iterator GetIterator() + { + return MapType::Iterator(Symbols); + } + +private: + PSymbolTable *ParentSymbolTable; MapType Symbols; friend class DObject; }; +// A symbol for a compiler tree node ---------------------------------------- + +class PSymbolTreeNode : public PSymbol +{ + DECLARE_CLASS(PSymbolTreeNode, PSymbol); +public: + struct ZCC_TreeNode *Node; + + PSymbolTreeNode(FName name, struct ZCC_TreeNode *node) : PSymbol(name), Node(node) {} + PSymbolTreeNode() : PSymbol(NAME_None) {} +}; + extern PSymbolTable GlobalSymbols; // Basic information shared by all types ------------------------------------ @@ -179,6 +203,7 @@ class PType : public PTypeBase HAS_OBJECT_POINTERS; protected: enum { MetaClassNum = CLASSREG_PClassType }; + public: typedef PClassType MetaClass; MetaClass *GetClass() const; @@ -196,10 +221,13 @@ public: unsigned int Align; // this type's preferred alignment PType *HashNext; // next type in this type table PSymbolTable Symbols; + bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument. + FString mDescriptiveName; + BYTE loadOp, storeOp, moveOp, RegType, RegCount; - PType(); - PType(unsigned int size, unsigned int align); + PType(unsigned int size = 1, unsigned int align = 1); virtual ~PType(); + virtual bool isNumeric() { return false; } bool AddConversion(PType *target, void (*convertconst)(ZCC_ExprConstant *, class FSharedStringArena &)); @@ -240,14 +268,33 @@ public: virtual double GetValueFloat(void *addr) const; // Gets the opcode to store from a register to memory - virtual int GetStoreOp() const; + int GetStoreOp() const + { + return storeOp; + } // Gets the opcode to load from memory to a register - virtual int GetLoadOp() const; + int GetLoadOp() const + { + return loadOp; + } + + // Gets the opcode to move from register to another register + int GetMoveOp() const + { + return moveOp; + } // Gets the register type for this type - virtual int GetRegType() const; + int GetRegType() const + { + return RegType; + } + int GetRegCount() const + { + return RegCount; + } // Returns true if this type matches the two identifiers. Referring to the // above table, any type is identified by at most two characteristics. Each // type that implements this function will cast these to the appropriate type. @@ -259,6 +306,8 @@ public: // Get the type IDs used by IsMatch virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + const char *DescriptiveName() const; + size_t PropagateMark(); static void StaticInit(); @@ -351,8 +400,12 @@ public: PTypeBase *Outer; // object this type is contained within FName TypeName; // this type's name - PNamedType() : Outer(NULL) {} - PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {} + PNamedType() : Outer(NULL) { + mDescriptiveName = "NamedType"; + } + PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) { + mDescriptiveName = name.GetChars(); + } virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; @@ -365,7 +418,7 @@ class PInt : public PBasicType { DECLARE_CLASS(PInt, PBasicType); public: - PInt(unsigned int size, bool unsign); + PInt(unsigned int size, bool unsign, bool compatible = true); void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; @@ -374,13 +427,13 @@ public: virtual void SetValue(void *addr, double val); virtual int GetValueInt(void *addr) const; virtual double GetValueFloat(void *addr) const; - virtual int GetStoreOp() const; - virtual int GetLoadOp() const; - virtual int GetRegType() const; + virtual bool isNumeric() override { return IntCompatible; } bool Unsigned; + bool IntCompatible; protected: PInt(); + void SetOps(); }; class PBool : public PInt @@ -403,11 +456,10 @@ public: virtual void SetValue(void *addr, double val); virtual int GetValueInt(void *addr) const; virtual double GetValueFloat(void *addr) const; - virtual int GetStoreOp() const; - virtual int GetLoadOp() const; - virtual int GetRegType() const; + virtual bool isNumeric() override { return true; } protected: PFloat(); + void SetOps(); private: struct SymbolInitF { @@ -432,8 +484,6 @@ class PString : public PBasicType public: PString(); - virtual int GetRegType() const; - void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *special=NULL) const override; @@ -470,6 +520,13 @@ public: PColor(); }; +class PStateLabel : public PInt +{ + DECLARE_CLASS(PStateLabel, PInt); +public: + PStateLabel(); +}; + // Pointers ----------------------------------------------------------------- class PStatePointer : public PBasicType @@ -480,10 +537,6 @@ public: void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; - - virtual int GetStoreOp() const; - virtual int GetLoadOp() const; - virtual int GetRegType() const; }; class PPointer : public PBasicType @@ -491,13 +544,11 @@ class PPointer : public PBasicType DECLARE_CLASS(PPointer, PBasicType); HAS_OBJECT_POINTERS; public: - PPointer(PType *pointsat); + PPointer(); + PPointer(PType *pointsat, bool isconst = false); PType *PointedType; - - virtual int GetStoreOp() const; - virtual int GetLoadOp() const; - virtual int GetRegType() const; + bool IsConst; virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; @@ -506,7 +557,7 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; protected: - PPointer(); + void SetOps(); }; class PClassPointer : public PPointer @@ -532,13 +583,12 @@ class PField : public PSymbol DECLARE_CLASS(PField, PSymbol); HAS_OBJECT_POINTERS public: - PField(FName name, PType *type) : PSymbol(name), Offset(0), Type(type), Flags(0) {} - PField(FName name, PType *type, DWORD flags) : PSymbol(name), Offset(0), Type(type), Flags(flags) {} - PField(FName name, PType *type, DWORD flags, unsigned offset) : PSymbol(name), Offset(offset), Type(type), Flags(flags) {} + PField(FName name, PType *type, DWORD flags = 0, size_t offset = 0, int bitvalue = -1); - unsigned int Offset; + size_t Offset; PType *Type; DWORD Flags; + int BitValue; protected: PField(); }; @@ -630,8 +680,10 @@ public: PStruct(FName name, PTypeBase *outer); TArray Fields; + bool HasNativeFields; virtual PField *AddField(FName name, PType *type, DWORD flags=0); + virtual PField *AddNativeField(FName name, PType *type, size_t address, DWORD flags = 0, int bitvalue = -1); size_t PropagateMark(); @@ -668,19 +720,27 @@ class PFunction : public PSymbol public: struct Variant { - //PPrototype *Proto; + PPrototype *Proto; VMFunction *Implementation; TArray ArgFlags; // Should be the same length as Proto->ArgumentTypes + TArray ArgNames; // we need the names to access them later when the function gets compiled. + DWORD Flags; + PClass *SelfClass; }; TArray Variants; - DWORD Flags; + PClass *OwningClass = nullptr; - unsigned AddVariant(PPrototype *proto, TArray &argflags, VMFunction *impl); + unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags); + int GetImplicitArgs() + { + if (Variants[0].Flags & VARF_Action) return 3; + else if (Variants[0].Flags & VARF_Method) return 1; + return 0; + } size_t PropagateMark(); - PFunction(FName name) : PSymbol(name), Flags(0) {} - PFunction() : PSymbol(NAME_None), Flags(0) {} + PFunction(PClass *owner = nullptr, FName name = NAME_None) : PSymbol(name), OwningClass(owner) {} }; // Meta-info for every class derived from DObject --------------------------- @@ -699,8 +759,9 @@ protected: // We unravel _WITH_META here just as we did for PType. enum { MetaClassNum = CLASSREG_PClassClass }; TArray SpecialInits; - virtual void Derive(PClass *newclass); + void Derive(PClass *newclass, FName name); void InitializeSpecials(void *addr) const; + void SetSuper(); public: typedef PClassClass MetaClass; MetaClass *GetClass() const; @@ -709,18 +770,24 @@ public: void WriteAllFields(FSerializer &ar, const void *addr) const; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; bool ReadAllFields(FSerializer &ar, void *addr) const; + void InitializeDefaults(); + int FindVirtualIndex(FName name, PPrototype *proto); + virtual void DeriveData(PClass *newclass); - virtual void DeriveData(PClass *newclass) {} static void StaticInit(); static void StaticShutdown(); static void StaticBootstrap(); // Per-class information ------------------------------------- PClass *ParentClass; // the class this class derives from + PClass *VMExported; // this is here to allow script classes to override native virtual functions const size_t *Pointers; // object pointers defined by this class *only* const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default BYTE *Defaults; bool bRuntimeClass; // class was defined at run-time, not compile-time + bool bExported; // This type has been declared in a script + bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility + TArray Virtuals; // virtual function table void (*ConstructNative)(void *); @@ -764,7 +831,7 @@ public: static PClassActor *FindActor(const FString &name) { return FindActor(FName(name, true)); } static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); } static PClassActor *FindActor(FName name); - PClass *FindClassTentative(FName name, bool fatal = true); // not static! + PClass *FindClassTentative(FName name); static TArray AllClasses; @@ -777,7 +844,7 @@ class PClassType : public PClass protected: public: PClassType(); - virtual void Derive(PClass *newclass); + virtual void DeriveData(PClass *newclass); PClass *TypeTableType; // The type to use for hashing into the type table }; @@ -799,17 +866,6 @@ inline PClass::MetaClass *PClass::GetClass() const return static_cast(DObject::GetClass()); } -// A class that hasn't had its parent class defined yet --------------------- - -class PClassWaitingForParent : public PClass -{ - DECLARE_CLASS(PClassWaitingForParent, PClass); -public: - PClassWaitingForParent(FName myname, FName parentname); - - FName ParentName; -}; - // Type tables -------------------------------------------------------------- struct FTypeTable @@ -836,9 +892,8 @@ PVector *NewVector(unsigned int size); PMap *NewMap(PType *keytype, PType *valuetype); PArray *NewArray(PType *type, unsigned int count); PDynArray *NewDynArray(PType *type); -PPointer *NewPointer(PType *type); +PPointer *NewPointer(PType *type, bool isconst = false); PClassPointer *NewClassPointer(PClass *restrict); -PClassWaitingForParent *NewUnknownClass(FName myname, FName parentname); PEnum *NewEnum(FName name, PTypeBase *outer); PStruct *NewStruct(FName name, PTypeBase *outer); PPrototype *NewPrototype(const TArray &rettypes, const TArray &argtypes); @@ -856,7 +911,11 @@ extern PString *TypeString; extern PName *TypeName; extern PSound *TypeSound; extern PColor *TypeColor; +extern PStruct *TypeVector2; +extern PStruct *TypeVector3; extern PStatePointer *TypeState; +extern PStateLabel *TypeStateLabel; +extern PPointer *TypeNullPtr; // A constant value --------------------------------------------------------- diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 815b49dc4..700a407fd 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -31,7 +31,7 @@ #include "serializer.h" #include "doomstat.h" -IMPLEMENT_CLASS (DSectorEffect) +IMPLEMENT_CLASS(DSectorEffect, false, false, false, false) DSectorEffect::DSectorEffect () : DThinker(STAT_SECTOREFFECT) @@ -71,9 +71,11 @@ void DSectorEffect::Serialize(FSerializer &arc) arc("sector", m_Sector); } -IMPLEMENT_POINTY_CLASS (DMover) - DECLARE_POINTER(interpolation) -END_POINTERS +IMPLEMENT_CLASS(DMover, false, true, false, false) + +IMPLEMENT_POINTERS_START(DMover) + IMPLEMENT_POINTER(interpolation) +IMPLEMENT_POINTERS_END DMover::DMover () { @@ -106,9 +108,7 @@ void DMover::StopInterpolation(bool force) } } - - -IMPLEMENT_CLASS (DMovingFloor) +IMPLEMENT_CLASS(DMovingFloor, false, false, false, false) DMovingFloor::DMovingFloor () { @@ -121,7 +121,7 @@ DMovingFloor::DMovingFloor (sector_t *sector) interpolation = sector->SetInterpolation(sector_t::FloorMove, true); } -IMPLEMENT_CLASS (DMovingCeiling) +IMPLEMENT_CLASS(DMovingCeiling, false, false, false, false) DMovingCeiling::DMovingCeiling () { diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 114d260df..06cd5dbfa 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -40,6 +40,7 @@ #include "doomerrors.h" #include "serializer.h" #include "d_player.h" +#include "virtual.h" static cycle_t ThinkCycles; @@ -47,7 +48,7 @@ extern cycle_t BotSupportCycles; extern cycle_t ActionCycles; extern int BotWTG; -IMPLEMENT_CLASS (DThinker) +IMPLEMENT_CLASS(DThinker, false, false, false, true) DThinker *NextToThink; @@ -480,7 +481,7 @@ void FThinkerIterator::Reinit () m_SearchingFresh = false; } -DThinker *FThinkerIterator::Next () +DThinker *FThinkerIterator::Next (bool exact) { if (m_ParentType == NULL) { @@ -496,7 +497,11 @@ DThinker *FThinkerIterator::Next () { DThinker *thinker = m_CurrThinker; m_CurrThinker = thinker->NextThinker; - if (thinker->IsKindOf(m_ParentType)) + if (exact) + { + if (thinker->IsA(m_ParentType)) return thinker; + } + else if (thinker->IsKindOf(m_ParentType)) { return thinker; } @@ -521,6 +526,44 @@ DThinker *FThinkerIterator::Next () return NULL; } +// This is for scripting, which needs the iterator wrapped into an object with the needed functions exported. +// Unfortunately we cannot have templated type conversions in scripts. +class DThinkerIterator : public DObject, public FThinkerIterator +{ + DECLARE_CLASS(DThinkerIterator, DObject) + +public: + DThinkerIterator(PClass *cls = nullptr, int statnum = MAX_STATNUM + 1) + : FThinkerIterator(cls, statnum) + { + } +}; + +IMPLEMENT_CLASS(DThinkerIterator, false, false, false, false); +DEFINE_ACTION_FUNCTION(DThinkerIterator, Create) +{ + PARAM_PROLOGUE; + PARAM_CLASS_DEF(type, DThinker); + PARAM_INT_DEF(statnum); + ACTION_RETURN_OBJECT(new DThinkerIterator(type, statnum)); +} + +DEFINE_ACTION_FUNCTION(DThinkerIterator, Next) +{ + PARAM_SELF_PROLOGUE(DThinkerIterator); + ACTION_RETURN_OBJECT(self->Next()); +} + +DEFINE_ACTION_FUNCTION(DThinkerIterator, Reinit) +{ + PARAM_SELF_PROLOGUE(DThinkerIterator); + self->Reinit(); + return 0; +} + + + + ADD_STAT (think) { FString out; diff --git a/src/dthinker.h b/src/dthinker.h index 3f9647297..95985c2fb 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -121,7 +121,7 @@ private: public: FThinkerIterator (const PClass *type, int statnum=MAX_STATNUM+1); FThinkerIterator (const PClass *type, int statnum, DThinker *prev); - DThinker *Next (); + DThinker *Next (bool exact = false); void Reinit (); }; @@ -146,9 +146,9 @@ public: TThinkerIterator (const char *subclass, int statnum=MAX_STATNUM+1) : FThinkerIterator(PClass::FindClass(subclass), statnum) { } - T *Next () + T *Next (bool exact = false) { - return static_cast(FThinkerIterator::Next ()); + return static_cast(FThinkerIterator::Next (exact)); } }; diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index cc096ed60..ddc1a4bd4 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -1785,9 +1785,7 @@ public: void Destroy() { Super::Destroy(); m_Sector->lightingdata=NULL; } }; - - -IMPLEMENT_CLASS (DLightLevel) +IMPLEMENT_CLASS(DLightLevel, false, false, false, false) void DLightLevel::Serialize(FSerializer &arc) { @@ -3636,7 +3634,7 @@ void FParser::SF_Pow() { if (CheckArgs(2)) { - t_return.setDouble(pow(floatvalue(t_argv[0]), floatvalue(t_argv[1]))); + t_return.setDouble(g_pow(floatvalue(t_argv[0]), floatvalue(t_argv[1]))); } } diff --git a/src/fragglescript/t_prepro.cpp b/src/fragglescript/t_prepro.cpp index 619b6d570..2129df54f 100644 --- a/src/fragglescript/t_prepro.cpp +++ b/src/fragglescript/t_prepro.cpp @@ -71,9 +71,11 @@ // //========================================================================== -IMPLEMENT_POINTY_CLASS(DFsSection) - DECLARE_POINTER(next) -END_POINTERS +IMPLEMENT_CLASS(DFsSection, false, true, false, false) + +IMPLEMENT_POINTERS_START(DFsSection) + IMPLEMENT_POINTER(next) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/fragglescript/t_script.cpp b/src/fragglescript/t_script.cpp index f1376b7eb..a40122623 100644 --- a/src/fragglescript/t_script.cpp +++ b/src/fragglescript/t_script.cpp @@ -75,23 +75,23 @@ AActor *trigger_obj; // //========================================================================== -#define DECLARE_16_POINTERS(v, i) \ - DECLARE_POINTER(v[i]) \ - DECLARE_POINTER(v[i+1]) \ - DECLARE_POINTER(v[i+2]) \ - DECLARE_POINTER(v[i+3]) \ - DECLARE_POINTER(v[i+4]) \ - DECLARE_POINTER(v[i+5]) \ - DECLARE_POINTER(v[i+6]) \ - DECLARE_POINTER(v[i+7]) \ - DECLARE_POINTER(v[i+8]) \ - DECLARE_POINTER(v[i+9]) \ - DECLARE_POINTER(v[i+10]) \ - DECLARE_POINTER(v[i+11]) \ - DECLARE_POINTER(v[i+12]) \ - DECLARE_POINTER(v[i+13]) \ - DECLARE_POINTER(v[i+14]) \ - DECLARE_POINTER(v[i+15]) \ +#define IMPLEMENT_16_POINTERS(v, i) \ + IMPLEMENT_POINTER(v[i]) \ + IMPLEMENT_POINTER(v[i+1]) \ + IMPLEMENT_POINTER(v[i+2]) \ + IMPLEMENT_POINTER(v[i+3]) \ + IMPLEMENT_POINTER(v[i+4]) \ + IMPLEMENT_POINTER(v[i+5]) \ + IMPLEMENT_POINTER(v[i+6]) \ + IMPLEMENT_POINTER(v[i+7]) \ + IMPLEMENT_POINTER(v[i+8]) \ + IMPLEMENT_POINTER(v[i+9]) \ + IMPLEMENT_POINTER(v[i+10]) \ + IMPLEMENT_POINTER(v[i+11]) \ + IMPLEMENT_POINTER(v[i+12]) \ + IMPLEMENT_POINTER(v[i+13]) \ + IMPLEMENT_POINTER(v[i+14]) \ + IMPLEMENT_POINTER(v[i+15]) \ //========================================================================== // @@ -99,30 +99,32 @@ AActor *trigger_obj; // //========================================================================== -IMPLEMENT_POINTY_CLASS(DFsScript) - DECLARE_POINTER(parent) - DECLARE_POINTER(trigger) - DECLARE_16_POINTERS(sections, 0) - DECLARE_POINTER(sections[16]) - DECLARE_16_POINTERS(variables, 0) - DECLARE_16_POINTERS(children, 0) - DECLARE_16_POINTERS(children, 16) - DECLARE_16_POINTERS(children, 32) - DECLARE_16_POINTERS(children, 48) - DECLARE_16_POINTERS(children, 64) - DECLARE_16_POINTERS(children, 80) - DECLARE_16_POINTERS(children, 96) - DECLARE_16_POINTERS(children, 112) - DECLARE_16_POINTERS(children, 128) - DECLARE_16_POINTERS(children, 144) - DECLARE_16_POINTERS(children, 160) - DECLARE_16_POINTERS(children, 176) - DECLARE_16_POINTERS(children, 192) - DECLARE_16_POINTERS(children, 208) - DECLARE_16_POINTERS(children, 224) - DECLARE_16_POINTERS(children, 240) - DECLARE_POINTER(children[256]) -END_POINTERS +IMPLEMENT_CLASS(DFsScript, false, true, false, false) + +IMPLEMENT_POINTERS_START(DFsScript) + IMPLEMENT_POINTER(parent) + IMPLEMENT_POINTER(trigger) + IMPLEMENT_16_POINTERS(sections, 0) + IMPLEMENT_POINTER(sections[16]) + IMPLEMENT_16_POINTERS(variables, 0) + IMPLEMENT_16_POINTERS(children, 0) + IMPLEMENT_16_POINTERS(children, 16) + IMPLEMENT_16_POINTERS(children, 32) + IMPLEMENT_16_POINTERS(children, 48) + IMPLEMENT_16_POINTERS(children, 64) + IMPLEMENT_16_POINTERS(children, 80) + IMPLEMENT_16_POINTERS(children, 96) + IMPLEMENT_16_POINTERS(children, 112) + IMPLEMENT_16_POINTERS(children, 128) + IMPLEMENT_16_POINTERS(children, 144) + IMPLEMENT_16_POINTERS(children, 160) + IMPLEMENT_16_POINTERS(children, 176) + IMPLEMENT_16_POINTERS(children, 192) + IMPLEMENT_16_POINTERS(children, 208) + IMPLEMENT_16_POINTERS(children, 224) + IMPLEMENT_16_POINTERS(children, 240) + IMPLEMENT_POINTER(children[256]) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -267,12 +269,14 @@ void DFsScript::ParseScript(char *position) // //========================================================================== -IMPLEMENT_POINTY_CLASS(DRunningScript) - DECLARE_POINTER(prev) - DECLARE_POINTER(next) - DECLARE_POINTER(trigger) - DECLARE_16_POINTERS(variables, 0) -END_POINTERS +IMPLEMENT_CLASS(DRunningScript, false, true, false, false) + +IMPLEMENT_POINTERS_START(DRunningScript) + IMPLEMENT_POINTER(prev) + IMPLEMENT_POINTER(next) + IMPLEMENT_POINTER(trigger) + IMPLEMENT_16_POINTERS(variables, 0) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -375,10 +379,13 @@ void DRunningScript::Serialize(FSerializer &arc) // The main thinker // //========================================================================== -IMPLEMENT_POINTY_CLASS(DFraggleThinker) - DECLARE_POINTER(RunningScripts) - DECLARE_POINTER(LevelScript) -END_POINTERS + +IMPLEMENT_CLASS(DFraggleThinker, false, true, false, false) + +IMPLEMENT_POINTERS_START(DFraggleThinker) + IMPLEMENT_POINTER(RunningScripts) + IMPLEMENT_POINTER(LevelScript) +IMPLEMENT_POINTERS_END TObjPtr DFraggleThinker::ActiveThinker; diff --git a/src/fragglescript/t_variable.cpp b/src/fragglescript/t_variable.cpp index 125f32367..23d24b78a 100644 --- a/src/fragglescript/t_variable.cpp +++ b/src/fragglescript/t_variable.cpp @@ -179,10 +179,12 @@ AActor* actorvalue(const svalue_t &svalue) // //========================================================================== -IMPLEMENT_POINTY_CLASS(DFsVariable) - DECLARE_POINTER (next) - DECLARE_POINTER (actor) -END_POINTERS +IMPLEMENT_CLASS(DFsVariable, false, true, false, false) + +IMPLEMENT_POINTERS_START(DFsVariable) + IMPLEMENT_POINTER(next) + IMPLEMENT_POINTER(actor) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/g_doom/a_arachnotron.cpp b/src/g_doom/a_arachnotron.cpp deleted file mode 100644 index 62660c7f5..000000000 --- a/src/g_doom/a_arachnotron.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* -#include "actor.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -DEFINE_ACTION_FUNCTION(AActor, A_BspiAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - A_FaceTarget (self); - - // launch a missile - P_SpawnMissile (self, self->target, PClass::FindActor("ArachnotronPlasma")); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BabyMetal) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_BODY, "baby/walk", 1, ATTN_IDLE); - A_Chase (stack, self); - return 0; -} diff --git a/src/g_doom/a_archvile.cpp b/src/g_doom/a_archvile.cpp deleted file mode 100644 index 84481e5f6..000000000 --- a/src/g_doom/a_archvile.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "s_sound.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -// -// PIT_VileCheck -// Detect a corpse that could be raised. -// -void A_Fire(AActor *self, double height); - - -// -// A_VileStart -// -DEFINE_ACTION_FUNCTION(AActor, A_VileStart) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_VOICE, "vile/start", 1, ATTN_NORM); - return 0; -} - - -// -// A_Fire -// Keep fire in front of player unless out of sight -// -DEFINE_ACTION_FUNCTION(AActor, A_StartFire) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_BODY, "vile/firestrt", 1, ATTN_NORM); - A_Fire (self, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FireCrackle) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_BODY, "vile/firecrkl", 1, ATTN_NORM); - A_Fire (self, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Fire) -{ - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(height) { height = 0; } - - A_Fire(self, height); - return 0; -} - -void A_Fire(AActor *self, double height) -{ - AActor *dest; - - dest = self->tracer; - if (dest == NULL || self->target == NULL) - return; - - // don't move it if the vile lost sight - if (!P_CheckSight (self->target, dest, 0) ) - return; - - DVector3 newpos = dest->Vec3Angle(24., dest->Angles.Yaw, height); - self->SetOrigin(newpos, true); -} - - - -// -// A_VileTarget -// Spawn the hellfire -// -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget) -{ - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(fire, AActor) { fire = PClass::FindActor("ArchvileFire"); } - - AActor *fog; - - if (!self->target) - return 0; - - A_FaceTarget (self); - - fog = Spawn (fire, self->target->Pos(), ALLOW_REPLACE); - - self->tracer = fog; - fog->target = self; - fog->tracer = self->target; - A_Fire(fog, 0); - return 0; -} - - - - -// -// A_VileAttack -// - -// A_VileAttack flags -#define VAF_DMGTYPEAPPLYTODIRECT 1 - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack) -{ - PARAM_ACTION_PROLOGUE; - PARAM_SOUND_OPT (snd) { snd = "vile/stop"; } - PARAM_INT_OPT (dmg) { dmg = 20; } - PARAM_INT_OPT (blastdmg) { blastdmg = 70; } - PARAM_INT_OPT (blastrad) { blastrad = 70; } - PARAM_FLOAT_OPT (thrust) { thrust = 1; } - PARAM_NAME_OPT (dmgtype) { dmgtype = NAME_Fire; } - PARAM_INT_OPT (flags) { flags = 0; } - - AActor *fire, *target; - - if (NULL == (target = self->target)) - return 0; - - A_FaceTarget (self); - - if (!P_CheckSight (self, target, 0) ) - return 0; - - S_Sound (self, CHAN_WEAPON, snd, 1, ATTN_NORM); - - int newdam; - - if (flags & VAF_DMGTYPEAPPLYTODIRECT) - newdam = P_DamageMobj (target, self, self, dmg, dmgtype); - - else - newdam = P_DamageMobj (target, self, self, dmg, NAME_None); - - P_TraceBleed (newdam > 0 ? newdam : dmg, target); - - fire = self->tracer; - - if (fire != NULL) - { - // move the fire between the vile and the player - DVector3 pos = target->Vec3Angle(-24., self->Angles.Yaw, 0); - fire->SetOrigin (pos, true); - - P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0); - } - if (!(target->flags7 & MF7_DONTTHRUST)) - { - target->Vel.Z = thrust * 1000 / MAX(1, target->Mass); - } - return 0; -} diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index b0e725910..5807ce175 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -7,112 +7,17 @@ #include "s_sound.h" #include "statnums.h" #include "a_specialspot.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" #include "g_level.h" */ -static FRandom pr_brainscream ("BrainScream"); -static FRandom pr_brainexplode ("BrainExplode"); static FRandom pr_spawnfly ("SpawnFly"); -DEFINE_ACTION_FUNCTION(AActor, A_BrainAwake) -{ - PARAM_ACTION_PROLOGUE; - // killough 3/26/98: only generates sound now - S_Sound (self, CHAN_VOICE, "brain/sight", 1, ATTN_NONE); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BrainPain) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_VOICE, "brain/pain", 1, ATTN_NONE); - return 0; -} - -static void BrainishExplosion (const DVector3 &pos) -{ - AActor *boom = Spawn("Rocket", pos, NO_REPLACE); - if (boom != NULL) - { - boom->DeathSound = "misc/brainexplode"; - boom->Vel.Z = pr_brainscream() /128.; - - PClassActor *cls = PClass::FindActor("BossBrain"); - if (cls != NULL) - { - FState *state = cls->FindState(NAME_Brainexplode); - if (state != NULL) - boom->SetState (state); - } - boom->effects = 0; - boom->SetDamage(0); // disables collision detection which is not wanted here - boom->tics -= pr_brainscream() & 7; - if (boom->tics < 1) - boom->tics = 1; - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_BrainScream) -{ - PARAM_ACTION_PROLOGUE; - - for (double x = -196; x < +320; x += 8) - { - // (1 / 512.) is actually what the original value of 128 did, even though it probably meant 128 map units. - BrainishExplosion(self->Vec2OffsetZ(x, -320, (1 / 512.) + pr_brainexplode() * 2)); - } - S_Sound (self, CHAN_VOICE, "brain/death", 1, ATTN_NONE); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BrainExplode) -{ - PARAM_ACTION_PROLOGUE; - double x = pr_brainexplode.Random2() / 32.; - DVector3 pos = self->Vec2OffsetZ(x, 0, 1 / 512. + pr_brainexplode() * 2); - BrainishExplosion(pos); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BrainDie) -{ - PARAM_ACTION_PROLOGUE; - - // [RH] If noexit, then don't end the level. - if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT)) - return 0; - - // New dmflag: Kill all boss spawned monsters before ending the level. - if (dmflags2 & DF2_KILLBOSSMONST) - { - int count; // Repeat until we have no more boss-spawned monsters. - do // (e.g. Pain Elementals can spawn more to kill upon death.) - { - TThinkerIterator it; - AActor *mo; - count = 0; - while ((mo = it.Next())) - { - if (mo->health > 0 && mo->flags4 & MF4_BOSSSPAWNED) - { - P_DamageMobj(mo, self, self, mo->health, NAME_None, - DMG_NO_ARMOR|DMG_FORCED|DMG_THRUSTLESS|DMG_NO_FACTOR); - count++; - } - } - } while (count != 0); - } - - G_ExitLevel (0, false); - return 0; -} - DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS_DEF(spawntype, AActor); DSpotState *state = DSpotState::GetSpotState(); AActor *targ; @@ -173,153 +78,3 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit) return 0; } -static void SpawnFly(AActor *self, PClassActor *spawntype, FSoundID sound) -{ - AActor *newmobj; - AActor *fog; - AActor *eye = self->master; // The eye is the spawnshot's master, not the target! - AActor *targ = self->target; // Unlike other projectiles, the target is the intended destination. - int r; - - // [GZ] Should be more viable than a countdown... - if (self->special2 != 0) - { - if (self->special2 > level.maptime) - return; // still flying - } - else - { - if (self->reactiontime == 0 || --self->reactiontime != 0) - return; // still flying - } - - if (spawntype != NULL) - { - fog = Spawn (spawntype, targ->Pos(), ALLOW_REPLACE); - if (fog != NULL) S_Sound (fog, CHAN_BODY, sound, 1, ATTN_NORM); - } - - FName SpawnName; - - DDropItem *di; // di will be our drop item list iterator - DDropItem *drop; // while drop stays as the reference point. - int n = 0; - - // First see if this cube has its own actor list - drop = self->GetDropItems(); - - // If not, then default back to its master's list - if (drop == NULL && eye != NULL) - drop = eye->GetDropItems(); - - if (drop != NULL) - { - for (di = drop; di != NULL; di = di->Next) - { - if (di->Name != NAME_None) - { - if (di->Amount < 0) - { - di->Amount = 1; // default value is -1, we need a positive value. - } - n += di->Amount; // this is how we can weight the list. - } - } - di = drop; - n = pr_spawnfly(n); - while (n >= 0) - { - if (di->Name != NAME_None) - { - n -= di->Amount; // logically, none of the -1 values have survived by now. - } - if ((di->Next != NULL) && (n >= 0)) - { - di = di->Next; - } - else - { - n = -1; - } - } - SpawnName = di->Name; - } - if (SpawnName == NAME_None) - { - // Randomly select monster to spawn. - r = pr_spawnfly (); - - // Probability distribution (kind of :), - // decreasing likelihood. - if (r < 50) SpawnName = "DoomImp"; - else if (r < 90) SpawnName = "Demon"; - else if (r < 120) SpawnName = "Spectre"; - else if (r < 130) SpawnName = "PainElemental"; - else if (r < 160) SpawnName = "Cacodemon"; - else if (r < 162) SpawnName = "Archvile"; - else if (r < 172) SpawnName = "Revenant"; - else if (r < 192) SpawnName = "Arachnotron"; - else if (r < 222) SpawnName = "Fatso"; - else if (r < 246) SpawnName = "HellKnight"; - else SpawnName = "BaronOfHell"; - } - spawntype = PClass::FindActor(SpawnName); - if (spawntype != NULL) - { - newmobj = Spawn (spawntype, targ->Pos(), ALLOW_REPLACE); - if (newmobj != NULL) - { - // Make the new monster hate what the boss eye hates - if (eye != NULL) - { - newmobj->CopyFriendliness (eye, false); - } - // Make it act as if it was around when the player first made noise - // (if the player has made noise). - newmobj->LastHeard = newmobj->Sector->SoundTarget; - - if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL)) - { - newmobj->SetState (newmobj->SeeState); - } - if (!(newmobj->ObjectFlags & OF_EuthanizeMe)) - { - // telefrag anything in this spot - P_TeleportMove (newmobj, newmobj->Pos(), true); - } - newmobj->flags4 |= MF4_BOSSSPAWNED; - } - } - - // remove self (i.e., cube). - self->Destroy (); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnFly) -{ - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; } - - FSoundID sound; - - if (spawntype != NULL) - { - sound = GetDefaultByType(spawntype)->SeeSound; - } - else - { - spawntype = PClass::FindActor("SpawnFire"); - sound = "brain/spawn"; - } - SpawnFly(self, spawntype, sound); - return 0; -} - -// travelling cube sound -DEFINE_ACTION_FUNCTION(AActor, A_SpawnSound) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_BODY, "brain/cube", 1, ATTN_IDLE); - SpawnFly(self, PClass::FindActor("SpawnFire"), "brain/spawn"); - return 0; -} diff --git a/src/g_doom/a_bruiser.cpp b/src/g_doom/a_bruiser.cpp deleted file mode 100644 index 0d2f83aee..000000000 --- a/src/g_doom/a_bruiser.cpp +++ /dev/null @@ -1,23 +0,0 @@ -static FRandom pr_bruisattack ("BruisAttack"); - - -DEFINE_ACTION_FUNCTION(AActor, A_BruisAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - if (self->CheckMeleeRange ()) - { - int damage = (pr_bruisattack()%8+1)*10; - S_Sound (self, CHAN_WEAPON, "baron/melee", 1, ATTN_NORM); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; - } - - // launch a missile - P_SpawnMissile (self, self->target, PClass::FindActor("BaronBall")); - return 0; -} diff --git a/src/g_doom/a_cacodemon.cpp b/src/g_doom/a_cacodemon.cpp deleted file mode 100644 index 3532374cf..000000000 --- a/src/g_doom/a_cacodemon.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "s_sound.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_headattack ("HeadAttack"); - -DEFINE_ACTION_FUNCTION(AActor, A_HeadAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - A_FaceTarget (self); - if (self->CheckMeleeRange ()) - { - int damage = (pr_headattack()%6+1)*10; - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; - } - - // launch a missile - P_SpawnMissile (self, self->target, PClass::FindActor("CacodemonBall")); - return 0; -} diff --git a/src/g_doom/a_cyberdemon.cpp b/src/g_doom/a_cyberdemon.cpp deleted file mode 100644 index 9e0ddd1dd..000000000 --- a/src/g_doom/a_cyberdemon.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -#include "actor.h" -#include "p_local.h" -#include "s_sound.h" -#include "p_enemy.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -DEFINE_ACTION_FUNCTION(AActor, A_CyberAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - A_FaceTarget (self); - P_SpawnMissile (self, self->target, PClass::FindActor("Rocket")); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_Hoof) -{ - PARAM_ACTION_PROLOGUE; - - S_Sound (self, CHAN_BODY, "cyber/hoof", 1, ATTN_IDLE); - A_Chase (stack, self); - return 0; -} diff --git a/src/g_doom/a_demon.cpp b/src/g_doom/a_demon.cpp deleted file mode 100644 index 3f8e2f626..000000000 --- a/src/g_doom/a_demon.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_sargattack ("SargAttack"); - -DEFINE_ACTION_FUNCTION(AActor, A_SargAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - A_FaceTarget (self); - if (self->CheckMeleeRange ()) - { - int damage = ((pr_sargattack()%10)+1)*4; - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - } - return 0; -} diff --git a/src/g_doom/a_doomimp.cpp b/src/g_doom/a_doomimp.cpp deleted file mode 100644 index f00b53a42..000000000 --- a/src/g_doom/a_doomimp.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_troopattack ("TroopAttack"); - -// -// A_TroopAttack -// -DEFINE_ACTION_FUNCTION(AActor, A_TroopAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - A_FaceTarget (self); - if (self->CheckMeleeRange ()) - { - int damage = (pr_troopattack()%8+1)*3; - S_Sound (self, CHAN_WEAPON, "imp/melee", 1, ATTN_NORM); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; - } - - // launch a missile - P_SpawnMissile (self, self->target, PClass::FindActor("DoomImpBall")); - return 0; -} diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 129c32f1e..eabf887f0 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -7,7 +7,7 @@ #include "gi.h" #include "doomstat.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "p_enemy.h" #include "a_doomglobal.h" @@ -19,41 +19,11 @@ #include "p_maputl.h" #include "serializer.h" #include "g_shared/a_pickups.h" +#include "vm.h" // Include all the other Doom stuff here to reduce compile time -#include "a_arachnotron.cpp" -#include "a_archvile.cpp" #include "a_bossbrain.cpp" -#include "a_bruiser.cpp" -#include "a_cacodemon.cpp" -#include "a_cyberdemon.cpp" -#include "a_demon.cpp" -#include "a_doomimp.cpp" #include "a_doomweaps.cpp" -#include "a_fatso.cpp" -#include "a_keen.cpp" -#include "a_lostsoul.cpp" #include "a_painelemental.cpp" -#include "a_possessed.cpp" -#include "a_revenant.cpp" -#include "a_spidermaster.cpp" #include "a_scriptedmarine.cpp" -// The barrel of green goop ------------------------------------------------ - -DEFINE_ACTION_FUNCTION(AActor, A_BarrelDestroy) -{ - PARAM_ACTION_PROLOGUE; - - if (dmflags2 & DF2_BARRELS_RESPAWN) - { - self->Height = self->GetDefault()->Height; - self->renderflags |= RF_INVISIBLE; - self->flags &= ~MF_SOLID; - } - else - { - self->Destroy (); - } - return 0; -} diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index a35a31b61..bc962800f 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -11,7 +11,7 @@ #include "p_effect.h" #include "gi.h" #include "templates.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" */ @@ -28,7 +28,7 @@ static FRandom pr_oldbfg ("OldBFG"); // DEFINE_ACTION_FUNCTION(AActor, A_Punch) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -69,7 +69,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch) // DEFINE_ACTION_FUNCTION(AActor, A_FirePistol) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); bool accurate; @@ -115,18 +115,18 @@ enum SAW_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) { - PARAM_ACTION_PROLOGUE; - PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; } - PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; } - PARAM_INT_OPT (damage) { damage = 2; } - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FLOAT_OPT (range) { range = 0; } - PARAM_ANGLE_OPT (spread_xy) { spread_xy = 2.8125; } - PARAM_ANGLE_OPT (spread_z) { spread_z = 0.; } - PARAM_FLOAT_OPT (lifesteal) { lifesteal = 0; } - PARAM_INT_OPT (lifestealmax) { lifestealmax = 0; } - PARAM_CLASS_OPT (armorbonustype, ABasicArmorBonus) { armorbonustype = NULL; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_SOUND_DEF (fullsound) + PARAM_SOUND_DEF (hitsound) + PARAM_INT_DEF (damage) + PARAM_CLASS_DEF (pufftype, AActor) + PARAM_INT_DEF (flags) + PARAM_FLOAT_DEF (range) + PARAM_ANGLE_DEF (spread_xy) + PARAM_ANGLE_DEF (spread_z) + PARAM_FLOAT_DEF (lifesteal) + PARAM_INT_DEF (lifestealmax) + PARAM_CLASS_DEF (armorbonustype, ABasicArmorBonus) DAngle angle; DAngle slope; @@ -257,7 +257,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) // DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); int i; player_t *player; @@ -291,7 +291,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun) // DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); int i; DAngle angle; @@ -336,29 +336,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) return 0; } -DEFINE_ACTION_FUNCTION(AActor, A_OpenShotgun2) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_WEAPON, "weapons/sshoto", 1, ATTN_NORM); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_LoadShotgun2) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CloseShotgun2) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_WEAPON, "weapons/sshotc", 1, ATTN_NORM); - A_ReFire (self); - return 0; -} - - //------------------------------------------------------------------------------------ // // Setting a random flash like some of Doom's weapons can easily crash when the @@ -411,7 +388,7 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i // DEFINE_ACTION_FUNCTION(AActor, A_FireCGun) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -456,7 +433,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCGun) // DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -479,8 +456,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) // DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(grenade, AActor) { grenade = PClass::FindActor("Grenade"); } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_CLASS_DEF(grenade, AActor); player_t *player; @@ -511,7 +488,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade) // DEFINE_ACTION_FUNCTION(AActor, A_FirePlasma) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -574,38 +551,32 @@ static void FireRailgun(AActor *self, int offset_xy, bool fromweapon) DEFINE_ACTION_FUNCTION(AActor, A_FireRailgun) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); FireRailgun(self, 0, ACTION_CALL_FROM_PSPRITE()); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunRight) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); FireRailgun(self, 10, ACTION_CALL_FROM_PSPRITE()); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunLeft) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); FireRailgun(self, -10, ACTION_CALL_FROM_PSPRITE()); return 0; } -DEFINE_ACTION_FUNCTION(AActor, A_RailWait) -{ - // Okay, this was stupid. Just use a NULL function instead of this. - return 0; -} - // // A_FireBFG // DEFINE_ACTION_FUNCTION(AActor, A_FireBFG) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -638,15 +609,15 @@ enum BFG_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT (spraytype, AActor) { spraytype = NULL; } - PARAM_INT_OPT (numrays) { numrays = 0; } - PARAM_INT_OPT (damagecnt) { damagecnt = 0; } - PARAM_ANGLE_OPT (angle) { angle = 0.; } - PARAM_FLOAT_OPT (distance) { distance = 0; } - PARAM_ANGLE_OPT (vrange) { vrange = 0.; } - PARAM_INT_OPT (defdamage) { defdamage = 0; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS_DEF (spraytype, AActor) + PARAM_INT_DEF (numrays) + PARAM_INT_DEF (damagecnt) + PARAM_ANGLE_DEF (angle) + PARAM_FLOAT_DEF (distance) + PARAM_ANGLE_DEF (vrange) + PARAM_INT_DEF (defdamage) + PARAM_INT_DEF (flags) int i; int j; @@ -717,16 +688,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray) return 0; } -// -// A_BFGsound -// -DEFINE_ACTION_FUNCTION(AActor, A_BFGsound) -{ - PARAM_ACTION_PROLOGUE; - S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM); - return 0; -} - // // A_FireOldBFG // @@ -738,7 +699,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BFGsound) DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PClassActor *plasma[] = { PClass::FindActor("PlasmaBall1"), PClass::FindActor("PlasmaBall2") }; AActor * mo = NULL; diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp deleted file mode 100644 index 872e1982d..000000000 --- a/src/g_doom/a_fatso.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -// -// Mancubus attack, -// firing three missiles in three different directions? -// Doesn't look like it. -// -#define FATSPREAD (90./8) - -DEFINE_ACTION_FUNCTION(AActor, A_FatRaise) -{ - PARAM_ACTION_PROLOGUE; - - A_FaceTarget (self); - S_Sound (self, CHAN_WEAPON, "fatso/raiseguns", 1, ATTN_NORM); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1) -{ - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } - - AActor *missile; - - if (!self->target) - return 0; - - if (spawntype == NULL) spawntype = PClass::FindActor("FatShot"); - - A_FaceTarget (self); - // Change direction to ... - self->Angles.Yaw += FATSPREAD; - P_SpawnMissile (self, self->target, spawntype); - - missile = P_SpawnMissile (self, self->target, spawntype); - if (missile != NULL) - { - missile->Angles.Yaw += FATSPREAD; - missile->VelFromAngle(); - } - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack2) -{ - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } - - AActor *missile; - - if (!self->target) - return 0; - - if (spawntype == NULL) spawntype = PClass::FindActor("FatShot"); - - A_FaceTarget (self); - // Now here choose opposite deviation. - self->Angles.Yaw -= FATSPREAD; - P_SpawnMissile (self, self->target, spawntype); - - missile = P_SpawnMissile (self, self->target, spawntype); - if (missile != NULL) - { - missile->Angles.Yaw -= FATSPREAD*2; - missile->VelFromAngle(); - } - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack3) -{ - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } - - AActor *missile; - - if (!self->target) - return 0; - - if (spawntype == NULL) spawntype = PClass::FindActor("FatShot"); - - A_FaceTarget (self); - - missile = P_SpawnMissile (self, self->target, spawntype); - if (missile != NULL) - { - missile->Angles.Yaw -= FATSPREAD/2; - missile->VelFromAngle(); - } - - missile = P_SpawnMissile (self, self->target, spawntype); - if (missile != NULL) - { - missile->Angles.Yaw += FATSPREAD/2; - missile->VelFromAngle(); - } - return 0; -} - -// -// killough 9/98: a mushroom explosion effect, sorta :) -// Original idea: Linguica -// - -enum -{ - MSF_Standard = 0, - MSF_Classic = 1, - MSF_DontHurt = 2, -}; - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) -{ - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; } - PARAM_INT_OPT (n) { n = 0; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FLOAT_OPT (vrange) { vrange = 4; } - PARAM_FLOAT_OPT (hrange) { hrange = 0.5; } - - int i, j; - - if (n == 0) - { - n = self->GetMissileDamage(0, 1); - } - if (spawntype == NULL) - { - spawntype = PClass::FindActor("FatShot"); - } - - P_RadiusAttack (self, self->target, 128, 128, self->DamageType, (flags & MSF_DontHurt) ? 0 : RADF_HURTSOURCE); - P_CheckSplash(self, 128.); - - // Now launch mushroom cloud - AActor *target = Spawn("Mapspot", self->Pos(), NO_REPLACE); // We need something to aim at. - AActor *master = (flags & MSF_DontHurt) ? (AActor*)(self->target) : self; - target->Height = self->Height; - for (i = -n; i <= n; i += 8) - { - for (j = -n; j <= n; j += 8) - { - AActor *mo; - target->SetXYZ( - self->X() + i, // Aim in many directions from source - self->Y() + j, - self->Z() + (P_AproxDistance(i,j) * vrange)); // Aim up fairly high - if ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options - (flags == 0 && (self->state->DefineFlags & SDF_DEHACKED) && (i_compatflags & COMPATF_MUSHROOM))) - { // Use old function for MBF compatibility - mo = P_OldSpawnMissile (self, master, target, spawntype); - } - else // Use normal function - { - mo = P_SpawnMissile(self, target, spawntype, master); - } - if (mo != NULL) - { // Slow it down a bit - mo->Vel *= hrange; - mo->flags &= ~MF_NOGRAVITY; // Make debris fall under gravity - } - } - } - target->Destroy(); - return 0; -} diff --git a/src/g_doom/a_keen.cpp b/src/g_doom/a_keen.cpp deleted file mode 100644 index d0a10da58..000000000 --- a/src/g_doom/a_keen.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "p_spec.h" -#include "p_enemy.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -// -// A_KeenDie -// DOOM II special, map 32. -// Uses special tag 666 by default. -// - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie) -{ - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(doortag) { doortag = 666; } - - A_Unblock(self, false); - - // scan the remaining thinkers to see if all Keens are dead - AActor *other; - TThinkerIterator iterator; - const PClass *matchClass = self->GetClass (); - - while ( (other = iterator.Next ()) ) - { - if (other != self && other->health > 0 && other->IsA (matchClass)) - { - // other Keen not dead - return 0; - } - } - - EV_DoDoor (DDoor::doorOpen, NULL, NULL, doortag, 2., 0, 0, 0); - return 0; -} - - diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp deleted file mode 100644 index 056802fe0..000000000 --- a/src/g_doom/a_lostsoul.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -#include "templates.h" -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gi.h" -#include "gstrings.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - - FRandom pr_oldsoul ("BetaLostSoul"); - -// -// SkullAttack -// Fly at the player like a missile. -// - -void A_SkullAttack(AActor *self, double speed) -{ - AActor *dest; - if (!self->target) - return; - - dest = self->target; - self->flags |= MF_SKULLFLY; - - S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM); - A_FaceTarget (self); - self->VelFromAngle(speed); - self->Vel.Z = (dest->Center() - self->Z()) / self->DistanceBySpeed(dest, speed); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack) -{ - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(speed) { speed = SKULLSPEED; } - - if (speed <= 0) - speed = SKULLSPEED; - A_SkullAttack(self, speed); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack) -{ - PARAM_ACTION_PROLOGUE; - - int damage; - if (!self || !self->target || self->target->GetSpecies() == self->GetSpecies()) - return 0; - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - A_FaceTarget(self); - damage = (pr_oldsoul()%8+1)*self->GetMissileDamage(0,1); - P_DamageMobj(self->target, self, self, damage, NAME_None); - return 0; -} - - - -//========================================================================== -// -// CVAR transsouls -// -// How translucent things drawn with STYLE_SoulTrans are. Normally, only -// Lost Souls have this render style, but a dehacked patch could give other -// things this style. Values less than 0.25 will automatically be set to -// 0.25 to ensure some degree of visibility. Likewise, values above 1.0 will -// be set to 1.0, because anything higher doesn't make sense. -// -//========================================================================== - -CUSTOM_CVAR (Float, transsouls, 0.75f, CVAR_ARCHIVE) -{ - if (self < 0.25f) - { - self = 0.25f; - } - else if (self > 1.f) - { - self = 1.f; - } -} diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 3620b88db..f2db5a240 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -6,7 +6,7 @@ #include "a_action.h" #include "templates.h" #include "m_bbox.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" */ @@ -21,7 +21,7 @@ enum PA_Flags // A_PainShootSkull // Spawn a lost soul and launch it at the target // -void A_PainShootSkull (AActor *self, DAngle Angle, PClassActor *spawntype, int flags = 0, int limit = -1) +void A_PainShootSkull (VMFrameStack *stack, AActor *self, DAngle Angle, PClassActor *spawntype, int flags = 0, int limit = -1) { AActor *other; double prestep; @@ -137,58 +137,22 @@ void A_PainShootSkull (AActor *self, DAngle Angle, PClassActor *spawntype, int f other->CopyFriendliness (self, !(flags & PAF_NOTARGET)); if (!(flags & PAF_NOSKULLATTACK)) - A_SkullAttack(other, SKULLSPEED); -} - - -// -// A_PainAttack -// Spawn a lost soul and launch it at the target -// -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; } - PARAM_ANGLE_OPT (angle) { angle = 0.; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_INT_OPT (limit) { limit = -1; } - - if (!(flags & PAF_AIMFACING)) - A_FaceTarget (self); - A_PainShootSkull (self, self->Angles.Yaw + angle, spawntype, flags, limit); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack) -{ - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } - - if (!self->target) - return 0; - - A_FaceTarget (self); - A_PainShootSkull (self, self->Angles.Yaw + 45., spawntype); - A_PainShootSkull (self, self->Angles.Yaw - 45., spawntype); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainDie) -{ - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } - - if (self->target != NULL && self->IsFriend(self->target)) - { // And I thought you were my friend! - self->flags &= ~MF_FRIENDLY; + { + DECLARE_VMFUNC(AActor, A_SkullAttack); + CallAction(stack, A_SkullAttack, other); } - A_Unblock(self, true); - A_PainShootSkull (self, self->Angles.Yaw + 90, spawntype); - A_PainShootSkull (self, self->Angles.Yaw + 180, spawntype); - A_PainShootSkull (self, self->Angles.Yaw + 270, spawntype); +} + + +DEFINE_ACTION_FUNCTION(AActor, A_PainShootSkull) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(spawntype, AActor); + PARAM_FLOAT(angle); + PARAM_INT_DEF(flags); + PARAM_INT_DEF(limit); + A_PainShootSkull(stack, self, angle, spawntype, flags, limit); + return 0; } + diff --git a/src/g_doom/a_possessed.cpp b/src/g_doom/a_possessed.cpp deleted file mode 100644 index f6b559c4b..000000000 --- a/src/g_doom/a_possessed.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_posattack ("PosAttack"); -static FRandom pr_sposattack ("SPosAttack"); -static FRandom pr_cposattack ("CPosAttack"); -static FRandom pr_cposrefire ("CPosRefire"); - -// -// A_PosAttack -// -DEFINE_ACTION_FUNCTION(AActor, A_PosAttack) -{ - PARAM_ACTION_PROLOGUE; - - int damage; - DAngle angle; - DAngle slope; - - if (!self->target) - return 0; - - A_FaceTarget (self); - angle = self->Angles.Yaw; - slope = P_AimLineAttack (self, angle, MISSILERANGE); - - S_Sound (self, CHAN_WEAPON, "grunt/attack", 1, ATTN_NORM); - angle += pr_posattack.Random2() * (22.5 / 256); - damage = ((pr_posattack()%5)+1)*3; - P_LineAttack (self, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff); - return 0; -} - -static void A_SPosAttack2 (AActor *self) -{ - int i; - DAngle bangle; - DAngle slope; - - A_FaceTarget (self); - bangle = self->Angles.Yaw; - slope = P_AimLineAttack (self, bangle, MISSILERANGE); - - for (i=0 ; i<3 ; i++) - { - DAngle angle = bangle + pr_sposattack.Random2() * (22.5 / 256); - int damage = ((pr_sposattack()%5)+1)*3; - P_LineAttack(self, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff); - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_SPosAttackUseAtkSound) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - A_SPosAttack2 (self); - return 0; -} - -// This version of the function, which uses a hard-coded sound, is -// meant for Dehacked only. -DEFINE_ACTION_FUNCTION(AActor, A_SPosAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - S_Sound (self, CHAN_WEAPON, "shotguy/attack", 1, ATTN_NORM); - A_SPosAttack2 (self); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CPosAttack) -{ - PARAM_ACTION_PROLOGUE; - - DAngle angle; - DAngle bangle; - int damage; - DAngle slope; - - if (!self->target) - return 0; - - // [RH] Andy Baker's stealth monsters - if (self->flags & MF_STEALTH) - { - self->visdir = 1; - } - - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - A_FaceTarget (self); - bangle = self->Angles.Yaw; - slope = P_AimLineAttack (self, bangle, MISSILERANGE); - - angle = bangle + pr_cposattack.Random2() * (22.5 / 256); - damage = ((pr_cposattack()%5)+1)*3; - P_LineAttack (self, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CPosRefire) -{ - PARAM_ACTION_PROLOGUE; - - // keep firing unless target got out of sight - A_FaceTarget (self); - - if (pr_cposrefire() < 40) - return 0; - - if (!self->target - || P_HitFriend (self) - || self->target->health <= 0 - || !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES)) - { - self->SetState (self->SeeState); - } - return 0; -} diff --git a/src/g_doom/a_revenant.cpp b/src/g_doom/a_revenant.cpp deleted file mode 100644 index 9c8a38602..000000000 --- a/src/g_doom/a_revenant.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* -#include "templates.h" -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -#include "g_level.h" -*/ - -static FRandom pr_tracer ("Tracer"); -static FRandom pr_skelfist ("SkelFist"); - -// -// A_SkelMissile -// -DEFINE_ACTION_FUNCTION(AActor, A_SkelMissile) -{ - PARAM_ACTION_PROLOGUE; - - AActor *missile; - - if (!self->target) - return 0; - - A_FaceTarget (self); - self->AddZ(16.); - missile = P_SpawnMissile(self, self->target, PClass::FindActor("RevenantTracer")); - self->AddZ(-16.); - - if (missile != NULL) - { - missile->SetOrigin(missile->Vec3Offset(missile->Vel.X, missile->Vel.Y, 0.), false); - missile->tracer = self->target; - } - return 0; -} - -#define TRACEANGLE (16.875) - -DEFINE_ACTION_FUNCTION(AActor, A_Tracer) -{ - PARAM_ACTION_PROLOGUE; - - double dist; - double slope; - AActor *dest; - AActor *smoke; - - // killough 1/18/98: this is why some missiles do not have smoke - // and some do. Also, internal demos start at random gametics, thus - // the bug in which revenants cause internal demos to go out of sync. - // - // killough 3/6/98: fix revenant internal demo bug by subtracting - // levelstarttic from gametic: - // - // [RH] level.time is always 0-based, so nothing special to do here. - - if (level.time & 3) - return 0; - - // spawn a puff of smoke behind the rocket - P_SpawnPuff (self, PClass::FindActor(NAME_BulletPuff), self->Pos(), self->Angles.Yaw, self->Angles.Yaw, 3); - - smoke = Spawn ("RevenantTracerSmoke", self->Vec3Offset(-self->Vel.X, -self->Vel.Y, 0.), ALLOW_REPLACE); - - smoke->Vel.Z = 1.; - smoke->tics -= pr_tracer()&3; - if (smoke->tics < 1) - smoke->tics = 1; - - // adjust direction - dest = self->tracer; - - if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest)) - return 0; - - // change angle - DAngle exact = self->AngleTo(dest); - DAngle diff = deltaangle(self->Angles.Yaw, exact); - - if (diff < 0) - { - self->Angles.Yaw -= TRACEANGLE; - if (deltaangle(self->Angles.Yaw, exact) > 0) - self->Angles.Yaw = exact; - } - else if (diff > 0) - { - self->Angles.Yaw += TRACEANGLE; - if (deltaangle(self->Angles.Yaw, exact) < 0.) - self->Angles.Yaw = exact; - } - - self->VelFromAngle(); - - if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))) - { - // change slope - dist = self->DistanceBySpeed(dest, self->Speed); - - if (dest->Height >= 56.) - { - slope = (dest->Z() + 40. - self->Z()) / dist; - } - else - { - slope = (dest->Z() + self->Height*(2./3) - self->Z()) / dist; - } - - if (slope < self->Vel.Z) - self->Vel.Z -= 1. / 8; - else - self->Vel.Z += 1. / 8; - } - return 0; -} - - -DEFINE_ACTION_FUNCTION(AActor, A_SkelWhoosh) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - A_FaceTarget (self); - S_Sound (self, CHAN_WEAPON, "skeleton/swing", 1, ATTN_NORM); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_SkelFist) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - return 0; - - A_FaceTarget (self); - - if (self->CheckMeleeRange ()) - { - int damage = ((pr_skelfist()%10)+1)*6; - S_Sound (self, CHAN_WEAPON, "skeleton/melee", 1, ATTN_NORM); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - } - return 0; -} diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 2c293a2de..da2c7f791 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -7,7 +7,7 @@ #include "a_doomglobal.h" #include "s_sound.h" #include "r_data/r_translate.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -19,7 +19,7 @@ static FRandom pr_m_gunshot ("SMarineGunshot"); static FRandom pr_m_saw ("SMarineSaw"); static FRandom pr_m_fireshotgun2 ("SMarineFireSSG"); -IMPLEMENT_CLASS (AScriptedMarine) +IMPLEMENT_CLASS(AScriptedMarine, false, false, false, false) void AScriptedMarine::Serialize(FSerializer &arc) { @@ -150,8 +150,8 @@ void AScriptedMarine::Tick () DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Refire) { - PARAM_ACTION_PROLOGUE; - PARAM_BOOL_OPT(ignoremissile) { ignoremissile = false; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(ignoremissile); if (self->target == NULL || self->target->health <= 0) { @@ -182,7 +182,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Refire) DEFINE_ACTION_FUNCTION(AActor, A_M_SawRefire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL || self->target->health <= 0) { @@ -204,7 +204,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_SawRefire) DEFINE_ACTION_FUNCTION(AActor, A_MarineNoise) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (static_cast(self)->CurrentWeapon == AScriptedMarine::WEAPON_Chainsaw) { @@ -221,7 +221,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MarineNoise) DEFINE_ACTION_FUNCTION(AActor, A_MarineChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); CALL_ACTION(A_MarineNoise, self); A_Chase (stack, self); return 0; @@ -235,7 +235,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MarineChase) DEFINE_ACTION_FUNCTION(AActor, A_MarineLook) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); CALL_ACTION(A_MarineNoise, self); CALL_ACTION(A_Look, self); return 0; @@ -249,11 +249,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_MarineLook) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw) { - PARAM_ACTION_PROLOGUE; - PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; } - PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; } - PARAM_INT_OPT (damage) { damage = 2; } - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_SOUND_DEF (fullsound) + PARAM_SOUND_DEF (hitsound) + PARAM_INT_DEF (damage) + PARAM_CLASS_DEF (pufftype, AActor) if (self->target == NULL) return 0; @@ -347,7 +347,7 @@ static void MarinePunch(AActor *self, int damagemul) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Punch) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT(mult); MarinePunch(self, mult); @@ -384,7 +384,7 @@ void P_GunShot2 (AActor *mo, bool accurate, DAngle pitch, PClassActor *pufftype) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FirePistol) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(accurate); if (self->target == NULL) @@ -405,7 +405,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FirePistol) DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle pitch; @@ -431,7 +431,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun) DEFINE_ACTION_FUNCTION(AActor, A_M_CheckAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->special1 != 0 || self->target == NULL) { @@ -452,7 +452,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_CheckAttack) DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle pitch; @@ -483,7 +483,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun2) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FireCGun) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(accurate); if (self->target == NULL) @@ -508,7 +508,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FireCGun) DEFINE_ACTION_FUNCTION(AActor, A_M_FireMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; @@ -533,7 +533,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_FireMissile) DEFINE_ACTION_FUNCTION(AActor, A_M_FireRailgun) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; @@ -551,7 +551,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_FireRailgun) DEFINE_ACTION_FUNCTION(AActor, A_M_FirePlasma) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; @@ -570,7 +570,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_FirePlasma) DEFINE_ACTION_FUNCTION(AActor, A_M_BFGsound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; @@ -597,7 +597,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_BFGsound) DEFINE_ACTION_FUNCTION(AActor, A_M_FireBFG) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; diff --git a/src/g_doom/a_spidermaster.cpp b/src/g_doom/a_spidermaster.cpp deleted file mode 100644 index aaafc4d99..000000000 --- a/src/g_doom/a_spidermaster.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* -#include "templates.h" -#include "actor.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_spidrefire ("SpidRefire"); - -DEFINE_ACTION_FUNCTION(AActor, A_SpidRefire) -{ - PARAM_ACTION_PROLOGUE; - - // keep firing unless target got out of sight - A_FaceTarget (self); - - if (pr_spidrefire() < 10) - return 0; - - if (!self->target - || P_HitFriend (self) - || self->target->health <= 0 - || !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES)) - { - self->SetState (self->SeeState); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_Metal) -{ - PARAM_ACTION_PROLOGUE; - - S_Sound (self, CHAN_BODY, "spider/walk", 1, ATTN_IDLE); - A_Chase (stack, self); - return 0; -} diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp index 7f62d5f0e..8a109d46d 100644 --- a/src/g_heretic/a_chicken.cpp +++ b/src/g_heretic/a_chicken.cpp @@ -11,7 +11,7 @@ #include "p_enemy.h" #include "d_event.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ void P_UpdateBeak (AActor *actor); @@ -29,7 +29,7 @@ public: void MorphPlayerThink (); }; -IMPLEMENT_CLASS(AChickenPlayer) +IMPLEMENT_CLASS(AChickenPlayer, false, false, false, false) void AChickenPlayer::MorphPlayerThink () { @@ -66,7 +66,7 @@ void AChickenPlayer::MorphPlayerThink () DEFINE_ACTION_FUNCTION(AActor, A_ChicAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) { @@ -89,7 +89,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChicAttack) DEFINE_ACTION_FUNCTION(AActor, A_Feathers) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; int count; @@ -138,7 +138,7 @@ void P_UpdateBeak (AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_BeakRaise) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -170,7 +170,7 @@ void P_PlayPeck (AActor *chicken) DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -205,7 +205,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1) DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp index f5870f09e..5ab4067d3 100644 --- a/src/g_heretic/a_dsparil.cpp +++ b/src/g_heretic/a_dsparil.cpp @@ -9,7 +9,7 @@ #include "a_sharedglobal.h" #include "gstrings.h" #include "a_specialspot.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -28,7 +28,7 @@ static FRandom pr_bluespark ("BlueSpark"); DEFINE_ACTION_FUNCTION(AActor, A_Sor1Pain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->special1 = 20; // Number of steps to walk fast CALL_ACTION(A_Pain, self); @@ -43,7 +43,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Sor1Pain) DEFINE_ACTION_FUNCTION(AActor, A_Sor1Chase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->special1) { @@ -64,7 +64,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Sor1Chase) DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; DAngle angle; @@ -120,7 +120,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack) DEFINE_ACTION_FUNCTION(AActor, A_SorcererRise) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -173,7 +173,7 @@ void P_DSparilTeleport (AActor *actor) DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Decide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); static const int chance[] = { @@ -201,7 +201,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Decide) DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Attack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int chance; @@ -243,7 +243,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Attack) DEFINE_ACTION_FUNCTION(AActor, A_BlueSpark) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; AActor *mo; @@ -266,7 +266,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BlueSpark) DEFINE_ACTION_FUNCTION(AActor, A_GenWizard) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -301,7 +301,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenWizard) DEFINE_ACTION_FUNCTION(AActor, A_Sor2DthInit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->special1 = 7; // Animation loop counter P_Massacre (); // Kill monsters early @@ -316,7 +316,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Sor2DthInit) DEFINE_ACTION_FUNCTION(AActor, A_Sor2DthLoop) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (--self->special1) { // Need to loop diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index 518abb44a..169d0e771 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -5,7 +5,7 @@ #include "gstrings.h" #include "p_local.h" #include "s_sound.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ // Tome of power ------------------------------------------------------------ @@ -17,8 +17,7 @@ public: bool Use (bool pickup); }; - -IMPLEMENT_CLASS (AArtiTomeOfPower) +IMPLEMENT_CLASS(AArtiTomeOfPower, false, false, false, false) bool AArtiTomeOfPower::Use (bool pickup) { @@ -47,7 +46,7 @@ bool AArtiTomeOfPower::Use (bool pickup) DEFINE_ACTION_FUNCTION(AActor, A_TimeBomb) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->AddZ(32, false); self->RenderStyle = STYLE_Add; @@ -64,8 +63,7 @@ public: bool Use (bool pickup); }; - -IMPLEMENT_CLASS (AArtiTimeBomb) +IMPLEMENT_CLASS(AArtiTimeBomb, false, false, false, false) bool AArtiTimeBomb::Use (bool pickup) { diff --git a/src/g_heretic/a_hereticimp.cpp b/src/g_heretic/a_hereticimp.cpp deleted file mode 100644 index 81185c0c1..000000000 --- a/src/g_heretic/a_hereticimp.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* -#include "templates.h" -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "gstrings.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_impmsatk ("ImpMsAttack"); -static FRandom pr_imp ("ImpExplode"); - - -//---------------------------------------------------------------------------- -// -// PROC A_ImpMsAttack -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ImpMsAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target || pr_impmsatk() > 64) - { - self->SetState (self->SeeState); - return 0; - } - A_SkullAttack(self, 12.); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpExplode -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ImpExplode) -{ - PARAM_ACTION_PROLOGUE; - - AActor *chunk; - - self->flags &= ~MF_NOGRAVITY; - - chunk = Spawn("HereticImpChunk1", self->Pos(), ALLOW_REPLACE); - chunk->Vel.X = pr_imp.Random2() / 64.; - chunk->Vel.Y = pr_imp.Random2() / 64.; - chunk->Vel.Z = 9; - - chunk = Spawn("HereticImpChunk2", self->Pos(), ALLOW_REPLACE); - chunk->Vel.X = pr_imp.Random2() / 64.; - chunk->Vel.Y = pr_imp.Random2() / 64.; - chunk->Vel.Z = 9; - if (self->special1 == 666) - { // Extreme death crash - self->SetState (self->FindState("XCrash")); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpDeath -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ImpDeath) -{ - PARAM_ACTION_PROLOGUE; - - self->flags &= ~MF_SOLID; - self->flags2 |= MF2_FLOORCLIP; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpXDeath1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ImpXDeath1) -{ - PARAM_ACTION_PROLOGUE; - - self->flags &= ~MF_SOLID; - self->flags |= MF_NOGRAVITY; - self->flags2 |= MF2_FLOORCLIP; - self->special1 = 666; // Flag the crash routine - return 0; -} - diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 36969f6e7..35b24eb93 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -6,7 +6,7 @@ #include "p_local.h" #include "s_sound.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "p_enemy.h" #include "a_specialspot.h" #include "g_level.h" @@ -18,16 +18,14 @@ #include "a_morph.h" #include "p_spec.h" #include "serializer.h" +#include "vm.h" // Include all the other Heretic stuff here to reduce compile time #include "a_chicken.cpp" #include "a_dsparil.cpp" #include "a_hereticartifacts.cpp" -#include "a_hereticimp.cpp" #include "a_hereticweaps.cpp" #include "a_ironlich.cpp" -#include "a_knight.cpp" -#include "a_wizard.cpp" static FRandom pr_podpain ("PodPain"); @@ -46,8 +44,8 @@ static FRandom pr_volcimpact ("VolcBallImpact"); DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT (gootype, AActor) { gootype = PClass::FindActor("PodGoo"); } + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS_DEF (gootype, AActor) int count; int chance; @@ -77,7 +75,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain) DEFINE_ACTION_FUNCTION(AActor, A_RemovePod) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -101,8 +99,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_RemovePod) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MakePod) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(podtype, AActor) { podtype = PClass::FindActor("Pod"); } + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS_DEF(podtype, AActor) AActor *mo; @@ -132,7 +130,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MakePod) DEFINE_ACTION_FUNCTION(AActor, A_AccTeleGlitter) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (++self->health > 35) { @@ -150,7 +148,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AccTeleGlitter) DEFINE_ACTION_FUNCTION(AActor, A_VolcanoSet) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->tics = 105 + (pr_volcano() & 127); return 0; @@ -164,7 +162,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcanoSet) DEFINE_ACTION_FUNCTION(AActor, A_VolcanoBlast) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; int count; @@ -192,7 +190,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcanoBlast) DEFINE_ACTION_FUNCTION(AActor, A_VolcBallImpact) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); unsigned int i; AActor *tiny; diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index eb7d49983..a888be884 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -11,7 +11,7 @@ #include "gstrings.h" #include "gi.h" #include "r_data/r_translate.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" */ @@ -61,7 +61,7 @@ extern bool P_AutoUseChaosDevice (player_t *player); DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; DAngle slope; @@ -107,7 +107,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack) DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -144,7 +144,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL1) DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); int i; DAngle angle; @@ -187,7 +187,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL2) DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -216,7 +216,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL1) DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -247,7 +247,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL2) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle Angle; int damage; @@ -358,7 +358,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AMaceFX4) +IMPLEMENT_CLASS(AMaceFX4, false, false, false, false) int AMaceFX4::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -421,7 +421,7 @@ void FireMacePL1B (AActor *actor) DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *ball; player_t *player; @@ -461,7 +461,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL1) DEFINE_ACTION_FUNCTION(AActor, A_MacePL1Check) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->special1 == 0) { @@ -498,7 +498,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MacePL1Check) DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if ((self->health != MAGIC_JUNK) && (self->flags & MF_INBOUNCE)) { // Bounce @@ -526,7 +526,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact) DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *tiny; @@ -579,7 +579,7 @@ boom: DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *mo; player_t *player; @@ -618,7 +618,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL2) DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; AActor *target; @@ -726,7 +726,7 @@ void ABlasterFX1::Effect () } } -IMPLEMENT_CLASS(ABlasterFX1) +IMPLEMENT_CLASS(ABlasterFX1, false, false, false, false) // Ripper ------------------------------------------------------------------- @@ -738,7 +738,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(ARipper) +IMPLEMENT_CLASS(ARipper, false, false, false, false) int ARipper::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -761,7 +761,7 @@ int ARipper::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -798,7 +798,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1) DEFINE_ACTION_FUNCTION(AActor, A_SpawnRippers) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); unsigned int i; DAngle angle; @@ -828,7 +828,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AHornRodFX2) +IMPLEMENT_CLASS(AHornRodFX2, false, false, false, false) int AHornRodFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -849,7 +849,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (ARainPillar) +IMPLEMENT_CLASS(ARainPillar, false, false, false, false) int ARainPillar::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -871,7 +871,7 @@ public: TObjPtr Rain1, Rain2; }; -IMPLEMENT_CLASS (ARainTracker) +IMPLEMENT_CLASS(ARainTracker, false, false, false, false) void ARainTracker::Serialize(FSerializer &arc) { @@ -888,7 +888,7 @@ void ARainTracker::Serialize(FSerializer &arc) DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *mo; player_t *player; @@ -924,7 +924,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL1) DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; AActor *MissileActor; @@ -964,7 +964,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL2) DEFINE_ACTION_FUNCTION(AActor, A_AddPlayerRain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); ARainTracker *tracker; @@ -1024,7 +1024,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AddPlayerRain) DEFINE_ACTION_FUNCTION(AActor, A_SkullRodStorm) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; ARainTracker *tracker; @@ -1095,7 +1095,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkullRodStorm) DEFINE_ACTION_FUNCTION(AActor, A_RainImpact) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->Z() > self->floorz) { self->SetState (self->FindState("NotFloor")); @@ -1115,7 +1115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RainImpact) DEFINE_ACTION_FUNCTION(AActor, A_HideInCeiling) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // We use bouncecount to store the 3D floor index double foo; @@ -1158,8 +1158,8 @@ public: void EndPowerup (); }; -IMPLEMENT_CLASS (APhoenixRod) -IMPLEMENT_CLASS (APhoenixRodPowered) +IMPLEMENT_CLASS(APhoenixRod, false, false, false, false) +IMPLEMENT_CLASS(APhoenixRodPowered, false, false, false, false) void APhoenixRodPowered::EndPowerup () { @@ -1177,8 +1177,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; - -IMPLEMENT_CLASS (APhoenixFX1) +IMPLEMENT_CLASS(APhoenixFX1, false, false, false, false) int APhoenixFX1::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -1199,7 +1198,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (APhoenixFX2) +IMPLEMENT_CLASS(APhoenixFX2, false, false, false, false) int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -1218,7 +1217,7 @@ int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -1246,7 +1245,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL1) DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *puff; DAngle angle; @@ -1271,7 +1270,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff) DEFINE_ACTION_FUNCTION(AActor, A_InitPhoenixPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -1294,7 +1293,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InitPhoenixPL2) DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *mo; @@ -1347,7 +1346,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) DEFINE_ACTION_FUNCTION(AActor, A_ShutdownPhoenixPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -1373,7 +1372,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShutdownPhoenixPL2) DEFINE_ACTION_FUNCTION(AActor, A_FlameEnd) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Vel.Z += 1.5; return 0; @@ -1387,7 +1386,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlameEnd) DEFINE_ACTION_FUNCTION(AActor, A_FloatPuff) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Vel.Z += 1.8; return 0; diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index a88748407..8068c251b 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -7,7 +7,7 @@ #include "p_enemy.h" #include "a_action.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -22,7 +22,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AWhirlwind) +IMPLEMENT_CLASS(AWhirlwind, false, false, false, false) int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -63,7 +63,7 @@ int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_LichAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; AActor *fire; @@ -143,7 +143,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack) DEFINE_ACTION_FUNCTION(AActor, A_WhirlwindSeek) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->health -= 3; if (self->health < 0) @@ -174,7 +174,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WhirlwindSeek) DEFINE_ACTION_FUNCTION(AActor, A_LichIceImpact) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); unsigned int i; AActor *shard; @@ -199,7 +199,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichIceImpact) DEFINE_ACTION_FUNCTION(AActor, A_LichFireGrow) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->health--; self->AddZ(9.); diff --git a/src/g_heretic/a_knight.cpp b/src/g_heretic/a_knight.cpp deleted file mode 100644 index 9f42a328a..000000000 --- a/src/g_heretic/a_knight.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "a_action.h" -#include "a_sharedglobal.h" -#include "gstrings.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_dripblood ("DripBlood"); -static FRandom pr_knightatk ("KnightAttack"); - -//---------------------------------------------------------------------------- -// -// PROC A_DripBlood -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_DripBlood) -{ - PARAM_ACTION_PROLOGUE; - - AActor *mo; - - double xo = pr_dripblood.Random2() / 32.; - double yo = pr_dripblood.Random2() / 32.; - mo = Spawn ("Blood", self->Vec3Offset(xo, yo, 0.), ALLOW_REPLACE); - mo->Vel.X = pr_dripblood.Random2 () / 64.; - mo->Vel.Y = pr_dripblood.Random2() / 64.; - mo->Gravity = 1./8; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_KnightAttack -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_KnightAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - { - return 0; - } - if (self->CheckMeleeRange ()) - { - int damage = pr_knightatk.HitDice (3); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - S_Sound (self, CHAN_BODY, "hknight/melee", 1, ATTN_NORM); - return 0; - } - // Throw axe - S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM); - if (self->flags & MF_SHADOW || pr_knightatk () < 40) - { // Red axe - P_SpawnMissileZ (self, self->Z() + 36, self->target, PClass::FindActor("RedAxe")); - return 0; - } - // Green axe - P_SpawnMissileZ (self, self->Z() + 36, self->target, PClass::FindActor("KnightAxe")); - return 0; -} - diff --git a/src/g_heretic/a_wizard.cpp b/src/g_heretic/a_wizard.cpp deleted file mode 100644 index 704488f16..000000000 --- a/src/g_heretic/a_wizard.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "a_action.h" -#include "gstrings.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_wizatk3 ("WizAtk3"); - -//---------------------------------------------------------------------------- -// -// PROC A_GhostOff -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_GhostOff) -{ - PARAM_ACTION_PROLOGUE; - - self->RenderStyle = STYLE_Normal; - self->flags3 &= ~MF3_GHOST; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WizAtk1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_WizAtk1) -{ - PARAM_ACTION_PROLOGUE; - - A_FaceTarget (self); - CALL_ACTION(A_GhostOff, self); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WizAtk2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_WizAtk2) -{ - PARAM_ACTION_PROLOGUE; - - A_FaceTarget (self); - self->Alpha = HR_SHADOW; - self->RenderStyle = STYLE_Translucent; - self->flags3 |= MF3_GHOST; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WizAtk3 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_WizAtk3) -{ - PARAM_ACTION_PROLOGUE; - - AActor *mo; - - CALL_ACTION(A_GhostOff, self); - if (!self->target) - { - return 0; - } - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - if (self->CheckMeleeRange()) - { - int damage = pr_wizatk3.HitDice (4); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; - } - PClassActor *fx = PClass::FindActor("WizardFX1"); - mo = P_SpawnMissile (self, self->target, fx); - if (mo != NULL) - { - P_SpawnMissileAngle(self, fx, mo->Angles.Yaw - 45. / 8, mo->Vel.Z); - P_SpawnMissileAngle(self, fx, mo->Angles.Yaw + 45. / 8, mo->Vel.Z); - } - return 0; -} diff --git a/src/g_hexen/a_bats.cpp b/src/g_hexen/a_bats.cpp deleted file mode 100644 index 56c7ac024..000000000 --- a/src/g_hexen/a_bats.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_batspawn ("BatSpawn"); -static FRandom pr_batmove ("BatMove"); - -//=========================================================================== -// Bat Spawner Variables -// special1 frequency counter -// special2 -// args[0] frequency of spawn (1=fastest, 10=slowest) -// args[1] spread angle (0..255) -// args[2] -// args[3] duration of bats (in octics) -// args[4] turn amount per move (in degrees) -// -// Bat Variables -// special2 lifetime counter -// args[4] turn amount per move (in degrees) -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_BatSpawnInit) -{ - PARAM_ACTION_PROLOGUE; - - self->special1 = 0; // Frequency count - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BatSpawn) -{ - PARAM_ACTION_PROLOGUE; - - AActor *mo; - int delta; - DAngle angle; - - // Countdown until next spawn - if (self->special1-- > 0) return 0; - self->special1 = self->args[0]; // Reset frequency count - - delta = self->args[1]; - if (delta==0) delta=1; - - angle = self->Angles.Yaw + (((pr_batspawn() % delta) - (delta >> 1)) * (360 / 256.)); - - mo = P_SpawnMissileAngle (self, PClass::FindActor("Bat"), angle, 0); - if (mo) - { - mo->args[0] = pr_batspawn()&63; // floatbob index - mo->args[4] = self->args[4]; // turn degrees - mo->special2 = self->args[3]<<3; // Set lifetime - mo->target = self; - } - return 0; -} - - -DEFINE_ACTION_FUNCTION(AActor, A_BatMove) -{ - PARAM_ACTION_PROLOGUE; - - DAngle newangle; - - if (self->special2 < 0) - { - self->SetState (self->FindState(NAME_Death)); - } - self->special2 -= 2; // Called every 2 tics - - if (pr_batmove()<128) - { - newangle = self->Angles.Yaw + self->args[4]; - } - else - { - newangle = self->Angles.Yaw - self->args[4]; - } - - // Adjust velocity vector to new direction - self->VelFromAngle(newangle, self->Speed); - - if (pr_batmove()<15) - { - S_Sound (self, CHAN_VOICE, "BatScream", 1, ATTN_IDLE); - } - - // Handle Z movement - self->SetZ(self->target->Z() + 2 * BobSin(self->args[0])); - self->args[0] = (self->args[0]+3)&63; - return 0; -} diff --git a/src/g_hexen/a_bishop.cpp b/src/g_hexen/a_bishop.cpp deleted file mode 100644 index 5fb95d8be..000000000 --- a/src/g_hexen/a_bishop.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "s_sound.h" -#include "a_action.h" -#include "m_random.h" -#include "a_hexenglobal.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_boom ("BishopBoom"); -static FRandom pr_atk ("BishopAttack"); -static FRandom pr_decide ("BishopDecide"); -static FRandom pr_doblur ("BishopDoBlur"); -static FRandom pr_sblur ("BishopSpawnBlur"); -static FRandom pr_pain ("BishopPainBlur"); - -//============================================================================ -// -// A_BishopAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (!self->target) - { - return 0; - } - S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM); - if (self->CheckMeleeRange()) - { - int damage = pr_atk.HitDice (4); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; - } - self->special1 = (pr_atk() & 3) + 5; - return 0; -} - -//============================================================================ -// -// A_BishopAttack2 -// -// Spawns one of a string of bishop missiles -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack2) -{ - PARAM_ACTION_PROLOGUE; - - AActor *mo; - - if (!self->target || !self->special1) - { - self->special1 = 0; - self->SetState (self->SeeState); - return 0; - } - mo = P_SpawnMissile (self, self->target, PClass::FindActor("BishopFX")); - if (mo != NULL) - { - mo->tracer = self->target; - } - self->special1--; - return 0; -} - -//============================================================================ -// -// A_BishopMissileWeave -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) -{ - PARAM_ACTION_PROLOGUE; - - A_Weave(self, 2, 2, 2., 1.); - return 0; -} - -//============================================================================ -// -// A_BishopDecide -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopDecide) -{ - PARAM_ACTION_PROLOGUE; - - if (pr_decide() < 220) - { - return 0; - } - else - { - self->SetState (self->FindState ("Blur")); - } - return 0; -} - -//============================================================================ -// -// A_BishopDoBlur -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopDoBlur) -{ - PARAM_ACTION_PROLOGUE; - - self->special1 = (pr_doblur() & 3) + 3; // Random number of blurs - if (pr_doblur() < 120) - { - self->Thrust(self->Angles.Yaw + 90, 11); - } - else if (pr_doblur() > 125) - { - self->Thrust(self->Angles.Yaw - 90, 11); - } - else - { // Thrust forward - self->Thrust(11); - } - S_Sound (self, CHAN_BODY, "BishopBlur", 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_BishopSpawnBlur -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopSpawnBlur) -{ - PARAM_ACTION_PROLOGUE; - - AActor *mo; - - if (!--self->special1) - { - self->Vel.X = self->Vel.Y = 0; - if (pr_sblur() > 96) - { - self->SetState (self->SeeState); - } - else - { - self->SetState (self->MissileState); - } - } - mo = Spawn ("BishopBlur", self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->Angles.Yaw = self->Angles.Yaw; - } - return 0; -} - -//============================================================================ -// -// A_BishopChase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopChase) -{ - PARAM_ACTION_PROLOGUE; - - double newz = self->Z() - BobSin(self->special2) / 2.; - self->special2 = (self->special2 + 4) & 63; - newz += BobSin(self->special2) / 2.; - self->SetZ(newz); - return 0; -} - -//============================================================================ -// -// A_BishopPuff -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopPuff) -{ - PARAM_ACTION_PROLOGUE; - - AActor *mo; - - mo = Spawn ("BishopPuff", self->PosPlusZ(40.), ALLOW_REPLACE); - if (mo) - { - mo->Vel.Z = -.5; - } - return 0; -} - -//============================================================================ -// -// A_BishopPainBlur -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopPainBlur) -{ - PARAM_ACTION_PROLOGUE; - - AActor *mo; - - if (pr_pain() < 64) - { - self->SetState (self->FindState ("Blur")); - return 0; - } - double xo = pr_pain.Random2() / 16.; - double yo = pr_pain.Random2() / 16.; - double zo = pr_pain.Random2() / 32.; - mo = Spawn ("BishopPainBlur", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - if (mo) - { - mo->Angles.Yaw = self->Angles.Yaw; - } - return 0; -} diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp index f906d247c..f8bc60a7f 100644 --- a/src/g_hexen/a_blastradius.cpp +++ b/src/g_hexen/a_blastradius.cpp @@ -95,13 +95,13 @@ enum DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT (blastflags) { blastflags = 0; } - PARAM_FLOAT_OPT (strength) { strength = 255; } - PARAM_FLOAT_OPT (radius) { radius = 255; } - PARAM_FLOAT_OPT (speed) { speed = 20; } - PARAM_CLASS_OPT (blasteffect, AActor) { blasteffect = PClass::FindActor("BlastEffect"); } - PARAM_SOUND_OPT (blastsound) { blastsound = "BlastRadius"; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT_DEF (blastflags) + PARAM_FLOAT_DEF (strength) + PARAM_FLOAT_DEF (radius) + PARAM_FLOAT_DEF (speed) + PARAM_CLASS_DEF (blasteffect, AActor) + PARAM_SOUND_DEF (blastsound) AActor *mo; TThinkerIterator iterator; diff --git a/src/g_hexen/a_boostarmor.cpp b/src/g_hexen/a_boostarmor.cpp index 3234174f3..1323af8a5 100644 --- a/src/g_hexen/a_boostarmor.cpp +++ b/src/g_hexen/a_boostarmor.cpp @@ -17,7 +17,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiBoostArmor) +IMPLEMENT_CLASS(AArtiBoostArmor, false, false, false, false) bool AArtiBoostArmor::Use (bool pickup) { diff --git a/src/g_hexen/a_centaur.cpp b/src/g_hexen/a_centaur.cpp deleted file mode 100644 index 692688b63..000000000 --- a/src/g_hexen/a_centaur.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* -#include "actor.h" -#include "p_enemy.h" -#include "a_action.h" -#include "m_random.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_centaurdefend ("CentaurDefend"); - -//============================================================================ -// -// A_CentaurDefend -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CentaurDefend) -{ - PARAM_ACTION_PROLOGUE; - - A_FaceTarget (self); - if (self->CheckMeleeRange() && pr_centaurdefend() < 32) - { - // This should unset REFLECTIVE as well - // (unless you want the Centaur to reflect projectiles forever!) - self->flags2&=~(MF2_REFLECTIVE|MF2_INVULNERABLE); - self->SetState (self->MeleeState); - } - return 0; -} diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp index 5b4eba2e8..2c66cb42d 100644 --- a/src/g_hexen/a_clericflame.cpp +++ b/src/g_hexen/a_clericflame.cpp @@ -10,7 +10,7 @@ #include "p_pspr.h" #include "gstrings.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ const double FLAMESPEED = 0.45; @@ -33,7 +33,7 @@ public: void Effect (); }; -IMPLEMENT_CLASS (ACFlameMissile) +IMPLEMENT_CLASS(ACFlameMissile, false, false, false, false) void ACFlameMissile::BeginPlay () { @@ -66,7 +66,7 @@ void ACFlameMissile::Effect () DEFINE_ACTION_FUNCTION(AActor, A_CFlameAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -93,7 +93,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlameAttack) DEFINE_ACTION_FUNCTION(AActor, A_CFlamePuff) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->renderflags &= ~RF_INVISIBLE; self->Vel.Zero(); @@ -109,7 +109,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlamePuff) DEFINE_ACTION_FUNCTION(AActor, A_CFlameMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; DAngle an; @@ -159,10 +159,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlameMissile) DEFINE_ACTION_FUNCTION(AActor, A_CFlameRotate) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle an = self->Angles.Yaw + 90.; - self->VelFromAngle(an, FLAMEROTSPEED); + self->VelFromAngle(FLAMEROTSPEED, an); self->Vel += DVector2(self->specialf1, self->specialf2); self->Angles.Yaw += 6.; diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index b08ab3e74..362434b02 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -7,7 +7,7 @@ #include "a_hexenglobal.h" #include "gstrings.h" #include "a_weaponpiece.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "doomstat.h" */ @@ -58,11 +58,11 @@ public: BYTE CHolyCount; }; -IMPLEMENT_CLASS (ACWeapWraithverge) +IMPLEMENT_CLASS(ACWeapWraithverge, false, false, false, false) // Holy Spirit -------------------------------------------------------------- -IMPLEMENT_CLASS (AHolySpirit) +IMPLEMENT_CLASS(AHolySpirit, false, false, false, false) bool AHolySpirit::Slam(AActor *thing) { @@ -131,7 +131,7 @@ bool AHolySpirit::SpecialBlastHandling (AActor *source, double strength) DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int j; AActor *mo; @@ -211,7 +211,7 @@ void SpawnSpiritTail (AActor *spirit) DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; FTranslatedLineTarget t; @@ -245,7 +245,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack) DEFINE_ACTION_FUNCTION(AActor, A_CHolyPalette) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -328,7 +328,7 @@ static void CHolyTailRemove (AActor *actor) DEFINE_ACTION_FUNCTION(AActor, A_CHolyTail) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *parent; @@ -446,7 +446,7 @@ static void CHolySeekerMissile (AActor *actor, DAngle thresh, DAngle turnMax) DEFINE_ACTION_FUNCTION(AActor, A_CHolySeek) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->health--; if (self->health <= 0) @@ -481,7 +481,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CHolySeek) DEFINE_ACTION_FUNCTION(AActor, A_CHolyCheckScream) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); CALL_ACTION(A_CHolySeek, self); if (pr_checkscream() < 20) @@ -504,7 +504,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CHolyCheckScream) DEFINE_ACTION_FUNCTION(AActor, A_ClericAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; diff --git a/src/g_hexen/a_clericmace.cpp b/src/g_hexen/a_clericmace.cpp index 69f1f729c..a15196cf8 100644 --- a/src/g_hexen/a_clericmace.cpp +++ b/src/g_hexen/a_clericmace.cpp @@ -2,7 +2,7 @@ #include "m_random.h" #include "p_local.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_maceatk ("CMaceAttack"); @@ -15,7 +15,7 @@ static FRandom pr_maceatk ("CMaceAttack"); DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index de4e1d75f..a838357d6 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -10,7 +10,7 @@ #include "p_pspr.h" #include "gstrings.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_staffcheck ("CStaffCheck"); @@ -25,7 +25,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (ACStaffMissile) +IMPLEMENT_CLASS(ACStaffMissile, false, false, false, false) int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -46,7 +46,7 @@ int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetyp DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); APlayerPawn *pmo; int damage; @@ -115,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *mo; player_t *player; @@ -153,7 +153,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack) DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_Weave(self, 3, 0, 1., 0.); return 0; @@ -167,7 +167,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) DEFINE_ACTION_FUNCTION(AActor, A_CStaffInitBlink) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); self->weaponspecial = (pr_blink()>>1)+20; return 0; @@ -181,7 +181,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffInitBlink) DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheckBlink) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player && self->player->ReadyWeapon) { diff --git a/src/g_hexen/a_dragon.cpp b/src/g_hexen/a_dragon.cpp index c94be3988..b79d92b36 100644 --- a/src/g_hexen/a_dragon.cpp +++ b/src/g_hexen/a_dragon.cpp @@ -6,7 +6,7 @@ #include "a_action.h" #include "m_random.h" #include "s_sound.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_dragonseek ("DragonSeek"); @@ -150,7 +150,7 @@ static void DragonSeek (AActor *actor, DAngle thresh, DAngle turnMax) DEFINE_ACTION_FUNCTION(AActor, A_DragonInitFlight) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); FActorIterator iterator (self->tid); @@ -175,7 +175,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonInitFlight) DEFINE_ACTION_FUNCTION(AActor, A_DragonFlight) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle angle; @@ -216,7 +216,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonFlight) DEFINE_ACTION_FUNCTION(AActor, A_DragonFlap) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); CALL_ACTION(A_DragonFlight, self); if (pr_dragonflap() < 240) @@ -238,7 +238,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonFlap) DEFINE_ACTION_FUNCTION(AActor, A_DragonAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); P_SpawnMissile (self, self->target, PClass::FindActor("DragonFireball")); return 0; @@ -252,7 +252,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonAttack) DEFINE_ACTION_FUNCTION(AActor, A_DragonFX2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; int i; @@ -283,7 +283,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonFX2) DEFINE_ACTION_FUNCTION(AActor, A_DragonPain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); CALL_ACTION(A_Pain, self); if (!self->tracer) @@ -301,7 +301,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonPain) DEFINE_ACTION_FUNCTION(AActor, A_DragonCheckCrash) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->Z() <= self->floorz) { diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index f47ad6a9d..1dc02d599 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -10,20 +10,15 @@ #include "p_pspr.h" #include "gstrings.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ +DECLARE_ACTION(A_Raise) + #define AXERANGE (2.25 * MELEERANGE) static FRandom pr_axeatk ("FAxeAtk"); -void A_FAxeCheckReady (AActor *actor); -void A_FAxeCheckUp (AActor *actor); -void A_FAxeCheckAtk (AActor *actor); -void A_FAxeCheckReadyG (AActor *actor); -void A_FAxeCheckUpG (AActor *actor); -void A_FAxeAttack (AActor *actor); - // The Fighter's Axe -------------------------------------------------------- class AFWeapAxe : public AFighterWeapon @@ -36,7 +31,7 @@ public: FState *GetAtkState (bool hold); }; -IMPLEMENT_CLASS (AFWeapAxe) +IMPLEMENT_CLASS(AFWeapAxe, false, false, false, false) FState *AFWeapAxe::GetUpState () { @@ -66,7 +61,7 @@ FState *AFWeapAxe::GetAtkState (bool hold) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReady) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -93,7 +88,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReady) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -120,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUp) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -147,7 +142,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUp) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -174,7 +169,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -197,7 +192,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int power; diff --git a/src/g_hexen/a_fighterhammer.cpp b/src/g_hexen/a_fighterhammer.cpp index c33737bfd..84eca78b7 100644 --- a/src/g_hexen/a_fighterhammer.cpp +++ b/src/g_hexen/a_fighterhammer.cpp @@ -10,7 +10,7 @@ #include "p_pspr.h" #include "gstrings.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ const double HAMMER_RANGE = 1.5 * MELEERANGE; @@ -25,7 +25,7 @@ static FRandom pr_hammeratk ("FHammerAtk"); DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -95,7 +95,7 @@ hammerdone: DEFINE_ACTION_FUNCTION(AActor, A_FHammerThrow) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *mo; player_t *player; diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index 3624ed625..7e1502a1c 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -8,12 +8,12 @@ #include "p_local.h" #include "a_action.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ -IMPLEMENT_CLASS (AFighterWeapon) -IMPLEMENT_CLASS (AClericWeapon) -IMPLEMENT_CLASS (AMageWeapon) +IMPLEMENT_CLASS(AFighterWeapon, false, false, false, false) +IMPLEMENT_CLASS(AClericWeapon, false, false, false, false) +IMPLEMENT_CLASS(AMageWeapon, false, false, false, false) static FRandom pr_fpatk ("FPunchAttack"); @@ -99,7 +99,7 @@ static bool TryPunch(APlayerPawn *pmo, DAngle angle, int damage, int power) DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); int damage; int i; diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index 3d04e984a..8f73ef48e 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -10,7 +10,7 @@ #include "gstrings.h" #include "a_hexenglobal.h" #include "a_weaponpiece.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_quietusdrop ("QuietusDrop"); @@ -59,7 +59,7 @@ public: int DoSpecialDamage(AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AFSwordMissile) +IMPLEMENT_CLASS(AFSwordMissile, false, false, false, false) int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype) { @@ -78,7 +78,7 @@ int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype DEFINE_ACTION_FUNCTION(AActor, A_FSwordAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -109,7 +109,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FSwordAttack) DEFINE_ACTION_FUNCTION(AActor, A_FSwordFlames) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; @@ -131,7 +131,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FSwordFlames) DEFINE_ACTION_FUNCTION(AActor, A_FighterAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp deleted file mode 100644 index 712363167..000000000 --- a/src/g_hexen/a_firedemon.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "s_sound.h" -#include "p_enemy.h" -#include "a_action.h" -#include "m_random.h" -#include "thingdef/thingdef.h" -*/ - -#define FIREDEMON_ATTACK_RANGE (64*8.) - -static FRandom pr_firedemonrock ("FireDemonRock"); -static FRandom pr_smbounce ("SMBounce"); -static FRandom pr_firedemonchase ("FiredChase"); -static FRandom pr_firedemonsplotch ("FiredSplotch"); - -//============================================================================ -// Fire Demon AI -// -// special1 index into floatbob -// special2 whether strafing or not -//============================================================================ - -//============================================================================ -// -// A_FiredSpawnRock -// -//============================================================================ - -void A_FiredSpawnRock (AActor *actor) -{ - AActor *mo; - PClassActor *rtype; - - switch (pr_firedemonrock() % 5) - { - case 0: - rtype = PClass::FindActor("FireDemonRock1"); - break; - case 1: - rtype = PClass::FindActor("FireDemonRock2"); - break; - case 2: - rtype = PClass::FindActor("FireDemonRock3"); - break; - case 3: - rtype = PClass::FindActor("FireDemonRock4"); - break; - case 4: - default: - rtype = PClass::FindActor("FireDemonRock5"); - break; - } - - double xo = (pr_firedemonrock() - 128) / 16.; - double yo = (pr_firedemonrock() - 128) / 16.; - double zo = pr_firedemonrock() / 32.; - mo = Spawn (rtype, actor->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - if (mo) - { - mo->target = actor; - mo->Vel.X = (pr_firedemonrock() - 128) / 64.; - mo->Vel.Y = (pr_firedemonrock() - 128) / 64.; - mo->Vel.Z = (pr_firedemonrock() / 64.); - mo->special1 = 2; // Number bounces - } - - // Initialize fire demon - actor->special2 = 0; - actor->flags &= ~MF_JUSTATTACKED; -} - -//============================================================================ -// -// A_FiredRocks -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FiredRocks) -{ - PARAM_ACTION_PROLOGUE; - - A_FiredSpawnRock (self); - A_FiredSpawnRock (self); - A_FiredSpawnRock (self); - A_FiredSpawnRock (self); - A_FiredSpawnRock (self); - return 0; -} - -//============================================================================ -// -// A_SmBounce -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SmBounce) -{ - PARAM_ACTION_PROLOGUE; - - // give some more velocity (x,y,&z) - self->SetZ(self->floorz + 1); - self->Vel.Z = 2. + pr_smbounce() / 64.; - self->Vel.X = pr_smbounce() % 3; - self->Vel.Y = pr_smbounce() % 3; - return 0; -} - -//============================================================================ -// -// A_FiredAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FiredAttack) -{ - PARAM_ACTION_PROLOGUE; - - if (self->target == NULL) - return 0; - AActor *mo = P_SpawnMissile (self, self->target, PClass::FindActor("FireDemonMissile")); - if (mo) S_Sound (self, CHAN_BODY, "FireDemonAttack", 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_FiredChase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FiredChase) -{ - PARAM_ACTION_PROLOGUE; - - int weaveindex = self->special1; - AActor *target = self->target; - DAngle ang; - double dist; - - if (self->reactiontime) self->reactiontime--; - if (self->threshold) self->threshold--; - - // Float up and down - self->AddZ(BobSin(weaveindex)); - self->special1 = (weaveindex + 2) & 63; - - // Ensure it stays above certain height - if (self->Z() < self->floorz + 64) - { - self->AddZ(2); - } - - if(!self->target || !(self->target->flags&MF_SHOOTABLE)) - { // Invalid target - P_LookForPlayers (self,true, NULL); - return 0; - } - - // Strafe - if (self->special2 > 0) - { - self->special2--; - } - else - { - self->special2 = 0; - self->Vel.X = self->Vel.Y = 0; - dist = self->Distance2D(target); - if (dist < FIREDEMON_ATTACK_RANGE) - { - if (pr_firedemonchase() < 30) - { - ang = self->AngleTo(target); - if (pr_firedemonchase() < 128) - ang += 90; - else - ang -= 90; - self->Thrust(ang, 8); - self->special2 = 3; // strafe time - } - } - } - - FaceMovementDirection (self); - - // Normal movement - if (!self->special2) - { - if (--self->movecount<0 || !P_Move (self)) - { - P_NewChaseDir (self); - } - } - - // Do missile attack - if (!(self->flags & MF_JUSTATTACKED)) - { - if (P_CheckMissileRange (self) && (pr_firedemonchase() < 20)) - { - self->SetState (self->MissileState); - self->flags |= MF_JUSTATTACKED; - return 0; - } - } - else - { - self->flags &= ~MF_JUSTATTACKED; - } - - // make active sound - if (pr_firedemonchase() < 3) - { - self->PlayActiveSound (); - } - return 0; -} - -//============================================================================ -// -// A_FiredSplotch -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FiredSplotch) -{ - PARAM_ACTION_PROLOGUE; - - AActor *mo; - - mo = Spawn ("FireDemonSplotch1", self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->Vel.X = (pr_firedemonsplotch() - 128) / 32.; - mo->Vel.Y = (pr_firedemonsplotch() - 128) / 32.; - mo->Vel.Z = (pr_firedemonsplotch() / 64.) + 3; - } - mo = Spawn ("FireDemonSplotch2", self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->Vel.X = (pr_firedemonsplotch() - 128) / 32.; - mo->Vel.Y = (pr_firedemonsplotch() - 128) / 32.; - mo->Vel.Z = (pr_firedemonsplotch() / 64.) + 3; - } - return 0; -} diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index ccc2bf112..335842887 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -10,7 +10,7 @@ #include "a_action.h" #include "a_hexenglobal.h" #include "w_wad.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -24,7 +24,7 @@ DECLARE_ACTION(A_CheckThrowBomb) // Poison Bag Artifact (Flechette) ------------------------------------------ -IMPLEMENT_CLASS (AArtiPoisonBag) +IMPLEMENT_CLASS(AArtiPoisonBag, false, false, false, false) // Poison Bag 1 (The Cleric's) ---------------------------------------------- @@ -35,7 +35,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiPoisonBag1) +IMPLEMENT_CLASS(AArtiPoisonBag1, false, false, false, false) bool AArtiPoisonBag1::Use (bool pickup) { @@ -60,7 +60,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiPoisonBag2) +IMPLEMENT_CLASS(AArtiPoisonBag2, false, false, false, false) bool AArtiPoisonBag2::Use (bool pickup) { @@ -85,7 +85,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiPoisonBag3) +IMPLEMENT_CLASS(AArtiPoisonBag3, false, false, false, false) bool AArtiPoisonBag3::Use (bool pickup) { @@ -136,7 +136,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiPoisonBagGiver) +IMPLEMENT_CLASS(AArtiPoisonBagGiver, false, false, false, false) bool AArtiPoisonBagGiver::Use (bool pickup) { @@ -167,7 +167,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiPoisonBagShooter) +IMPLEMENT_CLASS(AArtiPoisonBagShooter, false, false, false, false) bool AArtiPoisonBagShooter::Use (bool pickup) { @@ -296,7 +296,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS (APoisonCloud) +IMPLEMENT_CLASS(APoisonCloud, false, false, false, false) void APoisonCloud::BeginPlay () { @@ -362,7 +362,7 @@ int APoisonCloud::DoSpecialDamage (AActor *victim, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagInit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -382,7 +382,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagInit) DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagCheck) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (--self->special1 <= 0) { @@ -403,7 +403,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagCheck) DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagDamage) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int bobIndex; @@ -422,7 +422,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagDamage) DEFINE_ACTION_FUNCTION(AActor, A_CheckThrowBomb) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (--self->health <= 0) { @@ -439,7 +439,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckThrowBomb) DEFINE_ACTION_FUNCTION(AActor, A_CheckThrowBomb2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // [RH] Check using actual velocity, although the vel.z < 2 check still stands if (self->Vel.Z < 2 && self->Vel.LengthSquared() < (9./4.)) diff --git a/src/g_hexen/a_flies.cpp b/src/g_hexen/a_flies.cpp index 1023c12ae..7281dd8f2 100644 --- a/src/g_hexen/a_flies.cpp +++ b/src/g_hexen/a_flies.cpp @@ -60,7 +60,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlySearch) // So search the sectors instead. We can't potentially find something all // the way on the other side of the map and we can't find invisible corpses, // but at least we aren't crippled on maps with lots of stuff going on. - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); validcount++; AActor *other = FindCorpse(self, self->Sector, 5); @@ -74,7 +74,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlySearch) DEFINE_ACTION_FUNCTION(AActor, A_FlyBuzz) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *targ = self->target; diff --git a/src/g_hexen/a_fog.cpp b/src/g_hexen/a_fog.cpp index b89f8d38c..6b2bc9706 100644 --- a/src/g_hexen/a_fog.cpp +++ b/src/g_hexen/a_fog.cpp @@ -1,7 +1,7 @@ /* #include "m_random.h" #include "p_local.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_fogspawn ("FogSpawn"); @@ -27,7 +27,7 @@ static FRandom pr_fogspawn ("FogSpawn"); DEFINE_ACTION_FUNCTION(AActor, A_FogSpawn) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); static const char *fogs[3] = { @@ -70,7 +70,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FogSpawn) DEFINE_ACTION_FUNCTION(AActor, A_FogMove) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double speed = self->args[0]; int weaveindex; diff --git a/src/g_hexen/a_healingradius.cpp b/src/g_hexen/a_healingradius.cpp index c381f3964..25efbc3ca 100644 --- a/src/g_hexen/a_healingradius.cpp +++ b/src/g_hexen/a_healingradius.cpp @@ -25,7 +25,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiHealingRadius) +IMPLEMENT_CLASS(AArtiHealingRadius, false, false, false, false) bool AArtiHealingRadius::Use (bool pickup) { diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index c96c4cc1f..32ad9ab69 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -7,7 +7,7 @@ #include "m_random.h" #include "a_hexenglobal.h" #include "i_system.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -72,7 +72,7 @@ public: void Die (AActor *source, AActor *inflictor, int dmgflags); }; -IMPLEMENT_CLASS (AHeresiarch) +IMPLEMENT_CLASS(AHeresiarch, false, false, false, false) void AHeresiarch::Serialize(FSerializer &arc) { @@ -122,7 +122,7 @@ public: } }; -IMPLEMENT_CLASS (ASorcBall) +IMPLEMENT_CLASS(ASorcBall, false, false, false, false) // First ball (purple) - fires projectiles ---------------------------------- @@ -140,7 +140,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS (ASorcBall1) +IMPLEMENT_CLASS(ASorcBall1, false, false, false, false) // Second ball (blue) - generates the shield -------------------------------- @@ -156,7 +156,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS (ASorcBall2) +IMPLEMENT_CLASS(ASorcBall2, false, false, false, false) // Third ball (green) - summons Bishops ------------------------------------- @@ -172,7 +172,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS (ASorcBall3) +IMPLEMENT_CLASS(ASorcBall3, false, false, false, false) // Sorcerer spell 1 (The burning, bouncing head thing) ---------------------- @@ -218,7 +218,7 @@ void ASorcBall1::DoFireSpell () DEFINE_ACTION_FUNCTION(AActor, A_SorcSpinBalls) { - PARAM_ACTION_PROLOGUE_TYPE(AHeresiarch); + PARAM_SELF_PROLOGUE(AHeresiarch); AActor *mo; @@ -254,7 +254,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcSpinBalls) DEFINE_ACTION_FUNCTION(AActor, A_SorcBallOrbit) { - PARAM_ACTION_PROLOGUE_TYPE(ASorcBall); + PARAM_SELF_PROLOGUE(ASorcBall); // [RH] If no parent, then die instead of crashing if (self->target == NULL) @@ -380,7 +380,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcBallOrbit) DEFINE_ACTION_FUNCTION(AActor, A_SpeedBalls) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->args[3] = SORC_ACCELERATE; // speed mode self->args[2] = SORCBALL_TERMINAL_SPEED; // target speed @@ -676,7 +676,7 @@ void A_SorcOffense2(AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_SorcBossAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->args[3] = SORC_ACCELERATE; self->args[2] = SORCBALL_INITIAL_SPEED; @@ -693,7 +693,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcBossAttack) DEFINE_ACTION_FUNCTION(AActor, A_SpawnFizzle) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int speed = (int)self->Speed; DAngle rangle; AActor *mo; @@ -725,7 +725,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnFizzle) DEFINE_ACTION_FUNCTION(AActor, A_SorcFX1Seek) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_DoBounceCheck (self, "SorcererHeadScream"); P_SeekerMissile(self, 2, 6); @@ -751,7 +751,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcFX1Seek) // Split ball in two DEFINE_ACTION_FUNCTION(AActor, A_SorcFX2Split) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -785,7 +785,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcFX2Split) DEFINE_ACTION_FUNCTION(AActor, A_SorcFX2Orbit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle angle; DVector3 pos; @@ -852,7 +852,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcFX2Orbit) DEFINE_ACTION_FUNCTION(AActor, A_SpawnBishop) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; mo = Spawn("Bishop", self->Pos(), ALLOW_REPLACE); @@ -881,7 +881,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnBishop) DEFINE_ACTION_FUNCTION(AActor, A_SorcererBishopEntry) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); Spawn("SorcFX3Explosion", self->Pos(), ALLOW_REPLACE); S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM); @@ -898,7 +898,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcererBishopEntry) DEFINE_ACTION_FUNCTION(AActor, A_SorcFX4Check) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->special2-- <= 0) { @@ -917,7 +917,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcFX4Check) DEFINE_ACTION_FUNCTION(AActor, A_SorcBallPop) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_BODY, "SorcererBallPop", 1, ATTN_NONE); self->flags &= ~MF_NOGRAVITY; @@ -961,7 +961,7 @@ void A_DoBounceCheck (AActor *self, const char *sound) DEFINE_ACTION_FUNCTION(AActor, A_BounceCheck) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_DoBounceCheck (self, "SorcererBigBallExplode"); return 0; diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 31a17c3a3..1a635ff71 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -7,7 +7,7 @@ #include "a_sharedglobal.h" #include "a_hexenglobal.h" #include "i_system.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "gi.h" #include "g_level.h" #include "p_enemy.h" @@ -24,13 +24,11 @@ #include "p_maputl.h" #include "p_spec.h" #include "serializer.h" +#include "vm.h" // Include all the Hexen stuff here to reduce compile time -#include "a_bats.cpp" -#include "a_bishop.cpp" #include "a_blastradius.cpp" #include "a_boostarmor.cpp" -#include "a_centaur.cpp" #include "a_clericflame.cpp" #include "a_clericholy.cpp" #include "a_clericmace.cpp" @@ -40,7 +38,6 @@ #include "a_fighterhammer.cpp" #include "a_fighterplayer.cpp" #include "a_fighterquietus.cpp" -#include "a_firedemon.cpp" #include "a_flechette.cpp" #include "a_flies.cpp" #include "a_fog.cpp" diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index 28de8d46a..6d441ba57 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -11,7 +11,7 @@ #include "p_local.h" #include "p_lnspec.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "doomstat.h" */ @@ -39,7 +39,7 @@ public: void HitFloor (); }; -IMPLEMENT_CLASS (APottery1) +IMPLEMENT_CLASS(APottery1, false, false, false, false) void APottery1::HitFloor () { @@ -55,7 +55,7 @@ void APottery1::HitFloor () DEFINE_ACTION_FUNCTION(AActor, A_PotteryExplode) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo = NULL; int i; @@ -93,7 +93,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PotteryExplode) DEFINE_ACTION_FUNCTION(AActor, A_PotteryChooseBit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->SetState (self->FindState(NAME_Death) + 1 + 2*(pr_bit()%5)); self->tics = 256+(pr_bit()<<1); @@ -108,7 +108,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PotteryChooseBit) DEFINE_ACTION_FUNCTION(AActor, A_PotteryCheck) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; @@ -136,7 +136,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS (AZCorpseLynchedNoHeart) +IMPLEMENT_CLASS(AZCorpseLynchedNoHeart, false, false, false, false) void AZCorpseLynchedNoHeart::PostBeginPlay () { @@ -152,7 +152,7 @@ void AZCorpseLynchedNoHeart::PostBeginPlay () DEFINE_ACTION_FUNCTION(AActor, A_CorpseBloodDrip) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (pr_drip() <= 128) { @@ -169,7 +169,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CorpseBloodDrip) DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; int i; @@ -207,7 +207,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode) DEFINE_ACTION_FUNCTION(AActor, A_LeafSpawn) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; int i; @@ -238,7 +238,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LeafSpawn) DEFINE_ACTION_FUNCTION(AActor, A_LeafThrust) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (pr_leafthrust() <= 96) { @@ -255,7 +255,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LeafThrust) DEFINE_ACTION_FUNCTION(AActor, A_LeafCheck) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->special1++; if (self->special1 >= 20) @@ -287,7 +287,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LeafCheck) DEFINE_ACTION_FUNCTION(AActor, A_PoisonShroom) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->tics = 128 + (pr_shroom() << 1); return 0; @@ -301,7 +301,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PoisonShroom) DEFINE_ACTION_FUNCTION(AActor, A_SoAExplode) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; int i; @@ -344,7 +344,7 @@ public: void Activate (AActor *activator); }; -IMPLEMENT_CLASS (AZBell) +IMPLEMENT_CLASS(AZBell, false, false, false, false) void AZBell::Activate (AActor *activator) { @@ -362,7 +362,7 @@ void AZBell::Activate (AActor *activator) DEFINE_ACTION_FUNCTION(AActor, A_BellReset1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags |= MF_NOGRAVITY; self->Height *= 4; @@ -383,7 +383,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BellReset1) DEFINE_ACTION_FUNCTION(AActor, A_BellReset2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags |= MF_SHOOTABLE; self->flags &= ~MF_CORPSE; diff --git a/src/g_hexen/a_iceguy.cpp b/src/g_hexen/a_iceguy.cpp index d00e86041..1163a117a 100644 --- a/src/g_hexen/a_iceguy.cpp +++ b/src/g_hexen/a_iceguy.cpp @@ -6,7 +6,7 @@ #include "p_enemy.h" #include "a_action.h" #include "m_random.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_iceguylook ("IceGuyLook"); @@ -26,7 +26,7 @@ static const char *WispTypes[2] = DEFINE_ACTION_FUNCTION(AActor, A_IceGuyLook) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double dist; DAngle an; @@ -49,7 +49,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceGuyLook) DEFINE_ACTION_FUNCTION(AActor, A_IceGuyChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double dist; DAngle an; @@ -78,7 +78,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceGuyChase) DEFINE_ACTION_FUNCTION(AActor, A_IceGuyAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if(!self->target) { @@ -98,7 +98,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceGuyAttack) DEFINE_ACTION_FUNCTION(AActor, A_IceGuyDie) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Vel.Zero(); self->Height = self->GetDefault()->Height; @@ -114,7 +114,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceGuyDie) DEFINE_ACTION_FUNCTION(AActor, A_IceGuyMissileExplode) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; unsigned int i; diff --git a/src/g_hexen/a_korax.cpp b/src/g_hexen/a_korax.cpp index 7f0d3a43c..2824d8c0a 100644 --- a/src/g_hexen/a_korax.cpp +++ b/src/g_hexen/a_korax.cpp @@ -25,7 +25,7 @@ #include "a_action.h" #include "m_random.h" #include "i_system.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -88,7 +88,7 @@ extern void SpawnSpiritTail (AActor *spirit); DEFINE_ACTION_FUNCTION(AActor, A_KoraxChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *spot; @@ -155,7 +155,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KoraxChase) DEFINE_ACTION_FUNCTION(AActor, A_KoraxBonePop) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; int i; @@ -201,7 +201,7 @@ void KSpiritInit (AActor *spirit, AActor *korax) DEFINE_ACTION_FUNCTION(AActor, A_KoraxDecide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (pr_koraxdecide()<220) { @@ -222,7 +222,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KoraxDecide) DEFINE_ACTION_FUNCTION(AActor, A_KoraxMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); static const struct { const char *type, *sound; } choices[6] = { @@ -265,7 +265,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KoraxMissile) DEFINE_ACTION_FUNCTION(AActor, A_KoraxCommand) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle ang; int numcommands; @@ -399,7 +399,7 @@ static void A_KSpiritSeeker (AActor *actor, DAngle thresh, DAngle turnMax) DEFINE_ACTION_FUNCTION(AActor, A_KSpiritRoam) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->health-- <= 0) { @@ -432,7 +432,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KSpiritRoam) DEFINE_ACTION_FUNCTION(AActor, A_KBolt) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // Countdown lifetime if (self->special1-- <= 0) @@ -450,7 +450,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KBolt) DEFINE_ACTION_FUNCTION(AActor, A_KBoltRaise) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; diff --git a/src/g_hexen/a_magecone.cpp b/src/g_hexen/a_magecone.cpp index f31e57e58..da53a829c 100644 --- a/src/g_hexen/a_magecone.cpp +++ b/src/g_hexen/a_magecone.cpp @@ -10,7 +10,7 @@ #include "p_pspr.h" #include "gstrings.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ const int SHARDSPAWN_LEFT = 1; @@ -32,7 +32,7 @@ public: int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AFrostMissile) +IMPLEMENT_CLASS(AFrostMissile, false, false, false, false) int AFrostMissile::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { @@ -51,7 +51,7 @@ int AFrostMissile::DoSpecialDamage (AActor *victim, int damage, FName damagetype DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -112,7 +112,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1) DEFINE_ACTION_FUNCTION(AActor, A_ShedShard) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; int spawndir = self->special1; diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 896384f4e..b06d22ce5 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -10,7 +10,7 @@ #include "p_pspr.h" #include "gstrings.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -34,7 +34,7 @@ public: int SpecialMissileHit (AActor *victim); }; -IMPLEMENT_CLASS(ALightning) +IMPLEMENT_CLASS(ALightning, false, false, false, false) int ALightning::SpecialMissileHit (AActor *thing) { @@ -87,7 +87,7 @@ public: int SpecialMissileHit (AActor *thing); }; -IMPLEMENT_CLASS (ALightningZap) +IMPLEMENT_CLASS(ALightningZap, false, false, false, false) int ALightningZap::SpecialMissileHit (AActor *thing) { @@ -126,7 +126,7 @@ int ALightningZap::SpecialMissileHit (AActor *thing) DEFINE_ACTION_FUNCTION(AActor, A_LightningReady) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DoReadyWeapon(self); if (pr_lightningready() < 160) @@ -144,7 +144,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningReady) DEFINE_ACTION_FUNCTION(AActor, A_LightningClip) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *cMo; AActor *target = NULL; @@ -211,7 +211,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningClip) DEFINE_ACTION_FUNCTION(AActor, A_LightningZap) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PClassActor *lightning = PClass::FindActor(self->GetClass()->MissileName); AActor *mo; @@ -257,9 +257,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningZap) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MLightningAttack) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(floor, AActor) { floor = PClass::FindActor("LightningFloor"); } - PARAM_CLASS_OPT(ceiling, AActor) { ceiling = PClass::FindActor("LightningCeiling"); } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_CLASS_DEF(floor, AActor); + PARAM_CLASS_DEF(ceiling, AActor); AActor *fmo, *cmo; @@ -298,7 +298,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MLightningAttack) DEFINE_ACTION_FUNCTION(AActor, A_ZapMimic) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -326,7 +326,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ZapMimic) DEFINE_ACTION_FUNCTION(AActor, A_LastZap) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PClassActor *lightning = PClass::FindActor(self->GetClass()->MissileName); AActor *mo; @@ -353,7 +353,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LastZap) DEFINE_ACTION_FUNCTION(AActor, A_LightningRemove) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index d7b06d009..0b78bd279 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -7,7 +7,7 @@ #include "a_hexenglobal.h" #include "gstrings.h" #include "a_weaponpiece.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" */ @@ -56,7 +56,7 @@ public: BYTE MStaffCount; }; -IMPLEMENT_CLASS (AMWeapBloodscourge) +IMPLEMENT_CLASS(AMWeapBloodscourge, false, false, false, false) // Mage Staff FX2 (Bloodscourge) -------------------------------------------- @@ -68,7 +68,7 @@ public: bool SpecialBlastHandling (AActor *source, double strength); }; -IMPLEMENT_CLASS (AMageStaffFX2) +IMPLEMENT_CLASS(AMageStaffFX2, false, false, false, false) int AMageStaffFX2::SpecialMissileHit (AActor *victim) { @@ -122,7 +122,7 @@ void MStaffSpawn (AActor *pmo, DAngle angle, AActor *alttarget) DEFINE_ACTION_FUNCTION(AActor, A_MStaffAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; player_t *player; @@ -167,7 +167,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MStaffAttack) DEFINE_ACTION_FUNCTION(AActor, A_MStaffPalette) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -188,7 +188,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MStaffPalette) DEFINE_ACTION_FUNCTION(AActor, A_MStaffTrack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if ((self->tracer == 0) && (pr_mstafftrack()<50)) { @@ -250,7 +250,7 @@ void MStaffSpawn2 (AActor *actor, DAngle angle) DEFINE_ACTION_FUNCTION(AActor, A_MageAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) { diff --git a/src/g_hexen/a_pig.cpp b/src/g_hexen/a_pig.cpp index ea767dccd..41054da00 100644 --- a/src/g_hexen/a_pig.cpp +++ b/src/g_hexen/a_pig.cpp @@ -11,7 +11,7 @@ #include "p_enemy.h" #include "d_event.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_snoutattack ("SnoutAttack"); @@ -27,7 +27,7 @@ public: void MorphPlayerThink (); }; -IMPLEMENT_CLASS (APigPlayer) +IMPLEMENT_CLASS(APigPlayer, false, false, false, false) void APigPlayer::MorphPlayerThink () { @@ -58,7 +58,7 @@ void APigPlayer::MorphPlayerThink () DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -96,7 +96,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack) DEFINE_ACTION_FUNCTION(AActor, A_PigPain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); CALL_ACTION(A_Pain, self); if (self->Z() <= self->floorz) diff --git a/src/g_hexen/a_serpent.cpp b/src/g_hexen/a_serpent.cpp index 998466053..6f435747e 100644 --- a/src/g_hexen/a_serpent.cpp +++ b/src/g_hexen/a_serpent.cpp @@ -7,7 +7,7 @@ #include "a_action.h" #include "m_random.h" #include "p_terrain.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_serpentchase ("SerpentChase"); @@ -25,7 +25,7 @@ static FRandom pr_delaygib ("DelayGib"); DEFINE_ACTION_FUNCTION(AActor, A_SerpentUnHide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->renderflags &= ~RF_INVISIBLE; self->Floorclip = 24; @@ -40,7 +40,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentUnHide) DEFINE_ACTION_FUNCTION(AActor, A_SerpentHide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->renderflags |= RF_INVISIBLE; self->Floorclip = 0; @@ -56,7 +56,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentHide) DEFINE_ACTION_FUNCTION(AActor, A_SerpentRaiseHump) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Floorclip -= 4; return 0; @@ -70,7 +70,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentRaiseHump) DEFINE_ACTION_FUNCTION(AActor, A_SerpentLowerHump) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Floorclip += 4; return 0; @@ -86,7 +86,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentLowerHump) DEFINE_ACTION_FUNCTION(AActor, A_SerpentHumpDecide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->MissileState != NULL) { @@ -127,7 +127,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentHumpDecide) DEFINE_ACTION_FUNCTION(AActor, A_SerpentCheckForAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) { @@ -167,7 +167,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentCheckForAttack) DEFINE_ACTION_FUNCTION(AActor, A_SerpentChooseAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target || self->CheckMeleeRange()) { @@ -188,7 +188,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentChooseAttack) DEFINE_ACTION_FUNCTION(AActor, A_SerpentMeleeAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) { @@ -216,7 +216,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentMeleeAttack) DEFINE_ACTION_FUNCTION(AActor, A_SerpentSpawnGibs) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; static const char *GibTypes[] = @@ -250,7 +250,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentSpawnGibs) DEFINE_ACTION_FUNCTION(AActor, A_FloatGib) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Floorclip -= 1; return 0; @@ -264,7 +264,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FloatGib) DEFINE_ACTION_FUNCTION(AActor, A_SinkGib) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Floorclip += 1;; return 0; @@ -278,7 +278,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SinkGib) DEFINE_ACTION_FUNCTION(AActor, A_DelayGib) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->tics -= pr_delaygib()>>2; return 0; @@ -292,7 +292,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DelayGib) DEFINE_ACTION_FUNCTION(AActor, A_SerpentHeadCheck) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->Z() <= self->floorz) { diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp index 9f7396399..9b2cb5d6e 100644 --- a/src/g_hexen/a_spike.cpp +++ b/src/g_hexen/a_spike.cpp @@ -7,7 +7,7 @@ #include "a_sharedglobal.h" #include "s_sound.h" #include "m_bbox.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_thrustraise ("ThrustRaise"); @@ -31,9 +31,11 @@ public: TObjPtr DirtClump; }; -IMPLEMENT_POINTY_CLASS (AThrustFloor) - DECLARE_POINTER (DirtClump) -END_POINTERS +IMPLEMENT_CLASS(AThrustFloor, false, true, false, false) + +IMPLEMENT_POINTERS_START(AThrustFloor) + IMPLEMENT_POINTER(DirtClump) +IMPLEMENT_POINTERS_END void AThrustFloor::Serialize(FSerializer &arc) { @@ -79,7 +81,7 @@ void AThrustFloor::Deactivate (AActor *activator) DEFINE_ACTION_FUNCTION(AActor, A_ThrustInitUp) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->special2 = 5; // Raise speed self->args[0] = 1; // Mark as up @@ -92,7 +94,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustInitUp) DEFINE_ACTION_FUNCTION(AActor, A_ThrustInitDn) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->special2 = 5; // Raise speed self->args[0] = 0; // Mark as down @@ -108,7 +110,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustInitDn) DEFINE_ACTION_FUNCTION(AActor, A_ThrustRaise) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AThrustFloor *actor = static_cast(self); @@ -137,7 +139,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustRaise) DEFINE_ACTION_FUNCTION(AActor, A_ThrustLower) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (A_SinkMobj (self, 6)) { @@ -152,7 +154,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustLower) DEFINE_ACTION_FUNCTION(AActor, A_ThrustImpale) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // This doesn't need to iterate through portals. diff --git a/src/g_hexen/a_summon.cpp b/src/g_hexen/a_summon.cpp index eb5d825bf..7c0746c91 100644 --- a/src/g_hexen/a_summon.cpp +++ b/src/g_hexen/a_summon.cpp @@ -6,7 +6,7 @@ #include "p_local.h" #include "s_sound.h" #include "ravenshared.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -21,7 +21,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiDarkServant) +IMPLEMENT_CLASS(AArtiDarkServant, false, false, false, false) //============================================================================ // @@ -49,7 +49,7 @@ bool AArtiDarkServant::Use (bool pickup) DEFINE_ACTION_FUNCTION(AActor, A_Summon) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AMinotaurFriend *mo; diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp index 7333d9d91..4eeba53f9 100644 --- a/src/g_hexen/a_teleportother.cpp +++ b/src/g_hexen/a_teleportother.cpp @@ -7,7 +7,7 @@ #include "s_sound.h" #include "p_lnspec.h" #include "m_random.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "doomstat.h" */ @@ -34,7 +34,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiTeleportOther) +IMPLEMENT_CLASS(AArtiTeleportOther, false, false, false, false) // Teleport Other FX -------------------------------------------------------- @@ -45,7 +45,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (ATelOtherFX1) +IMPLEMENT_CLASS(ATelOtherFX1, false, false, false, false) static void TeloSpawn (AActor *source, const char *type) { @@ -63,35 +63,35 @@ static void TeloSpawn (AActor *source, const char *type) DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnA) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); TeloSpawn (self, "TelOtherFX2"); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnB) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); TeloSpawn (self, "TelOtherFX3"); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnC) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); TeloSpawn (self, "TelOtherFX4"); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnD) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); TeloSpawn (self, "TelOtherFX5"); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_CheckTeleRing) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->special1-- <= 0) { diff --git a/src/g_hexen/a_wraith.cpp b/src/g_hexen/a_wraith.cpp index 460fa6503..fcd0d75f3 100644 --- a/src/g_hexen/a_wraith.cpp +++ b/src/g_hexen/a_wraith.cpp @@ -7,7 +7,7 @@ #include "a_action.h" #include "m_random.h" #include "a_sharedglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_stealhealth ("StealHealth"); @@ -23,7 +23,7 @@ static FRandom pr_wraithfx4 ("WraithFX4"); DEFINE_ACTION_FUNCTION(AActor, A_WraithInit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->AddZ(48); @@ -45,7 +45,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WraithInit) DEFINE_ACTION_FUNCTION(AActor, A_WraithRaiseInit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->renderflags &= ~RF_INVISIBLE; self->flags2 &= ~MF2_NONSHOOTABLE; @@ -63,7 +63,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WraithRaiseInit) DEFINE_ACTION_FUNCTION(AActor, A_WraithRaise) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (A_RaiseMobj (self, 2)) { @@ -88,7 +88,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WraithRaise) DEFINE_ACTION_FUNCTION(AActor, A_WraithMelee) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int amount; @@ -110,7 +110,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WraithMelee) DEFINE_ACTION_FUNCTION(AActor, A_WraithFX2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; DAngle angle; @@ -147,7 +147,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WraithFX2) DEFINE_ACTION_FUNCTION(AActor, A_WraithFX3) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; int numdropped = pr_wraithfx3() % 15; @@ -242,7 +242,7 @@ void A_WraithFX4 (AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_WraithChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int weaveindex = self->WeaveIndexZ; self->AddZ(BobSin(weaveindex)); diff --git a/src/g_level.cpp b/src/g_level.cpp index 9e8448879..9a955a03e 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -903,7 +903,7 @@ public: void Tick (); }; -IMPLEMENT_CLASS (DAutosaver) +IMPLEMENT_CLASS(DAutosaver, false, false, false, false) void DAutosaver::Tick () { @@ -1848,6 +1848,58 @@ void FLevelLocals::AddScroller (int secnum) } } +//========================================================================== +// +// sets up the script-side version of FLevelLocals +// Since this is a global variable and the script compiler does +// not allow defining them, it will be fully set up here. +// +//========================================================================== + +void G_InitLevelLocalsForScript() +{ + PStruct *lstruct = NewStruct("LevelLocals", nullptr); + PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level); + GlobalSymbols.AddSymbol(levelf); + + // This only exports a selection of fields. Not everything here is useful to the playsim. + lstruct->AddNativeField("time", TypeSInt32, myoffsetof(FLevelLocals, time), VARF_ReadOnly); + lstruct->AddNativeField("maptime", TypeSInt32, myoffsetof(FLevelLocals, maptime), VARF_ReadOnly); + lstruct->AddNativeField("totaltime", TypeSInt32, myoffsetof(FLevelLocals, totaltime), VARF_ReadOnly); + lstruct->AddNativeField("starttime", TypeSInt32, myoffsetof(FLevelLocals, starttime), VARF_ReadOnly); + lstruct->AddNativeField("partime", TypeSInt32, myoffsetof(FLevelLocals, partime), VARF_ReadOnly); + lstruct->AddNativeField("sucktime", TypeSInt32, myoffsetof(FLevelLocals, sucktime), VARF_ReadOnly); + lstruct->AddNativeField("cluster", TypeSInt32, myoffsetof(FLevelLocals, cluster), VARF_ReadOnly); + lstruct->AddNativeField("clusterflags", TypeSInt32, myoffsetof(FLevelLocals, clusterflags), VARF_ReadOnly); + lstruct->AddNativeField("levelnum", TypeSInt32, myoffsetof(FLevelLocals, levelnum), VARF_ReadOnly); + //lstruct->AddNativeField("levelname", TypeString, myoffsetof(FLevelLocals, LevelName), VARF_ReadOnly); // must use an access function to resolve string table references. + lstruct->AddNativeField("mapname", TypeString, myoffsetof(FLevelLocals, MapName), VARF_ReadOnly); + lstruct->AddNativeField("nextmap", TypeString, myoffsetof(FLevelLocals, NextMap)); + lstruct->AddNativeField("nextsecretmap", TypeString, myoffsetof(FLevelLocals, NextSecretMap)); + lstruct->AddNativeField("maptype", TypeSInt32, myoffsetof(FLevelLocals, maptype), VARF_ReadOnly); + lstruct->AddNativeField("monsterstelefrag", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, LEVEL_MONSTERSTELEFRAG); + lstruct->AddNativeField("actownspecial", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, LEVEL_ACTOWNSPECIAL); + lstruct->AddNativeField("sndseqtotalctrl", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, LEVEL_SNDSEQTOTALCTRL); + lstruct->AddNativeField("allmap", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, (LEVEL2_ALLMAP)); + lstruct->AddNativeField("missilesactivateimpact", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, LEVEL2_MISSILESACTIVATEIMPACT); + lstruct->AddNativeField("monsterfallingdamage", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, LEVEL2_MONSTERFALLINGDAMAGE); + lstruct->AddNativeField("checkswitchrange", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, LEVEL2_CHECKSWITCHRANGE); + lstruct->AddNativeField("polygrind", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, LEVEL2_POLYGRIND); + lstruct->AddNativeField("music", TypeString, myoffsetof(FLevelLocals, Music), VARF_ReadOnly); + lstruct->AddNativeField("musicorder", TypeSInt32, myoffsetof(FLevelLocals, musicorder), VARF_ReadOnly); + lstruct->AddNativeField("total_secrets", TypeSInt32, myoffsetof(FLevelLocals, total_secrets), VARF_ReadOnly); + lstruct->AddNativeField("found_secrets", TypeSInt32, myoffsetof(FLevelLocals, found_secrets)); + lstruct->AddNativeField("total_items", TypeSInt32, myoffsetof(FLevelLocals, total_items), VARF_ReadOnly); + lstruct->AddNativeField("found_items", TypeSInt32, myoffsetof(FLevelLocals, found_items)); + lstruct->AddNativeField("total_monsters", TypeSInt32, myoffsetof(FLevelLocals, total_monsters), VARF_ReadOnly); + lstruct->AddNativeField("killed_monsters", TypeSInt32, myoffsetof(FLevelLocals, killed_monsters)); + lstruct->AddNativeField("gravity", TypeFloat64, myoffsetof(FLevelLocals, gravity)); + lstruct->AddNativeField("aircontrol", TypeFloat64, myoffsetof(FLevelLocals, aircontrol)); + lstruct->AddNativeField("airfriction", TypeFloat64, myoffsetof(FLevelLocals, airfriction)); + lstruct->AddNativeField("airsupply", TypeSInt32, myoffsetof(FLevelLocals, airsupply)); + lstruct->AddNativeField("teamdamage", TypeFloat64, myoffsetof(FLevelLocals, teamdamage)); +} + //========================================================================== // // Lists all currently defined maps diff --git a/src/g_level.h b/src/g_level.h index 9f8c5efd5..790eba344 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -110,6 +110,7 @@ struct FMapInfoParser void ParseAMColors(bool); FName CheckEndSequence(); FName ParseEndGame(); + void ParseDamageDefinition(); }; #define DEFINE_MAP_OPTION(name, old) \ @@ -259,7 +260,7 @@ struct FOptionalMapinfoDataPtr typedef TMap FOptData; typedef TMap FMusicMap; -enum EMapType +enum EMapType : int { MAPTYPE_UNKNOWN = 0, MAPTYPE_DOOM, diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index bc0470474..814a36435 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -1873,6 +1873,18 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i sc.ScriptError("doomednums definitions not supported with old MAPINFO syntax"); } } + else if (sc.Compare("damagetype")) + { + if (format_type != FMT_Old) + { + format_type = FMT_New; + ParseDamageDefinition(); + } + else + { + sc.ScriptError("damagetype definitions not supported with old MAPINFO syntax"); + } + } else if (sc.Compare("spawnnums")) { if (format_type != FMT_Old) diff --git a/src/g_pch.h b/src/g_pch.h index 3f44cf9b5..a22649815 100644 --- a/src/g_pch.h +++ b/src/g_pch.h @@ -18,3 +18,4 @@ #include #include #include +#include diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp index 9a43f8518..35387df45 100644 --- a/src/g_raven/a_artitele.cpp +++ b/src/g_raven/a_artitele.cpp @@ -23,7 +23,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiTeleport) +IMPLEMENT_CLASS(AArtiTeleport, false, false, false, false) bool AArtiTeleport::Use (bool pickup) { diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index 9f58ce4c3..dd4e4a8b8 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -8,12 +8,13 @@ #include "a_action.h" #include "gi.h" #include "w_wad.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "doomstat.h" #include "a_pickups.h" #include "d_player.h" #include "serializer.h" +#include "vm.h" #define MAULATORTICS (25*35) @@ -30,7 +31,7 @@ void P_MinotaurSlam (AActor *source, AActor *target); DECLARE_ACTION(A_MinotaurLook) -IMPLEMENT_CLASS(AMinotaur) +IMPLEMENT_CLASS(AMinotaur, false, false, false, false) void AMinotaur::Tick () { @@ -71,7 +72,7 @@ int AMinotaur::DoSpecialDamage (AActor *target, int damage, FName damagetype) // Minotaur Friend ---------------------------------------------------------- -IMPLEMENT_CLASS(AMinotaurFriend) +IMPLEMENT_CLASS(AMinotaurFriend, false, false, false, false) void AMinotaurFriend::BeginPlay () { @@ -116,12 +117,6 @@ void AMinotaurFriend::Die (AActor *source, AActor *inflictor, int dmgflags) } } -bool AMinotaurFriend::OkayToSwitchTarget (AActor *other) -{ - if (other == tracer) return false; // Do not target the master - return Super::OkayToSwitchTarget (other); -} - // Action functions for the minotaur ---------------------------------------- //---------------------------------------------------------------------------- @@ -134,7 +129,7 @@ bool AMinotaurFriend::OkayToSwitchTarget (AActor *other) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (Wads.CheckNumForName ("MNTRF1", ns_sprites) < 0 && Wads.CheckNumForName ("MNTRF0", ns_sprites) < 0) @@ -144,7 +139,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDeath) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -179,7 +174,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk1) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER); AActor *target; @@ -236,7 +231,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurCharge) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *puff; @@ -279,7 +274,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurCharge) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; DAngle angle; @@ -329,7 +324,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk3) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; player_t *player; @@ -385,7 +380,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk3) DEFINE_ACTION_FUNCTION(AActor, A_MntrFloorFire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -414,7 +409,7 @@ void P_MinotaurSlam (AActor *source, AActor *target) angle = source->AngleTo(target); thrust = 16 + pr_minotaurslam() / 64.; - target->VelFromAngle(angle, thrust); + target->VelFromAngle(thrust, angle); damage = pr_minotaurslam.HitDice (static_cast(source) ? 4 : 6); int newdam = P_DamageMobj (target, NULL, NULL, damage, NAME_Melee); P_TraceBleed (newdam > 0 ? newdam : damage, target, angle, 0.); @@ -442,7 +437,7 @@ void P_MinotaurSlam (AActor *source, AActor *target) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurRoam) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // In case pain caused him to skip his fade in. self->RenderStyle = STYLE_Normal; @@ -490,7 +485,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurRoam) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->IsKindOf(RUNTIME_CLASS(AMinotaurFriend))) { @@ -561,7 +556,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->IsKindOf(RUNTIME_CLASS(AMinotaurFriend))) { diff --git a/src/g_raven/ravenshared.h b/src/g_raven/ravenshared.h index 81824a957..3c6019ae7 100644 --- a/src/g_raven/ravenshared.h +++ b/src/g_raven/ravenshared.h @@ -21,7 +21,6 @@ public: int StartTime; void Die (AActor *source, AActor *inflictor, int dmgflags); - bool OkayToSwitchTarget (AActor *other); void BeginPlay (); void Serialize(FSerializer &arc); diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index c0ec37d09..edd97a6d4 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -1,5 +1,5 @@ #include "actor.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "p_conversation.h" #include "p_lnspec.h" #include "a_action.h" @@ -29,7 +29,7 @@ public: void Deactivate (AActor *activator); }; -IMPLEMENT_CLASS (ASwitchableDecoration) +IMPLEMENT_CLASS(ASwitchableDecoration, false, false, false, false) void ASwitchableDecoration::Activate (AActor *activator) { @@ -50,7 +50,7 @@ public: void Deactivate (AActor *activator) {} }; -IMPLEMENT_CLASS (ASwitchingDecoration) +IMPLEMENT_CLASS(ASwitchingDecoration, false, false, false, false) //---------------------------------------------------------------------------- // @@ -104,73 +104,9 @@ void A_Unblock(AActor *self, bool drop) DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking) { - PARAM_ACTION_PROLOGUE; - A_Unblock(self, true); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_Fall) -{ - PARAM_ACTION_PROLOGUE; - A_Unblock(self, true); - return 0; -} - -//========================================================================== -// -// A_SetFloorClip -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_SetFloorClip) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 |= MF2_FLOORCLIP; - self->AdjustFloorClip (); - return 0; -} - -//========================================================================== -// -// A_UnSetFloorClip -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetFloorClip) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 &= ~MF2_FLOORCLIP; - self->Floorclip = 0; - return 0; -} - -//========================================================================== -// -// A_HideThing -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_HideThing) -{ - PARAM_ACTION_PROLOGUE; - - self->renderflags |= RF_INVISIBLE; - return 0; -} - -//========================================================================== -// -// A_UnHideThing -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_UnHideThing) -{ - PARAM_ACTION_PROLOGUE; - - self->renderflags &= ~RF_INVISIBLE; + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(drop); + A_Unblock(self, drop); return 0; } @@ -182,7 +118,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_UnHideThing) DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int t = pr_freezedeath(); self->tics = 75+t+pr_freezedeath(); @@ -228,7 +164,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeath) DEFINE_ACTION_FUNCTION(AActor, A_GenericFreezeDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Translation = TRANSLATION(TRANSLATION_Standard, 7); CALL_ACTION(A_FreezeDeath, self); @@ -243,7 +179,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenericFreezeDeath) DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int floor; @@ -268,7 +204,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics) DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; int numChunks; @@ -368,9 +304,11 @@ private: DCorpsePointer () {} }; -IMPLEMENT_POINTY_CLASS(DCorpsePointer) - DECLARE_POINTER(Corpse) -END_POINTERS +IMPLEMENT_CLASS(DCorpsePointer, false, true, false, false) + +IMPLEMENT_POINTERS_START(DCorpsePointer) + IMPLEMENT_POINTER(Corpse) +IMPLEMENT_POINTERS_END CUSTOM_CVAR(Int, sv_corpsequeuesize, 64, CVAR_ARCHIVE|CVAR_SERVERINFO) { @@ -446,7 +384,7 @@ void DCorpsePointer::Serialize(FSerializer &arc) // throw another corpse on the queue DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (sv_corpsequeuesize > 0) { @@ -458,7 +396,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse) // Remove an self from the queue (for resurrection) DEFINE_ACTION_FUNCTION(AActor, A_DeQueueCorpse) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); TThinkerIterator iterator (STAT_CORPSEPOINTER); DCorpsePointer *corpsePtr; @@ -475,164 +413,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeQueueCorpse) return 0; } -//============================================================================ -// -// A_SetInvulnerable -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SetInvulnerable) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 |= MF2_INVULNERABLE; - return 0; -} - -//============================================================================ -// -// A_UnSetInvulnerable -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetInvulnerable) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 &= ~MF2_INVULNERABLE; - return 0; -} - -//============================================================================ -// -// A_SetReflective -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SetReflective) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 |= MF2_REFLECTIVE; - return 0; -} - -//============================================================================ -// -// A_UnSetReflective -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetReflective) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 &= ~MF2_REFLECTIVE; - return 0; -} - -//============================================================================ -// -// A_SetReflectiveInvulnerable -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SetReflectiveInvulnerable) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 |= MF2_REFLECTIVE|MF2_INVULNERABLE; - return 0; -} - -//============================================================================ -// -// A_UnSetReflectiveInvulnerable -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetReflectiveInvulnerable) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 &= ~(MF2_REFLECTIVE|MF2_INVULNERABLE); - return 0; -} - -//========================================================================== -// -// A_SetShootable -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_SetShootable) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 &= ~MF2_NONSHOOTABLE; - self->flags |= MF_SHOOTABLE; - return 0; -} - -//========================================================================== -// -// A_UnSetShootable -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetShootable) -{ - PARAM_ACTION_PROLOGUE; - - self->flags2 |= MF2_NONSHOOTABLE; - self->flags &= ~MF_SHOOTABLE; - return 0; -} - -//=========================================================================== -// -// A_NoGravity -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_NoGravity) -{ - PARAM_ACTION_PROLOGUE; - - self->flags |= MF_NOGRAVITY; - return 0; -} - -//=========================================================================== -// -// A_Gravity -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_Gravity) -{ - PARAM_ACTION_PROLOGUE; - - self->flags &= ~MF_NOGRAVITY; - self->Gravity = 1; - return 0; -} - -//=========================================================================== -// -// A_LowGravity -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_LowGravity) -{ - PARAM_ACTION_PROLOGUE; - - self->flags &= ~MF_NOGRAVITY; - self->Gravity = 1. / 8;; - return 0; -} - //=========================================================================== // // FaceMovementDirection @@ -669,3 +449,10 @@ void FaceMovementDirection(AActor *actor) break; } } + +DEFINE_ACTION_FUNCTION(AActor, FaceMovementDirection) +{ + PARAM_SELF_PROLOGUE(AActor); + FaceMovementDirection(self); + return 0; +} diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 50472e51d..636441a9d 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -8,12 +8,11 @@ #include "d_player.h" #include "serializer.h" - -IMPLEMENT_CLASS (AArmor) -IMPLEMENT_CLASS (ABasicArmor) -IMPLEMENT_CLASS (ABasicArmorPickup) -IMPLEMENT_CLASS (ABasicArmorBonus) -IMPLEMENT_CLASS (AHexenArmor) +IMPLEMENT_CLASS(AArmor, false, false, false, false) +IMPLEMENT_CLASS(ABasicArmor, false, false, false, false) +IMPLEMENT_CLASS(ABasicArmorPickup, false, false, false, false) +IMPLEMENT_CLASS(ABasicArmorBonus, false, false, false, false) +IMPLEMENT_CLASS(AHexenArmor, false, false, false, false) //=========================================================================== // diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 7e4970e04..7cf05613a 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -40,11 +40,11 @@ static FRandom pr_torch ("Torch"); #define TIMEFREEZE_TICS ( 12 * TICRATE ) */ -IMPLEMENT_CLASS (APowerup) +IMPLEMENT_CLASS(APowerup, false, false, false, false) // Powerup-Giver ------------------------------------------------------------- -IMPLEMENT_CLASS(PClassPowerupGiver) +IMPLEMENT_CLASS(PClassPowerupGiver, false, false, false, false) void PClassPowerupGiver::ReplaceClassRef(PClass *oldclass, PClass *newclass) { @@ -376,7 +376,7 @@ bool APowerup::GetNoTeleportFreeze () // Invulnerability Powerup --------------------------------------------------- -IMPLEMENT_CLASS (APowerInvulnerable) +IMPLEMENT_CLASS(APowerInvulnerable, false, false, false, false) //=========================================================================== // @@ -513,7 +513,7 @@ int APowerInvulnerable::AlterWeaponSprite (visstyle_t *vis) // Strength (aka Berserk) Powerup -------------------------------------------- -IMPLEMENT_CLASS (APowerStrength) +IMPLEMENT_CLASS(APowerStrength, false, false, false, false) //=========================================================================== // @@ -578,7 +578,7 @@ PalEntry APowerStrength::GetBlend () // Invisibility Powerup ------------------------------------------------------ -IMPLEMENT_CLASS (APowerInvisibility) +IMPLEMENT_CLASS(APowerInvisibility, false, false, false, false) // Invisibility flag combos #define INVISIBILITY_FLAGS1 (MF_SHADOW) @@ -783,7 +783,7 @@ bool APowerInvisibility::HandlePickup (AInventory *item) // Ironfeet Powerup ---------------------------------------------------------- -IMPLEMENT_CLASS (APowerIronFeet) +IMPLEMENT_CLASS(APowerIronFeet, false, false, false, false) //=========================================================================== // @@ -820,7 +820,7 @@ void APowerIronFeet::DoEffect () // Strife Environment Suit Powerup ------------------------------------------- -IMPLEMENT_CLASS (APowerMask) +IMPLEMENT_CLASS(APowerMask, false, false, false, false) //=========================================================================== // @@ -857,7 +857,7 @@ void APowerMask::DoEffect () // Light-Amp Powerup --------------------------------------------------------- -IMPLEMENT_CLASS (APowerLightAmp) +IMPLEMENT_CLASS(APowerLightAmp, false, false, false, false) //=========================================================================== // @@ -899,7 +899,7 @@ void APowerLightAmp::EndEffect () // Torch Powerup ------------------------------------------------------------- -IMPLEMENT_CLASS (APowerTorch) +IMPLEMENT_CLASS(APowerTorch, false, false, false, false) //=========================================================================== // @@ -962,7 +962,7 @@ void APowerTorch::DoEffect () // Flight (aka Wings of Wrath) powerup --------------------------------------- -IMPLEMENT_CLASS (APowerFlight) +IMPLEMENT_CLASS(APowerFlight, false, false, false, false) //=========================================================================== // @@ -1102,7 +1102,7 @@ bool APowerFlight::DrawPowerup (int x, int y) // Weapon Level 2 (aka Tome of Power) Powerup -------------------------------- -IMPLEMENT_CLASS (APowerWeaponLevel2) +IMPLEMENT_CLASS(APowerWeaponLevel2, false, false, false, false) //=========================================================================== // @@ -1193,7 +1193,7 @@ public: void Tick (); }; -IMPLEMENT_CLASS (APlayerSpeedTrail) +IMPLEMENT_CLASS(APlayerSpeedTrail, false, false, false, false) //=========================================================================== // @@ -1216,7 +1216,7 @@ void APlayerSpeedTrail::Tick () // Speed Powerup ------------------------------------------------------------- -IMPLEMENT_CLASS (APowerSpeed) +IMPLEMENT_CLASS(APowerSpeed, false, false, false, false) //=========================================================================== // @@ -1303,11 +1303,11 @@ void APowerSpeed::DoEffect () // Minotaur (aka Dark Servant) powerup --------------------------------------- -IMPLEMENT_CLASS (APowerMinotaur) +IMPLEMENT_CLASS(APowerMinotaur, false, false, false, false) // Targeter powerup --------------------------------------------------------- -IMPLEMENT_CLASS (APowerTargeter) +IMPLEMENT_CLASS(APowerTargeter, false, false, false, false) void APowerTargeter::Travelled () { @@ -1422,7 +1422,7 @@ void APowerTargeter::PositionAccuracy () // Frightener Powerup -------------------------------- -IMPLEMENT_CLASS (APowerFrightener) +IMPLEMENT_CLASS(APowerFrightener, false, false, false, false) //=========================================================================== // @@ -1458,7 +1458,7 @@ void APowerFrightener::EndEffect () // Buddha Powerup -------------------------------- -IMPLEMENT_CLASS (APowerBuddha) +IMPLEMENT_CLASS(APowerBuddha, false, false, false, false) //=========================================================================== // @@ -1494,11 +1494,11 @@ void APowerBuddha::EndEffect () // Scanner powerup ---------------------------------------------------------- -IMPLEMENT_CLASS (APowerScanner) +IMPLEMENT_CLASS(APowerScanner, false, false, false, false) // Time freezer powerup ----------------------------------------------------- -IMPLEMENT_CLASS( APowerTimeFreezer) +IMPLEMENT_CLASS( APowerTimeFreezer, false, false, false, false) //=========================================================================== // @@ -1625,7 +1625,7 @@ void APowerTimeFreezer::EndEffect() // Damage powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerDamage) +IMPLEMENT_CLASS(APowerDamage, false, false, false, false) //=========================================================================== // @@ -1682,7 +1682,7 @@ void APowerDamage::ModifyDamage(int damage, FName damageType, int &newdamage, bo // Quarter damage powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerProtection) +IMPLEMENT_CLASS(APowerProtection, false, false, false, false) #define PROTECTION_FLAGS3 (MF3_NORADIUSDMG | MF3_DONTMORPH | MF3_DONTSQUASH | MF3_DONTBLAST | MF3_NOTELEOTHER) #define PROTECTION_FLAGS5 (MF5_NOPAIN | MF5_DONTRIP) @@ -1760,7 +1760,7 @@ void APowerProtection::ModifyDamage(int damage, FName damageType, int &newdamage // Drain rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerDrain) +IMPLEMENT_CLASS(APowerDrain, false, false, false, false) //=========================================================================== // @@ -1800,7 +1800,7 @@ void APowerDrain::EndEffect( ) // Regeneration rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerRegeneration) +IMPLEMENT_CLASS(APowerRegeneration, false, false, false, false) //=========================================================================== // @@ -1822,7 +1822,7 @@ void APowerRegeneration::DoEffect() // High jump rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerHighJump) +IMPLEMENT_CLASS(APowerHighJump, false, false, false, false) //=========================================================================== // @@ -1860,7 +1860,7 @@ void APowerHighJump::EndEffect( ) // Double firing speed rune --------------------------------------------- -IMPLEMENT_CLASS(APowerDoubleFiringSpeed) +IMPLEMENT_CLASS(APowerDoubleFiringSpeed, false, false, false, false) //=========================================================================== // @@ -1898,7 +1898,7 @@ void APowerDoubleFiringSpeed::EndEffect( ) // Morph powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerMorph) +IMPLEMENT_CLASS(APowerMorph, false, false, false, false) //=========================================================================== // @@ -2002,7 +2002,7 @@ void APowerMorph::EndEffect( ) // Infinite Ammo Powerup ----------------------------------------------------- -IMPLEMENT_CLASS(APowerInfiniteAmmo) +IMPLEMENT_CLASS(APowerInfiniteAmmo, false, false, false, false) //=========================================================================== // diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 178f004ca..ab0df27e1 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -2,7 +2,7 @@ #include "info.h" #include "gi.h" #include "m_random.h" -#include "thingdef/thingdef.h" +#include "vm.h" static FRandom pr_orbit ("Orbit"); @@ -41,7 +41,7 @@ public: void Destroy(); }; -IMPLEMENT_CLASS(ACustomBridge) +IMPLEMENT_CLASS(ACustomBridge, false, false, false, false) void ACustomBridge::BeginPlay () { @@ -92,7 +92,7 @@ void ACustomBridge::Destroy() DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) { // Don't crash if somebody spawned this into the world @@ -121,8 +121,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BridgeInit) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(balltype, AActor) { balltype = NULL; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS_DEF(balltype, AActor); AActor *ball; @@ -156,7 +156,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(AInvisibleBridge) +IMPLEMENT_CLASS(AInvisibleBridge, false, false, false, false) void AInvisibleBridge::BeginPlay () { diff --git a/src/g_shared/a_camera.cpp b/src/g_shared/a_camera.cpp index fb3d81533..ae34c3cbc 100644 --- a/src/g_shared/a_camera.cpp +++ b/src/g_shared/a_camera.cpp @@ -64,7 +64,7 @@ protected: DAngle Range; }; -IMPLEMENT_CLASS (ASecurityCamera) +IMPLEMENT_CLASS(ASecurityCamera, false, false, false, false) void ASecurityCamera::Serialize(FSerializer &arc) { @@ -124,7 +124,7 @@ protected: DAngle MaxPitchChange; }; -IMPLEMENT_CLASS (AAimingCamera) +IMPLEMENT_CLASS(AAimingCamera, false, false, false, false) void AAimingCamera::Serialize(FSerializer &arc) { diff --git a/src/g_shared/a_debris.cpp b/src/g_shared/a_debris.cpp index 895c3b170..3be3c2240 100644 --- a/src/g_shared/a_debris.cpp +++ b/src/g_shared/a_debris.cpp @@ -25,7 +25,7 @@ public: } }; -IMPLEMENT_CLASS(AGlassShard) +IMPLEMENT_CLASS(AGlassShard, false, false, false, false) // Dirt stuff diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index e02ab1a52..06563f995 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -58,12 +58,14 @@ static int ImpactCount; CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE) -IMPLEMENT_POINTY_CLASS (DBaseDecal) - DECLARE_POINTER(WallPrev) - DECLARE_POINTER(WallNext) -END_POINTERS +IMPLEMENT_CLASS(DBaseDecal, false, true, false, false) -IMPLEMENT_CLASS (DImpactDecal) +IMPLEMENT_POINTERS_START(DBaseDecal) + IMPLEMENT_POINTER(WallPrev) + IMPLEMENT_POINTER(WallNext) +IMPLEMENT_POINTERS_END + +IMPLEMENT_CLASS(DImpactDecal, false, false, false, false) DBaseDecal::DBaseDecal () : DThinker(STAT_DECAL), @@ -744,7 +746,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS (ADecal) +IMPLEMENT_CLASS(ADecal, false, false, false, false) void ADecal::BeginPlay () { diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index 82349c1a7..ffca8a8fa 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -7,8 +7,7 @@ #include "b_bot.h" #include "p_checkposition.h" - -IMPLEMENT_CLASS(AFastProjectile) +IMPLEMENT_CLASS(AFastProjectile, false, false, false, false) //---------------------------------------------------------------------------- diff --git a/src/g_shared/a_flashfader.cpp b/src/g_shared/a_flashfader.cpp index 71673e5c7..8602f7a86 100644 --- a/src/g_shared/a_flashfader.cpp +++ b/src/g_shared/a_flashfader.cpp @@ -3,9 +3,11 @@ #include "d_player.h" #include "serializer.h" -IMPLEMENT_POINTY_CLASS (DFlashFader) - DECLARE_POINTER (ForWho) -END_POINTERS +IMPLEMENT_CLASS(DFlashFader, false, true, false, false) + +IMPLEMENT_POINTERS_START(DFlashFader) + IMPLEMENT_POINTER(ForWho) +IMPLEMENT_POINTERS_END DFlashFader::DFlashFader () { diff --git a/src/g_shared/a_fountain.cpp b/src/g_shared/a_fountain.cpp index 970bd8aaa..e89745fc7 100644 --- a/src/g_shared/a_fountain.cpp +++ b/src/g_shared/a_fountain.cpp @@ -46,7 +46,7 @@ public: void Deactivate (AActor *activator); }; -IMPLEMENT_CLASS (AParticleFountain) +IMPLEMENT_CLASS(AParticleFountain, false, false, false, false) void AParticleFountain::PostBeginPlay () { diff --git a/src/g_shared/a_hatetarget.cpp b/src/g_shared/a_hatetarget.cpp index 4d0d9a8e7..7d25bdb31 100644 --- a/src/g_shared/a_hatetarget.cpp +++ b/src/g_shared/a_hatetarget.cpp @@ -46,7 +46,7 @@ public: int TakeSpecialDamage(AActor *inflictor, AActor *source, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AHateTarget) +IMPLEMENT_CLASS(AHateTarget, false, false, false, false) void AHateTarget::BeginPlay() { diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index 2d2b5be87..69fbe48af 100644 --- a/src/g_shared/a_keys.cpp +++ b/src/g_shared/a_keys.cpp @@ -470,7 +470,7 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote) // //========================================================================== -IMPLEMENT_CLASS (AKey) +IMPLEMENT_CLASS(AKey, false, false, false, false) bool AKey::HandlePickup (AInventory *item) { diff --git a/src/g_shared/a_lightning.cpp b/src/g_shared/a_lightning.cpp index 3eaedffc9..f00560fc8 100644 --- a/src/g_shared/a_lightning.cpp +++ b/src/g_shared/a_lightning.cpp @@ -13,7 +13,7 @@ static FRandom pr_lightning ("Lightning"); -IMPLEMENT_CLASS (DLightningThinker) +IMPLEMENT_CLASS(DLightningThinker, false, false, false, false) DLightningThinker::DLightningThinker () : DThinker (STAT_LIGHTNING) diff --git a/src/g_shared/a_mapmarker.cpp b/src/g_shared/a_mapmarker.cpp index f8d7128c3..d874042c5 100644 --- a/src/g_shared/a_mapmarker.cpp +++ b/src/g_shared/a_mapmarker.cpp @@ -51,7 +51,7 @@ // //-------------------------------------------------------------------------- -IMPLEMENT_CLASS(AMapMarker) +IMPLEMENT_CLASS(AMapMarker, false, false, false, false) void AMapMarker::BeginPlay () { diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 46ae5cac7..506f18b2f 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -616,7 +616,7 @@ void InitAllPowerupEffects(AInventory *item) // Base class for morphing projectiles -------------------------------------- -IMPLEMENT_CLASS(AMorphProjectile) +IMPLEMENT_CLASS(AMorphProjectile, false, false, false, false) int AMorphProjectile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -650,9 +650,11 @@ void AMorphProjectile::Serialize(FSerializer &arc) // Morphed Monster (you must subclass this to do something useful) --------- -IMPLEMENT_POINTY_CLASS (AMorphedMonster) - DECLARE_POINTER (UnmorphedMe) -END_POINTERS +IMPLEMENT_CLASS(AMorphedMonster, false, true, false, false) + +IMPLEMENT_POINTERS_START(AMorphedMonster) + IMPLEMENT_POINTER(UnmorphedMe) +IMPLEMENT_POINTERS_END void AMorphedMonster::Serialize(FSerializer &arc) { diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index 76f128b15..030f5d368 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -66,9 +66,11 @@ public: TObjPtr Next; }; -IMPLEMENT_POINTY_CLASS (AInterpolationPoint) - DECLARE_POINTER (Next) -END_POINTERS +IMPLEMENT_CLASS(AInterpolationPoint, false, true, false, false) + +IMPLEMENT_POINTERS_START(AInterpolationPoint) + IMPLEMENT_POINTER(Next) +IMPLEMENT_POINTERS_END void AInterpolationPoint::Serialize(FSerializer &arc) { @@ -133,7 +135,7 @@ public: void Tick () {} // Does absolutely nothing itself }; -IMPLEMENT_CLASS (AInterpolationSpecial) +IMPLEMENT_CLASS(AInterpolationSpecial, false, false, false, false) /* == PathFollower: something that follows a camera path @@ -176,10 +178,12 @@ protected: int HoldTime; }; -IMPLEMENT_POINTY_CLASS (APathFollower) - DECLARE_POINTER (PrevNode) - DECLARE_POINTER (CurrNode) -END_POINTERS +IMPLEMENT_CLASS(APathFollower, false, true, false, false) + +IMPLEMENT_POINTERS_START(APathFollower) + IMPLEMENT_POINTER(PrevNode) + IMPLEMENT_POINTER(CurrNode) +IMPLEMENT_POINTERS_END void APathFollower::Serialize(FSerializer &arc) { @@ -476,7 +480,7 @@ protected: bool Interpolate (); }; -IMPLEMENT_CLASS (AActorMover) +IMPLEMENT_CLASS(AActorMover, false, false, false, false) void AActorMover::BeginPlay() { @@ -592,9 +596,11 @@ protected: TObjPtr Activator; }; -IMPLEMENT_POINTY_CLASS (AMovingCamera) - DECLARE_POINTER (Activator) -END_POINTERS +IMPLEMENT_CLASS(AMovingCamera, false, true, false, false) + +IMPLEMENT_POINTERS_START(AMovingCamera) + IMPLEMENT_POINTER(Activator) +IMPLEMENT_POINTERS_END void AMovingCamera::Serialize(FSerializer &arc) { diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index e80e54818..223a2f75f 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -14,7 +14,7 @@ #include "a_strifeglobal.h" #include "a_morph.h" #include "a_specialspot.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "g_game.h" #include "doomstat.h" @@ -24,7 +24,7 @@ static FRandom pr_restore ("RestorePos"); -IMPLEMENT_CLASS(PClassInventory) +IMPLEMENT_CLASS(PClassInventory, false, false, false, false) PClassInventory::PClassInventory() { @@ -65,7 +65,13 @@ void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass) } } -IMPLEMENT_CLASS(PClassAmmo) +void PClassInventory::Finalize(FStateDefinitions &statedef) +{ + Super::Finalize(statedef); + ((AActor*)Defaults)->flags |= MF_SPECIAL; +} + +IMPLEMENT_CLASS(PClassAmmo, false, false, false, false) PClassAmmo::PClassAmmo() { @@ -81,7 +87,7 @@ void PClassAmmo::DeriveData(PClass *newclass) newc->DropAmount = DropAmount; } -IMPLEMENT_CLASS (AAmmo) +IMPLEMENT_CLASS(AAmmo, false, false, false, false) //=========================================================================== // @@ -349,7 +355,7 @@ bool P_GiveBody (AActor *actor, int num, int max) DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialThing1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->renderflags &= ~RF_INVISIBLE; if (static_cast(self)->DoRespawn ()) @@ -367,7 +373,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialThing1) DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialThing2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags |= MF_SPECIAL; if (!(self->GetDefault()->flags & MF_NOGRAVITY)) @@ -387,7 +393,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialThing2) DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialDoomThing) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->renderflags &= ~RF_INVISIBLE; self->flags |= MF_SPECIAL; @@ -412,7 +418,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialDoomThing) DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // Move item back to its original location DVector2 sp = self->SpawnPoint; @@ -464,9 +470,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) int AInventory::StaticLastMessageTic; const char *AInventory::StaticLastMessage; -IMPLEMENT_POINTY_CLASS (AInventory) - DECLARE_POINTER (Owner) -END_POINTERS +IMPLEMENT_CLASS(AInventory, false, true, false, false) + +IMPLEMENT_POINTERS_START(AInventory) + IMPLEMENT_POINTER(Owner) +IMPLEMENT_POINTERS_END //=========================================================================== // @@ -1346,7 +1354,7 @@ bool AInventory::DrawPowerup (int x, int y) /* AArtifact implementation */ /***************************************************************************/ -IMPLEMENT_CLASS (APowerupGiver) +IMPLEMENT_CLASS(APowerupGiver, false, false, false, false) //=========================================================================== // @@ -1636,7 +1644,8 @@ void AInventory::DetachFromOwner () { } -IMPLEMENT_CLASS (ACustomInventory) +IMPLEMENT_CLASS(AStateProvider, false, false, false, false) +IMPLEMENT_CLASS(ACustomInventory, false, false, false, false) //=========================================================================== // @@ -1681,7 +1690,7 @@ bool ACustomInventory::TryPickup (AActor *&toucher) return useok; } -IMPLEMENT_CLASS(PClassHealth) +IMPLEMENT_CLASS(PClassHealth, false, false, false, false) //=========================================================================== // @@ -1696,7 +1705,7 @@ PClassHealth::PClassHealth() //=========================================================================== // -// PClassHealth :: Derive +// PClassHealth :: DeriveData // //=========================================================================== @@ -1710,7 +1719,7 @@ void PClassHealth::DeriveData(PClass *newclass) newc->LowHealthMessage = LowHealthMessage; } -IMPLEMENT_CLASS (AHealth) +IMPLEMENT_CLASS(AHealth, false, false, false, false) //=========================================================================== // @@ -1753,7 +1762,7 @@ bool AHealth::TryPickup (AActor *&other) return false; } -IMPLEMENT_CLASS (AHealthPickup) +IMPLEMENT_CLASS(AHealthPickup, false, false, false, false) //=========================================================================== // @@ -2006,9 +2015,8 @@ void ABackpackItem::DetachFromOwner () // //=========================================================================== -IMPLEMENT_CLASS(ABackpackItem) - -IMPLEMENT_CLASS (AMapRevealer) +IMPLEMENT_CLASS(ABackpackItem, false, false, false, false) +IMPLEMENT_CLASS(AMapRevealer, false, false, false, false) //=========================================================================== // @@ -2033,7 +2041,7 @@ bool AMapRevealer::TryPickup (AActor *&toucher) // //=========================================================================== -IMPLEMENT_CLASS(AScoreItem) +IMPLEMENT_CLASS(AScoreItem, false, false, false, false) //=========================================================================== // diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 9dba52639..6dc2d0bc5 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -139,6 +139,7 @@ public: PClassInventory(); virtual void DeriveData(PClass *newclass); virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); + void Finalize(FStateDefinitions &statedef); FString PickupMessage; int GiveQuest; // Optionally give one of the quest items. @@ -225,10 +226,15 @@ private: static const char *StaticLastMessage; }; -// CustomInventory: Supports the Use, Pickup, and Drop states from 96x -class ACustomInventory : public AInventory +class AStateProvider : public AInventory { - DECLARE_CLASS (ACustomInventory, AInventory) + DECLARE_CLASS(AStateProvider, AInventory) +}; + +// CustomInventory: Supports the Use, Pickup, and Drop states from 96x +class ACustomInventory : public AStateProvider +{ + DECLARE_CLASS (ACustomInventory, AStateProvider) public: // This is used when an inventory item's use state sequence is executed. @@ -274,14 +280,15 @@ protected: public: PClassWeapon(); virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); + void Finalize(FStateDefinitions &statedef); int SlotNumber; int SlotPriority; }; -class AWeapon : public AInventory +class AWeapon : public AStateProvider { - DECLARE_CLASS_WITH_META(AWeapon, AInventory, PClassWeapon) + DECLARE_CLASS_WITH_META(AWeapon, AStateProvider, PClassWeapon) HAS_OBJECT_POINTERS public: DWORD WeaponFlags; diff --git a/src/g_shared/a_puzzleitems.cpp b/src/g_shared/a_puzzleitems.cpp index 233066edc..d243dc73c 100644 --- a/src/g_shared/a_puzzleitems.cpp +++ b/src/g_shared/a_puzzleitems.cpp @@ -8,7 +8,7 @@ #include "doomstat.h" #include "v_font.h" -IMPLEMENT_CLASS(PClassPuzzleItem) +IMPLEMENT_CLASS(PClassPuzzleItem, false, false, false, false) void PClassPuzzleItem::DeriveData(PClass *newclass) { @@ -17,7 +17,7 @@ void PClassPuzzleItem::DeriveData(PClass *newclass) static_cast(newclass)->PuzzFailMessage = PuzzFailMessage; } -IMPLEMENT_CLASS(APuzzleItem) +IMPLEMENT_CLASS(APuzzleItem, false, false, false, false) bool APuzzleItem::HandlePickup (AInventory *item) { diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 98e505b2b..80a53ee08 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -14,9 +14,11 @@ static FRandom pr_quake ("Quake"); -IMPLEMENT_POINTY_CLASS (DEarthquake) - DECLARE_POINTER (m_Spot) -END_POINTERS +IMPLEMENT_CLASS(DEarthquake, false, true, false, false) + +IMPLEMENT_POINTERS_START(DEarthquake) + IMPLEMENT_POINTER(m_Spot) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index ac162a241..2b2c82956 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -14,7 +14,7 @@ #include "statnums.h" #include "gstrings.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "v_text.h" #include "doomstat.h" #include "doomdata.h" @@ -231,4 +231,4 @@ class ARandomSpawner : public AActor }; -IMPLEMENT_CLASS (ARandomSpawner) +IMPLEMENT_CLASS(ARandomSpawner, false, false, false, false) diff --git a/src/g_shared/a_secrettrigger.cpp b/src/g_shared/a_secrettrigger.cpp index 286ea5011..372cef07d 100644 --- a/src/g_shared/a_secrettrigger.cpp +++ b/src/g_shared/a_secrettrigger.cpp @@ -50,7 +50,7 @@ public: void Activate (AActor *activator); }; -IMPLEMENT_CLASS (ASecretTrigger) +IMPLEMENT_CLASS(ASecretTrigger, false, false, false, false) void ASecretTrigger::PostBeginPlay () { diff --git a/src/g_shared/a_sectoraction.cpp b/src/g_shared/a_sectoraction.cpp index 38435e16b..61a69b1b3 100644 --- a/src/g_shared/a_sectoraction.cpp +++ b/src/g_shared/a_sectoraction.cpp @@ -37,7 +37,7 @@ // The base class for sector actions ---------------------------------------- -IMPLEMENT_CLASS (ASectorAction) +IMPLEMENT_CLASS(ASectorAction, false, false, false, false) ASectorAction::ASectorAction (bool activatedByUse) : ActivatedByUse (activatedByUse) {} @@ -142,7 +142,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActEnter) +IMPLEMENT_CLASS(ASecActEnter, false, false, false, false) bool ASecActEnter::DoTriggerAction (AActor *triggerer, int activationType) @@ -160,7 +160,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActExit) +IMPLEMENT_CLASS(ASecActExit, false, false, false, false) bool ASecActExit::DoTriggerAction (AActor *triggerer, int activationType) @@ -180,7 +180,8 @@ public: // Skull Tag uses 9999 for a special that is triggered whenever // the player is on the sector's floor. I think this is more useful. -IMPLEMENT_CLASS (ASecActHitFloor) + +IMPLEMENT_CLASS(ASecActHitFloor, false, false, false, false) bool ASecActHitFloor::DoTriggerAction (AActor *triggerer, int activationType) @@ -198,7 +199,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActHitCeil) +IMPLEMENT_CLASS(ASecActHitCeil, false, false, false, false) bool ASecActHitCeil::DoTriggerAction (AActor *triggerer, int activationType) @@ -217,7 +218,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActUse) +IMPLEMENT_CLASS(ASecActUse, false, false, false, false) bool ASecActUse::DoTriggerAction (AActor *triggerer, int activationType) @@ -236,7 +237,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActUseWall) +IMPLEMENT_CLASS(ASecActUseWall, false, false, false, false) bool ASecActUseWall::DoTriggerAction (AActor *triggerer, int activationType) @@ -254,7 +255,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActEyesDive) +IMPLEMENT_CLASS(ASecActEyesDive, false, false, false, false) bool ASecActEyesDive::DoTriggerAction (AActor *triggerer, int activationType) @@ -272,7 +273,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActEyesSurface) +IMPLEMENT_CLASS(ASecActEyesSurface, false, false, false, false) bool ASecActEyesSurface::DoTriggerAction (AActor *triggerer, int activationType) @@ -290,7 +291,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActEyesBelowC) +IMPLEMENT_CLASS(ASecActEyesBelowC, false, false, false, false) bool ASecActEyesBelowC::DoTriggerAction (AActor *triggerer, int activationType) @@ -308,7 +309,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActEyesAboveC) +IMPLEMENT_CLASS(ASecActEyesAboveC, false, false, false, false) bool ASecActEyesAboveC::DoTriggerAction (AActor *triggerer, int activationType) @@ -326,7 +327,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS (ASecActHitFakeFloor) +IMPLEMENT_CLASS(ASecActHitFakeFloor, false, false, false, false) bool ASecActHitFakeFloor::DoTriggerAction (AActor *triggerer, int activationType) diff --git a/src/g_shared/a_setcolor.cpp b/src/g_shared/a_setcolor.cpp index 4e2725756..585b9fcf6 100644 --- a/src/g_shared/a_setcolor.cpp +++ b/src/g_shared/a_setcolor.cpp @@ -15,7 +15,7 @@ class AColorSetter : public AActor }; -IMPLEMENT_CLASS(AColorSetter) +IMPLEMENT_CLASS(AColorSetter, false, false, false, false) class AFadeSetter : public AActor { @@ -30,4 +30,4 @@ class AFadeSetter : public AActor }; -IMPLEMENT_CLASS(AFadeSetter) +IMPLEMENT_CLASS(AFadeSetter, false, false, false, false) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 89c785e3e..148a452e0 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -42,7 +42,7 @@ // arg0 = Visibility*4 for this skybox -IMPLEMENT_CLASS (ASkyViewpoint) +IMPLEMENT_CLASS(ASkyViewpoint, false, false, false, false) // If this actor has no TID, make it the default sky box void ASkyViewpoint::BeginPlay () @@ -73,7 +73,7 @@ void ASkyViewpoint::Destroy () Super::Destroy(); } -IMPLEMENT_CLASS (ASkyCamCompat) +IMPLEMENT_CLASS(ASkyCamCompat, false, false, false, false) void ASkyCamCompat::BeginPlay() { @@ -98,7 +98,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS (ASkyPicker) +IMPLEMENT_CLASS(ASkyPicker, false, false, false, false) void ASkyPicker::PostBeginPlay () { @@ -142,7 +142,7 @@ void ASkyPicker::PostBeginPlay () // arg0 = opacity of plane; 0 = invisible, 255 = fully opaque -IMPLEMENT_CLASS (AStackPoint) +IMPLEMENT_CLASS(AStackPoint, false, false, false, false) void AStackPoint::BeginPlay () { @@ -160,7 +160,7 @@ public: void Destroy (); }; -IMPLEMENT_CLASS (ASectorSilencer) +IMPLEMENT_CLASS(ASectorSilencer, false, false, false, false) void ASectorSilencer::BeginPlay () { @@ -184,7 +184,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS (ASectorFlagSetter) +IMPLEMENT_CLASS(ASectorFlagSetter, false, false, false, false) void ASectorFlagSetter::BeginPlay () { diff --git a/src/g_shared/a_soundenvironment.cpp b/src/g_shared/a_soundenvironment.cpp index ba0171157..8e5cb133b 100644 --- a/src/g_shared/a_soundenvironment.cpp +++ b/src/g_shared/a_soundenvironment.cpp @@ -46,7 +46,7 @@ public: void Activate (AActor *deactivator); }; -IMPLEMENT_CLASS (ASoundEnvironment) +IMPLEMENT_CLASS(ASoundEnvironment, false, false, false, false) void ASoundEnvironment::PostBeginPlay () { diff --git a/src/g_shared/a_soundsequence.cpp b/src/g_shared/a_soundsequence.cpp index f09b5b7ad..25380a4c7 100644 --- a/src/g_shared/a_soundsequence.cpp +++ b/src/g_shared/a_soundsequence.cpp @@ -80,9 +80,11 @@ public: TObjPtr Sequence; }; -IMPLEMENT_POINTY_CLASS(ASoundSequenceSlot) - DECLARE_POINTER(Sequence) -END_POINTERS +IMPLEMENT_CLASS(ASoundSequenceSlot, false, true, false, false) + +IMPLEMENT_POINTERS_START(ASoundSequenceSlot) + IMPLEMENT_POINTER(Sequence) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -109,7 +111,7 @@ public: void MarkPrecacheSounds () const; }; -IMPLEMENT_CLASS (ASoundSequence) +IMPLEMENT_CLASS(ASoundSequence, false, false, false, false) //========================================================================== // diff --git a/src/g_shared/a_spark.cpp b/src/g_shared/a_spark.cpp index 4bc9dc4c4..654ad710b 100644 --- a/src/g_shared/a_spark.cpp +++ b/src/g_shared/a_spark.cpp @@ -45,7 +45,7 @@ public: void Activate (AActor *activator); }; -IMPLEMENT_CLASS (ASpark) +IMPLEMENT_CLASS(ASpark, false, false, false, false) void ASpark::Activate (AActor *activator) { diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 1d8d1f72d..86d0b5e8a 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -37,7 +37,7 @@ #include "p_local.h" #include "statnums.h" #include "i_system.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" #include "serializer.h" #include "a_pickups.h" @@ -45,9 +45,8 @@ static FRandom pr_spot ("SpecialSpot"); static FRandom pr_spawnmace ("SpawnMace"); - -IMPLEMENT_CLASS(DSpotState) -IMPLEMENT_CLASS (ASpecialSpot) +IMPLEMENT_CLASS(DSpotState, false, false, false, false) +IMPLEMENT_CLASS(ASpecialSpot, false, false, false, false) TObjPtr DSpotState::SpotState; //---------------------------------------------------------------------------- @@ -380,11 +379,11 @@ void ASpecialSpot::Destroy() DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnSingleItem) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (cls, AActor); - PARAM_INT_OPT (fail_sp) { fail_sp = 0; } - PARAM_INT_OPT (fail_co) { fail_co = 0; } - PARAM_INT_OPT (fail_dm) { fail_dm = 0; } + PARAM_INT_DEF (fail_sp) + PARAM_INT_DEF (fail_co) + PARAM_INT_DEF (fail_dm) AActor *spot = NULL; DSpotState *state = DSpotState::GetSpotState(); diff --git a/src/g_shared/a_waterzone.cpp b/src/g_shared/a_waterzone.cpp index 50fc6825b..556d08d7a 100644 --- a/src/g_shared/a_waterzone.cpp +++ b/src/g_shared/a_waterzone.cpp @@ -42,7 +42,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS (AWaterZone) +IMPLEMENT_CLASS(AWaterZone, false, false, false, false) void AWaterZone::PostBeginPlay () { diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp index aefce18c1..7aa9591e9 100644 --- a/src/g_shared/a_weaponpiece.cpp +++ b/src/g_shared/a_weaponpiece.cpp @@ -3,8 +3,8 @@ #include "doomstat.h" #include "serializer.h" -IMPLEMENT_CLASS(PClassWeaponPiece) -IMPLEMENT_CLASS (AWeaponHolder) +IMPLEMENT_CLASS(PClassWeaponPiece, false, false, false, false) +IMPLEMENT_CLASS(AWeaponHolder, false, false, false, false) void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) { @@ -24,10 +24,11 @@ void AWeaponHolder::Serialize(FSerializer &arc) ("pieceweapon", PieceWeapon); } +IMPLEMENT_CLASS(AWeaponPiece, false, true, false, false) -IMPLEMENT_POINTY_CLASS (AWeaponPiece) - DECLARE_POINTER (FullWeapon) -END_POINTERS +IMPLEMENT_POINTERS_START(AWeaponPiece) + IMPLEMENT_POINTER(FullWeapon) +IMPLEMENT_POINTERS_END void AWeaponPiece::Serialize(FSerializer &arc) diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index b1ede0187..9063c6c2c 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -13,7 +13,7 @@ #include "cmdlib.h" #include "templates.h" #include "sbar.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" #include "g_level.h" #include "d_net.h" @@ -21,11 +21,13 @@ #define BONUSADD 6 -IMPLEMENT_POINTY_CLASS (AWeapon) - DECLARE_POINTER (Ammo1) - DECLARE_POINTER (Ammo2) - DECLARE_POINTER (SisterWeapon) -END_POINTERS +IMPLEMENT_CLASS(AWeapon, false, true, false, false) + +IMPLEMENT_POINTERS_START(AWeapon) + IMPLEMENT_POINTER(Ammo1) + IMPLEMENT_POINTER(Ammo2) + IMPLEMENT_POINTER(SisterWeapon) +IMPLEMENT_POINTERS_END FString WeaponSection; TArray KeyConfWeapons; @@ -36,7 +38,7 @@ TMap Weapons_hton; static int ntoh_cmp(const void *a, const void *b); -IMPLEMENT_CLASS(PClassWeapon) +IMPLEMENT_CLASS(PClassWeapon, false, false, false, false) PClassWeapon::PClassWeapon() { @@ -67,6 +69,38 @@ void PClassWeapon::ReplaceClassRef(PClass *oldclass, PClass *newclass) } } +void PClassWeapon::Finalize(FStateDefinitions &statedef) +{ + Super::Finalize(statedef); + FState *ready = FindState(NAME_Ready); + FState *select = FindState(NAME_Select); + FState *deselect = FindState(NAME_Deselect); + FState *fire = FindState(NAME_Fire); + + // Consider any weapon without any valid state abstract and don't output a warning + // This is for creating base classes for weapon groups that only set up some properties. + if (ready || select || deselect || fire) + { + if (!ready) + { + I_Error("Weapon %s doesn't define a ready state.", TypeName.GetChars()); + } + if (!select) + { + I_Error("Weapon %s doesn't define a select state.", TypeName.GetChars()); + } + if (!deselect) + { + I_Error("Weapon %s doesn't define a deselect state.", TypeName.GetChars()); + } + if (!fire) + { + I_Error("Weapon %s doesn't define a fire state.", TypeName.GetChars()); + } + } +} + + //=========================================================================== // // AWeapon :: Serialize @@ -757,7 +791,7 @@ FState *AWeapon::GetStateForButtonName (FName button) /* Weapon giver ***********************************************************/ -IMPLEMENT_CLASS(AWeaponGiver) +IMPLEMENT_CLASS(AWeaponGiver, false, false, false, false) void AWeaponGiver::Serialize(FSerializer &arc) { @@ -1891,9 +1925,9 @@ PClassWeapon *Net_ReadWeapon(BYTE **stream) DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_ZoomFactor) { - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT (zoom) { zoom = 1; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF(zoom); + PARAM_INT_DEF(flags); if (self->player != NULL && self->player->ReadyWeapon != NULL) { @@ -1919,7 +1953,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_ZoomFactor) DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_SetCrosshair) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT(xhair); if (self->player != NULL && self->player->ReadyWeapon != NULL) diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index b86cf6417..e9370ae79 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -44,13 +44,15 @@ EXTERN_CVAR(Int, con_scaletext) int active_con_scaletext(); -IMPLEMENT_POINTY_CLASS (DHUDMessage) - DECLARE_POINTER(Next) -END_POINTERS +IMPLEMENT_CLASS(DHUDMessage, false, true, false, false) -IMPLEMENT_CLASS (DHUDMessageFadeOut) -IMPLEMENT_CLASS (DHUDMessageFadeInOut) -IMPLEMENT_CLASS (DHUDMessageTypeOnFadeOut) +IMPLEMENT_POINTERS_START(DHUDMessage) + IMPLEMENT_POINTER(Next) +IMPLEMENT_POINTERS_END + +IMPLEMENT_CLASS(DHUDMessageFadeOut, false, false, false, false) +IMPLEMENT_CLASS(DHUDMessageFadeInOut, false, false, false, false) +IMPLEMENT_CLASS(DHUDMessageTypeOnFadeOut, false, false, false, false) /************************************************************************* * Basic HUD message. Appears and disappears without any special effects * diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 42f28173c..304101311 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -57,6 +57,7 @@ #include "p_acs.h" #include "gstrings.h" #include "version.h" +#include "cmdlib.h" #define ARTIFLASH_OFFSET (statusBar->invBarOffset+6) enum @@ -1530,11 +1531,13 @@ private: SBarInfoMainBlock *lastPopup; }; -IMPLEMENT_POINTY_CLASS(DSBarInfo) - DECLARE_POINTER(ammo1) - DECLARE_POINTER(ammo2) - DECLARE_POINTER(armor) -END_POINTERS +IMPLEMENT_CLASS(DSBarInfo, false, true, false, false) + +IMPLEMENT_POINTERS_START(DSBarInfo) + IMPLEMENT_POINTER(ammo1) + IMPLEMENT_POINTER(ammo2) + IMPLEMENT_POINTER(armor) +IMPLEMENT_POINTERS_END DBaseStatusBar *CreateCustomStatusBar (int script) { diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index c4d8ec1ed..4733c6e41 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -52,6 +52,7 @@ #include "d_net.h" #include "d_player.h" #include "r_utility.h" +#include "cmdlib.h" #include diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 5e76b422f..80d221cfc 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -54,6 +54,7 @@ #include "serializer.h" #include "gstrings.h" #include "r_utility.h" +#include "cmdlib.h" #include "../version.h" @@ -61,11 +62,13 @@ #define XHAIRPICKUPSIZE (2+XHAIRSHRINKSIZE) #define POWERUPICONSIZE 32 -IMPLEMENT_POINTY_CLASS(DBaseStatusBar) - DECLARE_POINTER(Messages[0]) - DECLARE_POINTER(Messages[1]) - DECLARE_POINTER(Messages[2]) -END_POINTERS +IMPLEMENT_CLASS(DBaseStatusBar, false, true, false, false) + +IMPLEMENT_POINTERS_START(DBaseStatusBar) + IMPLEMENT_POINTER(Messages[0]) + IMPLEMENT_POINTER(Messages[1]) + IMPLEMENT_POINTER(Messages[2]) +IMPLEMENT_POINTERS_END EXTERN_CVAR (Bool, am_showmonsters) EXTERN_CVAR (Bool, am_showsecrets) diff --git a/src/g_strife/a_acolyte.cpp b/src/g_strife/a_acolyte.cpp index e8049da1b..a21c06619 100644 --- a/src/g_strife/a_acolyte.cpp +++ b/src/g_strife/a_acolyte.cpp @@ -7,7 +7,7 @@ #include "s_sound.h" #include "a_strifeglobal.h" #include "doomdata.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" */ @@ -27,7 +27,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_HideDecepticon) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); EV_DoDoor (DDoor::doorClose, NULL, self, 999, 8., 0, 0, 0); if (self->target != NULL && self->target->player != NULL) @@ -45,7 +45,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_HideDecepticon) DEFINE_ACTION_FUNCTION(AActor, A_AcolyteDie) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; @@ -92,7 +92,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AcolyteDie) DEFINE_ACTION_FUNCTION(AActor, A_BeShadowyFoe) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->RenderStyle = STYLE_Translucent; self->Alpha = HR_SHADOW; @@ -108,7 +108,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeShadowyFoe) DEFINE_ACTION_FUNCTION(AActor, A_AcolyteBits) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->SpawnFlags & MTF_SHADOW) { diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp index a7624785b..a1c20355f 100644 --- a/src/g_strife/a_alienspectres.cpp +++ b/src/g_strife/a_alienspectres.cpp @@ -9,7 +9,7 @@ #include "a_strifeglobal.h" #include "c_console.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" */ @@ -20,7 +20,7 @@ static FRandom pr_spectrechunk ("212e4"); DEFINE_ACTION_FUNCTION(AActor, A_SpectreChunkSmall) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *foo = Spawn("AlienChunkSmall", self->PosPlusZ(10.), ALLOW_REPLACE); @@ -41,7 +41,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectreChunkSmall) DEFINE_ACTION_FUNCTION(AActor, A_SpectreChunkLarge) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *foo = Spawn("AlienChunkLarge", self->PosPlusZ(10.), ALLOW_REPLACE); @@ -62,7 +62,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectreChunkLarge) DEFINE_ACTION_FUNCTION(AActor, A_Spectre3Attack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; @@ -86,7 +86,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Spectre3Attack) DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *player; char voc[32]; diff --git a/src/g_strife/a_coin.cpp b/src/g_strife/a_coin.cpp index 5848164bd..87c4619d3 100644 --- a/src/g_strife/a_coin.cpp +++ b/src/g_strife/a_coin.cpp @@ -6,7 +6,7 @@ // Coin --------------------------------------------------------------------- -IMPLEMENT_CLASS (ACoin) +IMPLEMENT_CLASS(ACoin, false, false, false, false) const char *ACoin::PickupMessage () { diff --git a/src/g_strife/a_crusader.cpp b/src/g_strife/a_crusader.cpp index b54fdd427..05835a5f9 100644 --- a/src/g_strife/a_crusader.cpp +++ b/src/g_strife/a_crusader.cpp @@ -6,7 +6,7 @@ #include "p_enemy.h" #include "s_sound.h" #include "a_strifeglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static bool CrusaderCheckRange (AActor *self) @@ -20,7 +20,7 @@ static bool CrusaderCheckRange (AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_CrusaderChoose) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; @@ -51,7 +51,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderChoose) DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepLeft) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Angles.Yaw += 90./16; AActor *misl = P_SpawnMissileZAimed (self, self->Z() + 48, self->target, PClass::FindActor("FastFlameMissile")); @@ -64,7 +64,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepLeft) DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepRight) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Angles.Yaw -= 90./16; AActor *misl = P_SpawnMissileZAimed (self, self->Z() + 48, self->target, PClass::FindActor("FastFlameMissile")); @@ -77,7 +77,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepRight) DEFINE_ACTION_FUNCTION(AActor, A_CrusaderRefire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL || self->target->health <= 0 || @@ -90,7 +90,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderRefire) DEFINE_ACTION_FUNCTION(AActor, A_CrusaderDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (CheckBossDeath (self)) { diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp index 72eeaac3a..535022901 100644 --- a/src/g_strife/a_entityboss.cpp +++ b/src/g_strife/a_entityboss.cpp @@ -6,7 +6,7 @@ #include "p_enemy.h" #include "s_sound.h" #include "a_strifeglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ @@ -14,7 +14,7 @@ static FRandom pr_entity ("Entity"); DEFINE_ACTION_FUNCTION(AActor, A_SubEntityDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (CheckBossDeath (self)) { @@ -42,7 +42,7 @@ DECLARE_ACTION(A_Spectre3Attack) DEFINE_ACTION_FUNCTION(AActor, A_EntityAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // Apparent Strife bug: Case 5 was unreachable because they used % 5 instead of % 6. // I've fixed that by making case 1 duplicate it, since case 1 did nothing. @@ -75,7 +75,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityAttack) DEFINE_ACTION_FUNCTION(AActor, A_SpawnEntity) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *entity = Spawn("EntityBoss", self->PosPlusZ(70.), ALLOW_REPLACE); if (entity != NULL) @@ -90,7 +90,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnEntity) DEFINE_ACTION_FUNCTION(AActor, A_EntityDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *second; double secondRadius = GetDefaultByName("EntitySecond")->radius * 2; @@ -109,7 +109,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityDeath) second = Spawn("EntitySecond", pos, ALLOW_REPLACE); second->CopyFriendliness(self, true); A_FaceTarget(second); - second->VelFromAngle(an, velmul[i]); + second->VelFromAngle(velmul[i], an); } return 0; } diff --git a/src/g_strife/a_inquisitor.cpp b/src/g_strife/a_inquisitor.cpp index e372d8de1..a4c2d72f4 100644 --- a/src/g_strife/a_inquisitor.cpp +++ b/src/g_strife/a_inquisitor.cpp @@ -5,14 +5,14 @@ #include "p_local.h" #include "p_enemy.h" #include "s_sound.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_inq ("Inquisitor"); DEFINE_ACTION_FUNCTION(AActor, A_InquisitorWalk) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_BODY, "inquisitor/walk", 1, ATTN_NORM); A_Chase (stack, self); @@ -30,7 +30,7 @@ bool InquisitorCheckDistance (AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_InquisitorDecide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; @@ -52,7 +52,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorDecide) DEFINE_ACTION_FUNCTION(AActor, A_InquisitorAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *proj; @@ -80,7 +80,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorAttack) DEFINE_ACTION_FUNCTION(AActor, A_InquisitorJump) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double dist; double speed; @@ -102,7 +102,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorJump) DEFINE_ACTION_FUNCTION(AActor, A_InquisitorCheckLand) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->reactiontime--; if (self->reactiontime < 0 || @@ -125,7 +125,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorCheckLand) DEFINE_ACTION_FUNCTION(AActor, A_TossArm) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *foo = Spawn("InquisitorArm", self->PosPlusZ(24.), ALLOW_REPLACE); foo->Angles.Yaw = self->Angles.Yaw - 90. + pr_inq.Random2() * (360./1024.); diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp index ead116c63..0f1bef7cc 100644 --- a/src/g_strife/a_loremaster.cpp +++ b/src/g_strife/a_loremaster.cpp @@ -5,7 +5,7 @@ #include "m_random.h" #include "p_local.h" #include "s_sound.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ // Loremaster (aka Priest) -------------------------------------------------- @@ -17,7 +17,7 @@ public: int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS (ALoreShot) +IMPLEMENT_CLASS(ALoreShot, false, false, false, false) int ALoreShot::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { @@ -33,7 +33,7 @@ int ALoreShot::DoSpecialDamage (AActor *victim, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_LoremasterChain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_BODY, "loremaster/active", 1, ATTN_NORM); Spawn("LoreShot2", self->Pos(), ALLOW_REPLACE); diff --git a/src/g_strife/a_oracle.cpp b/src/g_strife/a_oracle.cpp index f1f0b0b2b..f49849922 100644 --- a/src/g_strife/a_oracle.cpp +++ b/src/g_strife/a_oracle.cpp @@ -4,13 +4,13 @@ #include "a_strifeglobal.h" #include "p_enemy.h" #include "r_defs.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ DEFINE_ACTION_FUNCTION(AActor, A_WakeOracleSpectre) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); TThinkerIterator it(NAME_AlienSpectre3); AActor *spectre = it.Next(); diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp index bed5f838b..c00e7fb01 100644 --- a/src/g_strife/a_programmer.cpp +++ b/src/g_strife/a_programmer.cpp @@ -6,7 +6,7 @@ #include "p_enemy.h" #include "s_sound.h" #include "a_strifeglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "doomstat.h" */ @@ -23,7 +23,7 @@ public: PalEntry GetBlend (); }; -IMPLEMENT_CLASS (AProgLevelEnder) +IMPLEMENT_CLASS(AProgLevelEnder, false, false, false, false) //============================================================================ // @@ -74,7 +74,7 @@ PalEntry AProgLevelEnder::GetBlend () DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerMelee) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int damage; @@ -102,7 +102,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerMelee) DEFINE_ACTION_FUNCTION(AActor, A_SpotLightning) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *spot; @@ -128,7 +128,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpotLightning) DEFINE_ACTION_FUNCTION(AActor, A_SpawnProgrammerBase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *foo = Spawn("ProgrammerBase", self->PosPlusZ(24.), ALLOW_REPLACE); if (foo != NULL) @@ -148,7 +148,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnProgrammerBase) DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!CheckBossDeath (self)) return 0; diff --git a/src/g_strife/a_reaver.cpp b/src/g_strife/a_reaver.cpp index 372aea794..9c6e9f6b9 100644 --- a/src/g_strife/a_reaver.cpp +++ b/src/g_strife/a_reaver.cpp @@ -6,14 +6,14 @@ #include "m_random.h" #include "p_local.h" #include "a_strifeglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_reaverattack ("ReaverAttack"); DEFINE_ACTION_FUNCTION(AActor, A_ReaverRanged) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target != NULL) { diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index f2031a7a3..7f21886bf 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -8,7 +8,7 @@ #include "gi.h" #include "a_sharedglobal.h" #include "a_strifeglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" */ @@ -22,7 +22,7 @@ static FRandom pr_shootgun ("ShootGun"); DEFINE_ACTION_FUNCTION(AActor, A_ShootGun) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle pitch; @@ -47,7 +47,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (ATeleporterBeacon) +IMPLEMENT_CLASS(ATeleporterBeacon, false, false, false, false) bool ATeleporterBeacon::Use (bool pickup) { @@ -74,7 +74,7 @@ bool ATeleporterBeacon::Use (bool pickup) DEFINE_ACTION_FUNCTION(AActor, A_Beacon) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *owner = self->target; AActor *rebel; diff --git a/src/g_strife/a_sentinel.cpp b/src/g_strife/a_sentinel.cpp index 91adbb01e..44946c84a 100644 --- a/src/g_strife/a_sentinel.cpp +++ b/src/g_strife/a_sentinel.cpp @@ -4,14 +4,14 @@ #include "a_action.h" #include "p_local.h" #include "m_random.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_sentinelrefire ("SentinelRefire"); DEFINE_ACTION_FUNCTION(AActor, A_SentinelBob) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double minz, maxz; @@ -43,7 +43,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelBob) DEFINE_ACTION_FUNCTION(AActor, A_SentinelAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *missile, *trail; @@ -75,7 +75,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelAttack) DEFINE_ACTION_FUNCTION(AActor, A_SentinelRefire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_FaceTarget (self); diff --git a/src/g_strife/a_spectral.cpp b/src/g_strife/a_spectral.cpp index 00b19055c..c7012accf 100644 --- a/src/g_strife/a_spectral.cpp +++ b/src/g_strife/a_spectral.cpp @@ -6,7 +6,7 @@ #include "s_sound.h" #include "m_random.h" #include "a_strifeglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ class ASpectralMonster : public AActor @@ -16,7 +16,7 @@ public: void Touch (AActor *toucher); }; -IMPLEMENT_CLASS (ASpectralMonster) +IMPLEMENT_CLASS(ASpectralMonster, false, false, false, false) void ASpectralMonster::Touch (AActor *toucher) { @@ -26,7 +26,7 @@ void ASpectralMonster::Touch (AActor *toucher) DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightningTail) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *foo = Spawn("SpectralLightningHTail", self->Vec3Offset(-self->Vel.X, -self->Vel.Y, 0.), ALLOW_REPLACE); @@ -37,7 +37,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightningTail) DEFINE_ACTION_FUNCTION(AActor, A_SpectralBigBallLightning) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PClassActor *cls = PClass::FindActor("SpectralLightningH3"); if (cls) @@ -56,7 +56,7 @@ static FRandom pr_zap5 ("Zap5"); DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightning) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *flash; @@ -90,7 +90,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightning) DEFINE_ACTION_FUNCTION(AActor, A_Tracer2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *dest; double dist; diff --git a/src/g_strife/a_stalker.cpp b/src/g_strife/a_stalker.cpp index 8ee07de8a..9189ef8de 100644 --- a/src/g_strife/a_stalker.cpp +++ b/src/g_strife/a_stalker.cpp @@ -5,7 +5,7 @@ #include "p_local.h" #include "p_enemy.h" #include "s_sound.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_stalker ("Stalker"); @@ -13,7 +13,7 @@ static FRandom pr_stalker ("Stalker"); DEFINE_ACTION_FUNCTION(AActor, A_StalkerChaseDecide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!(self->flags & MF_NOGRAVITY)) { @@ -28,7 +28,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StalkerChaseDecide) DEFINE_ACTION_FUNCTION(AActor, A_StalkerLookInit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); FState *state; if (self->flags & MF_NOGRAVITY) @@ -48,7 +48,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StalkerLookInit) DEFINE_ACTION_FUNCTION(AActor, A_StalkerDrop) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags5 &= ~MF5_NOVERTICALMELEERANGE; self->flags &= ~MF_NOGRAVITY; @@ -57,7 +57,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StalkerDrop) DEFINE_ACTION_FUNCTION(AActor, A_StalkerAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->flags & MF_NOGRAVITY) { @@ -79,7 +79,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StalkerAttack) DEFINE_ACTION_FUNCTION(AActor, A_StalkerWalk) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_BODY, "stalker/walk", 1, ATTN_NORM); A_Chase (stack, self); diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index 26ac88393..c1b9d75d6 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -13,17 +13,17 @@ #include "a_keys.h" #include "c_console.h" #include "templates.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "doomstat.h" */ // Degnin Ore --------------------------------------------------------------- -IMPLEMENT_CLASS(ADegninOre) +IMPLEMENT_CLASS(ADegninOre, false, false, false, false) DEFINE_ACTION_FUNCTION(AActor, A_RemoveForceField) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~MF_SPECIAL; @@ -75,7 +75,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS (AHealthTraining) +IMPLEMENT_CLASS(AHealthTraining, false, false, false, false) bool AHealthTraining::TryPickup (AActor *&toucher) { @@ -105,7 +105,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AScanner) +IMPLEMENT_CLASS(AScanner, false, false, false, false) bool AScanner::Use (bool pickup) { @@ -130,7 +130,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS (APrisonPass) +IMPLEMENT_CLASS(APrisonPass, false, false, false, false) bool APrisonPass::TryPickup (AActor *&toucher) { @@ -163,7 +163,7 @@ bool APrisonPass::SpecialDropAction (AActor *dropper) // actions and cannot be held. ---------------------------------------------- //--------------------------------------------------------------------------- -IMPLEMENT_CLASS (ADummyStrifeItem) +IMPLEMENT_CLASS(ADummyStrifeItem, false, false, false, false) // Sound the alarm! --------------------------------------------------------- @@ -175,7 +175,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS (ARaiseAlarm) +IMPLEMENT_CLASS(ARaiseAlarm, false, false, false, false) bool ARaiseAlarm::TryPickup (AActor *&toucher) { @@ -209,7 +209,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS (AOpenDoor222) +IMPLEMENT_CLASS(AOpenDoor222, false, false, false, false) bool AOpenDoor222::TryPickup (AActor *&toucher) { @@ -228,7 +228,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS (ACloseDoor222) +IMPLEMENT_CLASS(ACloseDoor222, false, false, false, false) bool ACloseDoor222::TryPickup (AActor *&toucher) { @@ -262,7 +262,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS (AOpenDoor224) +IMPLEMENT_CLASS(AOpenDoor224, false, false, false, false) bool AOpenDoor224::TryPickup (AActor *&toucher) { @@ -287,7 +287,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS (AAmmoFillup) +IMPLEMENT_CLASS(AAmmoFillup, false, false, false, false) bool AAmmoFillup::TryPickup (AActor *&toucher) { @@ -325,7 +325,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS (AHealthFillup) +IMPLEMENT_CLASS(AHealthFillup, false, false, false, false) bool AHealthFillup::TryPickup (AActor *&toucher) { @@ -342,7 +342,7 @@ bool AHealthFillup::TryPickup (AActor *&toucher) // Upgrade Stamina ---------------------------------------------------------- -IMPLEMENT_CLASS (AUpgradeStamina) +IMPLEMENT_CLASS(AUpgradeStamina, false, false, false, false) bool AUpgradeStamina::TryPickup (AActor *&toucher) { @@ -360,7 +360,7 @@ bool AUpgradeStamina::TryPickup (AActor *&toucher) // Upgrade Accuracy --------------------------------------------------------- -IMPLEMENT_CLASS (AUpgradeAccuracy) +IMPLEMENT_CLASS(AUpgradeAccuracy, false, false, false, false) bool AUpgradeAccuracy::TryPickup (AActor *&toucher) { @@ -373,7 +373,7 @@ bool AUpgradeAccuracy::TryPickup (AActor *&toucher) // Start a slideshow -------------------------------------------------------- -IMPLEMENT_CLASS (ASlideshowStarter) +IMPLEMENT_CLASS(ASlideshowStarter, false, false, false, false) bool ASlideshowStarter::TryPickup (AActor *&toucher) { diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index ad6bbe133..1580f127f 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -10,7 +10,7 @@ #include "p_enemy.h" #include "p_lnspec.h" #include "c_console.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" #include "gstrings.h" #include "a_keys.h" @@ -21,6 +21,7 @@ #include "serializer.h" #include "p_spec.h" #include "portal.h" +#include "vm.h" // Include all the other Strife stuff here to reduce compile time #include "a_acolyte.cpp" @@ -71,7 +72,7 @@ public: int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AForceFieldGuard) +IMPLEMENT_CLASS(AForceFieldGuard, false, false, false, false) int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) { @@ -86,7 +87,7 @@ int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int DEFINE_ACTION_FUNCTION(AActor, A_SetShadow) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags |= MF_STRIFEx8000000|MF_SHADOW; self->RenderStyle = STYLE_Translucent; @@ -96,7 +97,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetShadow) DEFINE_ACTION_FUNCTION(AActor, A_ClearShadow) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~(MF_STRIFEx8000000|MF_SHADOW); self->RenderStyle = STYLE_Normal; @@ -108,7 +109,7 @@ static FRandom pr_gethurt ("HurtMe!"); DEFINE_ACTION_FUNCTION(AActor, A_GetHurt) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags4 |= MF4_INCOMBAT; if ((pr_gethurt() % 5) == 0) @@ -127,7 +128,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GetHurt) DEFINE_ACTION_FUNCTION(AActor, A_TurretLook) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *target; @@ -159,7 +160,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_TurretLook) DEFINE_ACTION_FUNCTION(AActor, A_KlaxonBlare) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (--self->reactiontime < 0) { @@ -196,7 +197,7 @@ public: void Die (AActor *source, AActor *inflictor, int dmgflags); }; -IMPLEMENT_CLASS (APowerCoupling) +IMPLEMENT_CLASS(APowerCoupling, false, false, false, false) void APowerCoupling::Die (AActor *source, AActor *inflictor, int dmgflags) { @@ -238,7 +239,7 @@ public: } }; -IMPLEMENT_CLASS (AMeat) +IMPLEMENT_CLASS(AMeat, false, false, false, false) //========================================================================== // @@ -248,7 +249,7 @@ IMPLEMENT_CLASS (AMeat) DEFINE_ACTION_FUNCTION(AActor, A_TossGib) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); const char *gibtype = (self->flags & MF_NOBLOOD) ? "Junk" : "Meat"; AActor *gib = Spawn (gibtype, self->PosPlusZ(24.), ALLOW_REPLACE); @@ -268,7 +269,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_TossGib) DEFINE_ACTION_FUNCTION(AActor, A_FLoopActiveSound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->ActiveSound != 0 && !(level.time & 7)) { @@ -279,7 +280,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FLoopActiveSound) DEFINE_ACTION_FUNCTION(AActor, A_Countdown) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (--self->reactiontime <= 0) { @@ -291,7 +292,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Countdown) DEFINE_ACTION_FUNCTION(AActor, A_LoopActiveSound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->ActiveSound != 0 && !S_IsActorPlayingSomething (self, CHAN_VOICE, -1)) { @@ -302,7 +303,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LoopActiveSound) DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); sector_t *sec = self->Sector; @@ -331,7 +332,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain) DEFINE_ACTION_FUNCTION(AActor, A_ClearSoundTarget) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *actor; @@ -346,7 +347,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ClearSoundTarget) DEFINE_ACTION_FUNCTION(AActor, A_ItBurnsItBurns) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_VOICE, "human/imonfire", 1, ATTN_NORM); @@ -364,7 +365,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ItBurnsItBurns) DEFINE_ACTION_FUNCTION(AActor, A_DropFire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *drop = Spawn("FireDroplet", self->PosPlusZ(24.), ALLOW_REPLACE); drop->Vel.Z = -1.; @@ -374,7 +375,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DropFire) DEFINE_ACTION_FUNCTION(AActor, A_CrispyPlayer) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player != nullptr && self->player->mo == self) { @@ -400,7 +401,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrispyPlayer) DEFINE_ACTION_FUNCTION(AActor, A_HandLower) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player != nullptr) { diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index be3c3bf2b..be8452046 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -6,7 +6,7 @@ #include "s_sound.h" #include "p_enemy.h" #include "templates.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "doomstat.h" */ @@ -94,7 +94,7 @@ void P_DaggerAlert (AActor *target, AActor *emitter) DEFINE_ACTION_FUNCTION(AActor, A_JabDagger) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -146,9 +146,9 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_AlertMonsters) { - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(maxdist) { maxdist = 0; } - PARAM_INT_OPT(Flags) { Flags = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF(maxdist); + PARAM_INT_DEF(Flags); AActor * target = NULL; AActor * emitter = self; @@ -184,7 +184,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (APoisonBolt) +IMPLEMENT_CLASS(APoisonBolt, false, false, false, false) int APoisonBolt::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -212,7 +212,7 @@ int APoisonBolt::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_ClearFlash) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; @@ -231,7 +231,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ClearFlash) DEFINE_ACTION_FUNCTION(AActor, A_ShowElectricFlash) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player != nullptr) { @@ -248,7 +248,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShowElectricFlash) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireArrow) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS(ti, AActor); DAngle savedangle; @@ -307,7 +307,7 @@ void P_StrifeGunShot (AActor *mo, bool accurate, DAngle pitch) DEFINE_ACTION_FUNCTION(AActor, A_FireAssaultGun) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); bool accurate; @@ -343,7 +343,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireAssaultGun) DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; DAngle savedangle; @@ -374,7 +374,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile) DEFINE_ACTION_FUNCTION(AActor, A_RocketInFlight) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *trail; @@ -398,7 +398,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RocketInFlight) DEFINE_ACTION_FUNCTION(AActor, A_FlameDie) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags |= MF_NOGRAVITY; self->Vel.Z = pr_flamedie() & 3; @@ -413,7 +413,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlameDie) DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; @@ -450,7 +450,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer) DEFINE_ACTION_FUNCTION(AActor, A_FireMauler1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -494,7 +494,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMauler1) DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2Pre) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); S_Sound (self, CHAN_WEAPON, "weapons/mauler2charge", 1, ATTN_NORM); @@ -516,7 +516,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2Pre) DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -544,7 +544,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2) DEFINE_ACTION_FUNCTION(AActor, A_MaulerTorpedoWave) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *wavedef = GetDefaultByName("MaulerTorpedoWave"); double savedz; @@ -607,7 +607,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (APhosphorousFire) +IMPLEMENT_CLASS(APhosphorousFire, false, false, false, false) int APhosphorousFire::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -620,7 +620,7 @@ int APhosphorousFire::DoSpecialDamage (AActor *target, int damage, FName damaget DEFINE_ACTION_FUNCTION(AActor, A_BurnArea) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); P_RadiusAttack (self, self->target, 128, 128, self->DamageType, RADF_HURTSOURCE); return 0; @@ -628,7 +628,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BurnArea) DEFINE_ACTION_FUNCTION(AActor, A_Burnination) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Vel.Z -= 8; self->Vel.X += (pr_phburn.Random2 (3)); @@ -688,7 +688,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burnination) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS(grenadetype, AActor); PARAM_ANGLE(angleofs); PARAM_STATE(flash) @@ -734,7 +734,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade) // The Almighty Sigil! ------------------------------------------------------ -IMPLEMENT_CLASS(ASigil) +IMPLEMENT_CLASS(ASigil, false, false, false, false) //============================================================================ // @@ -821,7 +821,7 @@ AInventory *ASigil::CreateCopy (AActor *other) DEFINE_ACTION_FUNCTION(AActor, A_SelectPiece) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); int pieces = MIN (static_cast(self)->NumPieces, 5); @@ -847,7 +847,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectPiece) DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilView) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DPSprite *pspr; int pieces; @@ -874,7 +874,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilView) DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilDown) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DPSprite *pspr; int pieces; @@ -904,7 +904,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilDown) DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); DPSprite *pspr; int pieces; @@ -927,7 +927,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilAttack) DEFINE_ACTION_FUNCTION(AActor, A_SigilCharge) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); if (self->player != NULL) @@ -945,7 +945,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SigilCharge) DEFINE_ACTION_FUNCTION(AActor, A_LightInverse) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -962,7 +962,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightInverse) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *spot; player_t *player = self->player; @@ -988,7 +988,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1) spot = Spawn("SpectralLightningSpot", self->Pos(), ALLOW_REPLACE); if (spot != NULL) { - spot->VelFromAngle(self->Angles.Yaw, 28.); + spot->VelFromAngle(28., self->Angles.Yaw); } } if (spot != NULL) @@ -1007,7 +1007,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil2) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; @@ -1029,7 +1029,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil2) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil3) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *spot; player_t *player = self->player; @@ -1063,7 +1063,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil3) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); AActor *spot; player_t *player = self->player; @@ -1089,7 +1089,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4) spot = P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningBigV1")); if (spot != NULL) { - spot->VelFromAngle(self->Angles.Yaw, spot->Speed); + spot->VelFromAngle(spot->Speed, self->Angles.Yaw); } } return 0; @@ -1103,7 +1103,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil5) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; diff --git a/src/g_strife/a_templar.cpp b/src/g_strife/a_templar.cpp index 547d4d73e..0bfa00b24 100644 --- a/src/g_strife/a_templar.cpp +++ b/src/g_strife/a_templar.cpp @@ -6,14 +6,14 @@ #include "p_enemy.h" #include "s_sound.h" #include "a_strifeglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_templar ("Templar"); DEFINE_ACTION_FUNCTION(AActor, A_TemplarAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int damage; DAngle angle; diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp index fed1c4337..5e1bc42d2 100644 --- a/src/g_strife/a_thingstoblowup.cpp +++ b/src/g_strife/a_thingstoblowup.cpp @@ -6,8 +6,8 @@ #include "p_enemy.h" #include "a_action.h" #include "gstrings.h" -#include "thingdef/thingdef.h" -#include "thingdef/thingdef.h" +#include "vm.h" +#include "vm.h" #include "doomstat.h" */ @@ -16,7 +16,7 @@ static FRandom pr_lightout ("LightOut"); DEFINE_ACTION_FUNCTION(AActor, A_Bang4Cloud) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double xo = (pr_bang4cloud.Random2() & 3) * (10. / 64); double yo = (pr_bang4cloud.Random2() & 3) * (10. / 64); @@ -63,7 +63,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveQuestItem) DEFINE_ACTION_FUNCTION(AActor, A_ExtraLightOff) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target != NULL && self->target->player != NULL) { @@ -74,7 +74,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ExtraLightOff) DEFINE_ACTION_FUNCTION(AActor, A_Explode512) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); P_RadiusAttack (self, self->target, 512, 512, NAME_None, RADF_HURTSOURCE); if (self->target != NULL && self->target->player != NULL) @@ -90,7 +90,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode512) DEFINE_ACTION_FUNCTION(AActor, A_LightGoesOut) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *foo; sector_t *sec = self->Sector; diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index bcdf624d7..73e31e676 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -17,6 +17,7 @@ #include "g_level.h" #include "colormatcher.h" #include "v_palette.h" +#include "cmdlib.h" // Number of tics to move the popscreen up and down. #define POP_TIME (TICRATE/8) @@ -850,7 +851,7 @@ private: double ItemFlash; }; -IMPLEMENT_CLASS(DStrifeStatusBar); +IMPLEMENT_CLASS(DStrifeStatusBar, false, false, false, false); DBaseStatusBar *CreateStrifeStatusBar () { diff --git a/src/info.cpp b/src/info.cpp index 79c8e4268..e771108c3 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -52,8 +52,10 @@ #include "cmdlib.h" #include "g_level.h" #include "stats.h" -#include "thingdef/thingdef.h" +#include "vm.h" +#include "thingdef.h" #include "d_player.h" +#include "doomerrors.h" extern void LoadActors (); extern void InitBotStuff(); @@ -66,7 +68,7 @@ cycle_t ActionCycles; void FState::SetAction(const char *name) { - ActionFunc = FindGlobalActionFunction(name)->Variants[0].Implementation; + ActionFunc = FindVMFunction(RUNTIME_CLASS(AActor), name); } bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret) @@ -75,8 +77,8 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, { ActionCycles.Clock(); - static VMFrameStack stack; - VMValue params[3] = { self, stateowner, VMValue(info, ATAG_STATEINFO) }; + VMFrameStack stack; + VMValue params[3] = { self, stateowner, VMValue(info, ATAG_GENERIC) }; // 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. @@ -92,13 +94,13 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, } if (stateret == NULL) { - stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL); + stack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL); } else { VMReturn ret; ret.PointerAt((void **)stateret); - stack.Call(ActionFunc, params, countof(params), &ret, 1, NULL); + stack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL); } ActionCycles.Unclock(); return true; @@ -151,9 +153,11 @@ int GetSpriteIndex(const char * spritename, bool add) return (lastindex = (int)sprites.Push (temp)); } -IMPLEMENT_POINTY_CLASS(PClassActor) - DECLARE_POINTER(DropItems) -END_POINTERS +IMPLEMENT_CLASS(PClassActor, false, true, false, false) + +IMPLEMENT_POINTERS_START(PClassActor) + IMPLEMENT_POINTER(DropItems) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -281,6 +285,7 @@ void PClassActor::DeriveData(PClass *newclass) assert(newclass->IsKindOf(RUNTIME_CLASS(PClassActor))); PClassActor *newa = static_cast(newclass); + newa->DefaultStateUsage = DefaultStateUsage; newa->Obituary = Obituary; newa->HitObituary = HitObituary; newa->DeathHeight = DeathHeight; @@ -353,32 +358,71 @@ size_t PClassActor::PropagateMark() //========================================================================== // -// PClassActor :: InitializeNativeDefaults +// PClassActor :: SetReplacement // -// This is used by DECORATE to assign ActorInfos to internal classes +// Sets as a replacement class for another class. // //========================================================================== -void PClassActor::InitializeNativeDefaults() +bool PClassActor::SetReplacement(FName replaceName) { - Symbols.SetParentTable(&ParentClass->Symbols); - assert(Defaults == NULL); - Defaults = (BYTE *)M_Malloc(Size); - if (ParentClass->Defaults != NULL) + // Check for "replaces" + if (replaceName != NAME_None) { - memcpy(Defaults, ParentClass->Defaults, ParentClass->Size); - if (Size > ParentClass->Size) + // Get actor name + PClassActor *replacee = PClass::FindActor(replaceName); + + if (replacee == nullptr) { - memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size); + return false; + } + if (replacee != nullptr) + { + replacee->Replacement = this; + Replacee = replacee; } } - else + return true; +} + +//========================================================================== +// +// PClassActor :: SetDropItems +// +// Sets a new drop item list +// +//========================================================================== + +void PClassActor::SetDropItems(DDropItem *drops) +{ + DropItems = drops; + GC::WriteBarrier(this, DropItems); +} + + +//========================================================================== +// +// PClassActor :: Finalize +// +// Installs the parsed states and does some sanity checking +// +//========================================================================== + +void PClassActor::Finalize(FStateDefinitions &statedef) +{ + AActor *defaults = (AActor*)Defaults; + + try { - memset (Defaults, 0, Size); - // Non-DECORATE properties that must be set. - ((AActor*)Defaults)->DamageMultiply = 1.; // fixme: Make this a DECORATE property. - ((AActor*)Defaults)->ConversationRoot = -1; + statedef.FinishStates(this, defaults); } + catch (CRecoverableError &) + { + statedef.MakeStateDefines(NULL); + throw; + } + statedef.InstallStates(this, defaults); + statedef.MakeStateDefines(NULL); } //========================================================================== @@ -747,3 +791,43 @@ int DamageTypeDefinition::ApplyMobjDamageFactor(int damage, FName type, DmgFacto double factor = GetMobjDamageFactor(type, factors); return int(damage * factor); } + +//========================================================================== +// +// Reads a damage definition +// +//========================================================================== + +void FMapInfoParser::ParseDamageDefinition() +{ + sc.MustGetString(); + FName damageType = sc.String; + + DamageTypeDefinition dtd; + + ParseOpenBrace(); + while (sc.MustGetAnyToken(), sc.TokenType != '}') + { + if (sc.Compare("FACTOR")) + { + sc.MustGetStringName("="); + sc.MustGetFloat(); + dtd.DefaultFactor = sc.Float; + if (dtd.DefaultFactor == 0) dtd.ReplaceFactor = true; + } + else if (sc.Compare("REPLACEFACTOR")) + { + dtd.ReplaceFactor = true; + } + else if (sc.Compare("NOARMOR")) + { + dtd.NoArmor = true; + } + else + { + sc.ScriptError("Unexpected data (%s) in damagetype definition.", sc.String); + } + } + + dtd.Apply(damageType); +} diff --git a/src/info.h b/src/info.h index 0e49e1f8f..0b7d4dfc3 100644 --- a/src/info.h +++ b/src/info.h @@ -53,8 +53,29 @@ struct Baggage; class FScanner; struct FActorInfo; class FIntCVar; +class FStateDefinitions; -enum EStateType +enum EStateDefineFlags +{ + SDF_NEXT = 0, + SDF_STATE = 1, + SDF_STOP = 2, + SDF_WAIT = 3, + SDF_LABEL = 4, + SDF_INDEX = 5, + SDF_MASK = 7, + SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump +}; + +enum EStateUseFlags +{ + SUF_ACTOR = 1, + SUF_OVERLAY = 2, + SUF_WEAPON = 4, + SUF_ITEM = 8, +}; + +enum EStateType : int // this must ensure proper alignment. { STATE_Actor, STATE_Psprite, @@ -84,11 +105,12 @@ struct FState WORD sprite; SWORD Tics; WORD TicRange; + short Light; BYTE Frame; + BYTE UseFlags; BYTE DefineFlags; // Unused byte so let's use it during state creation. int Misc1; // Was changed to SBYTE, reverted to long for MBF compat int Misc2; // Was changed to BYTE, reverted to long for MBF compat - short Light; BYTE Fullbright:1; // State is fullbright BYTE SameFrame:1; // Ignore Frame (except when spawning actor) BYTE Fast:1; @@ -140,6 +162,10 @@ struct FState { Frame = frame - 'A'; } + inline bool CheckUse(int usetype) + { + return !!(UseFlags & usetype); + } void SetAction(VMFunction *func) { ActionFunc = func; } void ClearAction() { ActionFunc = NULL; } void SetAction(const char *name); @@ -221,7 +247,9 @@ public: void SetDamageFactor(FName type, double factor); void SetPainChance(FName type, int chance); size_t PropagateMark(); - void InitializeNativeDefaults(); + bool SetReplacement(FName replaceName); + void SetDropItems(DDropItem *drops); + virtual void Finalize(FStateDefinitions &statedef); FState *FindState(int numnames, FName *names, bool exact=false) const; FState *FindStateByString(const char *name, bool exact=false); @@ -243,6 +271,7 @@ public: PClassActor *Replacee; int NumOwnedStates; BYTE GameFilter; + uint8_t DefaultStateUsage; // state flag defaults for blocks without a qualifier. WORD SpawnID; WORD ConversationID; SWORD DoomEdNum; @@ -298,6 +327,44 @@ struct FDoomEdEntry int Args[5]; }; +struct FStateLabelStorage +{ + TArray Storage; + + int AddPointer(FState *ptr) + { + if (ptr != nullptr) + { + int pos = Storage.Reserve(sizeof(ptr) + sizeof(int)); + memset(&Storage[pos], 0, sizeof(int)); + memcpy(&Storage[pos + sizeof(int)], &ptr, sizeof(ptr)); + return pos / 4 + 1; + } + else return 0; + } + + int AddNames(TArray &names) + { + int siz = names.Size(); + if (siz > 1) + { + int pos = Storage.Reserve(sizeof(int) + sizeof(FName) * names.Size()); + memcpy(&Storage[pos], &siz, sizeof(int)); + memcpy(&Storage[pos + sizeof(int)], &names[0], sizeof(FName) * names.Size()); + return pos / 4 + 1; + } + else + { + // don't store single name states in the array. + return names[0].GetIndex() + 0x10000000; + } + } + + FState *GetState(int pos, PClassActor *cls); +}; + +extern FStateLabelStorage StateLabels; + enum ESpecialMapthings { SMT_Player1Start = 1, @@ -340,23 +407,4 @@ int GetSpriteIndex(const char * spritename, bool add = true); TArray &MakeStateNameList(const char * fname); void AddStateLight(FState *state, const char *lname); -// Standard parameters for all action functons -// self - Actor this action is to operate on (player if a weapon) -// stateowner - Actor this action really belongs to (may be an item) -// callingstate - State this action was called from -#define PARAM_ACTION_PROLOGUE_TYPE(type) \ - PARAM_PROLOGUE; \ - PARAM_OBJECT (self, type); \ - PARAM_OBJECT_OPT (stateowner, AActor) { stateowner = self; } \ - PARAM_STATEINFO_OPT (stateinfo) { stateinfo = nullptr; } \ - -#define PARAM_ACTION_PROLOGUE PARAM_ACTION_PROLOGUE_TYPE(AActor) - -// Number of action paramaters -#define NAP 3 - -#define PARAM_SELF_PROLOGUE(type) \ - PARAM_PROLOGUE; \ - PARAM_OBJECT(self, type); - #endif // __INFO_H__ diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index ba4566e9d..be8f58e19 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -54,14 +54,16 @@ FIntermissionDescriptorList IntermissionDescriptors; -IMPLEMENT_CLASS(DIntermissionScreen) -IMPLEMENT_CLASS(DIntermissionScreenFader) -IMPLEMENT_CLASS(DIntermissionScreenText) -IMPLEMENT_CLASS(DIntermissionScreenCast) -IMPLEMENT_CLASS(DIntermissionScreenScroller) -IMPLEMENT_POINTY_CLASS(DIntermissionController) - DECLARE_POINTER(mScreen) -END_POINTERS +IMPLEMENT_CLASS(DIntermissionScreen, false, false, false, false) +IMPLEMENT_CLASS(DIntermissionScreenFader, false, false, false, false) +IMPLEMENT_CLASS(DIntermissionScreenText, false, false, false, false) +IMPLEMENT_CLASS(DIntermissionScreenCast, false, false, false, false) +IMPLEMENT_CLASS(DIntermissionScreenScroller, false, false, false, false) +IMPLEMENT_CLASS(DIntermissionController, false, true, false, false) + +IMPLEMENT_POINTERS_START(DIntermissionController) + IMPLEMENT_POINTER(mScreen) +IMPLEMENT_POINTERS_END extern int NoWipe; diff --git a/src/m_argv.cpp b/src/m_argv.cpp index 5d4aa97a3..7d82ed834 100644 --- a/src/m_argv.cpp +++ b/src/m_argv.cpp @@ -37,7 +37,7 @@ #include "cmdlib.h" #include "i_system.h" -IMPLEMENT_CLASS (DArgs) +IMPLEMENT_CLASS(DArgs, false, false, false, false) //=========================================================================== // diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 7c110a52c..c53192ee7 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -1033,9 +1033,11 @@ public: } }; -IMPLEMENT_POINTY_CLASS(DSuicider) - DECLARE_POINTER(Pawn) -END_POINTERS +IMPLEMENT_CLASS(DSuicider, false, true, false, false) + +IMPLEMENT_POINTERS_START(DSuicider) + IMPLEMENT_POINTER(Pawn) +IMPLEMENT_POINTERS_END void cht_Suicide (player_t *plyr) { diff --git a/src/math/cmath.h b/src/math/cmath.h index 9fd0b570d..5c02c4e87 100644 --- a/src/math/cmath.h +++ b/src/math/cmath.h @@ -23,6 +23,7 @@ double c_tanh(double); double c_exp(double); double c_log(double); double c_log10(double); +double c_pow(double, double); } @@ -114,6 +115,7 @@ inline double cosdeg(double v) #define g_exp exp #define g_log log #define g_log10 log10 +#define g_pow pow #else #define g_asin c_asin #define g_acos c_acos @@ -139,6 +141,7 @@ inline double cosdeg(double v) #define g_exp c_exp #define g_log c_log #define g_log10 c_log10 +#define g_pow c_pow #endif diff --git a/src/math/pow.c b/src/math/pow.c new file mode 100644 index 000000000..c55fa81fd --- /dev/null +++ b/src/math/pow.c @@ -0,0 +1,756 @@ +/* pow.c + * + * Power function + * + * + * + * SYNOPSIS: + * + * double x, y, z, pow(); + * + * z = pow( x, y ); + * + * + * + * DESCRIPTION: + * + * Computes x raised to the yth power. Analytically, + * + * x**y = exp( y log(x) ). + * + * Following Cody and Waite, this program uses a lookup table + * of 2**-i/16 and pseudo extended precision arithmetic to + * obtain an extra three bits of accuracy in both the logarithm + * and the exponential. + * + * + * + * ACCURACY: + * + * Relative error: + * arithmetic domain # trials peak rms + * IEEE -26,26 30000 4.2e-16 7.7e-17 + * DEC -26,26 60000 4.8e-17 9.1e-18 + * 1/26 < x < 26, with log(x) uniformly distributed. + * -26 < y < 26, y uniformly distributed. + * IEEE 0,8700 30000 1.5e-14 2.1e-15 + * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed. + * + * + * ERROR MESSAGES: + * + * message condition value returned + * pow overflow x**y > MAXNUM INFINITY + * pow underflow x**y < 1/MAXNUM 0.0 + * pow domain x<0 and y noninteger 0.0 + * + */ + +/* +Cephes Math Library Release 2.8: June, 2000 +Copyright 1984, 1995, 2000 by Stephen L. Moshier +*/ + + +#include "mconf.h" +static char fname[] = {"pow"}; + +#define SQRTH 0.70710678118654752440 + +#ifdef UNK +static double P[] = { + 4.97778295871696322025E-1, + 3.73336776063286838734E0, + 7.69994162726912503298E0, + 4.66651806774358464979E0 +}; +static double Q[] = { +/* 1.00000000000000000000E0, */ + 9.33340916416696166113E0, + 2.79999886606328401649E1, + 3.35994905342304405431E1, + 1.39995542032307539578E1 +}; +/* 2^(-i/16), IEEE precision */ +static double A[] = { + 1.00000000000000000000E0, + 9.57603280698573700036E-1, + 9.17004043204671215328E-1, + 8.78126080186649726755E-1, + 8.40896415253714502036E-1, + 8.05245165974627141736E-1, + 7.71105412703970372057E-1, + 7.38413072969749673113E-1, + 7.07106781186547572737E-1, + 6.77127773468446325644E-1, + 6.48419777325504820276E-1, + 6.20928906036742001007E-1, + 5.94603557501360513449E-1, + 5.69394317378345782288E-1, + 5.45253866332628844837E-1, + 5.22136891213706877402E-1, + 5.00000000000000000000E-1 +}; +static double B[] = { + 0.00000000000000000000E0, + 1.64155361212281360176E-17, + 4.09950501029074826006E-17, + 3.97491740484881042808E-17, +-4.83364665672645672553E-17, + 1.26912513974441574796E-17, + 1.99100761573282305549E-17, +-1.52339103990623557348E-17, + 0.00000000000000000000E0 +}; +static double R[] = { + 1.49664108433729301083E-5, + 1.54010762792771901396E-4, + 1.33335476964097721140E-3, + 9.61812908476554225149E-3, + 5.55041086645832347466E-2, + 2.40226506959099779976E-1, + 6.93147180559945308821E-1 +}; + +#define douba(k) A[k] +#define doubb(k) B[k] +#define MEXP 16383.0 +#ifdef DENORMAL +#define MNEXP -17183.0 +#else +#define MNEXP -16383.0 +#endif +#endif + +#ifdef DEC +static unsigned short P[] = { +0037776,0156313,0175332,0163602, +0040556,0167577,0052366,0174245, +0040766,0062753,0175707,0055564, +0040625,0052035,0131344,0155636, +}; +static unsigned short Q[] = { +/*0040200,0000000,0000000,0000000,*/ +0041025,0052644,0154404,0105155, +0041337,0177772,0007016,0047646, +0041406,0062740,0154273,0020020, +0041137,0177054,0106127,0044555, +}; +static unsigned short A[] = { +0040200,0000000,0000000,0000000, +0040165,0022575,0012444,0103314, +0040152,0140306,0163735,0022071, +0040140,0146336,0166052,0112341, +0040127,0042374,0145326,0116553, +0040116,0022214,0012437,0102201, +0040105,0063452,0010525,0003333, +0040075,0004243,0117530,0006067, +0040065,0002363,0031771,0157145, +0040055,0054076,0165102,0120513, +0040045,0177326,0124661,0050471, +0040036,0172462,0060221,0120422, +0040030,0033760,0050615,0134251, +0040021,0141723,0071653,0010703, +0040013,0112701,0161752,0105727, +0040005,0125303,0063714,0044173, +0040000,0000000,0000000,0000000 +}; +static unsigned short B[] = { +0000000,0000000,0000000,0000000, +0021473,0040265,0153315,0140671, +0121074,0062627,0042146,0176454, +0121413,0003524,0136332,0066212, +0121767,0046404,0166231,0012553, +0121257,0015024,0002357,0043574, +0021736,0106532,0043060,0056206, +0121310,0020334,0165705,0035326, +0000000,0000000,0000000,0000000 +}; + +static unsigned short R[] = { +0034173,0014076,0137624,0115771, +0035041,0076763,0003744,0111311, +0035656,0141766,0041127,0074351, +0036435,0112533,0073611,0116664, +0037143,0054106,0134040,0152223, +0037565,0176757,0176026,0025551, +0040061,0071027,0173721,0147572 +}; + +/* +static double R[] = { +0.14928852680595608186e-4, +0.15400290440989764601e-3, +0.13333541313585784703e-2, +0.96181290595172416964e-2, +0.55504108664085595326e-1, +0.24022650695909537056e0, +0.69314718055994529629e0 +}; +*/ +#define douba(k) (*(double *)&A[(k)<<2]) +#define doubb(k) (*(double *)&B[(k)<<2]) +#define MEXP 2031.0 +#define MNEXP -2031.0 +#endif + +#ifdef IBMPC +static unsigned short P[] = { +0x5cf0,0x7f5b,0xdb99,0x3fdf, +0xdf15,0xea9e,0xddef,0x400d, +0xeb6f,0x7f78,0xccbd,0x401e, +0x9b74,0xb65c,0xaa83,0x4012, +}; +static unsigned short Q[] = { +/*0x0000,0x0000,0x0000,0x3ff0,*/ +0x914e,0x9b20,0xaab4,0x4022, +0xc9f5,0x41c1,0xffff,0x403b, +0x6402,0x1b17,0xccbc,0x4040, +0xe92e,0x918a,0xffc5,0x402b, +}; +static unsigned short A[] = { +0x0000,0x0000,0x0000,0x3ff0, +0x90da,0xa2a4,0xa4af,0x3fee, +0xa487,0xdcfb,0x5818,0x3fed, +0x529c,0xdd85,0x199b,0x3fec, +0xd3ad,0x995a,0xe89f,0x3fea, +0xf090,0x82a3,0xc491,0x3fe9, +0xa0db,0x422a,0xace5,0x3fe8, +0x0187,0x73eb,0xa114,0x3fe7, +0x3bcd,0x667f,0xa09e,0x3fe6, +0x5429,0xdd48,0xab07,0x3fe5, +0x2a27,0xd536,0xbfda,0x3fe4, +0x3422,0x4c12,0xdea6,0x3fe3, +0xb715,0x0a31,0x06fe,0x3fe3, +0x6238,0x6e75,0x387a,0x3fe2, +0x517b,0x3c7d,0x72b8,0x3fe1, +0x890f,0x6cf9,0xb558,0x3fe0, +0x0000,0x0000,0x0000,0x3fe0 +}; +static unsigned short B[] = { +0x0000,0x0000,0x0000,0x0000, +0x3707,0xd75b,0xed02,0x3c72, +0xcc81,0x345d,0xa1cd,0x3c87, +0x4b27,0x5686,0xe9f1,0x3c86, +0x6456,0x13b2,0xdd34,0xbc8b, +0x42e2,0xafec,0x4397,0x3c6d, +0x82e4,0xd231,0xf46a,0x3c76, +0x8a76,0xb9d7,0x9041,0xbc71, +0x0000,0x0000,0x0000,0x0000 +}; +static unsigned short R[] = { +0x937f,0xd7f2,0x6307,0x3eef, +0x9259,0x60fc,0x2fbe,0x3f24, +0xef1d,0xc84a,0xd87e,0x3f55, +0x33b7,0x6ef1,0xb2ab,0x3f83, +0x1a92,0xd704,0x6b08,0x3fac, +0xc56d,0xff82,0xbfbd,0x3fce, +0x39ef,0xfefa,0x2e42,0x3fe6 +}; + +#define douba(k) (*(double *)&A[(k)<<2]) +#define doubb(k) (*(double *)&B[(k)<<2]) +#define MEXP 16383.0 +#ifdef DENORMAL +#define MNEXP -17183.0 +#else +#define MNEXP -16383.0 +#endif +#endif + +#ifdef MIEEE +static unsigned short P[] = { +0x3fdf,0xdb99,0x7f5b,0x5cf0, +0x400d,0xddef,0xea9e,0xdf15, +0x401e,0xccbd,0x7f78,0xeb6f, +0x4012,0xaa83,0xb65c,0x9b74 +}; +static unsigned short Q[] = { +0x4022,0xaab4,0x9b20,0x914e, +0x403b,0xffff,0x41c1,0xc9f5, +0x4040,0xccbc,0x1b17,0x6402, +0x402b,0xffc5,0x918a,0xe92e +}; +static unsigned short A[] = { +0x3ff0,0x0000,0x0000,0x0000, +0x3fee,0xa4af,0xa2a4,0x90da, +0x3fed,0x5818,0xdcfb,0xa487, +0x3fec,0x199b,0xdd85,0x529c, +0x3fea,0xe89f,0x995a,0xd3ad, +0x3fe9,0xc491,0x82a3,0xf090, +0x3fe8,0xace5,0x422a,0xa0db, +0x3fe7,0xa114,0x73eb,0x0187, +0x3fe6,0xa09e,0x667f,0x3bcd, +0x3fe5,0xab07,0xdd48,0x5429, +0x3fe4,0xbfda,0xd536,0x2a27, +0x3fe3,0xdea6,0x4c12,0x3422, +0x3fe3,0x06fe,0x0a31,0xb715, +0x3fe2,0x387a,0x6e75,0x6238, +0x3fe1,0x72b8,0x3c7d,0x517b, +0x3fe0,0xb558,0x6cf9,0x890f, +0x3fe0,0x0000,0x0000,0x0000 +}; +static unsigned short B[] = { +0x0000,0x0000,0x0000,0x0000, +0x3c72,0xed02,0xd75b,0x3707, +0x3c87,0xa1cd,0x345d,0xcc81, +0x3c86,0xe9f1,0x5686,0x4b27, +0xbc8b,0xdd34,0x13b2,0x6456, +0x3c6d,0x4397,0xafec,0x42e2, +0x3c76,0xf46a,0xd231,0x82e4, +0xbc71,0x9041,0xb9d7,0x8a76, +0x0000,0x0000,0x0000,0x0000 +}; +static unsigned short R[] = { +0x3eef,0x6307,0xd7f2,0x937f, +0x3f24,0x2fbe,0x60fc,0x9259, +0x3f55,0xd87e,0xc84a,0xef1d, +0x3f83,0xb2ab,0x6ef1,0x33b7, +0x3fac,0x6b08,0xd704,0x1a92, +0x3fce,0xbfbd,0xff82,0xc56d, +0x3fe6,0x2e42,0xfefa,0x39ef +}; + +#define douba(k) (*(double *)&A[(k)<<2]) +#define doubb(k) (*(double *)&B[(k)<<2]) +#define MEXP 16383.0 +#ifdef DENORMAL +#define MNEXP -17183.0 +#else +#define MNEXP -16383.0 +#endif +#endif + +/* log2(e) - 1 */ +#define LOG2EA 0.44269504088896340736 + +#define F W +#define Fa Wa +#define Fb Wb +#define G W +#define Ga Wa +#define Gb u +#define H W +#define Ha Wb +#define Hb Wb + +#ifdef ANSIPROT +extern double floor ( double ); +extern double fabs ( double ); +extern double frexp ( double, int * ); +extern double ldexp ( double, int ); +extern double polevl ( double, void *, int ); +extern double p1evl ( double, void *, int ); +extern double c_powi ( double, int ); +extern int signbit ( double ); +extern int isnan ( double ); +extern int isfinite ( double ); +static double reduc ( double ); +#else +double floor(), fabs(), frexp(), ldexp(); +double polevl(), p1evl(), c_powi(); +int signbit(), isnan(), isfinite(); +static double reduc(); +#endif +extern double MAXNUM; +#ifdef INFINITIES +extern double INFINITY; +#endif +#ifdef NANS +extern double NAN; +#endif +#ifdef MINUSZERO +extern double NEGZERO; +#endif + +double c_pow( x, y ) +double x, y; +{ +double w, z, W, Wa, Wb, ya, yb, u; +/* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */ +double aw, ay, wy; +int e, i, nflg, iyflg, yoddint; + +if( y == 0.0 ) + return( 1.0 ); +#ifdef NANS +if( isnan(x) ) + return( x ); +if( isnan(y) ) + return( y ); +#endif +if( y == 1.0 ) + return( x ); + + +#ifdef INFINITIES +if( !isfinite(y) && (x == 1.0 || x == -1.0) ) + { + mtherr( "pow", DOMAIN ); +#ifdef NANS + return( NAN ); +#else + return( INFINITY ); +#endif + } +#endif + +if( x == 1.0 ) + return( 1.0 ); + +if( y >= MAXNUM ) + { +#ifdef INFINITIES + if( x > 1.0 ) + return( INFINITY ); +#else + if( x > 1.0 ) + return( MAXNUM ); +#endif + if( x > 0.0 && x < 1.0 ) + return( 0.0); + if( x < -1.0 ) + { +#ifdef INFINITIES + return( INFINITY ); +#else + return( MAXNUM ); +#endif + } + if( x > -1.0 && x < 0.0 ) + return( 0.0 ); + } +if( y <= -MAXNUM ) + { + if( x > 1.0 ) + return( 0.0 ); +#ifdef INFINITIES + if( x > 0.0 && x < 1.0 ) + return( INFINITY ); +#else + if( x > 0.0 && x < 1.0 ) + return( MAXNUM ); +#endif + if( x < -1.0 ) + return( 0.0 ); +#ifdef INFINITIES + if( x > -1.0 && x < 0.0 ) + return( INFINITY ); +#else + if( x > -1.0 && x < 0.0 ) + return( MAXNUM ); +#endif + } +if( x >= MAXNUM ) + { +#if INFINITIES + if( y > 0.0 ) + return( INFINITY ); +#else + if( y > 0.0 ) + return( MAXNUM ); +#endif + return(0.0); + } +/* Set iyflg to 1 if y is an integer. */ +iyflg = 0; +w = floor(y); +if( w == y ) + iyflg = 1; + +/* Test for odd integer y. */ +yoddint = 0; +if( iyflg ) + { + ya = fabs(y); + ya = floor(0.5 * ya); + yb = 0.5 * fabs(w); + if( ya != yb ) + yoddint = 1; + } + +if( x <= -MAXNUM ) + { + if( y > 0.0 ) + { +#ifdef INFINITIES + if( yoddint ) + return( -INFINITY ); + return( INFINITY ); +#else + if( yoddint ) + return( -MAXNUM ); + return( MAXNUM ); +#endif + } + if( y < 0.0 ) + { +#ifdef MINUSZERO + if( yoddint ) + return( NEGZERO ); +#endif + return( 0.0 ); + } + } + +nflg = 0; /* flag = 1 if x<0 raised to integer power */ +if( x <= 0.0 ) + { + if( x == 0.0 ) + { + if( y < 0.0 ) + { +#ifdef MINUSZERO + if( signbit(x) && yoddint ) + return( -INFINITY ); +#endif +#ifdef INFINITIES + return( INFINITY ); +#else + return( MAXNUM ); +#endif + } + if( y > 0.0 ) + { +#ifdef MINUSZERO + if( signbit(x) && yoddint ) + return( NEGZERO ); +#endif + return( 0.0 ); + } + return( 1.0 ); + } + else + { + if( iyflg == 0 ) + { /* noninteger power of negative number */ + mtherr( fname, DOMAIN ); +#ifdef NANS + return(NAN); +#else + return(0.0L); +#endif + } + nflg = 1; + } + } + +/* Integer power of an integer. */ + +if( iyflg ) + { + i = (int)w; + w = floor(x); + if( (w == x) && (fabs(y) < 32768.0) ) + { + w = c_powi( x, (int) y ); + return( w ); + } + } + +if( nflg ) + x = fabs(x); + +/* For results close to 1, use a series expansion. */ +w = x - 1.0; +aw = fabs(w); +ay = fabs(y); +wy = w * y; +ya = fabs(wy); +if((aw <= 1.0e-3 && ay <= 1.0) + || (ya <= 1.0e-3 && ay >= 1.0)) + { + z = (((((w*(y-5.)/720. + 1./120.)*w*(y-4.) + 1./24.)*w*(y-3.) + + 1./6.)*w*(y-2.) + 0.5)*w*(y-1.) )*wy + wy + 1.; + goto done; + } +/* These are probably too much trouble. */ +#if 0 +w = y * log(x); +if (aw > 1.0e-3 && fabs(w) < 1.0e-3) + { + z = (((((( + w/7. + 1.)*w/6. + 1.)*w/5. + 1.)*w/4. + 1.)*w/3. + 1.)*w/2. + 1.)*w + 1.; + goto done; + } + +if(ya <= 1.0e-3 && aw <= 1.0e-4) + { + z = ((((( + wy*1./720. + + (-w*1./48. + 1./120.) )*wy + + ((w*17./144. - 1./12.)*w + 1./24.) )*wy + + (((-w*5./16. + 7./24.)*w - 1./4.)*w + 1./6.) )*wy + + ((((w*137./360. - 5./12.)*w + 11./24.)*w - 1./2.)*w + 1./2.) )*wy + + (((((-w*1./6. + 1./5.)*w - 1./4)*w + 1./3.)*w -1./2.)*w ) )*wy + + wy + 1.0; + goto done; + } +#endif + +/* separate significand from exponent */ +x = frexp( x, &e ); + +#if 0 +/* For debugging, check for gross overflow. */ +if( (e * y) > (MEXP + 1024) ) + goto overflow; +#endif + +/* Find significand of x in antilog table A[]. */ +i = 1; +if( x <= douba(9) ) + i = 9; +if( x <= douba(i+4) ) + i += 4; +if( x <= douba(i+2) ) + i += 2; +if( x >= douba(1) ) + i = -1; +i += 1; + + +/* Find (x - A[i])/A[i] + * in order to compute log(x/A[i]): + * + * log(x) = log( a x/a ) = log(a) + log(x/a) + * + * log(x/a) = log(1+v), v = x/a - 1 = (x-a)/a + */ +x -= douba(i); +x -= doubb(i/2); +x /= douba(i); + + +/* rational approximation for log(1+v): + * + * log(1+v) = v - v**2/2 + v**3 P(v) / Q(v) + */ +z = x*x; +w = x * ( z * polevl( x, P, 3 ) / p1evl( x, Q, 4 ) ); +w = w - ldexp( z, -1 ); /* w - 0.5 * z */ + +/* Convert to base 2 logarithm: + * multiply by log2(e) + */ +w = w + LOG2EA * w; +/* Note x was not yet added in + * to above rational approximation, + * so do it now, while multiplying + * by log2(e). + */ +z = w + LOG2EA * x; +z = z + x; + +/* Compute exponent term of the base 2 logarithm. */ +w = -i; +w = ldexp( w, -4 ); /* divide by 16 */ +w += e; +/* Now base 2 log of x is w + z. */ + +/* Multiply base 2 log by y, in extended precision. */ + +/* separate y into large part ya + * and small part yb less than 1/16 + */ +ya = reduc(y); +yb = y - ya; + + +F = z * y + w * yb; +Fa = reduc(F); +Fb = F - Fa; + +G = Fa + w * ya; +Ga = reduc(G); +Gb = G - Ga; + +H = Fb + Gb; +Ha = reduc(H); +w = ldexp( Ga+Ha, 4 ); + +/* Test the power of 2 for overflow */ +if( w > MEXP ) + { +#ifndef INFINITIES + mtherr( fname, OVERFLOW ); +#endif +#ifdef INFINITIES + if( nflg && yoddint ) + return( -INFINITY ); + return( INFINITY ); +#else + if( nflg && yoddint ) + return( -MAXNUM ); + return( MAXNUM ); +#endif + } + +if( w < (MNEXP - 1) ) + { +#ifndef DENORMAL + mtherr( fname, UNDERFLOW ); +#endif +#ifdef MINUSZERO + if( nflg && yoddint ) + return( NEGZERO ); +#endif + return( 0.0 ); + } + +e = (int)w; +Hb = H - Ha; + +if( Hb > 0.0 ) + { + e += 1; + Hb -= 0.0625; + } + +/* Now the product y * log2(x) = Hb + e/16.0. + * + * Compute base 2 exponential of Hb, + * where -0.0625 <= Hb <= 0. + */ +z = Hb * polevl( Hb, R, 6 ); /* z = 2**Hb - 1 */ + +/* Express e/16 as an integer plus a negative number of 16ths. + * Find lookup table entry for the fractional power of 2. + */ +if( e < 0 ) + i = 0; +else + i = 1; +i = e/16 + i; +e = 16*i - e; +w = douba( e ); +z = w + w * z; /* 2**-e * ( 1 + (2**Hb-1) ) */ +z = ldexp( z, i ); /* multiply by integer power of 2 */ + +done: + +/* Negate if odd integer power of negative number */ +if( nflg && yoddint ) + { +#ifdef MINUSZERO + if( z == 0.0 ) + z = NEGZERO; + else +#endif + z = -z; + } +return( z ); +} + + +/* Find a multiple of 1/16 that is within 1/16 of x. */ +static double reduc(x) +double x; +{ +double t; + +t = ldexp( x, 4 ); +t = floor( t ); +t = ldexp( t, -4 ); +return(t); +} diff --git a/src/math/powi.c b/src/math/powi.c new file mode 100644 index 000000000..ec80dc1d5 --- /dev/null +++ b/src/math/powi.c @@ -0,0 +1,186 @@ +/* powi.c + * + * Real raised to integer power + * + * + * + * SYNOPSIS: + * + * double x, y, powi(); + * int n; + * + * y = powi( x, n ); + * + * + * + * DESCRIPTION: + * + * Returns argument x raised to the nth power. + * The routine efficiently decomposes n as a sum of powers of + * two. The desired power is a product of two-to-the-kth + * powers of x. Thus to compute the 32767 power of x requires + * 28 multiplications instead of 32767 multiplications. + * + * + * + * ACCURACY: + * + * + * Relative error: + * arithmetic x domain n domain # trials peak rms + * DEC .04,26 -26,26 100000 2.7e-16 4.3e-17 + * IEEE .04,26 -26,26 50000 2.0e-15 3.8e-16 + * IEEE 1,2 -1022,1023 50000 8.6e-14 1.6e-14 + * + * Returns MAXNUM on overflow, zero on underflow. + * + */ + +/* powi.c */ + +/* +Cephes Math Library Release 2.8: June, 2000 +Copyright 1984, 1995, 2000 by Stephen L. Moshier +*/ + +#include "mconf.h" +#ifdef ANSIPROT +extern double log ( double ); +extern double frexp ( double, int * ); +extern int signbit ( double ); +#else +double log(), frexp(); +int signbit(); +#endif +extern double NEGZERO, INFINITY, MAXNUM, MAXLOG, MINLOG, LOGE2; + +double c_powi( x, nn ) +double x; +int nn; +{ +int n, e, sign, asign, lx; +double w, y, s; + +/* See pow.c for these tests. */ +if( x == 0.0 ) + { + if( nn == 0 ) + return( 1.0 ); + else if( nn < 0 ) + return( INFINITY ); + else + { + if( nn & 1 ) + return( x ); + else + return( 0.0 ); + } + } + +if( nn == 0 ) + return( 1.0 ); + +if( nn == -1 ) + return( 1.0/x ); + +if( x < 0.0 ) + { + asign = -1; + x = -x; + } +else + asign = 0; + + +if( nn < 0 ) + { + sign = -1; + n = -nn; + } +else + { + sign = 1; + n = nn; + } + +/* Even power will be positive. */ +if( (n & 1) == 0 ) + asign = 0; + +/* Overflow detection */ + +/* Calculate approximate logarithm of answer */ +s = frexp( x, &lx ); +e = (lx - 1)*n; +if( (e == 0) || (e > 64) || (e < -64) ) + { + s = (s - 7.0710678118654752e-1) / (s + 7.0710678118654752e-1); + s = (2.9142135623730950 * s - 0.5 + lx) * nn * LOGE2; + } +else + { + s = LOGE2 * e; + } + +if( s > MAXLOG ) + { + mtherr( "powi", OVERFLOW ); + y = INFINITY; + goto done; + } + +#if DENORMAL +if( s < MINLOG ) + { + y = 0.0; + goto done; + } + +/* Handle tiny denormal answer, but with less accuracy + * since roundoff error in 1.0/x will be amplified. + * The precise demarcation should be the gradual underflow threshold. + */ +if( (s < (-MAXLOG+2.0)) && (sign < 0) ) + { + x = 1.0/x; + sign = -sign; + } +#else +/* do not produce denormal answer */ +if( s < -MAXLOG ) + return(0.0); +#endif + + +/* First bit of the power */ +if( n & 1 ) + y = x; + +else + y = 1.0; + +w = x; +n >>= 1; +while( n ) + { + w = w * w; /* arg to the 2-to-the-kth power */ + if( n & 1 ) /* if that bit is set, then include in product */ + y *= w; + n >>= 1; + } + +if( sign < 0 ) + y = 1.0/y; + +done: + +if( asign ) + { + /* odd power of negative number */ + if( y == 0.0 ) + y = NEGZERO; + else + y = -y; + } +return(y); +} diff --git a/src/memarena.cpp b/src/memarena.cpp index b15fb12ea..e6e9edd6e 100644 --- a/src/memarena.cpp +++ b/src/memarena.cpp @@ -43,8 +43,6 @@ #include "c_dispatch.h" #include "zstring.h" -#define BLOCK_SIZE (10*1024) - struct FMemArena::Block { Block *NextBlock; @@ -74,10 +72,11 @@ static inline void *RoundPointer(void *ptr) // //========================================================================== -FMemArena::FMemArena() +FMemArena::FMemArena(int bs) { TopBlock = NULL; FreeBlocks = NULL; + BlockSize = bs; } //========================================================================== @@ -191,14 +190,14 @@ FMemArena::Block *FMemArena::AddBlock(size_t size) if (mem == NULL) { // Allocate a new block - if (size < BLOCK_SIZE) + if (size < BlockSize) { - size = BLOCK_SIZE; + size = BlockSize; } else { // Stick some free space at the end so we can use this block for // other things. - size += BLOCK_SIZE/2; + size += BlockSize/2; } mem = (Block *)M_Malloc(size); mem->Limit = (BYTE *)mem + size; diff --git a/src/memarena.h b/src/memarena.h index 73dbb5932..cc0c8f148 100644 --- a/src/memarena.h +++ b/src/memarena.h @@ -40,7 +40,7 @@ class FMemArena { public: - FMemArena(); + FMemArena(int blocksize = 10*1024); ~FMemArena(); void *Alloc(size_t size); @@ -55,6 +55,7 @@ protected: Block *TopBlock; Block *FreeBlocks; + int BlockSize; }; // An arena specializing in storage of FStrings. It knows how to free them, diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp index affcf7c9f..639c6bbef 100644 --- a/src/menu/colorpickermenu.cpp +++ b/src/menu/colorpickermenu.cpp @@ -331,7 +331,7 @@ public: } }; -IMPLEMENT_ABSTRACT_CLASS(DColorPickerMenu) +IMPLEMENT_CLASS(DColorPickerMenu, true, false, false, false) CCMD(undocolorpic) { diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 174b45d4b..cca13ad44 100644 --- a/src/menu/joystickmenu.cpp +++ b/src/menu/joystickmenu.cpp @@ -236,7 +236,7 @@ class DJoystickConfigMenu : public DOptionMenu DECLARE_CLASS(DJoystickConfigMenu, DOptionMenu) }; -IMPLEMENT_CLASS(DJoystickConfigMenu) +IMPLEMENT_CLASS(DJoystickConfigMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index bcb61d6eb..7fdd0c5bc 100644 --- a/src/menu/listmenu.cpp +++ b/src/menu/listmenu.cpp @@ -42,7 +42,7 @@ #include "d_event.h" #include "menu/menu.h" -IMPLEMENT_CLASS(DListMenu) +IMPLEMENT_CLASS(DListMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 99c34ab3e..6d543228c 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -119,7 +119,7 @@ public: }; -IMPLEMENT_CLASS(DLoadSaveMenu) +IMPLEMENT_CLASS(DLoadSaveMenu, false, false, false, false) TArray DLoadSaveMenu::SaveGames; int DLoadSaveMenu::LastSaved = -1; @@ -934,7 +934,7 @@ public: }; -IMPLEMENT_CLASS(DSaveMenu) +IMPLEMENT_CLASS(DSaveMenu, false, false, false, false) //============================================================================= @@ -1102,7 +1102,7 @@ public: bool MenuEvent (int mkey, bool fromcontroller); }; -IMPLEMENT_CLASS(DLoadMenu) +IMPLEMENT_CLASS(DLoadMenu, false, false, false, false) //============================================================================= diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 7e938230e..6648c32b4 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -91,9 +91,11 @@ static bool MenuEnabled = true; // //============================================================================ -IMPLEMENT_POINTY_CLASS (DMenu) - DECLARE_POINTER(mParentMenu) -END_POINTERS +IMPLEMENT_CLASS(DMenu, false, true, false, false) + +IMPLEMENT_POINTERS_START(DMenu) + IMPLEMENT_POINTER(mParentMenu) +IMPLEMENT_POINTERS_END DMenu::DMenu(DMenu *parent) { diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 618189b4f..0fcf4e4d5 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -50,6 +50,7 @@ #include "m_joy.h" #include "gi.h" #include "i_sound.h" +#include "cmdlib.h" #include "optionmenuitems.h" diff --git a/src/menu/menuinput.cpp b/src/menu/menuinput.cpp index 892118742..c33e9fed2 100644 --- a/src/menu/menuinput.cpp +++ b/src/menu/menuinput.cpp @@ -40,10 +40,11 @@ #include "d_gui.h" #include "v_font.h" #include "v_palette.h" +#include "cmdlib.h" // [TP] New #includes #include "v_text.h" -IMPLEMENT_ABSTRACT_CLASS(DTextEnterMenu) +IMPLEMENT_CLASS(DTextEnterMenu, true, false, false, false) #define INPUTGRID_WIDTH 13 #define INPUTGRID_HEIGHT 5 diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index 601c3e736..de8fa1027 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -32,6 +32,7 @@ ** */ +#include #include "menu/menu.h" #include "d_event.h" #include "d_gui.h" @@ -72,7 +73,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DMessageBoxMenu) +IMPLEMENT_CLASS(DMessageBoxMenu, false, false, false, false) //============================================================================= // @@ -364,7 +365,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuitMenu) +IMPLEMENT_CLASS(DQuitMenu, false, false, false, false) //============================================================================= // @@ -457,7 +458,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DEndGameMenu) +IMPLEMENT_CLASS(DEndGameMenu, false, false, false, false) //============================================================================= // @@ -535,7 +536,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuickSaveMenu) +IMPLEMENT_CLASS(DQuickSaveMenu, false, false, false, false) //============================================================================= // @@ -631,7 +632,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuickLoadMenu) +IMPLEMENT_CLASS(DQuickLoadMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index efea7d910..1631c3d4b 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -64,8 +64,7 @@ void M_DrawConText (int color, int x, int y, const char *str) TAG_DONE); } - -IMPLEMENT_CLASS(DOptionMenu) +IMPLEMENT_CLASS(DOptionMenu, false, false, false, false) //============================================================================= // @@ -579,7 +578,7 @@ public: } }; -IMPLEMENT_CLASS(DGameplayMenu) +IMPLEMENT_CLASS(DGameplayMenu, false, false, false, false) class DCompatibilityMenu : public DOptionMenu { @@ -601,4 +600,4 @@ public: } }; -IMPLEMENT_CLASS(DCompatibilityMenu) +IMPLEMENT_CLASS(DCompatibilityMenu, false, false, false, false) diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index 0fadeca37..e83f4ada4 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -399,7 +399,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_ABSTRACT_CLASS(DEnterKey) +IMPLEMENT_CLASS(DEnterKey, true, false, false, false) #endif //============================================================================= diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index ce542c2f2..e32c7dd61 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -526,7 +526,7 @@ public: void Drawer (); }; -IMPLEMENT_CLASS(DPlayerMenu) +IMPLEMENT_CLASS(DPlayerMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/readthis.cpp b/src/menu/readthis.cpp index 0aa3c2fcd..0dfc47e73 100644 --- a/src/menu/readthis.cpp +++ b/src/menu/readthis.cpp @@ -54,7 +54,7 @@ public: bool MouseEvent(int type, int x, int y); }; -IMPLEMENT_CLASS(DReadThisMenu) +IMPLEMENT_CLASS(DReadThisMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index b1b4d792f..37f59149e 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -183,7 +183,7 @@ public: } }; -IMPLEMENT_CLASS(DVideoModeMenu) +IMPLEMENT_CLASS(DVideoModeMenu, false, false, false, false) //============================================================================= diff --git a/src/namedef.h b/src/namedef.h index 8def090fa..e9324d44b 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -209,7 +209,6 @@ xx(XDeath) xx(Burn) //xx(Ice) // already defined above xx(Disintegrate) -xx(Brainexplode) // Weapon animator names. xx(Select) @@ -313,6 +312,7 @@ xx(WaterLevel) xx(X) xx(Y) xx(Z) +xx(XY) xx(MomX) xx(MomY) xx(MomZ) @@ -436,6 +436,9 @@ xx(Scale) xx(ScaleX) xx(ScaleY) xx(Floatbobphase) +xx(Target) +xx(Master) +xx(Tracer) xx(Blocking) xx(Blockmonsters) @@ -671,13 +674,15 @@ xx(PlayerClass) xx(Wi_NoAutostartMap) // Decorate compatibility functions -xx(DecoRandom) -xx(DecoFRandom) -xx(DecoCallLineSpecial) -xx(DecoNameToClass) -xx(DecoFindMultiNameState) -xx(DecoFindSingleNameState) -xx(DecoHandleRuntimeState) +xx(BuiltinTypeCheck) +xx(BuiltinRandom) +xx(BuiltinFRandom) +xx(BuiltinCallLineSpecial) +xx(BuiltinNameToClass) +xx(BuiltinFindMultiNameState) +xx(BuiltinFindSingleNameState) +xx(BuiltinHandleRuntimeState) +xx(BuiltinGetDefault) xx(Damage) // basic type names @@ -700,6 +705,8 @@ xx(Array) xx(Sound) xx(State) xx(Fixed) +xx(Vector2) +xx(Vector3) xx(Min) xx(Max) @@ -715,7 +722,18 @@ xx(Mant_Dig) xx(Min_10_Exp) xx(Max_10_Exp) +// implicit function parameters +xx(self) +xx(invoker) +xx(stateinfo) + xx(__decorate_internal_int__) xx(__decorate_internal_bool__) -xx(__decorate_internal_state__) xx(__decorate_internal_float__) +xx(ResolveState) + +xx(DamageFunction) +xx(Length) +xx(Unit) +xx(StateLabel) +xx(Overlay) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 1a60a0c4f..da8f76d7f 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -83,6 +83,7 @@ #include "a_morph.h" #include "i_music.h" #include "serializer.h" +#include "thingdef.h" #include "g_shared/a_pickups.h" @@ -1368,9 +1369,11 @@ private: DPlaneWatcher() {} }; -IMPLEMENT_POINTY_CLASS (DPlaneWatcher) - DECLARE_POINTER (Activator) -END_POINTERS +IMPLEMENT_CLASS(DPlaneWatcher, false, true, false, false) + +IMPLEMENT_POINTERS_START(DPlaneWatcher) + IMPLEMENT_POINTER(Activator) +IMPLEMENT_POINTERS_END DPlaneWatcher::DPlaneWatcher (AActor *it, line_t *line, int lineSide, bool ceiling, int tag, int height, int special, @@ -2857,10 +2860,12 @@ void FBehavior::StaticStopMyScripts (AActor *actor) //---- The ACS Interpreter ----// -IMPLEMENT_POINTY_CLASS (DACSThinker) - DECLARE_POINTER(LastScript) - DECLARE_POINTER(Scripts) -END_POINTERS +IMPLEMENT_CLASS(DACSThinker, false, true, false, false) + +IMPLEMENT_POINTERS_START(DACSThinker) + IMPLEMENT_POINTER(LastScript) + IMPLEMENT_POINTER(Scripts) +IMPLEMENT_POINTERS_END TObjPtr DACSThinker::ActiveThinker; @@ -2986,11 +2991,13 @@ void DACSThinker::StopScriptsFor (AActor *actor) } } -IMPLEMENT_POINTY_CLASS (DLevelScript) - DECLARE_POINTER(next) - DECLARE_POINTER(prev) - DECLARE_POINTER(activator) -END_POINTERS +IMPLEMENT_CLASS(DLevelScript, false, true, false, false) + +IMPLEMENT_POINTERS_START(DLevelScript) + IMPLEMENT_POINTER(next) + IMPLEMENT_POINTER(prev) + IMPLEMENT_POINTER(activator) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -5388,11 +5395,11 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) { if (!looping) { - S_PlaySound(spot, chan, sid, vol, atten, local); + S_PlaySound(spot, chan, sid, vol, atten, !!local); } else if (!S_IsActorPlayingSomething(spot, chan & 7, sid)) { - S_PlaySound(spot, chan | CHAN_LOOP, sid, vol, atten, local); + S_PlaySound(spot, chan | CHAN_LOOP, sid, vol, atten, !!local); } } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 73cade49a..967d5a9e5 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -61,7 +61,7 @@ #include "c_console.h" #include "doomerrors.h" #include "a_sharedglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "v_video.h" #include "v_font.h" #include "doomstat.h" @@ -77,6 +77,9 @@ #include "p_maputl.h" #include "p_spec.h" #include "templates.h" +#include "vm.h" +#include "v_text.h" +#include "thingdef.h" #include "math/cmath.h" AActor *SingleActorFromTID(int tid, AActor *defactor); @@ -125,17 +128,33 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) while (state != NULL) { + if (!(state->UseFlags & SUF_ITEM)) + { + auto so = FState::StaticFindStateOwner(state); + Printf(TEXTCOLOR_RED "State %s.%d not flagged for use in CustomInventory state chains.\n", so->TypeName.GetChars(), int(state - so->OwnedStates)); + return false; + } + this->state = state; nextstate = NULL; // assume no jump if (state->ActionFunc != NULL) { + if (state->ActionFunc->Unsafe) + { + // If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash. + auto owner = FState::StaticFindStateOwner(state); + Printf(TEXTCOLOR_RED "Unsafe state call in state %s.%d to %s which accesses user variables. The action function has been removed from this state\n", + owner->TypeName.GetChars(), state - owner->OwnedStates, static_cast(state->ActionFunc)->PrintableName.GetChars()); + state->ActionFunc = nullptr; + } + VMFrameStack stack; PPrototype *proto = state->ActionFunc->Proto; VMReturn *wantret; FStateParamInfo stp = { state, STATE_StateChain, PSP_WEAPON }; - params[2] = VMValue(&stp, ATAG_STATEINFO); + params[2] = VMValue(&stp, ATAG_GENERIC); retval = true; // assume success wantret = NULL; // assume no return value wanted numret = 0; @@ -166,7 +185,7 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) numret = 2; } } - stack.Call(state->ActionFunc, params, countof(params), wantret, numret); + stack.Call(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); // As long as even one state succeeds, the whole chain succeeds unless aborted below. // A state that wants to jump does not count as "succeeded". if (nextstate == NULL) @@ -195,6 +214,22 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) return !!result; } + +//========================================================================== +// +// GetPointer +// +// resolve AAPTR_* +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(AActor, GetPointer) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(ptr); + ACTION_RETURN_OBJECT(COPY_AAPTR(self, ptr)); +} + //========================================================================== // // CheckClass @@ -210,8 +245,8 @@ DEFINE_ACTION_FUNCTION(AActor, CheckClass) assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (checktype, AActor); - PARAM_INT_OPT (pick_pointer) { pick_pointer = AAPTR_DEFAULT; } - PARAM_BOOL_OPT (match_superclass) { match_superclass = false; } + PARAM_INT_DEF (pick_pointer); + PARAM_BOOL_DEF (match_superclass); self = COPY_AAPTR(self, pick_pointer); if (self == NULL) @@ -246,8 +281,8 @@ DEFINE_ACTION_FUNCTION(AActor, GetMissileDamage) assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); PARAM_INT(mask); - PARAM_INT(add) - PARAM_INT_OPT(pick_pointer) { pick_pointer = AAPTR_DEFAULT; } + PARAM_INT(add); + PARAM_INT_DEF(pick_pointer); self = COPY_AAPTR(self, pick_pointer); if (self == NULL) @@ -263,29 +298,6 @@ DEFINE_ACTION_FUNCTION(AActor, GetMissileDamage) return 0; } -//========================================================================== -// -// IsPointerEqual -// -// NON-ACTION function to check if two pointers are equal. -// -//========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, IsPointerEqual) -{ - if (numret > 0) - { - assert(ret != NULL); - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (ptr_select1); - PARAM_INT (ptr_select2); - - ret->SetInt(COPY_AAPTR(self, ptr_select1) == COPY_AAPTR(self, ptr_select2)); - return 1; - } - return 0; -} - //========================================================================== // // CountInv @@ -301,7 +313,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountInv) assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(itemtype, AInventory); - PARAM_INT_OPT(pick_pointer) { pick_pointer = AAPTR_DEFAULT; } + PARAM_INT_DEF(pick_pointer); self = COPY_AAPTR(self, pick_pointer); if (self == NULL || itemtype == NULL) @@ -332,7 +344,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetDistance) assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(checkz); - PARAM_INT_OPT(ptr) { ptr = AAPTR_TARGET; } + PARAM_INT_DEF(ptr); AActor *target = COPY_AAPTR(self, ptr); @@ -375,7 +387,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetAngle) assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); PARAM_INT(flags); - PARAM_INT_OPT(ptr) { ptr = AAPTR_TARGET; } + PARAM_INT_DEF(ptr) AActor *target = COPY_AAPTR(self, ptr); @@ -440,7 +452,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpriteAngle) { assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(ptr); AActor *target = COPY_AAPTR(self, ptr); if (target == nullptr) @@ -469,7 +481,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpriteRotation) { assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(ptr); AActor *target = COPY_AAPTR(self, ptr); if (target == nullptr) @@ -509,11 +521,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetZAt) { assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(px) { px = 0.; } - PARAM_FLOAT_OPT(py) { py = 0.; } - PARAM_ANGLE_OPT(angle) { angle = 0.; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(pick_pointer) { pick_pointer = AAPTR_DEFAULT; } + PARAM_FLOAT_DEF(px); + PARAM_FLOAT_DEF(py); + PARAM_ANGLE_DEF(angle); + PARAM_INT_DEF(flags); + PARAM_INT_DEF(pick_pointer); AActor *mobj = COPY_AAPTR(self, pick_pointer); if (mobj == nullptr) @@ -597,7 +609,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) { assert(ret != NULL); PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(ptr) { ptr = AAPTR_PLAYER1; } + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); if (!mobj || !mobj->player) @@ -658,7 +670,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetPlayerInput) assert(ret != nullptr); PARAM_SELF_PROLOGUE(AActor); PARAM_INT (inputnum); - PARAM_INT_OPT (ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); @@ -691,8 +703,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountProximity) PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(classname, AActor); PARAM_FLOAT(distance); - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(flags); + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); if (mobj == nullptr) @@ -710,7 +722,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountProximity) //=========================================================================== // -// __decorate_internal_state__ // __decorate_internal_int__ // __decorate_internal_bool__ // __decorate_internal_float__ @@ -720,13 +731,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountProximity) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_state__) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(returnme); - ACTION_RETURN_STATE(returnme); -} - DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_int__) { PARAM_SELF_PROLOGUE(AActor); @@ -768,9 +772,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RearrangePointers) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (ptr_target); - PARAM_INT_OPT (ptr_master) { ptr_master = AAPTR_DEFAULT; } - PARAM_INT_OPT (ptr_tracer) { ptr_tracer = AAPTR_TRACER; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_INT_DEF (ptr_master); + PARAM_INT_DEF (ptr_tracer); + PARAM_INT_DEF (flags); // Rearrange pointers internally @@ -850,8 +854,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TransferPointer) PARAM_INT (ptr_source); PARAM_INT (ptr_recipient); PARAM_INT (ptr_sourcefield); - PARAM_INT_OPT (ptr_recipientfield) { ptr_recipientfield = AAPTR_DEFAULT; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_INT_DEF (ptr_recipientfield); + PARAM_INT_DEF (flags); AActor *source, *recipient; @@ -889,8 +893,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TransferPointer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopyFriendliness) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT (ptr_source) { ptr_source = AAPTR_MASTER; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF (ptr_source); if (self->player != NULL) { @@ -905,39 +909,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopyFriendliness) return 0; } -//========================================================================== -// -// Simple flag changers -// -//========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_SetSolid) -{ - PARAM_ACTION_PROLOGUE; - self->flags |= MF_SOLID; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_UnsetSolid) -{ - PARAM_ACTION_PROLOGUE; - self->flags &= ~MF_SOLID; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_SetFloat) -{ - PARAM_ACTION_PROLOGUE; - self->flags |= MF_FLOAT; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_UnsetFloat) -{ - PARAM_ACTION_PROLOGUE; - self->flags &= ~(MF_FLOAT|MF_INFLOAT); - return 0; -} - //========================================================================== // // Customizable attack functions which use actor parameters. @@ -978,7 +949,7 @@ static void DoAttack (AActor *self, bool domelee, bool domissile, DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int MeleeDamage = self->GetClass()->MeleeDamage; FSoundID MeleeSound = self->GetClass()->MeleeSound; DoAttack(self, true, false, MeleeDamage, MeleeSound, NULL, 0); @@ -987,7 +958,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack) DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName); DoAttack(self, false, true, 0, 0, MissileType, self->GetClass()->MissileHeight); return 0; @@ -995,7 +966,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack) DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int MeleeDamage = self->GetClass()->MeleeDamage; FSoundID MeleeSound = self->GetClass()->MeleeSound; PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName); @@ -1026,13 +997,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BasicAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) { - PARAM_ACTION_PROLOGUE; - PARAM_SOUND_OPT (soundid) { soundid = "weapons/pistol"; } - PARAM_INT_OPT (channel) { channel = CHAN_BODY; } - PARAM_FLOAT_OPT (volume) { volume = 1; } - PARAM_BOOL_OPT (looping) { looping = false; } - PARAM_FLOAT_OPT (attenuation) { attenuation = ATTN_NORM; } - PARAM_BOOL_OPT (local) { local = false; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_SOUND_DEF (soundid); + PARAM_INT_DEF (channel); + PARAM_FLOAT_DEF (volume); + PARAM_BOOL_DEF (looping); + PARAM_FLOAT_DEF (attenuation); + PARAM_BOOL_DEF (local); if (!looping) { @@ -1050,8 +1021,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSound) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(slot) { slot = CHAN_VOICE; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(slot); S_StopSound(self, slot); return 0; @@ -1066,22 +1037,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSound) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayWeaponSound) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_SOUND(soundid); - - S_Sound(self, CHAN_WEAPON, soundid, 1, ATTN_NORM); - return 0; -} - DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySoundEx) { PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND (soundid); PARAM_NAME (channel); - PARAM_BOOL_OPT (looping) { looping = false; } - PARAM_INT_OPT (attenuation_raw) { attenuation_raw = 0; } + PARAM_BOOL_DEF (looping); + PARAM_INT_DEF (attenuation_raw); float attenuation; switch (attenuation_raw) @@ -1141,9 +1103,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SeekerMissile) PARAM_SELF_PROLOGUE(AActor); PARAM_INT(ang1); PARAM_INT(ang2); - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(chance) { chance = 50; } - PARAM_INT_OPT(distance) { distance = 10; } + PARAM_INT_DEF(flags); + PARAM_INT_DEF(chance); + PARAM_INT_DEF(distance); if ((flags & SMF_LOOK) && (self->tracer == 0) && (pr_seekermissile() 0 && (maxchance >= 256 || pr_cajump() < maxchance)) { int jumpnum = (count == 1 ? 0 : (pr_cajump() % count)); - PARAM_STATE_AT(paramnum + jumpnum, jumpto); + PARAM_STATE_ACTION_AT(paramnum + jumpnum, jumpto); ACTION_RETURN_STATE(jumpto); } ACTION_RETURN_STATE(NULL); @@ -1214,137 +1176,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) // State jump function // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHealthLower) + +DEFINE_ACTION_FUNCTION(AActor, CheckInventory) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (health); - PARAM_STATE (jump); - PARAM_INT_OPT (ptr_selector) { ptr_selector = AAPTR_DEFAULT; } - - AActor *measured; - - measured = COPY_AAPTR(self, ptr_selector); - - if (measured != NULL && measured->health < health) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); -} - -//========================================================================== -// -// State jump function -// -//========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetOutsideMeleeRange) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(jump); - - if (!self->CheckMeleeRange()) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); -} - -//========================================================================== -// -// State jump function -// -//========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInsideMeleeRange) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(jump); - - if (self->CheckMeleeRange()) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); -} - -//========================================================================== -// -// State jump function -// -//========================================================================== -static int DoJumpIfCloser(AActor *target, VM_ARGS) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT (dist); - PARAM_STATE (jump); - PARAM_BOOL_OPT(noz) { noz = false; } - - if (!target) - { // No target - no jump - ACTION_RETURN_STATE(NULL); - } - if (self->Distance2D(target) < dist && - (noz || - ((self->Z() > target->Z() && self->Z() - target->Top() < dist) || - (self->Z() <= target->Z() && target->Z() - self->Top() < dist)))) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfCloser) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *target; - - if (self->player == NULL) - { - target = self->target; - } - else - { - // Does the player aim at something that can be shot? - FTranslatedLineTarget t; - P_BulletSlope(self, &t, ALF_PORTALRESTRICT); - target = t.linetarget; - } - return DoJumpIfCloser(target, VM_ARGS_NAMES); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTracerCloser) -{ - PARAM_SELF_PROLOGUE(AActor); - return DoJumpIfCloser(self->tracer, VM_ARGS_NAMES); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfMasterCloser) -{ - PARAM_SELF_PROLOGUE(AActor); - return DoJumpIfCloser(self->master, VM_ARGS_NAMES); -} - -//========================================================================== -// -// State jump function -// -//========================================================================== -int DoJumpIfInventory(AActor *owner, AActor *self, VMValue *param, int numparam, VMReturn *ret, int numret) -{ - int paramnum = 0; PARAM_CLASS (itemtype, AInventory); PARAM_INT (itemamount); - PARAM_STATE (label); - PARAM_INT_OPT (setowner) { setowner = AAPTR_DEFAULT; } + PARAM_INT_DEF (setowner); - if (itemtype == NULL) + if (itemtype == nullptr) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } - owner = COPY_AAPTR(owner, setowner); - if (owner == NULL) + AActor *owner = COPY_AAPTR(self, setowner); + if (owner == nullptr) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } AInventory *item = owner->FindInventory(itemtype); @@ -1355,48 +1202,32 @@ int DoJumpIfInventory(AActor *owner, AActor *self, VMValue *param, int numparam, { if (item->Amount >= itemamount) { - ACTION_RETURN_STATE(label); + ACTION_RETURN_BOOL(true); } } else if (item->Amount >= item->MaxAmount) { - ACTION_RETURN_STATE(label); + ACTION_RETURN_BOOL(true); } } - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInventory) -{ - PARAM_SELF_PROLOGUE(AActor); - return DoJumpIfInventory(self, self, param, numparam, ret, numret); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetInventory) -{ - PARAM_SELF_PROLOGUE(AActor); - return DoJumpIfInventory(self->target, self, param, numparam, ret, numret); -} //========================================================================== // // State jump function // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckArmorType) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME (type); - PARAM_STATE (label); - PARAM_INT_OPT(amount) { amount = 1; } + PARAM_INT_DEF(amount); ABasicArmor *armor = (ABasicArmor *)self->FindInventory(NAME_BasicArmor); - if (armor && armor->ArmorType == type && armor->Amount >= amount) - { - ACTION_RETURN_STATE(label); - } - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(armor && armor->ArmorType == type && armor->Amount >= amount); } //========================================================================== @@ -1410,20 +1241,21 @@ enum XF_HURTSOURCE = 1, XF_NOTMISSILE = 4, XF_NOACTORTYPE = 1 << 3, + XF_NOSPLASH = 16, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT (damage) { damage = -1; } - PARAM_INT_OPT (distance) { distance = -1; } - PARAM_INT_OPT (flags) { flags = XF_HURTSOURCE; } - PARAM_BOOL_OPT (alert) { alert = false; } - PARAM_INT_OPT (fulldmgdistance) { fulldmgdistance = 0; } - PARAM_INT_OPT (nails) { nails = 0; } - PARAM_INT_OPT (naildamage) { naildamage = 10; } - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = PClass::FindActor(NAME_BulletPuff); } - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF (damage); + PARAM_INT_DEF (distance); + PARAM_INT_DEF (flags); + PARAM_BOOL_DEF (alert); + PARAM_INT_DEF (fulldmgdistance); + PARAM_INT_DEF (nails); + PARAM_INT_DEF (naildamage); + PARAM_CLASS_DEF (pufftype, AActor); + PARAM_NAME_DEF (damagetype); if (damage < 0) // get parameters from metadata { @@ -1460,7 +1292,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) if (flags & XF_NOTMISSILE) pflags |= RADF_SOURCEISSPOT; int count = P_RadiusAttack (self, self->target, damage, distance, damagetype, pflags, fulldmgdistance); - P_CheckSplash(self, distance); + if (!(flags & XF_NOSPLASH)) P_CheckSplash(self, distance); if (alert && self->target != NULL && self->target->player != NULL) { P_NoiseAlert(self->target, self); @@ -1483,11 +1315,11 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT (force) { force = 128; } - PARAM_INT_OPT (distance) { distance = -1; } - PARAM_INT_OPT (flags) { flags = RTF_AFFECTSOURCE; } - PARAM_INT_OPT (fullthrustdistance) { fullthrustdistance = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF (force); + PARAM_INT_DEF (distance); + PARAM_INT_DEF (flags); + PARAM_INT_DEF (fullthrustdistance); bool sourcenothrust = false; @@ -1523,11 +1355,11 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusDamageSelf) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(damage) { damage = 128; } - PARAM_FLOAT_OPT(distance) { distance = 128; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_CLASS_OPT(flashtype, AActor) { flashtype = NULL; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(damage); + PARAM_FLOAT_DEF(distance); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(flashtype, AActor); int i; int damageSteps; @@ -1586,11 +1418,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CallSpecial) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (special); - PARAM_INT_OPT (arg1) { arg1 = 0; } - PARAM_INT_OPT (arg2) { arg2 = 0; } - PARAM_INT_OPT (arg3) { arg3 = 0; } - PARAM_INT_OPT (arg4) { arg4 = 0; } - PARAM_INT_OPT (arg5) { arg5 = 0; } + PARAM_INT_DEF (arg1); + PARAM_INT_DEF (arg2); + PARAM_INT_DEF (arg3); + PARAM_INT_DEF (arg4); + PARAM_INT_DEF (arg5); bool res = !!P_ExecuteSpecial(special, NULL, self, false, arg1, arg2, arg3, arg4, arg5); @@ -1619,12 +1451,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (ti, AActor); - PARAM_FLOAT_OPT (Spawnheight) { Spawnheight = 32; } - PARAM_FLOAT_OPT (Spawnofs_xy) { Spawnofs_xy = 0; } - PARAM_ANGLE_OPT (Angle) { Angle = 0.; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_ANGLE_OPT (Pitch) { Pitch = 0.; } - PARAM_INT_OPT (ptr) { ptr = AAPTR_TARGET; } + PARAM_FLOAT_DEF (Spawnheight); + PARAM_FLOAT_DEF (Spawnofs_xy); + PARAM_ANGLE_DEF (Angle); + PARAM_INT_DEF (flags); + PARAM_ANGLE_DEF (Pitch); + PARAM_INT_DEF (ptr); AActor *ref = COPY_AAPTR(self, ptr); @@ -1771,13 +1603,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) PARAM_ANGLE (spread_z); PARAM_INT (numbullets); PARAM_INT (damageperbullet); - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = nullptr; } - PARAM_FLOAT_OPT (range) { range = 0; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_INT_OPT (ptr) { ptr = AAPTR_TARGET; } - PARAM_CLASS_OPT (missile, AActor) { missile = nullptr; } - PARAM_FLOAT_OPT (Spawnheight) { Spawnheight = 32; } - PARAM_FLOAT_OPT (Spawnofs_xy) { Spawnofs_xy = 0; } + PARAM_CLASS_DEF (pufftype, AActor); + PARAM_FLOAT_DEF (range); + PARAM_INT_DEF (flags); + PARAM_INT_DEF (ptr); + PARAM_CLASS_DEF (missile, AActor); + PARAM_FLOAT_DEF (Spawnheight); + PARAM_FLOAT_DEF (Spawnofs_xy); AActor *ref = COPY_AAPTR(self, ptr); @@ -1858,12 +1690,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) //========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMeleeAttack) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT (damage) { damage = 0; } - PARAM_SOUND_OPT (meleesound) { meleesound = 0; } - PARAM_SOUND_OPT (misssound) { misssound = 0; } - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_BOOL_OPT (bleed) { bleed = true; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF (damage); + PARAM_SOUND_DEF (meleesound); + PARAM_SOUND_DEF (misssound); + PARAM_NAME_DEF (damagetype); + PARAM_BOOL_DEF (bleed); if (damagetype == NAME_None) damagetype = NAME_Melee; // Melee is the default type @@ -1899,9 +1731,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack) PARAM_CLASS (ti, AActor); PARAM_FLOAT (spawnheight); PARAM_INT (damage); - PARAM_SOUND_OPT (meleesound) { meleesound = 0; } - PARAM_NAME_OPT (damagetype) { damagetype = NAME_Melee; } - PARAM_BOOL_OPT (bleed) { bleed = true; } + PARAM_SOUND_DEF (meleesound); + PARAM_NAME_DEF (damagetype); + PARAM_BOOL_DEF (bleed); if (!self->target) return 0; @@ -1945,8 +1777,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack) //========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfNoAmmo) { - PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_ACTION_PROLOGUE(AActor); + PARAM_STATE_ACTION(jump); if (!ACTION_CALL_FROM_PSPRITE() || self->player->ReadyWeapon == nullptr) { @@ -2016,17 +1848,17 @@ static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, b DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_ANGLE (spread_xy); PARAM_ANGLE (spread_z); PARAM_INT (numbullets); PARAM_INT (damageperbullet); - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = nullptr; } - PARAM_INT_OPT (flags) { flags = FBF_USEAMMO; } - PARAM_FLOAT_OPT (range) { range = 0; } - PARAM_CLASS_OPT (missile, AActor) { missile = nullptr; } - PARAM_FLOAT_OPT (Spawnheight) { Spawnheight = 0; } - PARAM_FLOAT_OPT (Spawnofs_xy) { Spawnofs_xy = 0; } + PARAM_CLASS_DEF (pufftype, AActor); + PARAM_INT_DEF (flags); + PARAM_FLOAT_DEF (range); + PARAM_CLASS_DEF (missile, AActor); + PARAM_FLOAT_DEF (Spawnheight); + PARAM_FLOAT_DEF (Spawnofs_xy); if (!self->player) return 0; @@ -2146,14 +1978,14 @@ enum FP_Flags }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS (ti, AActor); - PARAM_ANGLE_OPT (angle) { angle = 0.; } - PARAM_BOOL_OPT (useammo) { useammo = true; } - PARAM_FLOAT_OPT (spawnofs_xy) { spawnofs_xy = 0; } - PARAM_FLOAT_OPT (spawnheight) { spawnheight = 0; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_ANGLE_OPT (pitch) { pitch = 0.; } + PARAM_ANGLE_DEF (angle); + PARAM_BOOL_DEF (useammo); + PARAM_FLOAT_DEF (spawnofs_xy); + PARAM_FLOAT_DEF (spawnheight); + PARAM_INT_DEF (flags); + PARAM_ANGLE_DEF (pitch); if (!self->player) return 0; @@ -2223,17 +2055,17 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT (damage); - PARAM_BOOL_OPT (norandom) { norandom = false; } - PARAM_INT_OPT (flags) { flags = CPF_USEAMMO; } - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; } - PARAM_FLOAT_OPT (range) { range = 0; } - PARAM_FLOAT_OPT (lifesteal) { lifesteal = 0; } - PARAM_INT_OPT (lifestealmax) { lifestealmax = 0; } - PARAM_CLASS_OPT (armorbonustype, ABasicArmorBonus) { armorbonustype = NULL; } - PARAM_SOUND_OPT (MeleeSound) { MeleeSound = ""; } - PARAM_SOUND_OPT (MissSound) { MissSound = ""; } + PARAM_BOOL_DEF (norandom); + PARAM_INT_DEF (flags); + PARAM_CLASS_DEF (pufftype, AActor); + PARAM_FLOAT_DEF (range); + PARAM_FLOAT_DEF (lifesteal); + PARAM_INT_DEF (lifestealmax); + PARAM_CLASS_DEF (armorbonustype, ABasicArmorBonus); + PARAM_SOUND_DEF (MeleeSound); + PARAM_SOUND_DEF (MissSound); if (!self->player) return 0; @@ -2327,25 +2159,25 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) //========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT (damage); - PARAM_INT_OPT (spawnofs_xy) { spawnofs_xy = 0; } - PARAM_BOOL_OPT (useammo) { useammo = true; } - PARAM_COLOR_OPT (color1) { color1 = 0; } - PARAM_COLOR_OPT (color2) { color2 = 0; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FLOAT_OPT (maxdiff) { maxdiff = 0; } - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = PClass::FindActor(NAME_BulletPuff); } - PARAM_ANGLE_OPT (spread_xy) { spread_xy = 0.; } - PARAM_ANGLE_OPT (spread_z) { spread_z = 0.; } - PARAM_FLOAT_OPT (range) { range = 0; } - PARAM_INT_OPT (duration) { duration = 0; } - PARAM_FLOAT_OPT (sparsity) { sparsity = 1; } - PARAM_FLOAT_OPT (driftspeed) { driftspeed = 1; } - PARAM_CLASS_OPT (spawnclass, AActor){ spawnclass = NULL; } - PARAM_FLOAT_OPT (spawnofs_z) { spawnofs_z = 0; } - PARAM_INT_OPT (SpiralOffset) { SpiralOffset = 270; } - PARAM_INT_OPT (limit) { limit = 0; } + PARAM_INT_DEF (spawnofs_xy); + PARAM_BOOL_DEF (useammo); + PARAM_COLOR_DEF (color1); + PARAM_COLOR_DEF (color2); + PARAM_INT_DEF (flags); + PARAM_FLOAT_DEF (maxdiff); + PARAM_CLASS_DEF (pufftype, AActor); + PARAM_ANGLE_DEF (spread_xy); + PARAM_ANGLE_DEF (spread_z); + PARAM_FLOAT_DEF (range) ; + PARAM_INT_DEF (duration); + PARAM_FLOAT_DEF (sparsity); + PARAM_FLOAT_DEF (driftspeed); + PARAM_CLASS_DEF (spawnclass, AActor); + PARAM_FLOAT_DEF (spawnofs_z); + PARAM_INT_DEF (SpiralOffset); + PARAM_INT_DEF (limit); if (range == 0) range = 8192; if (sparsity == 0) sparsity=1.0; @@ -2408,23 +2240,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (damage); - PARAM_INT_OPT (spawnofs_xy) { spawnofs_xy = 0; } - PARAM_COLOR_OPT (color1) { color1 = 0; } - PARAM_COLOR_OPT (color2) { color2 = 0; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_INT_OPT (aim) { aim = CRF_DONTAIM; } - PARAM_FLOAT_OPT (maxdiff) { maxdiff = 0; } - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = PClass::FindActor(NAME_BulletPuff); } - PARAM_ANGLE_OPT (spread_xy) { spread_xy = 0.; } - PARAM_ANGLE_OPT (spread_z) { spread_z = 0.; } - PARAM_FLOAT_OPT (range) { range = 0; } - PARAM_INT_OPT (duration) { duration = 0; } - PARAM_FLOAT_OPT (sparsity) { sparsity = 1; } - PARAM_FLOAT_OPT (driftspeed) { driftspeed = 1; } - PARAM_CLASS_OPT (spawnclass, AActor){ spawnclass = NULL; } - PARAM_FLOAT_OPT (spawnofs_z) { spawnofs_z = 0; } - PARAM_INT_OPT (SpiralOffset) { SpiralOffset = 270; } - PARAM_INT_OPT (limit) { limit = 0; } + PARAM_INT_DEF (spawnofs_xy) + PARAM_COLOR_DEF (color1) + PARAM_COLOR_DEF (color2) + PARAM_INT_DEF (flags) + PARAM_INT_DEF (aim) + PARAM_FLOAT_DEF (maxdiff) + PARAM_CLASS_DEF (pufftype, AActor) + PARAM_ANGLE_DEF (spread_xy) + PARAM_ANGLE_DEF (spread_z) + PARAM_FLOAT_DEF (range) + PARAM_INT_DEF (duration) + PARAM_FLOAT_DEF (sparsity) + PARAM_FLOAT_DEF (driftspeed) + PARAM_CLASS_DEF (spawnclass, AActor) + PARAM_FLOAT_DEF (spawnofs_z) + PARAM_INT_DEF (SpiralOffset) + PARAM_INT_DEF (limit) if (range == 0) range = 8192.; if (sparsity == 0) sparsity = 1; @@ -2526,17 +2358,22 @@ static bool DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS) { int paramnum = 0; PARAM_CLASS (mi, AInventory); - PARAM_INT_OPT (amount) { amount = 1; } + PARAM_INT_DEF (amount) if (!orresult) { - PARAM_INT_OPT(setreceiver) { setreceiver = AAPTR_DEFAULT; } + PARAM_INT_DEF(setreceiver) receiver = COPY_AAPTR(receiver, setreceiver); } if (receiver == NULL) { // If there's nothing to receive it, it's obviously a fail, right? return false; } + // Owned inventory items cannot own anything because their Inventory pointer is repurposed for the owner's linked list. + if (receiver->IsKindOf(RUNTIME_CLASS(AInventory)) && static_cast(receiver)->Owner != nullptr) + { + return false; + } if (amount <= 0) { @@ -2631,11 +2468,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetInventory) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(itemtype, AInventory); PARAM_INT(amount); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - PARAM_BOOL_OPT(beyondMax) { beyondMax = false; } + PARAM_INT_DEF(ptr); + PARAM_BOOL_DEF(beyondMax); bool res = false; @@ -2724,8 +2561,8 @@ bool DoTakeInventory(AActor *receiver, bool orresult, VM_ARGS) { int paramnum = 0; PARAM_CLASS (itemtype, AInventory); - PARAM_INT_OPT (amount) { amount = 0; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_INT_DEF (amount); + PARAM_INT_DEF (flags); if (itemtype == NULL) { @@ -2733,7 +2570,7 @@ bool DoTakeInventory(AActor *receiver, bool orresult, VM_ARGS) } if (!orresult) { - PARAM_INT_OPT(setreceiver) { setreceiver = AAPTR_DEFAULT; } + PARAM_INT_DEF(setreceiver); receiver = COPY_AAPTR(receiver, setreceiver); } if (receiver == NULL) @@ -3011,12 +2848,12 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT (missile, AActor) { missile = PClass::FindActor("Unknown"); } - PARAM_FLOAT_OPT (distance) { distance = 0; } - PARAM_FLOAT_OPT (zheight) { zheight = 0; } - PARAM_BOOL_OPT (useammo) { useammo = true; } - PARAM_BOOL_OPT (transfer_translation) { transfer_translation = false; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_CLASS_DEF (missile, AActor) + PARAM_FLOAT_DEF (distance) + PARAM_FLOAT_DEF (zheight) + PARAM_BOOL_DEF (useammo) + PARAM_BOOL_DEF (transfer_translation) if (missile == NULL) { @@ -3061,16 +2898,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (missile, AActor); - PARAM_FLOAT_OPT (xofs) { xofs = 0; } - PARAM_FLOAT_OPT (yofs) { yofs = 0; } - PARAM_FLOAT_OPT (zofs) { zofs = 0; } - PARAM_FLOAT_OPT (xvel) { xvel = 0; } - PARAM_FLOAT_OPT (yvel) { yvel = 0; } - PARAM_FLOAT_OPT (zvel) { zvel = 0; } - PARAM_ANGLE_OPT (angle) { angle = 0.; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_INT_OPT (chance) { chance = 0; } - PARAM_INT_OPT (tid) { tid = 0; } + PARAM_FLOAT_DEF (xofs) + PARAM_FLOAT_DEF (yofs) + PARAM_FLOAT_DEF (zofs) + PARAM_FLOAT_DEF (xvel) + PARAM_FLOAT_DEF (yvel) + PARAM_FLOAT_DEF (zvel) + PARAM_ANGLE_DEF (angle) + PARAM_INT_DEF (flags) + PARAM_INT_DEF (chance) + PARAM_INT_DEF (tid) if (missile == NULL) { @@ -3143,12 +2980,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS (missile, AActor); - PARAM_FLOAT_OPT (zheight) { zheight = 0; } - PARAM_FLOAT_OPT (xyvel) { xyvel = 0; } - PARAM_FLOAT_OPT (zvel) { zvel = 0; } - PARAM_BOOL_OPT (useammo) { useammo = true; } + PARAM_FLOAT_DEF (zheight) + PARAM_FLOAT_DEF (xyvel) + PARAM_FLOAT_DEF (zvel) + PARAM_BOOL_DEF (useammo) if (missile == NULL) { @@ -3242,7 +3079,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SelectWeapon) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(cls, AWeapon); - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_INT_DEF(flags); bool selectPriority = !!(flags & SWF_SELECTPRIORITY); @@ -3287,8 +3124,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Print) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING (text); - PARAM_FLOAT_OPT (time) { time = 0; } - PARAM_NAME_OPT (fontname) { fontname = NAME_None; } + PARAM_FLOAT_DEF (time); + PARAM_NAME_DEF (fontname); if (text[0] == '$') text = GStrings(&text[1]); if (self->CheckLocalView (consoleplayer) || @@ -3322,8 +3159,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PrintBold) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING (text); - PARAM_FLOAT_OPT (time) { time = 0; } - PARAM_NAME_OPT (fontname) { fontname = NAME_None; } + PARAM_FLOAT_DEF (time); + PARAM_NAME_DEF (fontname); float saved = con_midtime; FFont *font = NULL; @@ -3399,7 +3236,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslucent) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT (alpha); - PARAM_INT_OPT (mode) { mode = 0; } + PARAM_INT_DEF (mode); mode = mode == 0 ? STYLE_Translucent : mode == 2 ? STYLE_Fuzzy : STYLE_Add; @@ -3418,7 +3255,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRenderStyle) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(alpha); - PARAM_INT_OPT(mode) { mode = 0; } + PARAM_INT_DEF(mode); self->Alpha = clamp(alpha, 0., 1.); self->RenderStyle = ERenderStyle(mode); @@ -3441,9 +3278,10 @@ enum FadeFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) { - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(reduce) { reduce = 0.1; } - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF(reduce); + PARAM_INT_DEF(flags); + if (reduce == 0) { @@ -3475,9 +3313,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeOut) { - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(reduce) { reduce = 0.1; } - PARAM_INT_OPT(flags) { flags = FTF_REMOVE; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF(reduce); + PARAM_INT_DEF(flags); if (reduce == 0) { @@ -3511,8 +3349,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeTo) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT (target); - PARAM_FLOAT_OPT (amount) { amount = 0.1; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_FLOAT_DEF (amount); + PARAM_INT_DEF (flags); self->RenderStyle.Flags &= ~STYLEF_Alpha1; @@ -3545,50 +3383,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeTo) return 0; } -//=========================================================================== -// -// A_Scale(float scalex, optional float scaley) -// -// Scales the actor's graphics. If scaley is 0, use scalex. -// -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetScale) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT (scalex); - PARAM_FLOAT_OPT (scaley) { scaley = scalex; } - PARAM_INT_OPT (ptr) { ptr = AAPTR_DEFAULT; } - PARAM_BOOL_OPT (usezero) { usezero = false; } - - AActor *ref = COPY_AAPTR(self, ptr); - - if (ref != NULL) - { - if (scaley == 0 && !usezero) - { - scaley = scalex; - } - ref->Scale = { scalex, scaley }; - } - return 0; -} - -//=========================================================================== -// -// A_SetMass(int mass) -// -// Sets the actor's mass. -// -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetMass) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (mass); - - self->Mass = mass; - return 0; -} - //=========================================================================== // // A_SpawnDebris @@ -3598,9 +3392,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnDebris) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (debris, AActor); - PARAM_BOOL_OPT (transfer_translation) { transfer_translation = false; } - PARAM_FLOAT_OPT (mult_h) { mult_h = 1; } - PARAM_FLOAT_OPT (mult_v) { mult_v = 1; } + PARAM_BOOL_DEF (transfer_translation) + PARAM_FLOAT_DEF (mult_h) + PARAM_FLOAT_DEF (mult_v) int i; AActor *mo; @@ -3654,22 +3448,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) { PARAM_SELF_PROLOGUE(AActor); PARAM_COLOR (color); - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_INT_OPT (lifetime) { lifetime = 35; } - PARAM_FLOAT_OPT (size) { size = 1.; } - PARAM_ANGLE_OPT (angle) { angle = 0.; } - PARAM_FLOAT_OPT (xoff) { xoff = 0; } - PARAM_FLOAT_OPT (yoff) { yoff = 0; } - PARAM_FLOAT_OPT (zoff) { zoff = 0; } - PARAM_FLOAT_OPT (xvel) { xvel = 0; } - PARAM_FLOAT_OPT (yvel) { yvel = 0; } - PARAM_FLOAT_OPT (zvel) { zvel = 0; } - PARAM_FLOAT_OPT (accelx) { accelx = 0; } - PARAM_FLOAT_OPT (accely) { accely = 0; } - PARAM_FLOAT_OPT (accelz) { accelz = 0; } - PARAM_FLOAT_OPT (startalpha) { startalpha = 1.; } - PARAM_FLOAT_OPT (fadestep) { fadestep = -1.; } - PARAM_FLOAT_OPT (sizestep) { sizestep = 0.; } + PARAM_INT_DEF (flags) + PARAM_INT_DEF (lifetime) + PARAM_FLOAT_DEF (size) + PARAM_ANGLE_DEF (angle) + PARAM_FLOAT_DEF (xoff) + PARAM_FLOAT_DEF (yoff) + PARAM_FLOAT_DEF (zoff) + PARAM_FLOAT_DEF (xvel) + PARAM_FLOAT_DEF (yvel) + PARAM_FLOAT_DEF (zvel) + PARAM_FLOAT_DEF (accelx) + PARAM_FLOAT_DEF (accely) + PARAM_FLOAT_DEF (accelz) + PARAM_FLOAT_DEF (startalpha) + PARAM_FLOAT_DEF (fadestep) + PARAM_FLOAT_DEF (sizestep) startalpha = clamp(startalpha, 0., 1.); if (fadestep > 0) fadestep = clamp(fadestep, 0., 1.); @@ -3711,10 +3505,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) // jumps if no player can see this actor // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckIfSeen) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(jump); for (int i = 0; i < MAXPLAYERS; i++) { @@ -3723,17 +3516,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight) // Always check sight from each player. if (P_CheckSight(players[i].mo, self, SF_IGNOREVISIBILITY)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } // If a player is viewing from a non-player, then check that too. if (players[i].camera != NULL && players[i].camera->player == NULL && P_CheckSight(players[i].camera, self, SF_IGNOREVISIBILITY)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } } } - ACTION_RETURN_STATE(jump); + ACTION_RETURN_BOOL(true); } //=========================================================================== @@ -3780,12 +3573,11 @@ static bool DoCheckSightOrRange(AActor *self, AActor *camera, double range, bool return false; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckSightOrRange) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(range); - PARAM_STATE(jump); - PARAM_BOOL_OPT(twodi) { twodi = false; } + PARAM_BOOL_DEF(twodi); range *= range; for (int i = 0; i < MAXPLAYERS; ++i) @@ -3795,26 +3587,25 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange) // Always check from each player. if (DoCheckSightOrRange(self, players[i].mo, range, twodi, true)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } // If a player is viewing from a non-player, check that too. if (players[i].camera != NULL && players[i].camera->player == NULL && DoCheckSightOrRange(self, players[i].camera, range, twodi, true)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } } } - ACTION_RETURN_STATE(jump); + ACTION_RETURN_BOOL(true); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckRange) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(range); - PARAM_STATE(jump); - PARAM_BOOL_OPT(twodi) { twodi = false; } + PARAM_BOOL_DEF(twodi); range *= range; for (int i = 0; i < MAXPLAYERS; ++i) @@ -3824,17 +3615,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange) // Always check from each player. if (DoCheckSightOrRange(self, players[i].mo, range, twodi, false)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } // If a player is viewing from a non-player, check that too. if (players[i].camera != NULL && players[i].camera->player == NULL && DoCheckSightOrRange(self, players[i].camera, range, twodi, false)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } } } - ACTION_RETURN_STATE(jump); + ACTION_RETURN_BOOL(true); } @@ -3871,7 +3662,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetBlend) PARAM_COLOR (color); PARAM_FLOAT (alpha); PARAM_INT (tics); - PARAM_COLOR_OPT (color2) { color2 = 0; } + PARAM_COLOR_DEF (color2); if (color == MAKEARGB(255,255,255,255)) color = 0; @@ -3887,20 +3678,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetBlend) } -//=========================================================================== -// -// A_JumpIf -// -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIf) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL (condition); - PARAM_STATE (jump); - - ACTION_RETURN_STATE(condition ? jump : NULL); -} - //=========================================================================== // // A_CountdownArg @@ -3911,7 +3688,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CountdownArg) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(cnt); - PARAM_STATE_OPT(state) { state = self->FindState(NAME_Death); } + PARAM_STATE_DEF(state) if (cnt<0 || cnt >= 5) return 0; if (!self->args[cnt]--) @@ -3926,6 +3703,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CountdownArg) } else { + if (state == nullptr) state = self->FindState(NAME_Death); self->SetState(state); } } @@ -3990,43 +3768,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst) return 0; } -//=========================================================================== -// -// A_CheckFloor -// [GRB] Jumps if actor is standing on floor -// -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFloor) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(jump); - - if (self->Z() <= self->floorz) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); -} - -//=========================================================================== -// -// A_CheckCeiling -// [GZ] Totally copied from A_CheckFloor, jumps if actor touches ceiling -// - -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckCeiling) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(jump); - - if (self->Top() >= self->ceilingz) // Height needs to be counted - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); -} - //=========================================================================== // // A_Stop @@ -4035,7 +3776,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckCeiling) //=========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_Stop) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->Vel.Zero(); if (self->player && self->player->mo == self && !(self->player->cheats & CF_PREDICTING)) { @@ -4073,8 +3814,8 @@ enum RS_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(flags) { flags = RSF_FOG; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(flags); bool oktorespawn = false; DVector3 pos = self->Pos(); @@ -4150,51 +3891,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayerSkinCheck) +DEFINE_ACTION_FUNCTION(AActor, PlayerSkinCheck) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(jump); - if (self->player != NULL && - skins[self->player->userinfo.GetSkin()].othergame) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(self->player != NULL && + skins[self->player->userinfo.GetSkin()].othergame); } -//=========================================================================== -// -// A_SetGravity -// -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetGravity) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT(gravity); - - self->Gravity = clamp(gravity, 0., 10.); - return 0; -} - - // [KS] *** Start of my modifications *** -//=========================================================================== -// -// A_ClearTarget -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_ClearTarget) -{ - PARAM_ACTION_PROLOGUE; - self->target = NULL; - self->LastHeard = NULL; - self->lastenemy = NULL; - return 0; -} - //========================================================================== // // A_CheckLOF (state jump, int flags = CRF_AIM_VERT|CRF_AIM_HOR, @@ -4323,7 +4029,7 @@ ETraceStatus CheckLOFTraceFunc(FTraceResults &trace, void *userdata) return TRACE_Abort; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckLOF) { // Check line of fire @@ -4336,16 +4042,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) DVector3 vel; PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE (jump); - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FLOAT_OPT (range) { range = 0; } - PARAM_FLOAT_OPT (minrange) { minrange = 0; } - PARAM_ANGLE_OPT (angle) { angle = 0.; } - PARAM_ANGLE_OPT (pitch) { pitch = 0.; } - PARAM_FLOAT_OPT (offsetheight) { offsetheight = 0; } - PARAM_FLOAT_OPT (offsetwidth) { offsetwidth = 0; } - PARAM_INT_OPT (ptr_target) { ptr_target = AAPTR_DEFAULT; } - PARAM_FLOAT_OPT (offsetforward) { offsetforward = 0; } + PARAM_INT_DEF (flags) + PARAM_FLOAT_DEF (range) + PARAM_FLOAT_DEF (minrange) + PARAM_ANGLE_DEF (angle) + PARAM_ANGLE_DEF (pitch) + PARAM_FLOAT_DEF (offsetheight) + PARAM_FLOAT_DEF (offsetwidth) + PARAM_INT_DEF (ptr_target) + PARAM_FLOAT_DEF (offsetforward) DAngle ang; @@ -4393,7 +4098,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) double distance = self->Distance3D(target); if (distance > range) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } } @@ -4442,7 +4147,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) } else { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } double cp = pitch.Cos(); @@ -4480,7 +4185,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) { if (minrange > 0 && trace.Distance < minrange) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if ((trace.HitType == TRACE_HitActor) && (trace.Actor != NULL) && !(lof_data.BadActor)) { @@ -4488,9 +4193,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) if (flags & (CLOFF_SETMASTER)) self->master = trace.Actor; if (flags & (CLOFF_SETTRACER)) self->tracer = trace.Actor; } - ACTION_RETURN_STATE(jump); + ACTION_RETURN_BOOL(true); } - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } //========================================================================== @@ -4525,14 +4230,13 @@ enum JLOS_flags JLOSF_CHECKTRACER = 1 << 12, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckIfTargetInLOS) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE (jump); - PARAM_ANGLE_OPT (fov) { fov = 0.; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FLOAT_OPT (dist_max) { dist_max = 0; } - PARAM_FLOAT_OPT (dist_close) { dist_close = 0; } + PARAM_ANGLE_DEF (fov) + PARAM_INT_DEF (flags) + PARAM_FLOAT_DEF (dist_max) + PARAM_FLOAT_DEF (dist_close) AActor *target, *viewport; FTranslatedLineTarget t; @@ -4559,11 +4263,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) if (target == NULL) { // [KS] Let's not call P_CheckSight unnecessarily in this case. - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if ((flags & JLOSF_DEADNOJUMP) && (target->health <= 0)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } doCheckSight = !(flags & JLOSF_NOSIGHT); @@ -4575,7 +4279,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) if (!t.linetarget) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } target = t.linetarget; @@ -4601,24 +4305,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) // [FDARI] If target is not a combatant, don't jump if ( (flags & JLOSF_COMBATANTONLY) && (!target->player) && !(target->flags3 & MF3_ISMONSTER)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } // [FDARI] If actors share team, don't jump if ((flags & JLOSF_ALLYNOJUMP) && self->IsFriend(target)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } double distance = self->Distance3D(target); if (dist_max && (distance > dist_max)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if (dist_close && (distance < dist_close)) { if (flags & JLOSF_CLOSENOJUMP) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if (flags & JLOSF_CLOSENOFOV) fov = 0.; @@ -4632,7 +4336,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) if (doCheckSight && !P_CheckSight (viewport, target, SF_IGNOREVISIBILITY)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if (flags & JLOSF_FLIPFOV) @@ -4649,10 +4353,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) if (an > (fov / 2)) { - ACTION_RETURN_STATE(NULL); // [KS] Outside of FOV - return + ACTION_RETURN_BOOL(false); // [KS] Outside of FOV - return } } - ACTION_RETURN_STATE(jump); + ACTION_RETURN_BOOL(true); } @@ -4663,14 +4367,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckIfInTargetLOS) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE (jump); - PARAM_ANGLE_OPT (fov) { fov = 0.; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FLOAT_OPT (dist_max) { dist_max = 0; } - PARAM_FLOAT_OPT (dist_close) { dist_close = 0; } + PARAM_ANGLE_DEF (fov) + PARAM_INT_DEF (flags) + PARAM_FLOAT_DEF (dist_max) + PARAM_FLOAT_DEF (dist_close) AActor *target; @@ -4692,19 +4395,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) if (target == NULL) { // [KS] Let's not call P_CheckSight unnecessarily in this case. - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if ((flags & JLOSF_DEADNOJUMP) && (target->health <= 0)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } double distance = self->Distance3D(target); if (dist_max && (distance > dist_max)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } bool doCheckSight = !(flags & JLOSF_NOSIGHT); @@ -4713,7 +4416,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) { if (flags & JLOSF_CLOSENOJUMP) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if (flags & JLOSF_CLOSENOFOV) fov = 0.; @@ -4728,14 +4431,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) if (an > (fov / 2)) { - ACTION_RETURN_STATE(NULL); // [KS] Outside of FOV - return + ACTION_RETURN_BOOL(false); // [KS] Outside of FOV - return } } if (doCheckSight && !P_CheckSight (target, self, SF_IGNOREVISIBILITY)) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } - ACTION_RETURN_STATE(jump); + ACTION_RETURN_BOOL(true); } //=========================================================================== @@ -4746,15 +4449,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if ( self->player == NULL || self->player->ReadyWeapon == NULL ) { ACTION_RETURN_STATE(NULL); } PARAM_INT (count); - PARAM_STATE (jump); - PARAM_BOOL_OPT (dontincrement) { dontincrement = false; } + PARAM_STATE_ACTION (jump); + PARAM_BOOL_DEF (dontincrement); if (numret > 0) { @@ -4799,7 +4502,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) DEFINE_ACTION_FUNCTION(AActor, A_ResetReloadCounter) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player == NULL || self->player->ReadyWeapon == NULL) return 0; @@ -4830,27 +4533,51 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckFlag) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING (flagname); - PARAM_STATE (jumpto); - PARAM_INT_OPT (checkpointer) { checkpointer = AAPTR_DEFAULT; } + PARAM_INT_DEF (checkpointer); AActor *owner = COPY_AAPTR(self, checkpointer); - if (owner == NULL) - { - ACTION_RETURN_STATE(NULL); - } - - if (CheckActorFlag(owner, flagname)) - { - ACTION_RETURN_STATE(jumpto); - } - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(owner != nullptr && CheckActorFlag(owner, flagname)); } +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeCountFlags) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(kill); + PARAM_INT_DEF(item); + PARAM_INT_DEF(secret); + + if (self->CountsAsKill() && self->health > 0) --level.total_monsters; + if (self->flags & MF_COUNTITEM) --level.total_items; + if (self->flags5 & MF5_COUNTSECRET) --level.total_secrets; + + if (kill != -1) + { + if (kill == 0) self->flags &= ~MF_COUNTKILL; + else self->flags |= MF_COUNTKILL; + } + + if (item != -1) + { + if (item == 0) self->flags &= ~MF_COUNTITEM; + else self->flags |= MF_COUNTITEM; + } + + if (secret != -1) + { + if (secret == 0) self->flags5 &= ~MF5_COUNTSECRET; + else self->flags5 |= MF5_COUNTSECRET; + } + if (self->CountsAsKill() && self->health > 0) ++level.total_monsters; + if (self->flags & MF_COUNTITEM) ++level.total_items; + if (self->flags5 & MF5_COUNTSECRET) ++level.total_secrets; + return 0; +} + //=========================================================================== // // A_RaiseMaster @@ -4858,8 +4585,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) //=========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_RaiseMaster) { - PARAM_ACTION_PROLOGUE; - PARAM_BOOL_OPT(copy) { copy = false; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(copy); if (self->master != NULL) { @@ -4875,8 +4602,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseMaster) //=========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren) { - PARAM_ACTION_PROLOGUE; - PARAM_BOOL_OPT(copy) { copy = false; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(copy); TThinkerIterator it; AActor *mo; @@ -4898,8 +4625,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren) //=========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings) { - PARAM_ACTION_PROLOGUE; - PARAM_BOOL_OPT(copy) { copy = false; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(copy); TThinkerIterator it; AActor *mo; @@ -4917,18 +4644,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings) return 0; } - //=========================================================================== - // -// [TP] A_FaceConsolePlayer -// -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_FaceConsolePlayer) -{ - // NOTE: It does nothing for ZDoom, since in a multiplayer game, each - // node has its own console player. - return 0; -} - //=========================================================================== // // A_MonsterRefire @@ -4974,10 +4689,10 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) { - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(angle) { angle = 0; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF(angle); + PARAM_INT_DEF(flags); + PARAM_INT_DEF(ptr); AActor *ref = COPY_AAPTR(self, ptr); if (ref != NULL) @@ -4999,8 +4714,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(pitch); - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(flags); + PARAM_INT_DEF(ptr); AActor *ref = COPY_AAPTR(self, ptr); @@ -5023,8 +4738,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRoll) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT (roll); - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_INT_OPT (ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF (flags); + PARAM_INT_DEF (ptr) ; AActor *ref = COPY_AAPTR(self, ptr); if (ref != NULL) @@ -5046,7 +4761,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ScaleVelocity) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(scale); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(ptr); AActor *ref = COPY_AAPTR(self, ptr); @@ -5076,12 +4791,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ScaleVelocity) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity) { - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT (x) { x = 0; } - PARAM_FLOAT_OPT (y) { y = 0; } - PARAM_FLOAT_OPT (z) { z = 0; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_INT_OPT (ptr) { ptr = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF (x) + PARAM_FLOAT_DEF (y) + PARAM_FLOAT_DEF (z) + PARAM_INT_DEF (flags) + PARAM_INT_DEF (ptr) AActor *ref = COPY_AAPTR(self, ptr); @@ -5117,51 +4832,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity) return 0; } -//=========================================================================== -// -// A_SetArg -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetArg) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(pos); - PARAM_INT(value); - - // Set the value of the specified arg - if ((size_t)pos < countof(self->args)) - { - self->args[pos] = value; - } - return 0; -} - -//=========================================================================== -// -// A_SetSpecial -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecial) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (spec); - PARAM_INT_OPT (arg0) { arg0 = 0; } - PARAM_INT_OPT (arg1) { arg1 = 0; } - PARAM_INT_OPT (arg2) { arg2 = 0; } - PARAM_INT_OPT (arg3) { arg3 = 0; } - PARAM_INT_OPT (arg4) { arg4 = 0; } - - self->special = spec; - self->args[0] = arg0; - self->args[1] = arg1; - self->args[2] = arg2; - self->args[3] = arg3; - self->args[4] = arg4; - return 0; -} - //=========================================================================== // // A_SetUserVar @@ -5172,7 +4842,7 @@ static PField *GetVar(DObject *self, FName varname) { PField *var = dyn_cast(self->GetClass()->Symbols.FindSymbol(varname, true)); - if (var == NULL || (var->Flags & VARF_Native) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType))) + if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType))) { Printf("%s is not a user variable in class %s\n", varname.GetChars(), self->GetClass()->TypeName.GetChars()); @@ -5221,7 +4891,7 @@ static PField *GetArrayVar(DObject *self, FName varname, int pos) { PField *var = dyn_cast(self->GetClass()->Symbols.FindSymbol(varname, true)); - if (var == NULL || (var->Flags & VARF_Native) || + if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || !var->Type->IsKindOf(RUNTIME_CLASS(PArray)) || !static_cast(var->Type)->ElementType->IsKindOf(RUNTIME_CLASS(PBasicType))) { @@ -5301,14 +4971,14 @@ enum T_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) { - PARAM_ACTION_PROLOGUE; - PARAM_STATE_OPT (teleport_state) { teleport_state = NULL; } - PARAM_CLASS_OPT (target_type, ASpecialSpot) { target_type = PClass::FindActor("BossSpot"); } - PARAM_CLASS_OPT (fog_type, AActor) { fog_type = PClass::FindActor("TeleportFog"); } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FLOAT_OPT (mindist) { mindist = 128; } - PARAM_FLOAT_OPT (maxdist) { maxdist = 0; } - PARAM_INT_OPT (ptr) { ptr = AAPTR_DEFAULT; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_STATE_DEF (teleport_state) + PARAM_CLASS_DEF (target_type, ASpecialSpot) + PARAM_CLASS_DEF (fog_type, AActor) + PARAM_INT_DEF (flags) + PARAM_FLOAT_DEF (mindist) + PARAM_FLOAT_DEF (maxdist) + PARAM_INT_DEF (ptr) AActor *ref = COPY_AAPTR(self, ptr); @@ -5469,20 +5139,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) return numret; } -//=========================================================================== -// -// A_Turn -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Turn) -{ - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(angle) { angle = 0; } - self->Angles.Yaw += angle; - return 0; -} - //=========================================================================== // // A_Quake @@ -5496,7 +5152,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Quake) PARAM_INT (duration); PARAM_INT (damrad); PARAM_INT (tremrad); - PARAM_SOUND_OPT (sound) { sound = "world/quake"; } + PARAM_SOUND_DEF (sound); P_StartQuake(self, 0, intensity, duration, damrad, tremrad, sound); return 0; @@ -5519,15 +5175,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_QuakeEx) PARAM_INT(duration); PARAM_INT(damrad); PARAM_INT(tremrad); - PARAM_SOUND_OPT (sound) { sound = "world/quake"; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_FLOAT_OPT(mulWaveX) { mulWaveX = 1.; } - PARAM_FLOAT_OPT(mulWaveY) { mulWaveY = 1.; } - PARAM_FLOAT_OPT(mulWaveZ) { mulWaveZ = 1.; } - PARAM_INT_OPT(falloff) { falloff = 0; } - PARAM_INT_OPT(highpoint) { highpoint = 0; } - PARAM_FLOAT_OPT(rollIntensity) { rollIntensity = 0.; } - PARAM_FLOAT_OPT(rollWave) { rollWave = 0.; } + PARAM_SOUND_DEF(sound); + PARAM_INT_DEF(flags); + PARAM_FLOAT_DEF(mulWaveX); + PARAM_FLOAT_DEF(mulWaveY); + PARAM_FLOAT_DEF(mulWaveZ); + PARAM_INT_DEF(falloff); + PARAM_INT_DEF(highpoint); + PARAM_FLOAT_DEF(rollIntensity); + PARAM_FLOAT_DEF(rollWave); P_StartQuakeXYZ(self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ, falloff, highpoint, rollIntensity, rollWave); return 0; @@ -5605,9 +5261,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Weave) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LineEffect) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(special) { special = 0; } - PARAM_INT_OPT(tag) { tag = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(special); + PARAM_INT_DEF(tag); line_t junk; maplinedef_t oldjunk; @@ -5640,16 +5296,16 @@ enum WolfAttackFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_SOUND_OPT (sound) { sound = "weapons/pistol"; } - PARAM_FLOAT_OPT (snipe) { snipe = 1.; } - PARAM_INT_OPT (maxdamage) { maxdamage = 64; } - PARAM_INT_OPT (blocksize) { blocksize = 128; } - PARAM_INT_OPT (pointblank) { pointblank = 2; } - PARAM_INT_OPT (longrange) { longrange = 4; } - PARAM_FLOAT_OPT (runspeed) { runspeed = 160; } - PARAM_CLASS_OPT (pufftype, AActor) { pufftype = PClass::FindActor(NAME_BulletPuff); } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF (flags) + PARAM_SOUND_DEF (sound) + PARAM_FLOAT_DEF (snipe) + PARAM_INT_DEF (maxdamage) + PARAM_INT_DEF (blocksize) + PARAM_INT_DEF (pointblank) + PARAM_INT_DEF (longrange) + PARAM_FLOAT_DEF (runspeed) + PARAM_CLASS_DEF (pufftype, AActor) if (!self->target) return 0; @@ -5745,17 +5401,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(destination_selector); - PARAM_FLOAT_OPT(xofs) { xofs = 0; } - PARAM_FLOAT_OPT(yofs) { yofs = 0; } - PARAM_FLOAT_OPT(zofs) { zofs = 0; } - PARAM_ANGLE_OPT(angle) { angle = 0.; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_STATE_OPT(success_state) { success_state = NULL; } - PARAM_FLOAT_OPT(heightoffset) { heightoffset = 0; } - PARAM_FLOAT_OPT(radiusoffset) { radiusoffset = 0; } - PARAM_ANGLE_OPT(pitch) { pitch = 0.; } + PARAM_FLOAT_DEF(xofs) + PARAM_FLOAT_DEF(yofs) + PARAM_FLOAT_DEF(zofs) + PARAM_ANGLE_DEF(angle) + PARAM_INT_DEF(flags) + PARAM_STATE_DEF(success_state) + PARAM_FLOAT_DEF(heightoffset) + PARAM_FLOAT_DEF(radiusoffset) + PARAM_ANGLE_DEF(pitch) AActor *reference; @@ -5805,104 +5461,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) return numret; } -//========================================================================== -// -// ACS_Named* stuff - -// -// These are exactly like their un-named line special equivalents, except -// they take strings instead of integers to indicate which script to run. -// Some of these probably aren't very useful, but they are included for -// the sake of completeness. -// -//========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedExecuteWithResult) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_NAME (scriptname); - PARAM_INT_OPT (arg1) { arg1 = 0; } - PARAM_INT_OPT (arg2) { arg2 = 0; } - PARAM_INT_OPT (arg3) { arg3 = 0; } - PARAM_INT_OPT (arg4) { arg4 = 0; } - - int res = P_ExecuteSpecial(ACS_ExecuteWithResult, NULL, self, false, -scriptname, arg1, arg2, arg3, arg4); - ACTION_RETURN_INT(res); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedExecute) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_NAME (scriptname); - PARAM_INT_OPT (mapnum) { mapnum = 0; } - PARAM_INT_OPT (arg1) { arg1 = 0; } - PARAM_INT_OPT (arg2) { arg2 = 0; } - PARAM_INT_OPT (arg3) { arg3 = 0; } - - int res = P_ExecuteSpecial(ACS_Execute, NULL, self, false, -scriptname, mapnum, arg1, arg2, arg3); - ACTION_RETURN_INT(res); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedExecuteAlways) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_NAME (scriptname); - PARAM_INT_OPT (mapnum) { mapnum = 0; } - PARAM_INT_OPT (arg1) { arg1 = 0; } - PARAM_INT_OPT (arg2) { arg2 = 0; } - PARAM_INT_OPT (arg3) { arg3 = 0; } - - int res = P_ExecuteSpecial(ACS_ExecuteAlways, NULL, self, false, -scriptname, mapnum, arg1, arg2, arg3); - ACTION_RETURN_INT(res); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedLockedExecute) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_NAME (scriptname); - PARAM_INT_OPT (mapnum) { mapnum = 0; } - PARAM_INT_OPT (arg1) { arg1 = 0; } - PARAM_INT_OPT (arg2) { arg2 = 0; } - PARAM_INT_OPT (lock) { lock = 0; } - - int res = P_ExecuteSpecial(ACS_LockedExecute, NULL, self, false, -scriptname, mapnum, arg1, arg2, lock); - ACTION_RETURN_INT(res); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedLockedExecuteDoor) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_NAME (scriptname); - PARAM_INT_OPT (mapnum) { mapnum = 0; } - PARAM_INT_OPT (arg1) { arg1 = 0; } - PARAM_INT_OPT (arg2) { arg2 = 0; } - PARAM_INT_OPT (lock) { lock = 0; } - - int res = P_ExecuteSpecial(ACS_LockedExecuteDoor, NULL, self, false, -scriptname, mapnum, arg1, arg2, lock); - ACTION_RETURN_INT(res); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedSuspend) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_NAME (scriptname); - PARAM_INT_OPT (mapnum) { mapnum = 0; } - - int res = P_ExecuteSpecial(ACS_Suspend, NULL, self, false, -scriptname, mapnum, 0, 0, 0); - ACTION_RETURN_INT(res); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedTerminate) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_NAME (scriptname); - PARAM_INT_OPT (mapnum) { mapnum = 0; } - - int res = P_ExecuteSpecial(ACS_Terminate, NULL, self, false, -scriptname, mapnum, 0, 0, 0); - ACTION_RETURN_INT(res); -} - - static bool DoCheckSpecies(AActor *mo, FName filterSpecies, bool exclude) { FName actorSpecies = mo->GetSpecies(); @@ -6099,11 +5657,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) PARAM_CLASS (item, AInventory); PARAM_FLOAT (distance); PARAM_INT (flags); - PARAM_INT_OPT (amount) { amount = 0; } - PARAM_CLASS_OPT (filter, AActor) { filter = nullptr; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_FLOAT_OPT (mindist) { mindist = 0; } - PARAM_INT_OPT (limit) { limit = 0; } + PARAM_INT_DEF (amount); + PARAM_CLASS_DEF (filter, AActor); + PARAM_NAME_DEF (species); + PARAM_FLOAT_DEF (mindist); + PARAM_INT_DEF (limit); // We need a valid item, valid targets, and a valid range if (item == nullptr || (flags & RGF_MASK) == 0 || !flags || distance <= 0 || mindist >= distance) @@ -6140,27 +5698,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) ACTION_RETURN_INT(given); } -//=========================================================================== -// -// A_CheckSpecies -// -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSpecies) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(jump); - PARAM_NAME_OPT(species) { species = NAME_None; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - - AActor *mobj = COPY_AAPTR(self, ptr); - - if (mobj != NULL && jump && mobj->GetSpecies() == species) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); -} - //========================================================================== // // A_SetTics @@ -6169,7 +5706,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSpecies) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(tics_to_set); if (ACTION_CALL_FROM_PSPRITE()) @@ -6190,21 +5727,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics) return 0; } -//========================================================================== -// -// A_SetDamageType -// -//========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetDamageType) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_NAME(damagetype); - - self->DamageType = damagetype; - return 0; -} - //========================================================================== // // A_DropItem @@ -6215,77 +5737,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (spawntype, AActor); - PARAM_INT_OPT (amount) { amount = -1; } - PARAM_INT_OPT (chance) { chance = 256; } + PARAM_INT_DEF(amount); + PARAM_INT_DEF(chance); P_DropItem(self, spawntype, amount, chance); return 0; } -//========================================================================== -// -// A_SetSpeed -// -//========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT(speed); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - - AActor *ref = COPY_AAPTR(self, ptr); - - if (ref != NULL) - { - ref->Speed = speed; - } - return 0; -} - -//========================================================================== -// -// A_SetFloatSpeed -// -//========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatSpeed) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT(speed); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - - AActor *ref = COPY_AAPTR(self, ptr); - - if (!ref) - { - return 0; - } - - ref->FloatSpeed = speed; - return 0; -} - -//========================================================================== -// -// A_SetPainThreshold -// -//========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPainThreshold) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(threshold); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - - AActor *ref = COPY_AAPTR(self, ptr); - - if (!ref) - { - return 0; - } - - ref->PainThreshold = threshold; - return 0; -} - //=========================================================================== // // Common A_Damage handler @@ -6360,12 +5818,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6383,12 +5841,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6407,12 +5865,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6431,12 +5889,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6455,12 +5913,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6485,12 +5943,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6566,13 +6024,13 @@ static void DoKill(AActor *killtarget, AActor *inflictor, AActor *source, FName //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) { - PARAM_ACTION_PROLOGUE; - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6589,13 +6047,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) { - PARAM_ACTION_PROLOGUE; - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6612,15 +6070,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) { - PARAM_ACTION_PROLOGUE; - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) - AActor *source = COPY_AAPTR(self, src); + AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); if (self->master != NULL) @@ -6635,13 +6093,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) { - PARAM_ACTION_PROLOGUE; - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6666,13 +6124,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) { - PARAM_ACTION_PROLOGUE; - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } - PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } - PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_NAME_DEF (damagetype) + PARAM_INT_DEF (flags) + PARAM_CLASS_DEF (filter, AActor) + PARAM_NAME_DEF (species) + PARAM_INT_DEF (src) + PARAM_INT_DEF (inflict) AActor *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); @@ -6742,10 +6200,10 @@ static void DoRemove(AActor *removetarget, int flags, PClassActor *filter, FName //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); if (self->target != NULL) { @@ -6761,10 +6219,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); if (self->tracer != NULL) { @@ -6780,10 +6238,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); if (self->master != NULL) { @@ -6799,11 +6257,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) { - PARAM_ACTION_PROLOGUE; - PARAM_BOOL_OPT (removeall) { removeall = false; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(removeall); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); TThinkerIterator it; AActor *mo; @@ -6825,11 +6283,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings) { - PARAM_ACTION_PROLOGUE; - PARAM_BOOL_OPT (removeall) { removeall = false; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(removeall); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); TThinkerIterator it; AActor *mo; @@ -6855,10 +6313,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Remove) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (removee); - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT(removee); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); AActor *reference = COPY_AAPTR(self, removee); if (reference != NULL) @@ -6896,7 +6354,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTeleFog) DEFINE_ACTION_FUNCTION(AActor, A_SwapTeleFog) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if ((self->TeleFogSourceType != self->TeleFogDestType)) //Does nothing if they're the same. { PClassActor *temp = self->TeleFogSourceType; @@ -6913,18 +6371,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_SwapTeleFog) // Changes the FloatBobPhase of the actor. //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatBobPhase) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(bob); - - //Respect float bob phase limits. - if (self && (bob >= 0 && bob <= 63)) - { - self->FloatBobPhase = bob; - } - return 0; -} //=========================================================================== // A_SetHealth @@ -6937,7 +6383,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetHealth) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (health); - PARAM_INT_OPT (ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF (ptr); AActor *mobj = COPY_AAPTR(self, ptr); @@ -6973,8 +6419,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetHealth) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); @@ -6995,44 +6441,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) return 0; } -//=========================================================================== -// A_JumpIfHigherOrLower -// -// Jumps if a target, master, or tracer is higher or lower than the calling -// actor. Can also specify how much higher/lower the actor needs to be than -// itself. Can also take into account the height of the actor in question, -// depending on which it's checking. This means adding height of the -// calling actor's self if the pointer is higher, or height of the pointer -// if its lower. -//=========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHigherOrLower) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(high); - PARAM_STATE(low); - PARAM_FLOAT_OPT(offsethigh) { offsethigh = 0; } - PARAM_FLOAT_OPT(offsetlow) { offsetlow = 0; } - PARAM_BOOL_OPT(includeHeight) { includeHeight = true; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_TARGET; } - - AActor *mobj = COPY_AAPTR(self, ptr); - - - if (mobj != NULL && mobj != self) //AAPTR_DEFAULT is completely useless in this regard. - { - if ((high) && (mobj->Z() > ((includeHeight ? self->Height : 0) + self->Z() + offsethigh))) - { - ACTION_RETURN_STATE(high); - } - else if ((low) && (mobj->Z() + (includeHeight ? mobj->Height : 0)) < (self->Z() + offsetlow)) - { - ACTION_RETURN_STATE(low); - } - } - ACTION_RETURN_STATE(NULL); -} - //=========================================================================== // A_SetSpecies(str species, ptr) // @@ -7042,7 +6450,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecies) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME(species); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); if (!mobj) @@ -7054,48 +6462,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecies) return 0; } -//=========================================================================== -// -// A_SetRipperLevel(int level) -// -// Sets the ripper level of the calling actor. -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipperLevel) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(level); - self->RipperLevel = level; - return 0; -} - -//=========================================================================== -// -// A_SetRipMin(int min) -// -// Sets the minimum level a ripper must be in order to rip through this actor. -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipMin) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(min); - self->RipLevelMin = min; - return 0; -} - -//=========================================================================== -// -// A_SetRipMax(int max) -// -// Sets the minimum level a ripper must be in order to rip through this actor. -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipMax) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(max); - self->RipLevelMax = max; - return 0; -} - //=========================================================================== // // A_SetChaseThreshold(int threshold, bool def, int ptr) @@ -7108,8 +6474,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetChaseThreshold) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(threshold); - PARAM_BOOL_OPT(def) { def = false; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_BOOL_DEF(def); + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); @@ -7131,29 +6497,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetChaseThreshold) // Checks to see if a certain actor class is close to the // actor/pointer within distance, in numbers. //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckProximity) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(jump); PARAM_CLASS(classname, AActor); PARAM_FLOAT(distance); - PARAM_INT_OPT(count) { count = 1; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(count); + PARAM_INT_DEF(flags); + PARAM_INT_DEF(ptr); - if (!jump) - { - if (!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER))) - { - ACTION_RETURN_STATE(NULL); - } - } - - if (P_Thing_CheckProximity(self, classname, distance, count, flags, ptr) && jump) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(!!P_Thing_CheckProximity(self, classname, distance, count, flags, ptr)); } /*=========================================================================== @@ -7177,23 +6530,22 @@ enum CBF CBF_ABSOLUTEANGLE = 1 << 8, //Absolute angle for offsets. }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckBlock) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(block) - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - PARAM_FLOAT_OPT(xofs) { xofs = 0; } - PARAM_FLOAT_OPT(yofs) { yofs = 0; } - PARAM_FLOAT_OPT(zofs) { zofs = 0; } - PARAM_ANGLE_OPT(angle) { angle = 0.; } + PARAM_INT_DEF(flags) + PARAM_INT_DEF(ptr) + PARAM_FLOAT_DEF(xofs) + PARAM_FLOAT_DEF(yofs) + PARAM_FLOAT_DEF(zofs) + PARAM_ANGLE_DEF(angle) AActor *mobj = COPY_AAPTR(self, ptr); //Needs at least one state jump to work. if (!mobj) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if (!(flags & CBF_ABSOLUTEANGLE)) @@ -7243,7 +6595,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) if (checker) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if (mobj->BlockingMobj) @@ -7257,23 +6609,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) } } - //[MC] If modders don't want jumping, but just getting the pointer, only abort at - //this point. I.e. A_CheckBlock("",CBF_SETTRACER) is like having CBF_NOLINES. - //It gets the mobj blocking, if any, and doesn't jump at all. - if (!block) - { - ACTION_RETURN_STATE(NULL); - } //[MC] I don't know why I let myself be persuaded not to include a flag. //If an actor is loaded with pointers, they don't really have any options to spare. //Also, fail if a dropoff or a step is too great to pass over when checking for dropoffs. - if ((!(flags & CBF_NOACTORS) && (mobj->BlockingMobj)) || (!(flags & CBF_NOLINES) && mobj->BlockingLine != NULL) || - ((flags & CBF_DROPOFF) && !checker)) - { - ACTION_RETURN_STATE(block); - } - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL((!(flags & CBF_NOACTORS) && (mobj->BlockingMobj)) || (!(flags & CBF_NOLINES) && mobj->BlockingLine != NULL) || + ((flags & CBF_DROPOFF) && !checker)); } //=========================================================================== @@ -7290,12 +6631,12 @@ enum FMDFlags }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection) { - PARAM_ACTION_PROLOGUE; - PARAM_ANGLE_OPT(offset) { offset = 0.; } - PARAM_ANGLE_OPT(anglelimit) { anglelimit = 0.; } - PARAM_ANGLE_OPT(pitchlimit) { pitchlimit = 0.; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_ANGLE_DEF(offset) + PARAM_ANGLE_DEF(anglelimit) + PARAM_ANGLE_DEF(pitchlimit) + PARAM_INT_DEF(flags) + PARAM_INT_DEF(ptr) AActor *mobj = COPY_AAPTR(self, ptr); @@ -7384,10 +6725,10 @@ enum CPSFFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT(from); PARAM_INT(to); - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_INT_DEF(flags); AActor *copyfrom = COPY_AAPTR(self, from); AActor *copyto = COPY_AAPTR(self, to); @@ -7402,52 +6743,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame) ACTION_RETURN_BOOL(true); } -//========================================================================== -// -// A_SetSpriteAngle(angle, ptr) -// -// Specifies which angle the actor must always draw its sprite from. -//========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpriteAngle) -{ - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(angle) { angle = 0.; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - - AActor *mobj = COPY_AAPTR(self, ptr); - - if (mobj == nullptr) - { - ACTION_RETURN_BOOL(false); - } - mobj->SpriteAngle = angle; - ACTION_RETURN_BOOL(true); -} - -//========================================================================== -// -// A_SetSpriteRotation(angle, ptr) -// -// Specifies how much to fake a sprite rotation. -//========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpriteRotation) -{ - PARAM_ACTION_PROLOGUE; - PARAM_ANGLE_OPT(angle) { angle = 0.; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - - AActor *mobj = COPY_AAPTR(self, ptr); - - if (mobj == nullptr) - { - ACTION_RETURN_BOOL(false); - } - mobj->SpriteRotation = angle; - ACTION_RETURN_BOOL(true); -} - //========================================================================== // // A_SetMaskRotation(anglestart, angleend, pitchstart, pitchend, flags, ptr) @@ -7465,13 +6760,13 @@ enum VRFFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetVisibleRotation) { - PARAM_ACTION_PROLOGUE; - PARAM_ANGLE_OPT(anglestart) { anglestart = 0.; } - PARAM_ANGLE_OPT(angleend) { angleend = 0.; } - PARAM_ANGLE_OPT(pitchstart) { pitchstart = 0.; } - PARAM_ANGLE_OPT(pitchend) { pitchend = 0.; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_ANGLE_DEF(anglestart) + PARAM_ANGLE_DEF(angleend) + PARAM_ANGLE_DEF(pitchstart) + PARAM_ANGLE_DEF(pitchend) + PARAM_INT_DEF(flags) + PARAM_INT_DEF(ptr) AActor *mobj = COPY_AAPTR(self, ptr); diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index 7e65bf05d..b3526c60d 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -865,7 +865,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS (ACustomSprite) +IMPLEMENT_CLASS(ACustomSprite, false, false, false, false) void ACustomSprite::BeginPlay () { diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 29b0c5095..d22dd6371 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -38,7 +38,7 @@ // //============================================================================ -IMPLEMENT_CLASS (DCeiling) +IMPLEMENT_CLASS(DCeiling, false, false, false, false) DCeiling::DCeiling () { diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 0bc2b98a8..5b37268b8 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -1103,7 +1103,7 @@ public: }; -IMPLEMENT_ABSTRACT_CLASS(DConversationMenu) +IMPLEMENT_CLASS(DConversationMenu, true, false, false, false) int DConversationMenu::mSelection; // needs to be preserved if the same dialogue is restarted diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 33e37218d..542308fa6 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -45,7 +45,7 @@ // //============================================================================ -IMPLEMENT_CLASS (DDoor) +IMPLEMENT_CLASS(DDoor, false, false, false, false) DDoor::DDoor () { @@ -513,7 +513,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing, // //============================================================================ -IMPLEMENT_CLASS (DAnimatedDoor) +IMPLEMENT_CLASS(DAnimatedDoor, false, false, false, false) DAnimatedDoor::DAnimatedDoor () { diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index b7ad54095..cbddb4840 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -43,7 +43,7 @@ #include "p_enemy.h" #include "a_sharedglobal.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "d_dehacked.h" #include "g_level.h" #include "r_utility.h" @@ -53,6 +53,7 @@ #include "p_spec.h" #include "p_checkposition.h" #include "math/cmath.h" +#include "vm.h" #include "gi.h" @@ -309,6 +310,12 @@ bool AActor::CheckMeleeRange () return true; } +DEFINE_ACTION_FUNCTION(AActor, CheckMeleeRange) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(self->CheckMeleeRange()); +} + //---------------------------------------------------------------------------- // // FUNC P_CheckMeleeRange2 @@ -407,6 +414,12 @@ bool P_CheckMissileRange (AActor *actor) return actor->SuggestMissileAttack (dist); } +DEFINE_ACTION_FUNCTION(AActor, CheckMissileRange) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(P_CheckMissileRange(self)); +} + bool AActor::SuggestMissileAttack (double dist) { // new version encapsulates the different behavior in flags instead of virtual functions @@ -454,6 +467,12 @@ bool P_HitFriend(AActor * self) return false; } +DEFINE_ACTION_FUNCTION(AActor, HitFriend) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(P_HitFriend(self)); +} + // // P_Move // Move in the current direction, @@ -694,6 +713,11 @@ bool P_Move (AActor *actor) } return true; } +DEFINE_ACTION_FUNCTION(AActor, MonsterMove) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(P_Move(self)); +} //============================================================================= @@ -1017,7 +1041,12 @@ void P_NewChaseDir(AActor * actor) } - +DEFINE_ACTION_FUNCTION(AActor, NewChaseDir) +{ + PARAM_SELF_PROLOGUE(AActor); + P_NewChaseDir(self); + return 0; +} //============================================================================= @@ -1777,6 +1806,13 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) } } +DEFINE_ACTION_FUNCTION(AActor, LookForPlayers) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL(allaround); + ACTION_RETURN_BOOL(P_LookForPlayers(self, allaround, nullptr)); +} + // // ACTION ROUTINES // @@ -1788,7 +1824,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) // DEFINE_ACTION_FUNCTION(AActor, A_Look) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *targ; @@ -1908,13 +1944,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FLOAT_OPT (minseedist) { minseedist = 0; } - PARAM_FLOAT_OPT (maxseedist) { maxseedist = 0; } - PARAM_FLOAT_OPT (maxheardist) { maxheardist = 0; } - PARAM_ANGLE_OPT (fov) { fov = 0.; } - PARAM_STATE_OPT (seestate) { seestate = NULL; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF (flags) + PARAM_FLOAT_DEF (minseedist) + PARAM_FLOAT_DEF (maxseedist) + PARAM_FLOAT_DEF (maxheardist) + PARAM_ANGLE_DEF (fov) + PARAM_STATE_DEF (seestate) AActor *targ = NULL; // Shuts up gcc double dist; @@ -2100,7 +2136,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) DEFINE_ACTION_FUNCTION(AActor, A_ClearLastHeard) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->LastHeard = NULL; return 0; } @@ -2125,8 +2161,8 @@ enum ChaseFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Wander) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(flags); A_Wander(self, flags); return 0; } @@ -2185,7 +2221,7 @@ void A_Wander(AActor *self, int flags) //========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_Look2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *targ; @@ -2487,7 +2523,7 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele DAngle ang = actor->AngleTo(actor->target); if (pr_chase() < 128) ang += 90.; else ang -= 90.; - actor->VelFromAngle(ang, 13.); + actor->VelFromAngle(13., ang); actor->FastChaseStrafeCount = 3; // strafe time } } @@ -2767,12 +2803,12 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) { - PARAM_ACTION_PROLOGUE; - PARAM_STATE_OPT (melee) { melee = NULL; } - PARAM_STATE_OPT (missile) { missile = NULL; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_STATE_DEF (melee) + PARAM_STATE_DEF (missile) + PARAM_INT_DEF (flags) - if (numparam >= NAP + 1) + if (numparam > 1) { if ((flags & CHF_RESURRECT) && P_CheckForResurrection(self, false)) return 0; @@ -2789,14 +2825,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) DEFINE_ACTION_FUNCTION(AActor, A_FastChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_DoChase(stack, self, true, self->MeleeState, self->MissileState, true, true, false, 0); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_VileChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!P_CheckForResurrection(self, true)) { A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); @@ -2809,8 +2845,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ExtChase) PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL (domelee); PARAM_BOOL (domissile); - PARAM_BOOL_OPT (playactive) { playactive = true; } - PARAM_BOOL_OPT (nightmarefast) { nightmarefast = false; } + PARAM_BOOL_DEF (playactive); + PARAM_BOOL_DEF (nightmarefast); // Now that A_Chase can handle state label parameters, this function has become rather useless... A_DoChase(stack, self, false, @@ -2944,45 +2980,18 @@ void A_FaceTarget(AActor *self) A_Face(self, self->target); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Face) { - PARAM_ACTION_PROLOGUE; - PARAM_ANGLE_OPT(max_turn) { max_turn = 0.; } - PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270.; } - PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0.; } - PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0.; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_FLOAT_OPT(z_add) { z_add = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(faceto, AActor) + PARAM_ANGLE_DEF(max_turn) + PARAM_ANGLE_DEF(max_pitch) + PARAM_ANGLE_DEF(ang_offset) + PARAM_ANGLE_DEF(pitch_offset) + PARAM_INT_DEF(flags) + PARAM_FLOAT_DEF(z_add) - A_Face(self, self->target, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster) -{ - PARAM_ACTION_PROLOGUE; - PARAM_ANGLE_OPT(max_turn) { max_turn = 0.; } - PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270.; } - PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0.; } - PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0.; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_FLOAT_OPT(z_add) { z_add = 0; } - - A_Face(self, self->master, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer) -{ - PARAM_ACTION_PROLOGUE; - PARAM_ANGLE_OPT(max_turn) { max_turn = 0.; } - PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270.; } - PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0.; } - PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0.; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_FLOAT_OPT(z_add) { z_add = 0; } - - A_Face(self, self->tracer, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); + A_Face(self, faceto, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); return 0; } @@ -2995,7 +3004,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer) //=========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; @@ -3041,7 +3050,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) DEFINE_ACTION_FUNCTION(AActor, A_Scream) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->DeathSound) { // Check for bosses. @@ -3060,7 +3069,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Scream) DEFINE_ACTION_FUNCTION(AActor, A_XScream) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player) S_Sound (self, CHAN_VOICE, "*gibbed", 1, ATTN_NORM); else @@ -3068,20 +3077,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_XScream) return 0; } -//=========================================================================== -// -// A_ScreamAndUnblock -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_ScreamAndUnblock) -{ - PARAM_ACTION_PROLOGUE; - CALL_ACTION(A_Scream, self); - A_Unblock(self, true); - return 0; -} - //=========================================================================== // // A_ActiveSound @@ -3090,28 +3085,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_ScreamAndUnblock) DEFINE_ACTION_FUNCTION(AActor, A_ActiveSound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->ActiveSound) { - S_Sound (self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM); + S_Sound(self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM); } return 0; } -//=========================================================================== -// -// A_ActiveAndUnblock -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_ActiveAndUnblock) -{ - PARAM_ACTION_PROLOGUE; - CALL_ACTION(A_ActiveSound, self); - A_Unblock(self, true); - return 0; -} - //--------------------------------------------------------------------------- // // Modifies the drop amount of this item according to the current skill's @@ -3256,7 +3237,7 @@ void P_TossItem (AActor *item) DEFINE_ACTION_FUNCTION(AActor, A_Pain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // [RH] Vary player pain sounds depending on health (ala Quake2) if (self->player && self->player->morphTics == 0) @@ -3302,16 +3283,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain) return 0; } -// killough 11/98: kill an object -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Die) -{ - PARAM_ACTION_PROLOGUE; - PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } - - P_DamageMobj(self, NULL, NULL, self->health, damagetype, DMG_FORCED); - return 0; -} - // // A_Detonate // killough 8/9/98: same as A_Explode, except that the damage is variable @@ -3319,7 +3290,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Die) DEFINE_ACTION_FUNCTION(AActor, A_Detonate) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int damage = self->GetMissileDamage(0, 1); P_RadiusAttack (self, self->target, damage, damage, self->DamageType, RADF_HURTSOURCE); P_CheckSplash(self, damage); @@ -3462,7 +3433,7 @@ void A_BossDeath(AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_BossDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_BossDeath(self); return 0; } @@ -3540,7 +3511,7 @@ bool A_RaiseMobj (AActor *actor, double speed) DEFINE_ACTION_FUNCTION(AActor, A_ClassBossHealth) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (multiplayer && !deathmatch) // co-op only { if (!self->special1) diff --git a/src/p_enemy.h b/src/p_enemy.h index 1be77a4ec..7f4424fd6 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -1,7 +1,8 @@ #ifndef __P_ENEMY_H__ #define __P_ENEMY_H__ -#include "thingdef/thingdef.h" +#include "vm.h" +#include "vectors.h" struct sector_t; class AActor; diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 62479e340..7b5ff5cc9 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -64,7 +64,7 @@ static void StartFloorSound (sector_t *sec) // //========================================================================== -IMPLEMENT_CLASS (DFloor) +IMPLEMENT_CLASS(DFloor, false, false, false, false) DFloor::DFloor () { @@ -815,10 +815,12 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed) // //========================================================================== -IMPLEMENT_POINTY_CLASS (DElevator) - DECLARE_POINTER(m_Interp_Floor) - DECLARE_POINTER(m_Interp_Ceiling) -END_POINTERS +IMPLEMENT_CLASS(DElevator, false, true, false, false) + +IMPLEMENT_POINTERS_START(DElevator) + IMPLEMENT_POINTER(m_Interp_Floor) + IMPLEMENT_POINTER(m_Interp_Ceiling) +IMPLEMENT_POINTERS_END DElevator::DElevator () { @@ -1103,10 +1105,9 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag) // //========================================================================== -IMPLEMENT_CLASS (DWaggleBase) - -IMPLEMENT_CLASS (DFloorWaggle) -IMPLEMENT_CLASS (DCeilingWaggle) +IMPLEMENT_CLASS(DWaggleBase, false, false, false, false) +IMPLEMENT_CLASS(DFloorWaggle, false, false, false, false) +IMPLEMENT_CLASS(DCeilingWaggle, false, false, false, false) DWaggleBase::DWaggleBase () { diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 261cfb8f3..48d13bebf 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1242,6 +1242,11 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // if (player) { + // Don't allow DMG_FORCED to work on ultimate degreeslessness/buddha and nodamage. + if ((player->cheats & (CF_GODMODE2 | CF_BUDDHA2)) || (player->mo->flags5 & MF5_NODAMAGE)) + { + flags &= ~DMG_FORCED; + } //Added by MC: Lets bots look allround for enemies if they survive an ambush. if (player->Bot != NULL) { @@ -1555,6 +1560,18 @@ dopain: return damage; } +DEFINE_ACTION_FUNCTION(AActor, DamageMobj) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(inflictor, AActor); + PARAM_OBJECT(source, AActor); + PARAM_INT(damage); + PARAM_NAME(mod); + PARAM_INT_DEF(flags); + PARAM_FLOAT_DEF(angle); + ACTION_RETURN_INT(P_DamageMobj(self, inflictor, source, damage, mod, flags, angle)); +} + void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int duration, int period, FName type) { // Check for invulnerability. diff --git a/src/p_lights.cpp b/src/p_lights.cpp index fb3ab339e..c44a22d4b 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -173,7 +173,7 @@ private: // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DLighting) +IMPLEMENT_CLASS(DLighting, false, false, false, false) DLighting::DLighting () { @@ -191,7 +191,7 @@ DLighting::DLighting (sector_t *sector) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DFireFlicker) +IMPLEMENT_CLASS(DFireFlicker, false, false, false, false) DFireFlicker::DFireFlicker () { @@ -258,7 +258,7 @@ DFireFlicker::DFireFlicker (sector_t *sector, int upper, int lower) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DFlicker) +IMPLEMENT_CLASS(DFlicker, false, false, false, false) DFlicker::DFlicker () { @@ -334,7 +334,7 @@ void EV_StartLightFlickering (int tag, int upper, int lower) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DLightFlash) +IMPLEMENT_CLASS(DLightFlash, false, false, false, false) DLightFlash::DLightFlash () { @@ -409,7 +409,7 @@ DLightFlash::DLightFlash (sector_t *sector, int min, int max) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DStrobe) +IMPLEMENT_CLASS(DStrobe, false, false, false, false) DStrobe::DStrobe () { @@ -667,7 +667,7 @@ void EV_LightChange (int tag, int value) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DGlow) +IMPLEMENT_CLASS(DGlow, false, false, false, false) DGlow::DGlow () { @@ -736,7 +736,7 @@ DGlow::DGlow (sector_t *sector) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DGlow2) +IMPLEMENT_CLASS(DGlow2, false, false, false, false) DGlow2::DGlow2 () { @@ -869,7 +869,7 @@ void EV_StartLightFading (int tag, int value, int tics) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DPhased) +IMPLEMENT_CLASS(DPhased, false, false, false, false) DPhased::DPhased () { diff --git a/src/p_map.cpp b/src/p_map.cpp index 5cc9bdf72..d7bffa589 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -444,6 +444,17 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi return true; } +DEFINE_ACTION_FUNCTION(AActor, TeleportMove) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_BOOL(telefrag); + PARAM_BOOL_DEF(modify); + ACTION_RETURN_BOOL(P_TeleportMove(self, DVector3(x, y, z), telefrag, modify)); +} + //========================================================================== // // [RH] P_PlayerStartStomp @@ -4043,6 +4054,18 @@ DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLin return result->linetarget ? result->pitch : t1->Angles.Pitch; } +DEFINE_ACTION_FUNCTION(AActor, AimLineAttack) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_ANGLE(angle); + PARAM_FLOAT(distance); + PARAM_POINTER_DEF(pLineTarget, FTranslatedLineTarget); + PARAM_ANGLE_DEF(vrange); + PARAM_INT_DEF(flags); + PARAM_OBJECT_DEF(target, AActor); + PARAM_OBJECT_DEF(friender, AActor); + ACTION_RETURN_FLOAT(P_AimLineAttack(self, angle, distance, pLineTarget, vrange, flags, target, friender).Degrees); +} //========================================================================== // @@ -4410,6 +4433,25 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } } +DEFINE_ACTION_FUNCTION(AActor, LineAttack) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_ANGLE(angle); + PARAM_FLOAT(distance); + PARAM_ANGLE(pitch); + PARAM_INT(damage); + PARAM_NAME(damageType); + PARAM_CLASS(puffType, AActor); + PARAM_INT_DEF(flags); + PARAM_POINTER_DEF(victim, FTranslatedLineTarget); + + int acdmg; + auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg); + if (numret > 0) ret[0].SetPointer(puff, ATAG_OBJECT); + if (numret > 1) ret[1].SetInt(acdmg), numret = 2; + return numret; +} + //========================================================================== // // P_LinePickActor @@ -4574,6 +4616,16 @@ void P_TraceBleed(int damage, AActor *target, AActor *missile) P_TraceBleed(damage, target->PosPlusZ(target->Height/2), target, missile->AngleTo(target), pitch); } +DEFINE_ACTION_FUNCTION(AActor, TraceBleed) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(damage); + PARAM_OBJECT(missile, AActor); + + P_TraceBleed(damage, self, missile); + return 0; +} + //========================================================================== // // diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index a3d4d0e9e..0a1d831d8 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -386,6 +386,14 @@ bool AActor::FixMapthingPos() return success; } +DEFINE_ACTION_FUNCTION(AActor, UnlinkFromWorld) +{ + PARAM_SELF_PROLOGUE(AActor); + self->UnlinkFromWorld(); + return 0; +} + + //========================================================================== // // P_SetThingPosition @@ -508,6 +516,13 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector) if (!spawningmapthing) UpdateRenderSectorList(); } +DEFINE_ACTION_FUNCTION(AActor, LinkToWorld) +{ + PARAM_SELF_PROLOGUE(AActor); + self->LinkToWorld(); + return 0; +} + void AActor::SetOrigin(double x, double y, double z, bool moving) { UnlinkFromWorld (); @@ -517,6 +532,17 @@ void AActor::SetOrigin(double x, double y, double z, bool moving) if (!moving) ClearInterpolation(); } +DEFINE_ACTION_FUNCTION(AActor, SetOrigin) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_BOOL(moving); + self->SetOrigin(x, y, z, moving); + return 0; +} + //=========================================================================== // // FBlockNode - allows to link actors into multiple blocks in the blockmap diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3e2011878..ce74684cc 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -53,7 +53,7 @@ #include "a_action.h" #include "a_keys.h" #include "p_conversation.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_game.h" #include "teaminfo.h" #include "r_data/r_translate.h" @@ -71,6 +71,8 @@ #include "p_checkposition.h" #include "serializer.h" #include "r_utility.h" +#include "thingdef.h" +#include "virtual.h" // MACROS ------------------------------------------------------------------ @@ -130,19 +132,21 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- -IMPLEMENT_POINTY_CLASS (AActor) - DECLARE_POINTER (target) - DECLARE_POINTER (lastenemy) - DECLARE_POINTER (tracer) - DECLARE_POINTER (goal) - DECLARE_POINTER (LastLookActor) - DECLARE_POINTER (Inventory) - DECLARE_POINTER (LastHeard) - DECLARE_POINTER (master) - DECLARE_POINTER (Poisoner) - DECLARE_POINTER (DamageFunc) - DECLARE_POINTER (alternative) -END_POINTERS +IMPLEMENT_CLASS(AActor, false, true, true, true) + +IMPLEMENT_POINTERS_START(AActor) + IMPLEMENT_POINTER(target) + IMPLEMENT_POINTER(lastenemy) + IMPLEMENT_POINTER(tracer) + IMPLEMENT_POINTER(goal) + IMPLEMENT_POINTER(LastLookActor) + IMPLEMENT_POINTER(Inventory) + IMPLEMENT_POINTER(LastHeard) + IMPLEMENT_POINTER(master) + IMPLEMENT_POINTER(Poisoner) + IMPLEMENT_POINTER(DamageFunc) + IMPLEMENT_POINTER(alternative) +IMPLEMENT_POINTERS_END AActor::~AActor () { @@ -150,6 +154,186 @@ AActor::~AActor () // Use Destroy() instead. } +extern FFlagDef InternalActorFlagDefs[]; +extern FFlagDef ActorFlagDefs[]; + +void AActor::InitNativeFields() +{ + PType *TypePlayer = NewPointer(TypeVoid); // placeholder + PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); + PType *TypeActorClass = NewClassPointer(RUNTIME_CLASS(AActor)); + PType *TypeInventory = NewPointer(RUNTIME_CLASS(AInventory)); + PStruct *sstruct = NewStruct("Sector", nullptr); + auto TypeSector = NewPointer(sstruct); + PType *array5 = NewArray(TypeSInt32, 5); + + auto meta = RUNTIME_CLASS(AActor); + + meta->AddNativeField("Player", TypePlayer, myoffsetof(AActor, player)); + meta->AddNativeField("Pos", TypeVector3, myoffsetof(AActor, __Pos), VARF_ReadOnly); + meta->AddNativeField(NAME_X, TypeFloat64, myoffsetof(AActor, __Pos.X), VARF_ReadOnly | VARF_Deprecated); // must remain read-only! + meta->AddNativeField(NAME_Y, TypeFloat64, myoffsetof(AActor, __Pos.Y), VARF_ReadOnly | VARF_Deprecated); // must remain read-only! + meta->AddNativeField(NAME_Z, TypeFloat64, myoffsetof(AActor, __Pos.Z), VARF_ReadOnly | VARF_Deprecated); // must remain read-only! + meta->AddNativeField("Prev", TypeVector3, myoffsetof(AActor, Prev)); + meta->AddNativeField("spriteAngle", TypeFloat64, myoffsetof(AActor, SpriteAngle)); + meta->AddNativeField("spriteRotation", TypeFloat64, myoffsetof(AActor, SpriteRotation)); + meta->AddNativeField(NAME_VisibleStartAngle, TypeFloat64, myoffsetof(AActor, VisibleStartAngle)); + meta->AddNativeField(NAME_VisibleStartPitch, TypeFloat64, myoffsetof(AActor, VisibleStartPitch)); + meta->AddNativeField(NAME_VisibleEndAngle, TypeFloat64, myoffsetof(AActor, VisibleEndAngle)); + meta->AddNativeField(NAME_VisibleEndPitch, TypeFloat64, myoffsetof(AActor, VisibleEndPitch)); + meta->AddNativeField(NAME_Angle, TypeFloat64, myoffsetof(AActor, Angles.Yaw)); + meta->AddNativeField(NAME_Pitch, TypeFloat64, myoffsetof(AActor, Angles.Pitch)); + meta->AddNativeField(NAME_Roll, TypeFloat64, myoffsetof(AActor, Angles.Roll)); + meta->AddNativeField("Vel", TypeVector3, myoffsetof(AActor, Vel)); + meta->AddNativeField(NAME_VelX, TypeFloat64, myoffsetof(AActor, Vel.X), VARF_ReadOnly | VARF_Deprecated); + meta->AddNativeField(NAME_VelY, TypeFloat64, myoffsetof(AActor, Vel.Y), VARF_ReadOnly | VARF_Deprecated); + meta->AddNativeField(NAME_VelZ, TypeFloat64, myoffsetof(AActor, Vel.Z), VARF_ReadOnly | VARF_Deprecated); + meta->AddNativeField(NAME_MomX, TypeFloat64, myoffsetof(AActor, Vel.X), VARF_ReadOnly | VARF_Deprecated); + meta->AddNativeField(NAME_MomY, TypeFloat64, myoffsetof(AActor, Vel.Y), VARF_ReadOnly | VARF_Deprecated); + meta->AddNativeField(NAME_MomZ, TypeFloat64, myoffsetof(AActor, Vel.Z), VARF_ReadOnly | VARF_Deprecated); + meta->AddNativeField(NAME_Speed, TypeFloat64, myoffsetof(AActor, Speed)); + meta->AddNativeField("FloatSpeed", TypeFloat64, myoffsetof(AActor, FloatSpeed)); + meta->AddNativeField("sprite", TypeSInt32, myoffsetof(AActor, sprite)); // this is an index, not a name! + meta->AddNativeField("frame", TypeUInt8, myoffsetof(AActor, frame)); + meta->AddNativeField("Scale", TypeVector2, myoffsetof(AActor, Scale)); + meta->AddNativeField(NAME_ScaleX, TypeFloat64, myoffsetof(AActor, Scale.X), VARF_Deprecated); + meta->AddNativeField(NAME_ScaleY, TypeFloat64, myoffsetof(AActor, Scale.Y), VARF_Deprecated); + //FRenderStyle RenderStyle; // how do we expose this? + meta->AddNativeField("picnum", TypeSInt32, myoffsetof(AActor, picnum)); // Do we need a variable type 'texture' to do this? + meta->AddNativeField(NAME_Alpha, TypeFloat64, myoffsetof(AActor, Alpha)); + meta->AddNativeField("fillcolor", TypeColor, myoffsetof(AActor, fillcolor)); + meta->AddNativeField("Sector", TypeSector, myoffsetof(AActor, Sector)); + //meta->AddNativeField("Subsector", TypeSubsector, myoffsetof(AActor, subsector)); + meta->AddNativeField(NAME_CeilingZ, TypeFloat64, myoffsetof(AActor, ceilingz), VARF_ReadOnly); + meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz), VARF_ReadOnly); + meta->AddNativeField("DropoffZ", TypeFloat64, myoffsetof(AActor, dropoffz), VARF_ReadOnly); + meta->AddNativeField("floorsector", TypeSector, myoffsetof(AActor, floorsector)); + meta->AddNativeField("floorpic", TypeSInt32, myoffsetof(AActor, floorpic)); // Do we need a variable type 'texture' to do this? + meta->AddNativeField("floorterrain", TypeSInt32, myoffsetof(AActor, floorterrain)); + meta->AddNativeField("ceilingsector", TypeSector, myoffsetof(AActor, ceilingsector)); + meta->AddNativeField("ceilingpic", TypeSInt32, myoffsetof(AActor, ceilingpic)); // Do we need a variable type 'texture' to do this? + meta->AddNativeField(NAME_Height, TypeFloat64, myoffsetof(AActor, Height)); + meta->AddNativeField(NAME_Radius, TypeFloat64, myoffsetof(AActor, radius), VARF_ReadOnly); + meta->AddNativeField("projectilepassheight",TypeFloat64, myoffsetof(AActor, projectilepassheight)); + meta->AddNativeField("tics", TypeSInt32, myoffsetof(AActor, tics)); + meta->AddNativeField("CurState", TypeState, myoffsetof(AActor, state), VARF_ReadOnly); // has to be renamed on the script side because it clashes with the same named type. + meta->AddNativeField(NAME_Damage, TypeSInt32, myoffsetof(AActor, DamageVal), VARF_ReadOnly); + meta->AddNativeField("projectilekickback", TypeSInt32, myoffsetof(AActor, projectileKickback)); + //DWORD VisibleToTeam; + meta->AddNativeField("special1", TypeSInt32, myoffsetof(AActor, special1)); + meta->AddNativeField("special2", TypeSInt32, myoffsetof(AActor, special2)); + meta->AddNativeField("specialf1", TypeFloat64, myoffsetof(AActor, specialf1)); + meta->AddNativeField("specialf2", TypeFloat64, myoffsetof(AActor, specialf2)); + meta->AddNativeField("weaponspecial", TypeSInt32, myoffsetof(AActor, weaponspecial)); + meta->AddNativeField(NAME_Health, TypeSInt32, myoffsetof(AActor, health), VARF_ReadOnly); + meta->AddNativeField("movedir", TypeUInt8, myoffsetof(AActor, movedir)); + meta->AddNativeField("visdir", TypeSInt8, myoffsetof(AActor, visdir)); + meta->AddNativeField("movecount", TypeSInt16, myoffsetof(AActor, movecount)); + meta->AddNativeField("strafecount", TypeSInt16, myoffsetof(AActor, strafecount)); + meta->AddNativeField(NAME_Target, TypeActor, myoffsetof(AActor, target)); + meta->AddNativeField(NAME_Master, TypeActor, myoffsetof(AActor, master)); + meta->AddNativeField(NAME_Tracer, TypeActor, myoffsetof(AActor, tracer)); + meta->AddNativeField("LastHeard", TypeActor, myoffsetof(AActor, LastHeard)); + meta->AddNativeField("LastEnemy", TypeActor, myoffsetof(AActor, lastenemy)); + meta->AddNativeField("LastLookActor", TypeActor, myoffsetof(AActor, LastLookActor)); + meta->AddNativeField(NAME_ReactionTime, TypeSInt32, myoffsetof(AActor, reactiontime)); + meta->AddNativeField(NAME_Threshold, TypeSInt32, myoffsetof(AActor, threshold)); + meta->AddNativeField(NAME_DefThreshold, TypeSInt32, myoffsetof(AActor, DefThreshold), VARF_ReadOnly); + meta->AddNativeField("SpawnPoint", TypeVector3, myoffsetof(AActor, SpawnPoint), VARF_ReadOnly); + meta->AddNativeField("SpawnAngle", TypeUInt16, myoffsetof(AActor, SpawnAngle), VARF_ReadOnly); + meta->AddNativeField("StartHealth", TypeSInt32, myoffsetof(AActor, StartHealth)); + meta->AddNativeField("WeaveIndexXY", TypeUInt16, myoffsetof(AActor, WeaveIndexXY)); + meta->AddNativeField("WeaveIndexZ", TypeUInt16, myoffsetof(AActor, WeaveIndexZ)); + meta->AddNativeField("skillrespawncount", TypeSInt32, myoffsetof(AActor, skillrespawncount)); + meta->AddNativeField(NAME_Args, array5, myoffsetof(AActor, args)); + meta->AddNativeField(NAME_Mass, TypeSInt32, myoffsetof(AActor, Mass)); + meta->AddNativeField(NAME_Special, TypeSInt32, myoffsetof(AActor, special)); + meta->AddNativeField(NAME_TID, TypeSInt32, myoffsetof(AActor, tid), VARF_ReadOnly); + meta->AddNativeField(NAME_TIDtoHate, TypeSInt32, myoffsetof(AActor, TIDtoHate), VARF_ReadOnly); + meta->AddNativeField(NAME_WaterLevel, TypeSInt32, myoffsetof(AActor, waterlevel), VARF_ReadOnly); + meta->AddNativeField(NAME_Score, TypeSInt32, myoffsetof(AActor, Score)); + meta->AddNativeField(NAME_Accuracy, TypeSInt32, myoffsetof(AActor, accuracy)); + meta->AddNativeField(NAME_Stamina, TypeSInt32, myoffsetof(AActor, stamina)); + meta->AddNativeField(NAME_MeleeRange, TypeFloat64, myoffsetof(AActor, meleerange)); + meta->AddNativeField("PainThreshold", TypeSInt32, myoffsetof(AActor, PainThreshold)); + meta->AddNativeField("Gravity", TypeFloat64, myoffsetof(AActor, Gravity)); + meta->AddNativeField("FloorClip", TypeFloat64, myoffsetof(AActor, Floorclip)); + meta->AddNativeField("DamageType", TypeName, myoffsetof(AActor, DamageType)); + meta->AddNativeField("DamageTypeReceived", TypeName, myoffsetof(AActor, DamageTypeReceived)); + meta->AddNativeField("FloatBobPhase", TypeUInt8, myoffsetof(AActor, FloatBobPhase)); + meta->AddNativeField("RipperLevel", TypeSInt32, myoffsetof(AActor, RipperLevel)); + meta->AddNativeField("RipLevelMin", TypeSInt32, myoffsetof(AActor, RipLevelMin)); + meta->AddNativeField("RipLevelMax", TypeSInt32, myoffsetof(AActor, RipLevelMax)); + meta->AddNativeField("Species", TypeName, myoffsetof(AActor, Species)); + meta->AddNativeField("Alternative", TypeActor, myoffsetof(AActor, alternative)); + meta->AddNativeField("goal", TypeActor, myoffsetof(AActor, goal)); + meta->AddNativeField("MinMissileChance", TypeUInt8, myoffsetof(AActor, MinMissileChance)); + meta->AddNativeField("LastLookPlayerNumber",TypeSInt8, myoffsetof(AActor, LastLookPlayerNumber)); + meta->AddNativeField("SpawnFlags", TypeUInt32, myoffsetof(AActor, SpawnFlags)); + meta->AddNativeField("meleethreshold", TypeFloat64, myoffsetof(AActor, meleethreshold)); + meta->AddNativeField("maxtargetrange", TypeFloat64, myoffsetof(AActor, maxtargetrange)); + meta->AddNativeField("bouncefactor", TypeFloat64, myoffsetof(AActor, bouncefactor)); + meta->AddNativeField("wallbouncefactor", TypeFloat64, myoffsetof(AActor, wallbouncefactor)); + meta->AddNativeField("bouncecount", TypeSInt32, myoffsetof(AActor, bouncecount)); + meta->AddNativeField("friction", TypeFloat64, myoffsetof(AActor, Friction)); + meta->AddNativeField("FastChaseStrafeCount",TypeSInt32, myoffsetof(AActor, FastChaseStrafeCount)); + meta->AddNativeField("pushfactor", TypeFloat64, myoffsetof(AActor, pushfactor)); + meta->AddNativeField("lastpush", TypeSInt32, myoffsetof(AActor, lastpush)); + meta->AddNativeField("activationtype", TypeSInt32, myoffsetof(AActor, activationtype)); + meta->AddNativeField("lastbump", TypeSInt32, myoffsetof(AActor, lastbump)); + meta->AddNativeField("DesignatedTeam", TypeSInt32, myoffsetof(AActor, DesignatedTeam)); + meta->AddNativeField("BlockingMobj", TypeActor, myoffsetof(AActor, BlockingMobj)); + //line_t *BlockingLine; // Line that blocked the last move + meta->AddNativeField("PoisonDamage", TypeSInt32, myoffsetof(AActor, PoisonDamage)); + meta->AddNativeField("PoisonDamageType", TypeName, myoffsetof(AActor, PoisonDamageType)); + meta->AddNativeField("PoisonDuration", TypeSInt32, myoffsetof(AActor, PoisonDuration)); + meta->AddNativeField("PoisonPeriod", TypeSInt32, myoffsetof(AActor, PoisonPeriod)); + meta->AddNativeField("PoisonDamageReceived",TypeSInt32, myoffsetof(AActor, PoisonDamageReceived)); + meta->AddNativeField("PoisonDamageTypeReceived", TypeName, myoffsetof(AActor, PoisonDamageTypeReceived)); + meta->AddNativeField("PoisonDurationReceived", TypeSInt32, myoffsetof(AActor, PoisonDurationReceived)); + meta->AddNativeField("PoisonPeriodReceived", TypeSInt32, myoffsetof(AActor, PoisonPeriodReceived)); + meta->AddNativeField("Poisoner", TypeActor, myoffsetof(AActor, Poisoner)); + meta->AddNativeField("Inv", TypeInventory, myoffsetof(AActor, Inventory)); // Needs to be renamed because it hides the actual type. + meta->AddNativeField("smokecounter", TypeUInt8, myoffsetof(AActor, smokecounter)); + meta->AddNativeField("FriendPlayer", TypeUInt8, myoffsetof(AActor, FriendPlayer)); + meta->AddNativeField("Translation", TypeUInt32, myoffsetof(AActor, Translation)); + meta->AddNativeField("AttackSound", TypeSound, myoffsetof(AActor, AttackSound)); + meta->AddNativeField("DeathSound", TypeSound, myoffsetof(AActor, DeathSound)); + meta->AddNativeField("SeeSound", TypeSound, myoffsetof(AActor, SeeSound)); + meta->AddNativeField("PainSound", TypeSound, myoffsetof(AActor, PainSound)); + meta->AddNativeField("ActiveSound", TypeSound, myoffsetof(AActor, ActiveSound)); + meta->AddNativeField("UseSound", TypeSound, myoffsetof(AActor, UseSound)); + meta->AddNativeField("BounceSound", TypeSound, myoffsetof(AActor, BounceSound)); + meta->AddNativeField("WallBounceSound", TypeSound, myoffsetof(AActor, WallBounceSound)); + meta->AddNativeField("CrushPainSound", TypeSound, myoffsetof(AActor, CrushPainSound)); + meta->AddNativeField("MaxDropoffHeight", TypeFloat64, myoffsetof(AActor, MaxDropOffHeight)); + meta->AddNativeField("MaxStepHeight", TypeFloat64, myoffsetof(AActor, MaxStepHeight)); + meta->AddNativeField("PainChance", TypeSInt16, myoffsetof(AActor, PainChance)); + meta->AddNativeField("PainType", TypeName, myoffsetof(AActor, PainType)); + meta->AddNativeField("DeathType", TypeName, myoffsetof(AActor, DeathType)); + meta->AddNativeField("DamageFactor", TypeFloat64, myoffsetof(AActor, DamageFactor)); + meta->AddNativeField("DamageMultiply", TypeFloat64, myoffsetof(AActor, DamageMultiply)); + meta->AddNativeField("TelefogSourceType", TypeActorClass, myoffsetof(AActor, TeleFogSourceType)); + meta->AddNativeField("TelefogDestType", TypeActorClass, myoffsetof(AActor, TeleFogDestType)); + meta->AddNativeField("SpawnState", TypeState, myoffsetof(AActor, SpawnState), VARF_ReadOnly); + meta->AddNativeField("SeeState", TypeState, myoffsetof(AActor, SeeState), VARF_ReadOnly); + meta->AddNativeField("MeleeState", TypeState, myoffsetof(AActor, MeleeState), VARF_ReadOnly); + meta->AddNativeField("MissileState", TypeState, myoffsetof(AActor, MissileState), VARF_ReadOnly); + //int ConversationRoot; // THe root of the current dialogue + //FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is "used." + //FDecalBase *DecalGenerator; + + // synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them. + for (size_t i = 0; ActorFlagDefs[i].flagbit != 0xffffffff; i++) + { + meta->AddNativeField(FStringf("b%s", ActorFlagDefs[i].name), (ActorFlagDefs[i].fieldsize == 4? TypeSInt32 : TypeSInt16), ActorFlagDefs[i].structoffset, ActorFlagDefs[i].varflags, ActorFlagDefs[i].flagbit); + } + for (size_t i = 0; InternalActorFlagDefs[i].flagbit != 0xffffffff; i++) + { + meta->AddNativeField(FStringf("b%s", InternalActorFlagDefs[i].name), (InternalActorFlagDefs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), InternalActorFlagDefs[i].structoffset, InternalActorFlagDefs[i].varflags, InternalActorFlagDefs[i].flagbit); + } +} + //========================================================================== // // AActor :: Serialize @@ -442,6 +626,14 @@ bool AActor::SetState (FState *newstate, bool nofunction) { prevsprite = -1; } + if (!(newstate->UseFlags & SUF_ACTOR)) + { + auto so = FState::StaticFindStateOwner(newstate); + Printf(TEXTCOLOR_RED "State %s.%d in %s not flagged for use as an actor sprite\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates), GetClass()->TypeName.GetChars()); + state = nullptr; + Destroy(); + return false; + } state = newstate; tics = GetTics(newstate); renderflags = (renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (newstate->GetFullbright()); @@ -509,6 +701,14 @@ bool AActor::SetState (FState *newstate, bool nofunction) return true; } +DEFINE_ACTION_FUNCTION(AActor, SetState) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER(state, FState); + PARAM_BOOL_DEF(nofunction); + ACTION_RETURN_BOOL(self->SetState(state, nofunction)); +}; + //============================================================================ // // AActor :: AddInventory @@ -981,6 +1181,15 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealt level.total_monsters += CountsAsKill(); } +DEFINE_ACTION_FUNCTION(AActor, CopyFriendliness) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + PARAM_BOOL_DEF(changetarget); + PARAM_BOOL_DEF(resethealth); + self->CopyFriendliness(other, changetarget, resethealth); + return 0; +} //============================================================================ // // AActor :: ObtainInventory @@ -1675,6 +1884,13 @@ bool AActor::CanSeek(AActor *target) const return true; } +DEFINE_ACTION_FUNCTION(AActor, CanSeek) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(target, AActor); + ACTION_RETURN_BOOL(self->CanSeek(target)); +} + //---------------------------------------------------------------------------- // // FUNC P_SeekerMissile @@ -3001,14 +3217,13 @@ int AActor::GetMissileDamage (int mask, int add) } VMFrameStack stack; VMValue param = this; - VMReturn results[2]; + VMReturn result; - int amount, calculated = false; + int amount; - results[0].IntAt(&amount); - results[1].IntAt(&calculated); + result.IntAt(&amount); - if (stack.Call(DamageFunc, ¶m, 1, results, 2) < 1) + if (stack.Call(DamageFunc, ¶m, 1, &result, 1) < 1) { // No results return 0; } @@ -3122,6 +3337,13 @@ void AActor::PlayActiveSound () } } +DEFINE_ACTION_FUNCTION(AActor, PlayActiveSound) +{ + PARAM_SELF_PROLOGUE(AActor); + self->PlayActiveSound(); + return 0; +} + bool AActor::IsOkayToAttack (AActor *link) { if (!(player // Original AActor::IsOkayToAttack was only for players @@ -4249,6 +4471,17 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a return actor; } +DEFINE_ACTION_FUNCTION(AActor, Spawn) +{ + PARAM_PROLOGUE; + PARAM_CLASS(type, AActor); + PARAM_FLOAT_DEF(x); + PARAM_FLOAT_DEF(y); + PARAM_FLOAT_DEF(z); + PARAM_INT_DEF(flags); + ACTION_RETURN_OBJECT(AActor::StaticSpawn(type, DVector3(x, y, z), replace_t(flags))); +} + PClassActor *ClassForSpawn(FName classname) { PClass *cls = PClass::FindClass(classname); @@ -4489,6 +4722,13 @@ void AActor::AdjustFloorClip () } } +DEFINE_ACTION_FUNCTION(AActor, AdjustFloorClip) +{ + PARAM_SELF_PROLOGUE(AActor); + self->AdjustFloorClip(); + return 0; +} + // // P_SpawnPlayer // Called when a player is spawned on the level. @@ -5211,7 +5451,20 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos1 return puff; } - +DEFINE_ACTION_FUNCTION(AActor, SpawnPuff) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(pufftype, AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_ANGLE(hitdir); + PARAM_ANGLE(particledir); + PARAM_INT(updown); + PARAM_INT_DEF(flags); + PARAM_OBJECT_DEF(victim, AActor); + ACTION_RETURN_OBJECT(P_SpawnPuff(self, pufftype, DVector3(x, y, z), hitdir, particledir, updown, flags, victim)); +} //--------------------------------------------------------------------------- // @@ -5806,6 +6059,13 @@ static double GetDefaultSpeed(PClassActor *type) return GetDefaultByType(type)->Speed; } +DEFINE_ACTION_FUNCTION(AActor, GetDefaultSpeed) +{ + PARAM_PROLOGUE; + PARAM_CLASS(type, AActor); + ACTION_RETURN_FLOAT(GetDefaultSpeed(type)); +} + //--------------------------------------------------------------------------- // // FUNC P_SpawnMissile @@ -5824,6 +6084,15 @@ AActor *P_SpawnMissile (AActor *source, AActor *dest, PClassActor *type, AActor return P_SpawnMissileXYZ (source->PosPlusZ(32 + source->GetBobOffset()), source, dest, type, true, owner); } +DEFINE_ACTION_FUNCTION(AActor, SpawnMissile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(dest, AActor); + PARAM_CLASS(type, AActor); + PARAM_OBJECT_DEF(owner, AActor); + ACTION_RETURN_OBJECT(P_SpawnMissile(self, dest, type, owner)); +} + AActor *P_SpawnMissileZ (AActor *source, double z, AActor *dest, PClassActor *type) { if (source == NULL) @@ -5833,6 +6102,15 @@ AActor *P_SpawnMissileZ (AActor *source, double z, AActor *dest, PClassActor *ty return P_SpawnMissileXYZ (source->PosAtZ(z), source, dest, type); } +DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(z); + PARAM_OBJECT(dest, AActor); + PARAM_CLASS(type, AActor); + ACTION_RETURN_OBJECT(P_SpawnMissileZ(self, z, dest, type)); +} + AActor *P_SpawnMissileXYZ (DVector3 pos, AActor *source, AActor *dest, PClassActor *type, bool checkspawn, AActor *owner) { if (source == NULL) @@ -5933,6 +6211,16 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct return th; } +DEFINE_ACTION_FUNCTION(AActor, OldSpawnMissile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(dest, AActor); + PARAM_CLASS(type, AActor); + PARAM_OBJECT_DEF(owner, AActor); + ACTION_RETURN_OBJECT(P_OldSpawnMissile(self, owner, dest, type)); +} + + //--------------------------------------------------------------------------- // // FUNC P_SpawnMissileAngle @@ -6020,6 +6308,19 @@ AActor *P_SpawnMissileAngleZSpeed (AActor *source, double z, return (!checkspawn || P_CheckMissileSpawn(mo, source->radius)) ? mo : NULL; } +DEFINE_ACTION_FUNCTION(AActor, SpawnMissileAngleZSpeed) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(z); + PARAM_CLASS(type, AActor); + PARAM_ANGLE(angle); + PARAM_FLOAT(vz); + PARAM_FLOAT(speed); + PARAM_OBJECT_DEF(owner, AActor); + PARAM_BOOL_DEF(checkspawn); + ACTION_RETURN_OBJECT(P_SpawnMissileAngleZSpeed(self, z, type, angle, vz, speed, owner, checkspawn)); +} + /* ================ = @@ -6213,6 +6514,12 @@ FName AActor::GetSpecies() return Species = thistype->TypeName; // [GZ] Speeds up future calls. } +DEFINE_ACTION_FUNCTION(AActor, GetSpecies) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(self->GetSpecies()); +} + //========================================================================== // // AActor :: IsFriend @@ -6239,6 +6546,13 @@ bool AActor::IsFriend (AActor *other) return false; } +DEFINE_ACTION_FUNCTION(AActor, isFriend) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_BOOL(self->IsFriend(other)); +} + //========================================================================== // // AActor :: IsHostile @@ -6462,6 +6776,12 @@ DDropItem *AActor::GetDropItems() const return GetClass()->DropItems; } +DEFINE_ACTION_FUNCTION(AActor, GetDropItems) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_OBJECT(self->GetDropItems()); +} + double AActor::GetGravity() const { if (flags & MF_NOGRAVITY) return 0; @@ -6566,14 +6886,184 @@ void AActor::SetTranslation(const char *trname) // silently ignore if the name does not exist, this would create some insane message spam otherwise. } +DEFINE_ACTION_FUNCTION(AActor, deltaangle) // should this be global? +{ + PARAM_PROLOGUE; + PARAM_FLOAT(a1); + PARAM_FLOAT(a2); + ACTION_RETURN_FLOAT(deltaangle(DAngle(a1), DAngle(a2)).Degrees); +} + +DEFINE_ACTION_FUNCTION(AActor, Distance2D) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_FLOAT(self->Distance2D(other)); +} + +DEFINE_ACTION_FUNCTION(AActor, AddZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(addz); + self->AddZ(addz); + return 0; +} + +DEFINE_ACTION_FUNCTION(AActor, SetZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(z); + self->SetZ(z); + return 0; +} + +DEFINE_ACTION_FUNCTION(AActor, SetDamage) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(dmg); + self->SetDamage(dmg); + return 0; +} + +DEFINE_ACTION_FUNCTION(AActor, GetDefaultByType) +{ + PARAM_PROLOGUE; + PARAM_CLASS(cls, AActor); + ACTION_RETURN_OBJECT(GetDefaultByType(cls)); +} + +DEFINE_ACTION_FUNCTION(AActor, GetBobOffset) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF(frac); + ACTION_RETURN_FLOAT(self->GetBobOffset(frac)); +} + +// This combines all 3 variations of the internal function +DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) +{ + PARAM_SELF_PROLOGUE(AActor); + if (numparam == 1) + { + self->VelFromAngle(); + } + else + { + PARAM_FLOAT(speed); + if (numparam == 2) + { + self->VelFromAngle(speed); + } + else + { + PARAM_ANGLE(angle); + self->VelFromAngle(speed, angle); + } + } + return 0; +} + +// This combines all 3 variations of the internal function +DEFINE_ACTION_FUNCTION(AActor, Thrust) +{ + PARAM_SELF_PROLOGUE(AActor); + if (numparam == 1) + { + self->Thrust(); + } + else + { + PARAM_FLOAT(speed); + if (numparam == 2) + { + self->Thrust(speed); + } + else + { + PARAM_ANGLE(angle); + self->Thrust(angle, speed); + } + } + return 0; +} + +DEFINE_ACTION_FUNCTION(AActor, AngleTo) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(targ, AActor); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees); +} + +DEFINE_ACTION_FUNCTION(AActor, DistanceBySpeed) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(targ, AActor); + PARAM_FLOAT(speed); + ACTION_RETURN_FLOAT(self->DistanceBySpeed(targ, speed)); +} + +DEFINE_ACTION_FUNCTION(AActor, SetXYZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + self->SetXYZ(x, y, z); + return 0; +} + +DEFINE_ACTION_FUNCTION(AActor, Vec3Angle) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(length) + PARAM_ANGLE(angle); + PARAM_FLOAT(z); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_VEC3(self->Vec3Angle(length, angle, z, absolute)); +} + +DEFINE_ACTION_FUNCTION(AActor, Vec2OffsetZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_VEC3(self->Vec2OffsetZ(x, y, z, absolute)); +} + +DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_VEC3(self->Vec3Offset(x, y, z, absolute)); +} + //---------------------------------------------------------------------------- // // DropItem handling // //---------------------------------------------------------------------------- -IMPLEMENT_POINTY_CLASS(DDropItem) - DECLARE_POINTER(Next) -END_POINTERS + +IMPLEMENT_CLASS(DDropItem, false, true, true, false) + +IMPLEMENT_POINTERS_START(DDropItem) + IMPLEMENT_POINTER(Next) +IMPLEMENT_POINTERS_END + +void DDropItem::InitNativeFields() +{ + auto meta = RUNTIME_CLASS(DDropItem); + PType *TypeDropItem = NewPointer(RUNTIME_CLASS(DDropItem)); + meta->AddNativeField("Next", TypeDropItem, myoffsetof(DDropItem, Next), VARF_ReadOnly); + meta->AddNativeField("Name", TypeName, myoffsetof(DDropItem, Name), VARF_ReadOnly); + meta->AddNativeField("Probability", TypeSInt32, myoffsetof(DDropItem, Probability), VARF_ReadOnly); + meta->AddNativeField("Amount", TypeSInt32, myoffsetof(DDropItem, Amount)); +} void PrintMiscActorInfo(AActor *query) { diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index a55bd5cdb..27eb13ec5 100644 --- a/src/p_pillar.cpp +++ b/src/p_pillar.cpp @@ -40,10 +40,12 @@ #include "serializer.h" #include "r_data/r_interpolate.h" -IMPLEMENT_POINTY_CLASS (DPillar) - DECLARE_POINTER(m_Interp_Floor) - DECLARE_POINTER(m_Interp_Ceiling) -END_POINTERS +IMPLEMENT_CLASS(DPillar, false, true, false, false) + +IMPLEMENT_POINTERS_START(DPillar) + IMPLEMENT_POINTER(m_Interp_Floor) + IMPLEMENT_POINTER(m_Interp_Ceiling) +IMPLEMENT_POINTERS_END DPillar::DPillar () { diff --git a/src/p_plats.cpp b/src/p_plats.cpp index 868f47138..9924a0f9c 100644 --- a/src/p_plats.cpp +++ b/src/p_plats.cpp @@ -35,7 +35,7 @@ static FRandom pr_doplat ("DoPlat"); -IMPLEMENT_CLASS (DPlat) +IMPLEMENT_CLASS(DPlat, false, false, false, false) DPlat::DPlat () { diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 2e591e20d..9ae7b530d 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -25,10 +25,11 @@ #include "gi.h" #include "p_pspr.h" #include "templates.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "d_player.h" #include "serializer.h" +#include "v_text.h" // MACROS ------------------------------------------------------------------ @@ -99,10 +100,12 @@ static const FGenericButtons ButtonChecks[] = // //------------------------------------------------------------------------ -IMPLEMENT_POINTY_CLASS(DPSprite) - DECLARE_POINTER(Caller) - DECLARE_POINTER(Next) -END_POINTERS +IMPLEMENT_CLASS(DPSprite, false, true, false, false) + +IMPLEMENT_POINTERS_START(DPSprite) + IMPLEMENT_POINTER(Caller) + IMPLEMENT_POINTER(Next) +IMPLEMENT_POINTERS_END //------------------------------------------------------------------------ // @@ -293,6 +296,27 @@ void DPSprite::SetState(FState *newstate, bool pending) Destroy(); return; } + + if (!(newstate->UseFlags & (SUF_OVERLAY|SUF_WEAPON))) // Weapon and overlay are mostly the same, the main difference is that weapon states restrict the self pointer to class Actor. + { + auto so = FState::StaticFindStateOwner(newstate); + Printf(TEXTCOLOR_RED "State %s.%d not flagged for use in overlays or weapons\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates)); + State = nullptr; + Destroy(); + return; + } + else if (!(newstate->UseFlags & SUF_WEAPON)) + { + if (Caller->IsKindOf(RUNTIME_CLASS(AWeapon))) + { + auto so = FState::StaticFindStateOwner(newstate); + Printf(TEXTCOLOR_RED "State %s.%d not flagged for use in weapons\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates)); + State = nullptr; + Destroy(); + return; + } + } + State = newstate; if (newstate->sprite != SPR_FIXED) @@ -335,6 +359,14 @@ void DPSprite::SetState(FState *newstate, bool pending) { FState *nextstate; FStateParamInfo stp = { newstate, STATE_Psprite, ID }; + if (newstate->ActionFunc != nullptr && newstate->ActionFunc->Unsafe) + { + // If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash. + auto owner = FState::StaticFindStateOwner(newstate); + Printf(TEXTCOLOR_RED "Unsafe state call in state %s.%d to %s which accesses user variables. The action function has been removed from this state\n", + owner->TypeName.GetChars(), newstate - owner->OwnedStates, static_cast(newstate->ActionFunc)->PrintableName.GetChars()); + newstate->ActionFunc = nullptr; + } if (newstate->CallAction(Owner->mo, Caller, &stp, &nextstate)) { // It's possible this call resulted in this very layer being replaced. @@ -742,8 +774,8 @@ void DoReadyWeapon(AActor *self) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT_DEF(flags); DoReadyWeaponToSwitch(self, !(flags & WRF_NoSwitch)); if ((flags & WRF_NoFire) != WRF_NoFire) DoReadyWeaponToFire(self, !(flags & WRF_NoPrimary), !(flags & WRF_NoSecondary)); @@ -874,8 +906,8 @@ static void P_CheckWeaponButtons (player_t *player) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_ReFire) { - PARAM_ACTION_PROLOGUE; - PARAM_STATE_OPT(state) { state = NULL; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_STATE_ACTION_DEF(state); A_ReFire(self, state); return 0; } @@ -912,7 +944,7 @@ void A_ReFire(AActor *self, FState *state) DEFINE_ACTION_FUNCTION(AInventory, A_ClearReFire) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; if (NULL != player) @@ -934,7 +966,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_ClearReFire) DEFINE_ACTION_FUNCTION(AInventory, A_CheckReload) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -1001,21 +1033,21 @@ void A_OverlayOffset(AActor *self, int layer, double wx, double wy, int flags) DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(layer) { layer = PSP_WEAPON; } - PARAM_FLOAT_OPT(wx) { wx = 0.; } - PARAM_FLOAT_OPT(wy) { wy = 32.; } - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT_DEF(layer) + PARAM_FLOAT_DEF(wx) + PARAM_FLOAT_DEF(wy) + PARAM_INT_DEF(flags) A_OverlayOffset(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), wx, wy, flags); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_WeaponOffset) { - PARAM_ACTION_PROLOGUE; - PARAM_FLOAT_OPT(wx) { wx = 0.; } - PARAM_FLOAT_OPT(wy) { wy = 32.; } - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF(wx) + PARAM_FLOAT_DEF(wy) + PARAM_INT_DEF(flags) A_OverlayOffset(self, PSP_WEAPON, wx, wy, flags); return 0; } @@ -1028,7 +1060,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WeaponOffset) DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(layer); PARAM_INT(flags); PARAM_BOOL(set); @@ -1071,8 +1103,8 @@ static double GetOverlayPosition(AActor *self, int layer, bool gety) DEFINE_ACTION_FUNCTION(AActor, OverlayX) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(layer) { layer = 0; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT_DEF(layer); if (ACTION_CALL_FROM_PSPRITE()) { @@ -1084,8 +1116,8 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayX) DEFINE_ACTION_FUNCTION(AActor, OverlayY) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(layer) { layer = 0; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_INT_DEF(layer); if (ACTION_CALL_FROM_PSPRITE()) { @@ -1103,7 +1135,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayY) DEFINE_ACTION_FUNCTION(AActor, OverlayID) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (ACTION_CALL_FROM_PSPRITE()) { @@ -1122,7 +1154,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayID) DEFINE_ACTION_FUNCTION(AInventory, A_Lower) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; DPSprite *psp; @@ -1170,7 +1202,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Lower) DEFINE_ACTION_FUNCTION(AInventory, A_Raise) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (self == nullptr) { @@ -1211,10 +1243,10 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Raise) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Overlay) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT (layer); - PARAM_STATE_OPT (state) { state = nullptr; } - PARAM_BOOL_OPT (dontoverride) { dontoverride = false; } + PARAM_STATE_ACTION_DEF(state); + PARAM_BOOL_DEF(dontoverride); player_t *player = self->player; @@ -1231,10 +1263,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Overlay) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ClearOverlays) { - PARAM_ACTION_PROLOGUE; - PARAM_INT_OPT(start) { start = 0; } - PARAM_INT_OPT(stop) { stop = 0; } - PARAM_BOOL_OPT(safety) { safety = true; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(start); + PARAM_INT_DEF(stop); + PARAM_BOOL_DEF(safety) if (self->player == nullptr) ACTION_RETURN_INT(0); @@ -1282,9 +1314,9 @@ enum GF_Flags DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { - PARAM_ACTION_PROLOGUE; - PARAM_STATE_OPT(flash) { flash = nullptr; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_ACTION_PROLOGUE(AActor); + PARAM_STATE_ACTION_DEF(flash); + PARAM_INT_DEF(flags); player_t *player = self->player; @@ -1350,6 +1382,19 @@ DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget, int aimfla return pitch; } +AActor *P_AimTarget(AActor *mo) +{ + FTranslatedLineTarget t; + P_BulletSlope(mo, &t, ALF_PORTALRESTRICT); + return t.linetarget; +} + +DEFINE_ACTION_FUNCTION(AActor, AimTarget) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_OBJECT(P_AimTarget(self)); +} + // // P_GunShot @@ -1370,42 +1415,9 @@ void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch) P_LineAttack (mo, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, pufftype); } -DEFINE_ACTION_FUNCTION(AInventory, A_Light0) -{ - PARAM_ACTION_PROLOGUE; - - if (self->player != NULL) - { - self->player->extralight = 0; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AInventory, A_Light1) -{ - PARAM_ACTION_PROLOGUE; - - if (self->player != NULL) - { - self->player->extralight = 1; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AInventory, A_Light2) -{ - PARAM_ACTION_PROLOGUE; - - if (self->player != NULL) - { - self->player->extralight = 2; - } - return 0; -} - DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_Light) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(light); if (self->player != NULL) diff --git a/src/p_pspr.h b/src/p_pspr.h index 4b50d9d0c..bd1b32cd5 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -25,7 +25,7 @@ // Basic data types. // Needs fixed point, and BAM angles. -#include "thingdef/thingdef.h" +//#include "vm.h" #define WEAPONBOTTOM 128. @@ -111,6 +111,7 @@ void P_FireWeapon (player_t *player); void P_DropWeapon (player_t *player); void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac); DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget = NULL, int aimflags = 0); +AActor *P_AimTarget(AActor *mo); void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch); @@ -119,7 +120,6 @@ void DoReadyWeaponToBob(AActor *self); void DoReadyWeaponToFire(AActor *self, bool primary = true, bool secondary = true); void DoReadyWeaponToSwitch(AActor *self, bool switchable = true); -DECLARE_ACTION(A_Raise) void A_ReFire(AActor *self, FState *state = NULL); #endif // __P_PSPR_H__ diff --git a/src/p_pusher.cpp b/src/p_pusher.cpp index 38c9c9720..f2f982a7f 100644 --- a/src/p_pusher.cpp +++ b/src/p_pusher.cpp @@ -74,10 +74,11 @@ protected: friend bool PIT_PushThing (AActor *thing); }; +IMPLEMENT_CLASS(DPusher, false, true, false, false) -IMPLEMENT_POINTY_CLASS (DPusher) - DECLARE_POINTER (m_Source) -END_POINTERS +IMPLEMENT_POINTERS_START(DPusher) + IMPLEMENT_POINTER(m_Source) +IMPLEMENT_POINTERS_END DPusher::DPusher () { diff --git a/src/p_scroll.cpp b/src/p_scroll.cpp index f2ece8b3d..f44eac25a 100644 --- a/src/p_scroll.cpp +++ b/src/p_scroll.cpp @@ -73,12 +73,13 @@ private: } }; +IMPLEMENT_CLASS(DScroller, false, true, false, false) -IMPLEMENT_POINTY_CLASS (DScroller) - DECLARE_POINTER (m_Interpolations[0]) - DECLARE_POINTER (m_Interpolations[1]) - DECLARE_POINTER (m_Interpolations[2]) -END_POINTERS +IMPLEMENT_POINTERS_START(DScroller) + IMPLEMENT_POINTER(m_Interpolations[0]) + IMPLEMENT_POINTER(m_Interpolations[1]) + IMPLEMENT_POINTER(m_Interpolations[2]) +IMPLEMENT_POINTERS_END //----------------------------------------------------------------------------- diff --git a/src/p_setup.cpp b/src/p_setup.cpp index aafed854b..11aef9d8d 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1688,7 +1688,7 @@ static void SetMapThingUserData(AActor *actor, unsigned udi) udi++; - if (var == NULL || (var->Flags & VARF_Native) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType))) + if (var == NULL || (var->Flags & (VARF_Native|VARF_Private|VARF_Protected|VARF_Static)) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType))) { DPrintf(DMSG_WARNING, "%s is not a user variable in class %s\n", varname.GetChars(), actor->GetClass()->TypeName.GetChars()); diff --git a/src/p_sight.cpp b/src/p_sight.cpp index c10365eea..319d5b3ec 100644 --- a/src/p_sight.cpp +++ b/src/p_sight.cpp @@ -905,6 +905,14 @@ done: return res; } +DEFINE_ACTION_FUNCTION(AActor, CheckSight) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(target, AActor); + PARAM_INT_DEF(flags); + ACTION_RETURN_BOOL(P_CheckSight(self, target, flags)); +} + ADD_STAT (sight) { FString out; diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 901016c14..fa7a55aba 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -660,7 +660,7 @@ protected: short LastLight; }; -IMPLEMENT_CLASS (DLightTransfer) +IMPLEMENT_CLASS(DLightTransfer, false, false, false, false) void DLightTransfer::Serialize(FSerializer &arc) { @@ -750,7 +750,7 @@ protected: BYTE Flags; }; -IMPLEMENT_CLASS (DWallLightTransfer) +IMPLEMENT_CLASS(DWallLightTransfer, false, false, false, false) void DWallLightTransfer::Serialize(FSerializer &arc) { diff --git a/src/p_states.cpp b/src/p_states.cpp index 1a8116e53..f7f237c77 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -39,7 +39,11 @@ #include "i_system.h" #include "c_dispatch.h" #include "v_text.h" -#include "thingdef/thingdef.h" +#include "vm.h" +#include "thingdef.h" + +// stores indices for symbolic state labels for some old-style DECORATE functions. +FStateLabelStorage StateLabels; // Each state is owned by an actor. Actors can own any number of // states, but a single state cannot be owned by more than one @@ -257,7 +261,94 @@ FState *PClassActor::FindStateByString(const char *name, bool exact) } +//========================================================================== +// +// validate a runtime state index. +// +//========================================================================== +static bool VerifyJumpTarget(PClassActor *cls, FState *CallingState, int index) +{ + while (cls != RUNTIME_CLASS(AActor)) + { + // both calling and target state need to belong to the same class. + if (cls->OwnsState(CallingState)) + { + return cls->OwnsState(CallingState + index); + } + + // We can safely assume the ParentClass is of type PClassActor + // since we stop when we see the Actor base class. + cls = static_cast(cls->ParentClass); + } + return false; +} + +//========================================================================== +// +// Get a statw pointer from a symbolic label +// +//========================================================================== + +FState *FStateLabelStorage::GetState(int pos, PClassActor *cls) +{ + if (pos > 0x10000000) + { + return cls? cls->FindState(ENamedName(pos - 0x10000000)) : nullptr; + } + else if (pos < 0) + { + // decode the combined value produced by the script. + int index = (pos >> 16) & 32767; + pos = ((pos & 65535) - 1) * 4; + FState *state; + memcpy(&state, &Storage[pos + sizeof(int)], sizeof(state)); + if (VerifyJumpTarget(cls, state, index)) + return state + index; + else + return nullptr; + } + else if (pos > 0) + { + int val; + pos = (pos - 1) * 4; + memcpy(&val, &Storage[pos], sizeof(int)); + + if (val == 0) + { + FState *state; + memcpy(&state, &Storage[pos + sizeof(int)], sizeof(state)); + return state; + } + else if (cls != nullptr) + { + FName *labels = (FName*)&Storage[pos + sizeof(int)]; + return cls->FindState(val, labels, false); + } + } + return nullptr; +} + +//========================================================================== +// +// State label conversion function for scripts +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(AActor, FindState) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STATE(newstate); + ACTION_RETURN_STATE(newstate); +} + +// same as above but context aware. +DEFINE_ACTION_FUNCTION_PARAMS(AActor, ResolveState) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_STATE_ACTION(newstate); + ACTION_RETURN_STATE(newstate); +} //========================================================================== // @@ -432,6 +523,11 @@ FStateLabels *FStateDefinitions::CreateStateLabelList(TArray & sta void FStateDefinitions::InstallStates(PClassActor *info, AActor *defaults) { + if (defaults == nullptr) + { + I_Error("Called InstallStates without actor defaults in %s", info->TypeName.GetChars()); + } + // First ensure we have a valid spawn state. FState *state = FindState("Spawn"); @@ -817,7 +913,7 @@ bool FStateDefinitions::SetLoop() // //========================================================================== -int FStateDefinitions::AddStates(FState *state, const char *framechars) +int FStateDefinitions::AddStates(FState *state, const char *framechars, const FScriptPosition &sc) { bool error = false; int frame = 0; @@ -843,6 +939,7 @@ int FStateDefinitions::AddStates(FState *state, const char *framechars) state->Frame = frame; state->SameFrame = noframe; StateArray.Push(*state); + SourceLines.Push(sc); ++count; // NODELAY flag is not carried past the first state @@ -872,6 +969,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) memcpy(realstates, &StateArray[0], count*sizeof(FState)); actor->OwnedStates = realstates; actor->NumOwnedStates = count; + SaveStateSourceLines(realstates, SourceLines); // adjust the state pointers // In the case new states are added these must be adjusted, too! @@ -916,6 +1014,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) } + //========================================================================== // // Prints all state label info to the logfile diff --git a/src/p_switch.cpp b/src/p_switch.cpp index c60b0fdcd..2d5423f08 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -320,7 +320,7 @@ bool P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *ques // //========================================================================== -IMPLEMENT_CLASS (DActiveButton) +IMPLEMENT_CLASS(DActiveButton, false, false, false, false) DActiveButton::DActiveButton () { diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index f65e2f402..01595ff65 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -47,7 +47,7 @@ extern void P_CalcHeight (player_t *player); CVAR (Bool, telezoom, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); -IMPLEMENT_CLASS (ATeleportFog) +IMPLEMENT_CLASS(ATeleportFog, false, false, false, false) void ATeleportFog::PostBeginPlay () { diff --git a/src/p_user.cpp b/src/p_user.cpp index 4a15e7f18..6b0b2cfe6 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -48,7 +48,7 @@ #include "doomdef.h" #include "c_dispatch.h" #include "tarray.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" #include "d_net.h" #include "gstrings.h" @@ -59,6 +59,7 @@ #include "p_blockmap.h" #include "a_morph.h" #include "p_spec.h" +#include "virtual.h" static FRandom pr_skullpop ("SkullPop"); @@ -508,7 +509,7 @@ int player_t::GetSpawnClass() // //=========================================================================== -IMPLEMENT_CLASS(PClassPlayerPawn) +IMPLEMENT_CLASS(PClassPlayerPawn, false, false, false, false) PClassPlayerPawn::PClassPlayerPawn() { @@ -622,12 +623,14 @@ void player_t::SendPitchLimits() const // //=========================================================================== -IMPLEMENT_POINTY_CLASS (APlayerPawn) - DECLARE_POINTER(InvFirst) - DECLARE_POINTER(InvSel) -END_POINTERS +IMPLEMENT_CLASS(APlayerPawn, false, true, false, true) -IMPLEMENT_CLASS (APlayerChunk) +IMPLEMENT_POINTERS_START(APlayerPawn) + IMPLEMENT_POINTER(InvFirst) + IMPLEMENT_POINTER(InvSel) +IMPLEMENT_POINTERS_END + +IMPLEMENT_CLASS(APlayerChunk, false, false, false, false) void APlayerPawn::Serialize(FSerializer &arc) { @@ -1549,7 +1552,7 @@ void APlayerPawn::TweakSpeeds (double &forward, double &side) DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int sound = 0; int chan = CHAN_VOICE; @@ -1625,8 +1628,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop) { - PARAM_ACTION_PROLOGUE; - PARAM_CLASS_OPT(spawntype, APlayerChunk) { spawntype = NULL; } + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS_DEF(spawntype, APlayerChunk); APlayerPawn *mo; player_t *player; @@ -1675,7 +1678,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop) DEFINE_ACTION_FUNCTION(AActor, A_CheckPlayerDone) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player == NULL) { diff --git a/src/po_man.cpp b/src/po_man.cpp index c779a8049..4e304daa8 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -172,9 +172,11 @@ static FPolyNode *FreePolyNodes; // //========================================================================== -IMPLEMENT_POINTY_CLASS (DPolyAction) - DECLARE_POINTER(m_Interpolation) -END_POINTERS +IMPLEMENT_CLASS(DPolyAction, false, true, false, false) + +IMPLEMENT_POINTERS_START(DPolyAction) + IMPLEMENT_POINTER(m_Interpolation) +IMPLEMENT_POINTERS_END DPolyAction::DPolyAction () { @@ -238,7 +240,7 @@ void DPolyAction::StopInterpolation () // //========================================================================== -IMPLEMENT_CLASS (DRotatePoly) +IMPLEMENT_CLASS(DRotatePoly, false, false, false, false) DRotatePoly::DRotatePoly () { @@ -255,7 +257,7 @@ DRotatePoly::DRotatePoly (int polyNum) // //========================================================================== -IMPLEMENT_CLASS (DMovePoly) +IMPLEMENT_CLASS(DMovePoly, false, false, false, false) DMovePoly::DMovePoly () { @@ -282,7 +284,7 @@ DMovePoly::DMovePoly (int polyNum) // //========================================================================== -IMPLEMENT_CLASS(DMovePolyTo) +IMPLEMENT_CLASS(DMovePolyTo, false, false, false, false) DMovePolyTo::DMovePolyTo() { @@ -307,7 +309,7 @@ DMovePolyTo::DMovePolyTo(int polyNum) // //========================================================================== -IMPLEMENT_CLASS (DPolyDoor) +IMPLEMENT_CLASS(DPolyDoor, false, false, false, false) DPolyDoor::DPolyDoor () { diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index 04c3a3f2e..a1e6056ca 100644 --- a/src/posix/sdl/sdlvideo.cpp +++ b/src/posix/sdl/sdlvideo.cpp @@ -78,7 +78,8 @@ private: SDLFB () {} }; -IMPLEMENT_CLASS(SDLFB) + +IMPLEMENT_CLASS(SDLFB, false, false, false, false) struct MiniModeInfo { diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp index e60223bac..871640f47 100644 --- a/src/r_data/r_interpolate.cpp +++ b/src/r_data/r_interpolate.cpp @@ -161,14 +161,17 @@ public: // //========================================================================== -IMPLEMENT_ABSTRACT_POINTY_CLASS(DInterpolation) -DECLARE_POINTER(Next) -DECLARE_POINTER(Prev) -END_POINTERS -IMPLEMENT_CLASS(DSectorPlaneInterpolation) -IMPLEMENT_CLASS(DSectorScrollInterpolation) -IMPLEMENT_CLASS(DWallScrollInterpolation) -IMPLEMENT_CLASS(DPolyobjInterpolation) +IMPLEMENT_CLASS(DInterpolation, true, true, false, false) + +IMPLEMENT_POINTERS_START(DInterpolation) + IMPLEMENT_POINTER(Next) + IMPLEMENT_POINTER(Prev) +IMPLEMENT_POINTERS_END + +IMPLEMENT_CLASS(DSectorPlaneInterpolation, false, false, false, false) +IMPLEMENT_CLASS(DSectorScrollInterpolation, false, false, false, false) +IMPLEMENT_CLASS(DWallScrollInterpolation, false, false, false, false) +IMPLEMENT_CLASS(DPolyobjInterpolation, false, false, false, false) //========================================================================== // diff --git a/src/r_utility.cpp b/src/r_utility.cpp index b009912f0..158834929 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -1104,3 +1104,27 @@ void FCanvasTextureInfo::Mark() } } + +//========================================================================== +// +// CVAR transsouls +// +// How translucent things drawn with STYLE_SoulTrans are. Normally, only +// Lost Souls have this render style. +// Values less than 0.25 will automatically be set to +// 0.25 to ensure some degree of visibility. Likewise, values above 1.0 will +// be set to 1.0, because anything higher doesn't make sense. +// +//========================================================================== + +CUSTOM_CVAR(Float, transsouls, 0.75f, CVAR_ARCHIVE) +{ + if (self < 0.25f) + { + self = 0.25f; + } + else if (self > 1.f) + { + self = 1.f; + } +} diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 8713fe554..3f4548040 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -53,50 +53,58 @@ static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int LumpSize, int CompressedSize, int GPFlags) { - switch (Method) + try { - case METHOD_STORED: - { - Reader->Read(Cache, LumpSize); - break; - } + switch (Method) + { + case METHOD_STORED: + { + Reader->Read(Cache, LumpSize); + break; + } - case METHOD_DEFLATE: - { - FileReaderZ frz(*Reader, true); - frz.Read(Cache, LumpSize); - break; - } + case METHOD_DEFLATE: + { + FileReaderZ frz(*Reader, true); + frz.Read(Cache, LumpSize); + break; + } - case METHOD_BZIP2: - { - FileReaderBZ2 frz(*Reader); - frz.Read(Cache, LumpSize); - break; - } + case METHOD_BZIP2: + { + FileReaderBZ2 frz(*Reader); + frz.Read(Cache, LumpSize); + break; + } - case METHOD_LZMA: - { - FileReaderLZMA frz(*Reader, LumpSize, true); - frz.Read(Cache, LumpSize); - break; - } + case METHOD_LZMA: + { + FileReaderLZMA frz(*Reader, LumpSize, true); + frz.Read(Cache, LumpSize); + break; + } - case METHOD_IMPLODE: - { - FZipExploder exploder; - exploder.Explode((unsigned char *)Cache, LumpSize, Reader, CompressedSize, GPFlags); - break; - } + case METHOD_IMPLODE: + { + FZipExploder exploder; + exploder.Explode((unsigned char *)Cache, LumpSize, Reader, CompressedSize, GPFlags); + break; + } - case METHOD_SHRINK: - { - ShrinkLoop((unsigned char *)Cache, LumpSize, Reader, CompressedSize); - break; - } + case METHOD_SHRINK: + { + ShrinkLoop((unsigned char *)Cache, LumpSize, Reader, CompressedSize); + break; + } - default: - assert(0); + default: + assert(0); + return false; + } + } + catch (CRecoverableError &err) + { + Printf("%s\n", err.GetMessage()); return false; } return true; diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 0db9365c2..c68df5f3c 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -2213,7 +2213,7 @@ private: int NextCheck; }; -IMPLEMENT_CLASS (AAmbientSound) +IMPLEMENT_CLASS(AAmbientSound, false, false, false, false) //========================================================================== // @@ -2470,7 +2470,7 @@ public: virtual void PostBeginPlay(); }; -IMPLEMENT_CLASS(AMusicChanger) +IMPLEMENT_CLASS(AMusicChanger, false, false, false, false) bool AMusicChanger::DoTriggerAction (AActor *triggerer, int activationType) { diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index 3b39965ff..1bed35ed5 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -285,12 +285,14 @@ void DSeqNode::SerializeSequences (FSerializer &arc) arc("sndseqlisthead", SequenceListHead); } -IMPLEMENT_POINTY_CLASS (DSeqNode) - DECLARE_POINTER(m_ChildSeqNode) - DECLARE_POINTER(m_ParentSeqNode) - DECLARE_POINTER(m_Next) - DECLARE_POINTER(m_Prev) -END_POINTERS +IMPLEMENT_CLASS(DSeqNode, false, true, false, false) + +IMPLEMENT_POINTERS_START(DSeqNode) + IMPLEMENT_POINTER(m_ChildSeqNode) + IMPLEMENT_POINTER(m_ParentSeqNode) + IMPLEMENT_POINTER(m_Next) + IMPLEMENT_POINTER(m_Prev) +IMPLEMENT_POINTERS_END DSeqNode::DSeqNode () : m_SequenceChoices(0) @@ -427,9 +429,11 @@ FName DSeqNode::GetSequenceName () const return Sequences[m_Sequence]->SeqName; } -IMPLEMENT_POINTY_CLASS (DSeqActorNode) - DECLARE_POINTER (m_Actor) -END_POINTERS +IMPLEMENT_CLASS(DSeqActorNode, false, true, false, false) + +IMPLEMENT_POINTERS_START(DSeqActorNode) + IMPLEMENT_POINTER(m_Actor) +IMPLEMENT_POINTERS_END void DSeqActorNode::Serialize(FSerializer &arc) { @@ -437,7 +441,7 @@ void DSeqActorNode::Serialize(FSerializer &arc) arc("actor", m_Actor); } -IMPLEMENT_CLASS (DSeqPolyNode) +IMPLEMENT_CLASS(DSeqPolyNode, false, false, false, false) void DSeqPolyNode::Serialize(FSerializer &arc) { @@ -445,7 +449,7 @@ void DSeqPolyNode::Serialize(FSerializer &arc) arc("poly", m_Poly); } -IMPLEMENT_CLASS (DSeqSectorNode) +IMPLEMENT_CLASS(DSeqSectorNode, false, false, false, false) void DSeqSectorNode::Serialize(FSerializer &arc) { diff --git a/src/sc_man.cpp b/src/sc_man.cpp index 3f5530ff3..254caed62 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -1006,6 +1006,8 @@ void FScanner::CheckOpen() // //========================================================================== int FScriptPosition::ErrorCounter; +int FScriptPosition::WarnCounter; +bool FScriptPosition::StrictErrors; // makes all OPTERRPR messages real errors. FScriptPosition::FScriptPosition(const FScriptPosition &other) { @@ -1044,10 +1046,13 @@ void FScriptPosition::Message (int severity, const char *message, ...) const { FString composed; - if ((severity == MSG_DEBUG || severity == MSG_DEBUGLOG) && developer < DMSG_NOTIFY) return; + if (severity == MSG_DEBUGLOG && developer < DMSG_NOTIFY) return; + if (severity == MSG_DEBUGERROR && developer < DMSG_ERROR) return; + if (severity == MSG_DEBUGWARN && developer < DMSG_WARNING) return; + if (severity == MSG_DEBUGMSG && developer < DMSG_NOTIFY) return; if (severity == MSG_OPTERROR) { - severity = strictdecorate ? MSG_ERROR : MSG_WARNING; + severity = StrictErrors || strictdecorate ? MSG_ERROR : MSG_WARNING; } if (message == NULL) @@ -1071,8 +1076,11 @@ void FScriptPosition::Message (int severity, const char *message, ...) const return; case MSG_WARNING: + case MSG_DEBUGWARN: + case MSG_DEBUGERROR: // This is intentionally not being printed as an 'error', the difference to MSG_DEBUGWARN is only the severity level at which it gets triggered. + WarnCounter++; type = "warning"; - color = TEXTCOLOR_YELLOW; + color = TEXTCOLOR_ORANGE; break; case MSG_ERROR: @@ -1082,7 +1090,7 @@ void FScriptPosition::Message (int severity, const char *message, ...) const break; case MSG_MESSAGE: - case MSG_DEBUG: + case MSG_DEBUGMSG: type = "message"; color = TEXTCOLOR_GREEN; break; diff --git a/src/sc_man.h b/src/sc_man.h index 359dd8140..fde6efbed 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -125,7 +125,9 @@ enum MSG_FATAL, MSG_ERROR, MSG_OPTERROR, - MSG_DEBUG, + MSG_DEBUGERROR, + MSG_DEBUGWARN, + MSG_DEBUGMSG, MSG_LOG, MSG_DEBUGLOG, MSG_MESSAGE @@ -139,7 +141,9 @@ enum struct FScriptPosition { + static int WarnCounter; static int ErrorCounter; + static bool StrictErrors; FString FileName; int ScriptLine; @@ -154,6 +158,7 @@ struct FScriptPosition void Message(int severity, const char *message,...) const; static void ResetErrorCounter() { + WarnCounter = 0; ErrorCounter = 0; } }; diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 92702f918..194582d73 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -118,14 +118,14 @@ std2: 'void' { RET(TK_Void); } 'struct' { RET(TK_Struct); } 'class' { RET(TK_Class); } - 'mode' { RET(TK_Mode); } 'enum' { RET(TK_Enum); } 'name' { RET(TK_Name); } 'string' { RET(TK_String); } 'sound' { RET(TK_Sound); } 'state' { RET(TK_State); } 'color' { RET(TK_Color); } - 'vector' { RET(TK_Vector); } + 'vector2' { RET(TK_Vector2); } + 'vector3' { RET(TK_Vector3); } 'map' { RET(TK_Map); } 'array' { RET(TK_Array); } 'in' { RET(TK_In); } @@ -152,7 +152,7 @@ std2: 'transient' { RET(TK_Transient); } 'final' { RET(TK_Final); } 'throws' { RET(TK_Throws); } - 'extends' { RET(TK_Extends); } + 'extend' { RET(TK_Extend); } 'public' { RET(TK_Public); } 'protected' { RET(TK_Protected); } 'private' { RET(TK_Private); } @@ -168,10 +168,11 @@ std2: 'optional' { RET(TK_Optional); } 'export' { RET(TK_Export); } 'virtual' { RET(TK_Virtual); } + 'override' { RET(TK_Override); } 'super' { RET(TK_Super); } 'global' { RET(TK_Global); } - 'self' { RET(TK_Self); } 'stop' { RET(TK_Stop); } + 'null' { RET(TK_Null); } 'is' { RET(TK_Is); } 'replaces' { RET(TK_Replaces); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 246462940..801d02be3 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -62,7 +62,6 @@ xx(TK_ULong, "'ulong'") xx(TK_Void, "'void'") xx(TK_Struct, "'struct'") xx(TK_Class, "'class'") -xx(TK_Mode, "'mode'") xx(TK_Enum, "'enum'") xx(TK_Name, "'name'") xx(TK_String, "'string'") @@ -90,7 +89,7 @@ xx(TK_Transient, "'transient'") xx(TK_Volatile, "'volatile'") xx(TK_Final, "'final'") xx(TK_Throws, "'throws'") -xx(TK_Extends, "'extends'") +xx(TK_Extend, "'extend'") xx(TK_Public, "'public'") xx(TK_Protected, "'protected'") xx(TK_Private, "'private'") @@ -106,15 +105,17 @@ xx(TK_Iterator, "'iterator'") xx(TK_Optional, "'optional'") xx(TK_Export, "'expert'") xx(TK_Virtual, "'virtual'") +xx(TK_Override, "'override'") xx(TK_Super, "'super'") +xx(TK_Null, "'null'") xx(TK_Global, "'global'") -xx(TK_Self, "'self'") xx(TK_Stop, "'stop'") xx(TK_Include, "'include'") xx(TK_Is, "'is'") xx(TK_Replaces, "'replaces'") -xx(TK_Vector, "'vector'") +xx(TK_Vector2, "'vector2'") +xx(TK_Vector3, "'vector3'") xx(TK_Map, "'map'") xx(TK_Array, "'array'") xx(TK_In, "'in'") diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp new file mode 100644 index 000000000..626dcde24 --- /dev/null +++ b/src/scripting/codegeneration/codegen.cpp @@ -0,0 +1,8434 @@ +/* +** thingdef_expression.cpp +** +** Expression evaluation +** +**--------------------------------------------------------------------------- +** Copyright 2008 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be +** covered by the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or (at +** your option) any later version. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include "actor.h" +#include "sc_man.h" +#include "tarray.h" +#include "templates.h" +#include "cmdlib.h" +#include "i_system.h" +#include "m_random.h" +#include "a_pickups.h" +#include "thingdef.h" +#include "p_lnspec.h" +#include "doomstat.h" +#include "codegen.h" +#include "m_fixed.h" +#include "vmbuilder.h" +#include "v_text.h" +#include "w_wad.h" +#include "math/cmath.h" + +extern FRandom pr_exrandom; +FMemArena FxAlloc(65536); + +struct FLOP +{ + ENamedName Name; + int Flop; + double (*Evaluate)(double); +}; + +// Decorate operates on degrees, so the evaluate functions need to convert +// degrees to radians for those that work with angles. +static const FLOP FxFlops[] = +{ + { NAME_Exp, FLOP_EXP, [](double v) { return g_exp(v); } }, + { NAME_Log, FLOP_LOG, [](double v) { return g_log(v); } }, + { NAME_Log10, FLOP_LOG10, [](double v) { return g_log10(v); } }, + { NAME_Sqrt, FLOP_SQRT, [](double v) { return g_sqrt(v); } }, + { NAME_Ceil, FLOP_CEIL, [](double v) { return ceil(v); } }, + { NAME_Floor, FLOP_FLOOR, [](double v) { return floor(v); } }, + + { NAME_ACos, FLOP_ACOS_DEG, [](double v) { return g_acos(v) * (180.0 / M_PI); } }, + { NAME_ASin, FLOP_ASIN_DEG, [](double v) { return g_asin(v) * (180.0 / M_PI); } }, + { NAME_ATan, FLOP_ATAN_DEG, [](double v) { return g_atan(v) * (180.0 / M_PI); } }, + { NAME_Cos, FLOP_COS_DEG, [](double v) { return g_cosdeg(v); } }, + { NAME_Sin, FLOP_SIN_DEG, [](double v) { return g_sindeg(v); } }, + { NAME_Tan, FLOP_TAN_DEG, [](double v) { return g_tan(v * (M_PI / 180.0)); } }, + + { NAME_CosH, FLOP_COSH, [](double v) { return g_cosh(v); } }, + { NAME_SinH, FLOP_SINH, [](double v) { return g_sinh(v); } }, + { NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(v); } }, +}; + +//========================================================================== +// +// FCompileContext +// +//========================================================================== + +FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump) + : ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount), Lump(lump) +{ + if (fnc != nullptr) Class = fnc->OwningClass; +} + +FCompileContext::FCompileContext(PClass *cls, bool fromdecorate) + : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1) +{ +} + +PSymbol *FCompileContext::FindInClass(FName identifier, PSymbolTable *&symt) +{ + return Class != nullptr? Class->Symbols.FindSymbolInTable(identifier, symt) : nullptr; +} + +PSymbol *FCompileContext::FindInSelfClass(FName identifier, PSymbolTable *&symt) +{ + // If we have no self we cannot retrieve any values from it. + if (Function == nullptr || Function->Variants[0].SelfClass == nullptr) return nullptr; + return Function->Variants[0].SelfClass->Symbols.FindSymbolInTable(identifier, symt); +} +PSymbol *FCompileContext::FindGlobal(FName identifier) +{ + return GlobalSymbols.FindSymbol(identifier, true); +} + +void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) +{ + assert(proto != nullptr); + bool fail = false; + + if (ReturnProto == nullptr) + { + ReturnProto = proto; + return; + } + + // 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 (ReturnProto->ReturnTypes.Size() < proto->ReturnTypes.Size()) + { // Make proto the shorter one to avoid code duplication below. + swapvalues(proto, ReturnProto); + } + // If one prototype returns nothing, they both must. + if (proto->ReturnTypes.Size() == 0) + { + if (ReturnProto->ReturnTypes.Size() != 0) + { + fail = true; + } + } + else + { + for (unsigned i = 0; i < proto->ReturnTypes.Size(); i++) + { + if (ReturnProto->ReturnTypes[i] != proto->ReturnTypes[i]) + { // Incompatible + fail = true; + break; + } + } + } + + if (fail) + { + pos.Message(MSG_ERROR, "Return type mismatch"); + } +} + +bool FCompileContext::CheckReadOnly(int flags) +{ + if (!(flags & VARF_ReadOnly)) return false; + if (!(flags & VARF_InternalAccess)) return true; + return Wads.GetLumpFile(Lump) != 0; +} + +FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name) +{ + if (Block == nullptr) + { + return nullptr; + } + else + { + return Block->FindLocalVariable(name, *this); + } +} + +//========================================================================== +// +// ExpEmit +// +//========================================================================== + +ExpEmit::ExpEmit(VMFunctionBuilder *build, int type, int count) +: RegNum(build->Registers[type].Get(count)), RegType(type), RegCount(count), Konst(false), Fixed(false), Final(false), Target(false) +{ +} + +void ExpEmit::Free(VMFunctionBuilder *build) +{ + if (!Fixed && !Konst && RegType <= REGT_TYPE) + { + build->Registers[RegType].Return(RegNum, RegCount); + } +} + +void ExpEmit::Reuse(VMFunctionBuilder *build) +{ + if (!Fixed && !Konst) + { + assert(RegCount == 1); + bool success = build->Registers[RegType].Reuse(RegNum); + assert(success && "Attempt to reuse a register that is already in use"); + } +} + +//========================================================================== +// +// FindBuiltinFunction +// +// Returns the symbol for a decorate utility function. If not found, create +// it and install it a local symbol table. +// +//========================================================================== + +static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func) +{ + PSymbol *sym = GlobalSymbols.FindSymbol(funcname, false); + if (sym == nullptr) + { + PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname); + VMNativeFunction *calldec = new VMNativeFunction(func, funcname); + symfunc->Function = calldec; + sym = symfunc; + GlobalSymbols.AddSymbol(sym); + } + return sym; +} + +//========================================================================== +// +// +// +//========================================================================== + +static bool AreCompatiblePointerTypes(PType *dest, PType *source) +{ + if (dest->IsKindOf(RUNTIME_CLASS(PPointer)) && source->IsKindOf(RUNTIME_CLASS(PPointer))) + { + // Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type. + auto fromtype = static_cast(source); + auto totype = static_cast(dest); + if (fromtype == nullptr) return true; + if (totype->IsConst && !fromtype->IsConst) return false; + if (fromtype == totype) return true; + if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass))) + { + auto fromcls = static_cast(fromtype->PointedType); + auto tocls = static_cast(totype->PointedType); + return (fromcls->IsDescendantOf(tocls)); + } + } + return false; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxExpression::Emit (VMFunctionBuilder *build) +{ + ScriptPosition.Message(MSG_ERROR, "Unemitted expression found"); + return ExpEmit(); +} + + +//========================================================================== +// +// +// +//========================================================================== + +bool FxExpression::isConstant() const +{ + return false; +} + +//========================================================================== +// +// +// +//========================================================================== + +VMFunction *FxExpression::GetDirectFunction() +{ + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxExpression::Resolve(FCompileContext &ctx) +{ + isresolved = true; + return this; +} + +//========================================================================== +// +// Returns true if we can write to the address. +// +//========================================================================== + +bool FxExpression::RequestAddress(FCompileContext &ctx, bool *writable) +{ + if (writable != nullptr) *writable = false; + return false; +} + +//========================================================================== +// +// Called by return statements. +// +//========================================================================== + +PPrototype *FxExpression::ReturnProto() +{ + assert(ValueType != nullptr); + + TArray ret(0); + TArray none(0); + if (ValueType != TypeVoid) + { + ret.Push(ValueType); + } + + return NewPrototype(ret, none); +} + +//========================================================================== +// +// +// +//========================================================================== + +static int EncodeRegType(ExpEmit reg) +{ + int regtype = reg.RegType; + if (reg.Konst) + { + regtype |= REGT_KONST; + } + else if (reg.RegCount == 2) + { + regtype |= REGT_MULTIREG2; + + } + else if (reg.RegCount == 3) + { + regtype |= REGT_MULTIREG3; + } + return regtype; +} + +//========================================================================== +// +// +// +//========================================================================== + +static int EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const FScriptPosition &pos) +{ + ExpEmit where = operand->Emit(build); + + if (where.RegType == REGT_NIL) + { + pos.Message(MSG_ERROR, "Attempted to pass a non-value"); + build->Emit(OP_PARAM, 0, where.RegType, where.RegNum); + return 1; + } + else + { + build->Emit(OP_PARAM, 0, EncodeRegType(where), where.RegNum); + where.Free(build); + return where.RegCount; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos) +{ + FxExpression *x; + PSymbolConstNumeric *csym = dyn_cast(sym); + if (csym != nullptr) + { + if (csym->ValueType->IsA(RUNTIME_CLASS(PInt))) + { + x = new FxConstant(csym->Value, pos); + } + else if (csym->ValueType->IsA(RUNTIME_CLASS(PFloat))) + { + x = new FxConstant(csym->Float, pos); + } + else + { + pos.Message(MSG_ERROR, "Invalid constant '%s'\n", csym->SymbolName.GetChars()); + return nullptr; + } + } + else + { + pos.Message(MSG_ERROR, "'%s' is not a constant\n", sym->SymbolName.GetChars()); + x = nullptr; + } + return x; +} + +ExpEmit FxConstant::Emit(VMFunctionBuilder *build) +{ + ExpEmit out; + + out.Konst = true; + int regtype = value.Type->GetRegType(); + out.RegType = regtype; + if (regtype == REGT_INT) + { + out.RegNum = build->GetConstantInt(value.Int); + } + else if (regtype == REGT_FLOAT) + { + out.RegNum = build->GetConstantFloat(value.Float); + } + else if (regtype == REGT_POINTER) + { + VM_ATAG tag = ATAG_GENERIC; + if (value.Type == TypeState) + { + tag = ATAG_STATE; + } + else if (value.Type->GetLoadOp() == OP_LO) + { + tag = ATAG_OBJECT; + } + out.RegNum = build->GetConstantAddress(value.pointer, tag); + } + else if (regtype == REGT_STRING) + { + out.RegNum = build->GetConstantString(value.GetString()); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Cannot emit needed constant"); + out.RegNum = 0; + } + return out; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxVectorValue::FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc) + :FxExpression(EFX_VectorValue, sc) +{ + xyz[0] = x; + xyz[1] = y; + xyz[2] = z; + isConst = false; + ValueType = TypeVoid; // we do not know yet +} + +FxVectorValue::~FxVectorValue() +{ + for (auto &a : xyz) + { + SAFE_DELETE(a); + } +} + +FxExpression *FxVectorValue::Resolve(FCompileContext&ctx) +{ + bool fails = false; + + for (auto &a : xyz) + { + if (a != nullptr) + { + a = a->Resolve(ctx); + if (a == nullptr) fails = true; + else + { + if (a->ValueType != TypeVector2) // a vec3 may be initialized with (vec2, z) + { + a = new FxFloatCast(a); + a = a->Resolve(ctx); + fails |= (a == nullptr); + } + } + } + } + if (fails) + { + delete this; + return nullptr; + } + // at this point there are three legal cases: + // * two floats = vector2 + // * three floats = vector3 + // * vector2 + float = vector3 + if (xyz[0]->ValueType == TypeVector2) + { + if (xyz[1]->ValueType != TypeFloat64 || xyz[2] != nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Not a valid vector"); + delete this; + return nullptr; + } + ValueType = TypeVector3; + if (xyz[0]->ExprType == EFX_VectorValue) + { + // If two vector initializers are nested, unnest them now. + auto vi = static_cast(xyz[0]); + xyz[2] = xyz[1]; + xyz[1] = vi->xyz[1]; + xyz[0] = vi->xyz[0]; + vi->xyz[0] = vi->xyz[1] = nullptr; // Don't delete our own expressions. + delete vi; + } + } + else if (xyz[0]->ValueType == TypeFloat64 && xyz[1]->ValueType == TypeFloat64) + { + ValueType = xyz[2] == nullptr ? TypeVector2 : TypeVector3; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Not a valid vector"); + delete this; + return nullptr; + } + + // check if all elements are constant. If so this can be emitted as a constant vector. + isConst = true; + for (auto &a : xyz) + { + if (a != nullptr && !a->isConstant()) isConst = false; + } + return this; +} + +static ExpEmit EmitKonst(VMFunctionBuilder *build, ExpEmit &emit) +{ + if (emit.Konst) + { + ExpEmit out(build, REGT_FLOAT); + build->Emit(OP_LKF, out.RegNum, emit.RegNum); + return out; + } + return emit; +} + +ExpEmit FxVectorValue::Emit(VMFunctionBuilder *build) +{ + // no const handling here. Ultimstely it's too rarely used (i.e. the only fully constant vector ever allocated in ZDoom is the 0-vector in a very few places) + // and the negatives (excessive allocation of float constants) outweigh the positives (saved a few instructions) + assert(xyz[0] != nullptr); + assert(xyz[1] != nullptr); + if (ValueType == TypeVector2) + { + ExpEmit tempxval = xyz[0]->Emit(build); + ExpEmit tempyval = xyz[1]->Emit(build); + ExpEmit xval = EmitKonst(build, tempxval); + ExpEmit yval = EmitKonst(build, tempyval); + assert(xval.RegType == REGT_FLOAT && yval.RegType == REGT_FLOAT); + if (yval.RegNum == xval.RegNum + 1) + { + // The results are already in two continuous registers so just return them as-is. + xval.RegCount++; + return xval; + } + else + { + // The values are not in continuous registers so they need to be copied together now. + ExpEmit out(build, REGT_FLOAT, 2); + build->Emit(OP_MOVEF, out.RegNum, xval.RegNum); + build->Emit(OP_MOVEF, out.RegNum + 1, yval.RegNum); + xval.Free(build); + yval.Free(build); + return out; + } + } + else if (xyz[0]->ValueType == TypeVector2) // vec2+float + { + ExpEmit xyval = xyz[0]->Emit(build); + ExpEmit tempzval = xyz[1]->Emit(build); + ExpEmit zval = EmitKonst(build, tempzval); + assert(xyval.RegType == REGT_FLOAT && xyval.RegCount == 2 && zval.RegType == REGT_FLOAT); + if (zval.RegNum == xyval.RegNum + 2) + { + // The results are already in three continuous registers so just return them as-is. + xyval.RegCount++; + return xyval; + } + else + { + // The values are not in continuous registers so they need to be copied together now. + ExpEmit out(build, REGT_FLOAT, 3); + build->Emit(OP_MOVEV2, out.RegNum, xyval.RegNum); + build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum); + xyval.Free(build); + zval.Free(build); + return out; + } + } + else // 3*float + { + assert(xyz[2] != nullptr); + ExpEmit tempxval = xyz[0]->Emit(build); + ExpEmit tempyval = xyz[1]->Emit(build); + ExpEmit tempzval = xyz[2]->Emit(build); + ExpEmit xval = EmitKonst(build, tempxval); + ExpEmit yval = EmitKonst(build, tempyval); + ExpEmit zval = EmitKonst(build, tempzval); + assert(xval.RegType == REGT_FLOAT && yval.RegType == REGT_FLOAT && zval.RegType == REGT_FLOAT); + if (yval.RegNum == xval.RegNum + 1 && zval.RegNum == xval.RegNum + 2) + { + // The results are already in three continuous registers so just return them as-is. + xval.RegCount += 2; + return xval; + } + else + { + // The values are not in continuous registers so they need to be copied together now. + ExpEmit out(build, REGT_FLOAT, 3); + //Try to optimize a bit... + if (yval.RegNum == xval.RegNum + 1) + { + build->Emit(OP_MOVEV2, out.RegNum, xval.RegNum); + build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum); + } + else if (zval.RegNum == yval.RegNum + 1) + { + build->Emit(OP_MOVEF, out.RegNum, xval.RegNum); + build->Emit(OP_MOVEV2, out.RegNum+1, yval.RegNum); + } + else + { + build->Emit(OP_MOVEF, out.RegNum, xval.RegNum); + build->Emit(OP_MOVEF, out.RegNum + 1, yval.RegNum); + build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum); + } + xval.Free(build); + yval.Free(build); + zval.Free(build); + return out; + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxBoolCast::FxBoolCast(FxExpression *x, bool needvalue) + : FxExpression(EFX_BoolCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeBool; + NeedValue = needvalue; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxBoolCast::~FxBoolCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxBoolCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType == TypeBool) + { + FxExpression *x = basex; + basex = nullptr; + delete this; + return x; + } + else if (basex->IsBoolCompat()) + { + if (basex->isConstant()) + { + assert(basex->ValueType != TypeState && "We shouldn't be able to generate a constant state ref"); + + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(constval.GetBool(), ScriptPosition); + delete this; + return x; + } + return this; + } + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit from = basex->Emit(build); + assert(!from.Konst); + assert(basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER); + + if (NeedValue) + { + ExpEmit to(build, REGT_INT); + from.Free(build); + // Preload result with 0. + build->Emit(OP_LI, to.RegNum, 0); + + // Check source against 0. + if (from.RegType == REGT_INT) + { + build->Emit(OP_EQ_R, 1, from.RegNum, to.RegNum); + } + else if (from.RegType == REGT_FLOAT) + { + build->Emit(OP_EQF_K, 1, from.RegNum, build->GetConstantFloat(0.)); + } + else if (from.RegType == REGT_POINTER) + { + build->Emit(OP_EQA_K, 1, from.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC)); + } + build->Emit(OP_JMP, 1); + + // Reload result with 1 if the comparison fell through. + build->Emit(OP_LI, to.RegNum, 1); + return to; + } + else + { + return from; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxIntCast::FxIntCast(FxExpression *x, bool nowarn, bool explicitly) +: FxExpression(EFX_IntCast, x->ScriptPosition) +{ + basex=x; + ValueType = TypeSInt32; + NoWarn = nowarn; + Explicit = explicitly; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxIntCast::~FxIntCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxIntCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType->GetRegType() == REGT_INT) + { + if (basex->ValueType->isNumeric() || Explicit) // names can be converted to int, but only with an explicit type cast. + { + FxExpression *x = basex; + x->ValueType = ValueType; + basex = nullptr; + delete this; + return x; + } + else + { + // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this serious error needs to be reduced to a warning. :( + // At least in ZScript, MSG_OPTERROR always means to report an error, not a warning so the problem only exists in DECORATE. + if (!basex->isConstant()) + ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); + FxExpression * x = new FxConstant(0, ScriptPosition); + delete this; + return x; + } + } + else if (basex->IsFloat()) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(constval.GetInt(), ScriptPosition); + if (!NoWarn && constval.GetInt() != constval.GetFloat()) + { + ScriptPosition.Message(MSG_WARNING, "Truncation of floating point constant %f", constval.GetFloat()); + } + + delete this; + return x; + } + else if (!NoWarn) + { + ScriptPosition.Message(MSG_WARNING, "Truncation of floating point value"); + } + + return this; + } + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxIntCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit from = basex->Emit(build); + assert(!from.Konst); + assert(basex->ValueType->GetRegType() == REGT_FLOAT); + from.Free(build); + ExpEmit to(build, REGT_INT); + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_F2I); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFloatCast::FxFloatCast(FxExpression *x) + : FxExpression(EFX_FloatCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeFloat64; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFloatCast::~FxFloatCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->IsFloat()) + { + FxExpression *x = basex; + basex = nullptr; + delete this; + return x; + } + else if (basex->ValueType->GetRegType() == REGT_INT) + { + if (basex->ValueType->isNumeric()) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition); + delete this; + return x; + } + return this; + } + else + { + // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( + // At least in ZScript, MSG_OPTERROR always means to report an error, not a warning so the problem only exists in DECORATE. + if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); + FxExpression *x = new FxConstant(0.0, ScriptPosition); + delete this; + return x; + } + } + else + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit from = basex->Emit(build); + assert(!from.Konst); + assert(basex->ValueType->GetRegType() == REGT_INT); + from.Free(build); + ExpEmit to(build, REGT_FLOAT); + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_I2F); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxNameCast::FxNameCast(FxExpression *x) + : FxExpression(EFX_NameCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeName; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxNameCast::~FxNameCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxNameCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType == TypeName) + { + FxExpression *x = basex; + basex = nullptr; + delete this; + return x; + } + else if (basex->ValueType == TypeString) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(constval.GetName(), ScriptPosition); + delete this; + return x; + } + return this; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Cannot convert to name"); + delete this; + return nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxNameCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit from = basex->Emit(build); + assert(!from.Konst); + assert(basex->ValueType == TypeString); + from.Free(build); + ExpEmit to(build, REGT_INT); + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_S2N); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxStringCast::FxStringCast(FxExpression *x) + : FxExpression(EFX_StringCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeString; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxStringCast::~FxStringCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxStringCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType == TypeString) + { + FxExpression *x = basex; + basex = nullptr; + delete this; + return x; + } + else if (basex->ValueType == TypeName) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(constval.GetString(), ScriptPosition); + delete this; + return x; + } + return this; + } + else if (basex->ValueType == TypeSound) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(S_sfx[constval.GetInt()].name, ScriptPosition); + delete this; + return x; + } + return this; + } + // although it could be done, let's not convert colors back to strings. + else + { + ScriptPosition.Message(MSG_ERROR, "Cannot convert to string"); + delete this; + return nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxStringCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit from = basex->Emit(build); + assert(!from.Konst); + + from.Free(build); + ExpEmit to(build, REGT_STRING); + if (basex->ValueType == TypeName) + { + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_N2S); + } + else if (basex->ValueType == TypeSound) + { + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_So2S); + } + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxColorCast::FxColorCast(FxExpression *x) + : FxExpression(EFX_ColorCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeColor; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxColorCast::~FxColorCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxColorCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType == TypeColor || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt)) + { + FxExpression *x = basex; + x->ValueType = TypeColor; + basex = nullptr; + delete this; + return x; + } + else if (basex->ValueType == TypeString) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + if (constval.GetString().Len() == 0) + { + // empty string means 'no state'. This would otherwise just cause endless errors and have the same result anyway. + FxExpression *x = new FxConstant(-1, ScriptPosition); + delete this; + return x; + } + else + { + FxExpression *x = new FxConstant(V_GetColor(nullptr, constval.GetString()), ScriptPosition); + delete this; + return x; + } + } + return this; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Cannot convert to color"); + delete this; + return nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxColorCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit from = basex->Emit(build); + assert(!from.Konst); + assert(basex->ValueType == TypeString); + from.Free(build); + ExpEmit to(build, REGT_INT); + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_S2Co); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxSoundCast::FxSoundCast(FxExpression *x) + : FxExpression(EFX_SoundCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeSound; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxSoundCast::~FxSoundCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxSoundCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType == TypeSound || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt)) + { + FxExpression *x = basex; + x->ValueType = TypeSound; + basex = nullptr; + delete this; + return x; + } + else if (basex->ValueType == TypeString) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(FSoundID(constval.GetString()), ScriptPosition); + delete this; + return x; + } + return this; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Cannot convert to sound"); + delete this; + return nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit from = basex->Emit(build); + assert(!from.Konst); + assert(basex->ValueType == TypeString); + from.Free(build); + ExpEmit to(build, REGT_INT); + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_S2So); + return to; +} + +//========================================================================== +// +// generic type cast operator +// +//========================================================================== + +FxTypeCast::FxTypeCast(FxExpression *x, PType *type, bool nowarn, bool explicitly) + : FxExpression(EFX_TypeCast, x->ScriptPosition) +{ + basex = x; + ValueType = type; + NoWarn = nowarn; + Explicit = explicitly; + assert(ValueType != nullptr); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxTypeCast::~FxTypeCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + // first deal with the simple types + if (ValueType == TypeError || basex->ValueType == TypeError) + { + ScriptPosition.Message(MSG_ERROR, "Trying to cast to invalid type."); + delete this; + return nullptr; + } + else if (ValueType == TypeVoid) // this should never happen + { + goto errormsg; + } + else if (basex->ValueType == TypeVoid) + { + goto errormsg; + } + else if (basex->ValueType == ValueType) + { + // don't go through the entire list if the types are the same. + goto basereturn; + } + else if (basex->ValueType == TypeNullPtr && (ValueType == TypeState || ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))) + { + goto basereturn; + } + else if (IsFloat()) + { + FxExpression *x = new FxFloatCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else if (ValueType->IsA(RUNTIME_CLASS(PInt))) + { + // This is only for casting to actual ints. Subtypes representing an int will be handled elsewhere. + FxExpression *x = new FxIntCast(basex, NoWarn, Explicit); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else if (ValueType == TypeBool) + { + FxExpression *x = new FxBoolCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else if (ValueType == TypeString) + { + FxExpression *x = new FxStringCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else if (ValueType == TypeName) + { + FxExpression *x = new FxNameCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else if (ValueType == TypeSound) + { + FxExpression *x = new FxSoundCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else if (ValueType == TypeColor) + { + FxExpression *x = new FxColorCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else if (ValueType == TypeStateLabel) + { + if (basex->ValueType == TypeNullPtr) + { + auto x = new FxConstant(0, ScriptPosition); + x->ValueType = TypeStateLabel; + delete this; + return x; + } + // Right now this only supports string constants. There should be an option to pass a string variable, too. + if (basex->isConstant() && (basex->ValueType == TypeString || basex->ValueType == TypeName)) + { + const char *s = static_cast(basex)->GetValue().GetString(); + if (*s == 0 && !ctx.FromDecorate) // DECORATE should never get here at all, but let's better be safe. + { + ScriptPosition.Message(MSG_ERROR, "State jump to empty label."); + delete this; + return nullptr; + } + FxExpression *x = new FxMultiNameState(s, basex->ScriptPosition); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else if (basex->IsNumeric() && basex->ValueType != TypeSound && basex->ValueType != TypeColor) + { + if (ctx.StateIndex < 0) + { + ScriptPosition.Message(MSG_ERROR, "State jumps with index can only be used in anonymous state functions."); + delete this; + return nullptr; + } + if (ctx.StateCount != 1) + { + ScriptPosition.Message(MSG_ERROR, "State jumps with index cannot be used on multistate definitions"); + delete this; + return nullptr; + } + if (basex->isConstant()) + { + int i = static_cast(basex)->GetValue().GetInt(); + if (i <= 0) + { + ScriptPosition.Message(MSG_ERROR, "State index must be positive"); + delete this; + return nullptr; + } + FxExpression *x = new FxStateByIndex(ctx.StateIndex + i, ScriptPosition); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + else + { + FxExpression *x = new FxRuntimeStateIndex(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + } + } + else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + { + FxExpression *x = new FxClassTypeCast(static_cast(ValueType), basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } + /* else if (ValueType->IsKindOf(RUNTIME_CLASS(PEnum))) + { + // this is not yet ready and does not get assigned to actual values. + } + */ + else if (ValueType->IsKindOf(RUNTIME_CLASS(PClass))) // this should never happen because the VM doesn't handle plain class types - just pointers + { + if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PClass))) + { + // class types are only compatible if the base type is a descendant of the result type. + auto fromtype = static_cast(basex->ValueType); + auto totype = static_cast(ValueType); + if (fromtype->IsDescendantOf(totype)) goto basereturn; + } + } + else if (AreCompatiblePointerTypes(ValueType, basex->ValueType)) + { + goto basereturn; + } + // todo: pointers to class objects. + // All other types are only compatible to themselves and have already been handled above by the equality check. + // Anything that falls through here is not compatible and must print an error. + +errormsg: + ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to %s", basex->ValueType->DescriptiveName(), ValueType->DescriptiveName()); + delete this; + return nullptr; + +basereturn: + auto x = basex; + x->ValueType = ValueType; + basex = nullptr; + delete this; + return x; + +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxTypeCast::Emit(VMFunctionBuilder *build) +{ + assert(false); + // This should never be reached + return ExpEmit(); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxPlusSign::FxPlusSign(FxExpression *operand) +: FxExpression(EFX_PlusSign, operand->ScriptPosition) +{ + Operand=operand; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxPlusSign::~FxPlusSign() +{ + SAFE_DELETE(Operand); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxPlusSign::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Operand, ctx); + + if (Operand->IsNumeric() || Operand->IsVector()) + { + FxExpression *e = Operand; + Operand = nullptr; + delete this; + return e; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } +} + +ExpEmit FxPlusSign::Emit(VMFunctionBuilder *build) +{ + return Operand->Emit(build); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMinusSign::FxMinusSign(FxExpression *operand) +: FxExpression(EFX_MinusSign, operand->ScriptPosition) +{ + Operand=operand; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMinusSign::~FxMinusSign() +{ + SAFE_DELETE(Operand); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMinusSign::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Operand, ctx); + + if (Operand->IsNumeric() || Operand->IsVector()) + { + if (Operand->isConstant()) + { + ExpVal val = static_cast(Operand)->GetValue(); + FxExpression *e = val.Type->GetRegType() == REGT_INT ? + new FxConstant(-val.Int, ScriptPosition) : + new FxConstant(-val.Float, ScriptPosition); + delete this; + return e; + } + ValueType = Operand->ValueType; + return this; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) +{ + assert(ValueType == Operand->ValueType); + ExpEmit from = Operand->Emit(build); + assert(from.Konst == 0); + assert(ValueType->GetRegCount() == from.RegCount); + // Do it in-place, unless a local variable + if (from.Fixed) + { + ExpEmit to = ExpEmit(build, from.RegType, from.RegCount); + build->Emit(Operand->ValueType->GetMoveOp(), to.RegNum, from.RegNum); + from = to; + } + + if (ValueType->GetRegType() == REGT_INT) + { + build->Emit(OP_NEG, from.RegNum, from.RegNum, 0); + } + else + { + assert(ValueType->GetRegType() == REGT_FLOAT); + switch (from.RegCount) + { + case 1: + build->Emit(OP_FLOP, from.RegNum, from.RegNum, FLOP_NEG); + break; + + case 2: + build->Emit(OP_NEGV2, from.RegNum, from.RegNum); + break; + + case 3: + build->Emit(OP_NEGV3, from.RegNum, from.RegNum); + break; + + } + } + return from; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxUnaryNotBitwise::FxUnaryNotBitwise(FxExpression *operand) +: FxExpression(EFX_UnaryNotBitwise, operand->ScriptPosition) +{ + Operand=operand; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxUnaryNotBitwise::~FxUnaryNotBitwise() +{ + SAFE_DELETE(Operand); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Operand, ctx); + + if (ctx.FromDecorate && Operand->IsFloat() /* lax */) + { + // DECORATE allows floats here so cast them to int. + Operand = new FxIntCast(Operand, true); + Operand = Operand->Resolve(ctx); + if (Operand == nullptr) + { + delete this; + return nullptr; + } + } + + // Names were not blocked in DECORATE here after the scripting branch merge. Now they are again. + if (!Operand->IsInteger()) + { + ScriptPosition.Message(MSG_ERROR, "Integer type expected"); + delete this; + return nullptr; + } + + if (Operand->isConstant()) + { + int result = ~static_cast(Operand)->GetValue().GetInt(); + FxExpression *e = new FxConstant(result, ScriptPosition); + delete this; + return e; + } + ValueType = TypeSInt32; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxUnaryNotBitwise::Emit(VMFunctionBuilder *build) +{ + assert(Operand->ValueType->GetRegType() == REGT_INT); + ExpEmit from = Operand->Emit(build); + assert(!from.Konst); + // Do it in-place. + build->Emit(OP_NOT, from.RegNum, from.RegNum, 0); + return from; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxUnaryNotBoolean::FxUnaryNotBoolean(FxExpression *operand) +: FxExpression(EFX_UnaryNotBoolean, operand->ScriptPosition) +{ + Operand=operand; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxUnaryNotBoolean::~FxUnaryNotBoolean() +{ + SAFE_DELETE(Operand); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxUnaryNotBoolean::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Operand, ctx); + + if (Operand->ValueType != TypeBool) + { + Operand = new FxBoolCast(Operand); + SAFE_RESOLVE(Operand, ctx); + } + + if (Operand->isConstant()) + { + bool result = !static_cast(Operand)->GetValue().GetBool(); + FxExpression *e = new FxConstant(result, ScriptPosition); + delete this; + return e; + } + + ValueType = TypeBool; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) +{ + assert(Operand->ValueType == ValueType); + assert(ValueType == TypeBool); + ExpEmit from = Operand->Emit(build); + assert(!from.Konst); + // boolean not is the same as XOR-ing the lowest bit + build->Emit(OP_XOR_RK, from.RegNum, from.RegNum, build->GetConstantInt(1)); + return from; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxSizeAlign::FxSizeAlign(FxExpression *operand, int which) + : FxExpression(EFX_SizeAlign, operand->ScriptPosition) +{ + Operand = operand; + Which = which; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxSizeAlign::~FxSizeAlign() +{ + SAFE_DELETE(Operand); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxSizeAlign::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Operand, ctx); + + auto type = Operand->ValueType; + if (Operand->isConstant()) + { + ScriptPosition.Message(MSG_ERROR, "cannot determine %s of a constant", Which == TK_AlignOf? "alignment" : "size"); + delete this; + return nullptr; + } + else if (!Operand->RequestAddress(ctx, nullptr)) + { + ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == TK_AlignOf ? "alignment" : "size"); + delete this; + return nullptr; + } + else + { + FxExpression *x = new FxConstant(Which == TK_AlignOf ? int(type->Align) : int(type->Size), Operand->ScriptPosition); + delete this; + return x->Resolve(ctx); + } +} + +ExpEmit FxSizeAlign::Emit(VMFunctionBuilder *build) +{ + return ExpEmit(); +} + +//========================================================================== +// +// FxPreIncrDecr +// +//========================================================================== + +FxPreIncrDecr::FxPreIncrDecr(FxExpression *base, int token) +: FxExpression(EFX_PreIncrDecr, base->ScriptPosition), Token(token), Base(base) +{ + AddressRequested = false; + AddressWritable = false; +} + +FxPreIncrDecr::~FxPreIncrDecr() +{ + SAFE_DELETE(Base); +} + +bool FxPreIncrDecr::RequestAddress(FCompileContext &ctx, bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = AddressWritable; + return true; +} + +FxExpression *FxPreIncrDecr::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Base, ctx); + + ValueType = Base->ValueType; + + if (!Base->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + else if (Base->ValueType == TypeBool) + { + ScriptPosition.Message(MSG_ERROR, "%s is not allowed on type bool", FScanner::TokenName(Token).GetChars()); + delete this; + return nullptr; + } + if (!Base->RequestAddress(ctx, &AddressWritable) || !AddressWritable ) + { + ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); + delete this; + return nullptr; + } + + return this; +} + +ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) +{ + assert(Token == TK_Incr || Token == TK_Decr); + assert(ValueType == Base->ValueType && IsNumeric()); + + int zero = build->GetConstantInt(0); + int regtype = ValueType->GetRegType(); + ExpEmit pointer = Base->Emit(build); + ExpEmit value = pointer; + + if (!pointer.Target) + { + value = ExpEmit(build, regtype); + build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero); + } + + if (regtype == REGT_INT) + { + build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, value.RegNum, value.RegNum, build->GetConstantInt(1)); + } + else + { + build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, value.RegNum, value.RegNum, build->GetConstantFloat(1.)); + } + + if (!pointer.Target) + { + build->Emit(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero); + } + + if (AddressRequested) + { + value.Free(build); + return pointer; + } + + pointer.Free(build); + return value; +} + +//========================================================================== +// +// FxPostIncrDecr +// +//========================================================================== + +FxPostIncrDecr::FxPostIncrDecr(FxExpression *base, int token) +: FxExpression(EFX_PostIncrDecr, base->ScriptPosition), Token(token), Base(base) +{ +} + +FxPostIncrDecr::~FxPostIncrDecr() +{ + SAFE_DELETE(Base); +} + +FxExpression *FxPostIncrDecr::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Base, ctx); + bool AddressWritable; + + ValueType = Base->ValueType; + + if (!Base->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + else if (Base->ValueType == TypeBool) + { + ScriptPosition.Message(MSG_ERROR, "%s is not allowed on type bool", FScanner::TokenName(Token).GetChars()); + delete this; + return nullptr; + } + if (!Base->RequestAddress(ctx, &AddressWritable) || !AddressWritable) + { + ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); + delete this; + return nullptr; + } + + return this; +} + +ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) +{ + assert(Token == TK_Incr || Token == TK_Decr); + assert(ValueType == Base->ValueType && IsNumeric()); + + int zero = build->GetConstantInt(0); + int regtype = ValueType->GetRegType(); + ExpEmit pointer = Base->Emit(build); + + if (!pointer.Target) + { + ExpEmit out(build, regtype); + build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero); + ExpEmit assign(build, regtype); + if (regtype == REGT_INT) + { + build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, assign.RegNum, out.RegNum, build->GetConstantInt(1)); + } + else + { + build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, assign.RegNum, out.RegNum, build->GetConstantFloat(1.)); + } + build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero); + pointer.Free(build); + assign.Free(build); + return out; + } + else if (NeedResult) + { + ExpEmit out(build, regtype); + if (regtype == REGT_INT) + { + build->Emit(OP_MOVE, out.RegNum, pointer.RegNum); + build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, pointer.RegNum, pointer.RegNum, build->GetConstantInt(1)); + } + else + { + build->Emit(OP_MOVEF, out.RegNum, pointer.RegNum); + build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, pointer.RegNum, pointer.RegNum, build->GetConstantFloat(1.)); + } + pointer.Free(build); + return out; + } + else + { + if (regtype == REGT_INT) + { + build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, pointer.RegNum, pointer.RegNum, build->GetConstantInt(1)); + } + else + { + build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, pointer.RegNum, pointer.RegNum, build->GetConstantFloat(1.)); + } + pointer.Free(build); + return ExpEmit(); + } +} + +//========================================================================== +// +// FxAssign +// +//========================================================================== + +FxAssign::FxAssign(FxExpression *base, FxExpression *right, bool ismodify) +: FxExpression(EFX_Assign, base->ScriptPosition), Base(base), Right(right), IsBitWrite(-1), IsModifyAssign(ismodify) +{ + AddressRequested = false; + AddressWritable = false; +} + +FxAssign::~FxAssign() +{ + SAFE_DELETE(Base); + SAFE_DELETE(Right); +} + +/* I don't think we should allow constructs like (a = b) = c;... +bool FxAssign::RequestAddress(FCompileContext &ctx, bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = AddressWritable; + return true; +} +*/ + +FxExpression *FxAssign::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Base, ctx); + + ValueType = Base->ValueType; + + SAFE_RESOLVE(Right, ctx); + + if (IsModifyAssign && Base->ValueType == TypeBool && Right->ValueType != TypeBool) + { + // If the modify operation resulted in a type promotion from bool to int, this must be blocked. + // (this means, for bool, only &=, ^= and |= are allowed, although DECORATE is more lax.) + ScriptPosition.Message(MSG_ERROR, "Invalid modify/assign operation with a boolean operand"); + delete this; + return nullptr; + } + + // keep the redundant handling for numeric types here to avoid problems with DECORATE. + // for non-numerics FxTypeCast can be used without issues. + if (Base->IsNumeric() && Right->IsNumeric()) + { + if (Right->ValueType != ValueType) + { + if (ValueType == TypeBool) + { + Right = new FxBoolCast(Right); + } + else if (ValueType->GetRegType() == REGT_INT) + { + Right = new FxIntCast(Right, ctx.FromDecorate); + } + else + { + Right = new FxFloatCast(Right); + } + SAFE_RESOLVE(Right, ctx); + } + } + else if (Base->ValueType == Right->ValueType) + { + if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PArray))) + { + ScriptPosition.Message(MSG_ERROR, "Cannot assign arrays"); + delete this; + return nullptr; + } + if (!Base->IsVector() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) + { + ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet"); + delete this; + return nullptr; + } + // Both types are the same so this is ok. + } + else + { + // pass it to FxTypeCast for complete handling. + Right = new FxTypeCast(Right, Base->ValueType, false); + SAFE_RESOLVE(Right, ctx); + } + + if (!Base->RequestAddress(ctx, &AddressWritable) || !AddressWritable) + { + ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); + delete this; + return nullptr; + } + + // Special case: Assignment to a bitfield. + if (Base->ExprType == EFX_StructMember || Base->ExprType == EFX_ClassMember) + { + auto f = static_cast(Base)->membervar; + if (f->BitValue != -1 && !ctx.CheckReadOnly(f->Flags)) + { + IsBitWrite = f->BitValue; + return this; + } + } + + return this; +} + +ExpEmit FxAssign::Emit(VMFunctionBuilder *build) +{ + static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; + assert(ValueType == Base->ValueType); + assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); + + ExpEmit pointer = Base->Emit(build); + Address = pointer; + + ExpEmit result = Right->Emit(build); + assert(result.RegType <= REGT_TYPE); + + if (pointer.Target) + { + if (result.Konst) + { + build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum); + } + else + { + build->Emit(Right->ValueType->GetMoveOp(), pointer.RegNum, result.RegNum); + } + } + else + { + if (result.Konst) + { + ExpEmit temp(build, result.RegType); + build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum); + result.Free(build); + result = temp; + } + + if (IsBitWrite == -1) + { + build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); + } + else + { + build->Emit(OP_SBIT, pointer.RegNum, result.RegNum, 1 << IsBitWrite); + } + + } + + if (AddressRequested) + { + result.Free(build); + return pointer; + } + + pointer.Free(build); + return result; +} + +//========================================================================== +// +// FxAssignSelf +// +//========================================================================== + +FxAssignSelf::FxAssignSelf(const FScriptPosition &pos) +: FxExpression(EFX_AssignSelf, pos) +{ + Assignment = nullptr; +} + +FxExpression *FxAssignSelf::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + + // This should never happen if FxAssignSelf is used correctly + assert(Assignment != nullptr); + + ValueType = Assignment->ValueType; + + return this; +} + +ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) +{ + assert(ValueType == Assignment->ValueType); + ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it + if (!pointer.Target) + { + ExpEmit out(build, ValueType->GetRegType()); + if (Assignment->IsBitWrite != -1) + { + build->Emit(OP_LBIT, out.RegNum, pointer.RegNum, 1 << Assignment->IsBitWrite); + } + else + { + build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0)); + } + return out; + } + else + { + return pointer; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxBinary::FxBinary(int o, FxExpression *l, FxExpression *r) +: FxExpression(EFX_Binary, l->ScriptPosition) +{ + Operator=o; + left=l; + right=r; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxBinary::~FxBinary() +{ + SAFE_DELETE(left); + SAFE_DELETE(right); +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) +{ + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) + { + delete this; + return false; + } + + if (left->ValueType == TypeString || right->ValueType == TypeString) + { + switch (Operator) + { + case '+': + // later + break; + + case '<': + case '>': + case TK_Geq: + case TK_Leq: + case TK_Eq: + case TK_Neq: + case TK_ApproxEq: + if (left->ValueType != TypeString) + { + left = new FxStringCast(left); + left = left->Resolve(ctx); + if (left == nullptr) + { + delete this; + return false; + } + } + if (right->ValueType != TypeString) + { + right = new FxStringCast(right); + right = right->Resolve(ctx); + if (right == nullptr) + { + delete this; + return false; + } + } + ValueType = TypeBool; + break; + + default: + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for comparison"); + delete this; + return false; + } + } + else if (left->IsVector() || right->IsVector()) + { + switch (Operator) + { + case '+': + case '-': + // a vector2 can be added to or subtracted from a vector 3 but it needs to be the right operand. + if (left->ValueType == right->ValueType || (left->ValueType == TypeVector3 && right->ValueType == TypeVector2)) + { + ValueType = left->ValueType; + return true; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for operator %c", Operator); + delete this; + return false; + } + break; + + case '/': + if (right->IsVector()) + { + // For division, the vector must be the first operand. + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for division"); + delete this; + return false; + } + case '*': + if (left->IsVector()) + { + right = new FxFloatCast(right); + right = right->Resolve(ctx); + if (right == nullptr) + { + delete this; + return false; + } + ValueType = left->ValueType; + } + else + { + left = new FxFloatCast(left); + left = left->Resolve(ctx); + if (left == nullptr) + { + delete this; + return false; + } + ValueType = right->ValueType; + } + break; + + case TK_Eq: + case TK_Neq: + if (left->ValueType != right->ValueType) + { + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for comparison"); + delete this; + return false; + } + ValueType = TypeBool; + break; + + default: + ScriptPosition.Message(MSG_ERROR, "Incompatible operation for vector type"); + delete this; + return false; + + } + } + else if (left->ValueType == TypeBool && right->ValueType == TypeBool) + { + if (Operator == '&' || Operator == '|' || Operator == '^' || ctx.FromDecorate) + { + ValueType = TypeBool; + } + else + { + ValueType = TypeSInt32; // math operations on bools result in integers. + } + } + else if (left->ValueType == TypeName && right->ValueType == TypeName) + { + // pointers can only be compared for equality. + if (Operator == TK_Eq || Operator == TK_Neq) + { + ValueType = TypeBool; + return true; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid operation for names"); + delete this; + return false; + } + } + else if (left->IsNumeric() && right->IsNumeric()) + { + if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) + { + ValueType = TypeSInt32; + } + else + { + ValueType = TypeFloat64; + } + } + else if (left->ValueType->GetRegType() == REGT_POINTER) + { + if (left->ValueType == right->ValueType || right->ValueType == TypeNullPtr || left->ValueType == TypeNullPtr || + AreCompatiblePointerTypes(left->ValueType, right->ValueType)) + { + // pointers can only be compared for equality. + if (Operator == TK_Eq || Operator == TK_Neq) + { + ValueType = TypeBool; + return true; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid operation for pointers"); + delete this; + return false; + } + } + } + else + { + // To check: It may be that this could pass in DECORATE, although setting TypeVoid here would pretty much prevent that. + ScriptPosition.Message(MSG_ERROR, "Incompatible operator"); + delete this; + return false; + } + assert(ValueType != nullptr && ValueType < (PType*)0xfffffffffffffff); + + if (castnumeric) + { + // later! + } + return true; +} + +void FxBinary::Promote(FCompileContext &ctx) +{ + if (left->ValueType->GetRegType() == REGT_FLOAT && right->ValueType->GetRegType() == REGT_INT) + { + right = (new FxFloatCast(right))->Resolve(ctx); + } + else if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_FLOAT) + { + left = (new FxFloatCast(left))->Resolve(ctx); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxAddSub::FxAddSub(int o, FxExpression *l, FxExpression *r) +: FxBinary(o, l, r) +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxAddSub::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + if (!ResolveLR(ctx, true)) + return nullptr; + + if (!IsNumeric() && !IsVector()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + else if (left->isConstant() && right->isConstant()) + { + if (IsFloat()) + { + double v; + double v1 = static_cast(left)->GetValue().GetFloat(); + double v2 = static_cast(right)->GetValue().GetFloat(); + + v = Operator == '+'? v1 + v2 : + Operator == '-'? v1 - v2 : 0; + + FxExpression *e = new FxConstant(v, ScriptPosition); + delete this; + return e; + } + else + { + int v; + int v1 = static_cast(left)->GetValue().GetInt(); + int v2 = static_cast(right)->GetValue().GetInt(); + + v = Operator == '+'? v1 + v2 : + Operator == '-'? v1 - v2 : 0; + + FxExpression *e = new FxConstant(v, ScriptPosition); + delete this; + return e; + + } + } + Promote(ctx); + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) +{ + assert(Operator == '+' || Operator == '-'); + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + if (Operator == '+') + { + // Since addition is commutative, only the second operand may be a constant. + if (op1.Konst) + { + swapvalues(op1, op2); + } + assert(!op1.Konst); + op1.Free(build); + op2.Free(build); + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + if (IsVector()) + { + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + build->Emit(right->ValueType == TypeVector2? OP_ADDV2_RR : OP_ADDV3_RR, to.RegNum, op1.RegNum, op2.RegNum); + if (left->ValueType == TypeVector3 && right->ValueType == TypeVector2 && to.RegNum != op1.RegNum) + { + // must move the z-coordinate + build->Emit(OP_MOVEF, to.RegNum + 2, op1.RegNum + 2); + } + return to; + } + else if (ValueType->GetRegType() == REGT_FLOAT) + { + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + build->Emit(op2.Konst ? OP_ADDF_RK : OP_ADDF_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + else + { + assert(ValueType->GetRegType() == REGT_INT); + assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT); + build->Emit(op2.Konst ? OP_ADD_RK : OP_ADD_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + } + else + { + // Subtraction is not commutative, so either side may be constant (but not both). + assert(!op1.Konst || !op2.Konst); + op1.Free(build); + op2.Free(build); + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + if (IsVector()) + { + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + build->Emit(right->ValueType == TypeVector2 ? OP_SUBV2_RR : OP_SUBV3_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + else if (ValueType->GetRegType() == REGT_FLOAT) + { + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + build->Emit(op1.Konst ? OP_SUBF_KR : op2.Konst ? OP_SUBF_RK : OP_SUBF_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + else + { + assert(ValueType->GetRegType() == REGT_INT); + assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT); + build->Emit(op1.Konst ? OP_SUB_KR : op2.Konst ? OP_SUB_RK : OP_SUB_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMulDiv::FxMulDiv(int o, FxExpression *l, FxExpression *r) +: FxBinary(o, l, r) +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + + if (!ResolveLR(ctx, true)) + return nullptr; + + if (!IsNumeric() && !IsVector()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + else if (left->isConstant() && right->isConstant()) + { + if (IsFloat()) + { + double v; + double v1 = static_cast(left)->GetValue().GetFloat(); + double v2 = static_cast(right)->GetValue().GetFloat(); + + if (Operator != '*' && v2 == 0) + { + ScriptPosition.Message(MSG_ERROR, "Division by 0"); + delete this; + return nullptr; + } + + v = Operator == '*'? v1 * v2 : + Operator == '/'? v1 / v2 : + Operator == '%'? fmod(v1, v2) : 0; + + FxExpression *e = new FxConstant(v, ScriptPosition); + delete this; + return e; + } + else + { + int v; + int v1 = static_cast(left)->GetValue().GetInt(); + int v2 = static_cast(right)->GetValue().GetInt(); + + if (Operator != '*' && v2 == 0) + { + ScriptPosition.Message(MSG_ERROR, "Division by 0"); + delete this; + return nullptr; + } + + v = Operator == '*'? v1 * v2 : + Operator == '/'? v1 / v2 : + Operator == '%'? v1 % v2 : 0; + + FxExpression *e = new FxConstant(v, ScriptPosition); + delete this; + return e; + + } + } + Promote(ctx); + return this; +} + + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) +{ + // allocate the result first so that the operation does not leave gaps in the register set. + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + + if (IsVector()) + { + assert(Operator != '%'); + if (right->IsVector()) + { + swapvalues(op1, op2); + } + int op; + if (op2.Konst) + { + op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RK : OP_MULVF3_RK) : (ValueType == TypeVector2 ? OP_DIVVF2_RK : OP_DIVVF3_RK); + } + else + { + op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RR : OP_MULVF3_RR) : (ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR); + } + op1.Free(build); + op2.Free(build); + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + build->Emit(op, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + + if (Operator == '*') + { + // Multiplication is commutative, so only the second operand may be constant. + if (op1.Konst) + { + swapvalues(op1, op2); + } + assert(!op1.Konst); + op1.Free(build); + op2.Free(build); + ExpEmit to(build, ValueType->GetRegType()); + if (ValueType->GetRegType() == REGT_FLOAT) + { + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + build->Emit(op2.Konst ? OP_MULF_RK : OP_MULF_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + else + { + assert(ValueType->GetRegType() == REGT_INT); + assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT); + build->Emit(op2.Konst ? OP_MUL_RK : OP_MUL_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + } + else + { + // Division is not commutative, so either side may be constant (but not both). + assert(!op1.Konst || !op2.Konst); + assert(Operator == '%' || Operator == '/'); + op1.Free(build); + op2.Free(build); + ExpEmit to(build, ValueType->GetRegType()); + if (ValueType->GetRegType() == REGT_FLOAT) + { + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + build->Emit(Operator == '/' ? (op1.Konst ? OP_DIVF_KR : op2.Konst ? OP_DIVF_RK : OP_DIVF_RR) + : (op1.Konst ? OP_MODF_KR : op2.Konst ? OP_MODF_RK : OP_MODF_RR), + to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + else + { + assert(ValueType->GetRegType() == REGT_INT); + assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT); + build->Emit(Operator == '/' ? (op1.Konst ? OP_DIV_KR : op2.Konst ? OP_DIV_RK : OP_DIV_RR) + : (op1.Konst ? OP_MOD_KR : op2.Konst ? OP_MOD_RK : OP_MOD_RR), + to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxPow::FxPow(FxExpression *l, FxExpression *r) + : FxBinary(TK_MulMul, new FxFloatCast(l), new FxFloatCast(r)) +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxPow::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + + if (!ResolveLR(ctx, true)) + return nullptr; + + if (!IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + if (left->isConstant() && right->isConstant()) + { + double v1 = static_cast(left)->GetValue().GetFloat(); + double v2 = static_cast(right)->GetValue().GetFloat(); + return new FxConstant(g_pow(v1, v2), left->ScriptPosition); + } + return this; +} + + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxPow::Emit(VMFunctionBuilder *build) +{ + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + + // Pow is not commutative, so either side may be constant (but not both). + assert(!op1.Konst || !op2.Konst); + op1.Free(build); + op2.Free(build); + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + ExpEmit to(build, REGT_FLOAT); + build->Emit((op1.Konst ? OP_POWF_KR : op2.Konst ? OP_POWF_RK : OP_POWF_RR), to.RegNum, op1.RegNum, op2.RegNum); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r) +: FxBinary(o, l, r) +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + if (!ResolveLR(ctx, true)) + return nullptr; + + if (!IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + else if (left->isConstant() && right->isConstant()) + { + int v; + + if (ValueType == TypeString) + { + FString v1 = static_cast(left)->GetValue().GetString(); + FString v2 = static_cast(right)->GetValue().GetString(); + int res = v1.Compare(v2); + v = Operator == '<' ? res < 0 : + Operator == '>' ? res > 0 : + Operator == TK_Geq ? res >= 0 : + Operator == TK_Leq ? res <= 0 : 0; + } + else if (IsFloat()) + { + double v1 = static_cast(left)->GetValue().GetFloat(); + double v2 = static_cast(right)->GetValue().GetFloat(); + v = Operator == '<'? v1 < v2 : + Operator == '>'? v1 > v2 : + Operator == TK_Geq? v1 >= v2 : + Operator == TK_Leq? v1 <= v2 : 0; + } + else + { + int v1 = static_cast(left)->GetValue().GetInt(); + int v2 = static_cast(right)->GetValue().GetInt(); + v = Operator == '<'? v1 < v2 : + Operator == '>'? v1 > v2 : + Operator == TK_Geq? v1 >= v2 : + Operator == TK_Leq? v1 <= v2 : 0; + } + FxExpression *e = new FxConstant(v, ScriptPosition); + delete this; + return e; + } + Promote(ctx); + ValueType = TypeBool; + return this; +} + + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build) +{ + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + assert(op1.RegType == op2.RegType); + assert(!op1.Konst || !op2.Konst); + + if (op1.RegType == REGT_STRING) + { + ExpEmit to(build, REGT_INT); + int a = Operator == '<' ? CMP_LT : + Operator == '>' ? CMP_LE | CMP_CHECK : + Operator == TK_Geq ? CMP_LT | CMP_CHECK : CMP_LE; + + if (op1.Konst) + { + a |= CMP_BK; + } + else + { + op1.Free(build); + } + if (op2.Konst) + { + a |= CMP_CK; + } + else + { + op2.Free(build); + } + + build->Emit(OP_LI, to.RegNum, 0, 0); + build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum); + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + return to; + } + else + { + assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT); + assert(Operator == '<' || Operator == '>' || Operator == TK_Geq || Operator == TK_Leq); + static const VM_UBYTE InstrMap[][4] = + { + { OP_LT_RR, OP_LTF_RR, 0 }, // < + { OP_LE_RR, OP_LEF_RR, 1 }, // > + { OP_LT_RR, OP_LTF_RR, 1 }, // >= + { OP_LE_RR, OP_LEF_RR, 0 } // <= + }; + int instr, check; + ExpEmit to(build, REGT_INT); + int index = Operator == '<' ? 0 : + Operator == '>' ? 1 : + Operator == TK_Geq ? 2 : 3; + + instr = InstrMap[index][op1.RegType == REGT_INT ? 0 : 1]; + check = InstrMap[index][2]; + if (op2.Konst) + { + instr += 1; + } + else + { + op2.Free(build); + } + if (op1.Konst) + { + instr += 2; + } + else + { + op1.Free(build); + } + + // See FxBoolCast for comments, since it's the same thing. + build->Emit(OP_LI, to.RegNum, 0, 0); + build->Emit(instr, check, op1.RegNum, op2.RegNum); + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + return to; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxCompareEq::FxCompareEq(int o, FxExpression *l, FxExpression *r) +: FxBinary(o, l, r) +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + + if (!ResolveLR(ctx, true)) + return nullptr; + + if (!left || !right) + { + delete this; + return nullptr; + } + + if (!IsNumeric() && !IsPointer() && !IsVector() && ValueType != TypeName) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + + if (Operator == TK_ApproxEq && left->ValueType->GetRegType() != REGT_FLOAT && left->ValueType->GetRegType() != REGT_STRING) + Operator = TK_Eq; + if (left->isConstant() && right->isConstant()) + { + int v; + + if (ValueType == TypeString) + { + FString v1 = static_cast(left)->GetValue().GetString(); + FString v2 = static_cast(right)->GetValue().GetString(); + if (Operator == TK_ApproxEq) v = !v1.CompareNoCase(v2); + else + { + v = !!v1.Compare(v2); + if (Operator == TK_Eq) v = !v; + } + } + else if (ValueType->GetRegType() == REGT_FLOAT) + { + double v1 = static_cast(left)->GetValue().GetFloat(); + double v2 = static_cast(right)->GetValue().GetFloat(); + v = Operator == TK_Eq? v1 == v2 : Operator == TK_Neq? v1 != v2 : fabs(v1-v2) < VM_EPSILON; + } + else + { + int v1 = static_cast(left)->GetValue().GetInt(); + int v2 = static_cast(right)->GetValue().GetInt(); + v = Operator == TK_Eq? v1 == v2 : v1 != v2; + } + FxExpression *e = new FxConstant(v, ScriptPosition); + delete this; + return e; + } + else + { + // also simplify comparisons against zero. For these a bool cast/unary not on the other value will do just as well and create better code. + if (Operator != TK_ApproxEq) + { + if (left->isConstant()) + { + bool leftisnull; + switch (left->ValueType->GetRegType()) + { + case REGT_INT: + leftisnull = static_cast(left)->GetValue().GetInt() == 0; + break; + + case REGT_FLOAT: + assert(left->ValueType->GetRegCount() == 1); // vectors should not be able to get here. + leftisnull = static_cast(left)->GetValue().GetFloat() == 0; + break; + + case REGT_POINTER: + leftisnull = static_cast(left)->GetValue().GetPointer() == nullptr; + break; + + default: + leftisnull = false; + } + if (leftisnull) + { + FxExpression *x; + if (Operator == TK_Eq) x = new FxUnaryNotBoolean(right); + else x = new FxBoolCast(right); + right = nullptr; + delete this; + return x->Resolve(ctx); + } + + } + if (right->isConstant()) + { + bool rightisnull; + switch (right->ValueType->GetRegType()) + { + case REGT_INT: + rightisnull = static_cast(right)->GetValue().GetInt() == 0; + break; + + case REGT_FLOAT: + assert(right->ValueType->GetRegCount() == 1); // vectors should not be able to get here. + rightisnull = static_cast(right)->GetValue().GetFloat() == 0; + break; + + case REGT_POINTER: + rightisnull = static_cast(right)->GetValue().GetPointer() == nullptr; + break; + + default: + rightisnull = false; + } + if (rightisnull) + { + FxExpression *x; + if (Operator == TK_Eq) x = new FxUnaryNotBoolean(left); + else x = new FxBoolCast(left); + left = nullptr; + delete this; + return x->Resolve(ctx); + } + } + } + } + Promote(ctx); + ValueType = TypeBool; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) +{ + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + assert(op1.RegType == op2.RegType); + int instr; + + if (op1.RegType == REGT_STRING) + { + ExpEmit to(build, REGT_INT); + assert(Operator == TK_Eq || Operator == TK_Neq || Operator == TK_ApproxEq); + int a = Operator == TK_Eq ? CMP_EQ : + Operator == TK_Neq ? CMP_EQ | CMP_CHECK : CMP_EQ | CMP_APPROX; + + if (op1.Konst) a|= CMP_BK; + if (op2.Konst) a |= CMP_CK; + + build->Emit(OP_LI, to.RegNum, 0, 0); + build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum); + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + op1.Free(build); + op2.Free(build); + return to; + } + else + { + + // Only the second operand may be constant. + if (op1.Konst) + { + swapvalues(op1, op2); + } + assert(!op1.Konst); + assert(op1.RegCount >= 1 && op1.RegCount <= 3); + + ExpEmit to(build, REGT_INT); + + static int flops[] = { OP_EQF_R, OP_EQV2_R, OP_EQV3_R }; + instr = op1.RegType == REGT_INT ? OP_EQ_R : + op1.RegType == REGT_FLOAT ? flops[op1.RegCount - 1] : + OP_EQA_R; + op1.Free(build); + if (!op2.Konst) + { + op2.Free(build); + } + else + { + instr += 1; + } + + // See FxUnaryNotBoolean for comments, since it's the same thing. + build->Emit(OP_LI, to.RegNum, 0, 0); + build->Emit(instr, Operator == TK_ApproxEq ? CMP_APPROX : ((Operator != TK_Eq) ? CMP_CHECK : 0), op1.RegNum, op2.RegNum); + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + return to; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxBinaryInt::FxBinaryInt(int o, FxExpression *l, FxExpression *r) +: FxBinary(o, l, r) +{ + ValueType = TypeSInt32; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + if (!ResolveLR(ctx, false)) + return nullptr; + + if (IsFloat() && ctx.FromDecorate) + { + // For DECORATE which allows floats here. ZScript does not. + if (left->ValueType->GetRegType() != REGT_INT) + { + left = new FxIntCast(left, ctx.FromDecorate); + left = left->Resolve(ctx); + } + if (right->ValueType->GetRegType() != REGT_INT) + { + right = new FxIntCast(right, ctx.FromDecorate); + right = right->Resolve(ctx); + } + if (left == nullptr || right == nullptr) + { + delete this; + return nullptr; + } + ValueType = TypeSInt32; + } + + if (ValueType->GetRegType() != REGT_INT) + { + ScriptPosition.Message(MSG_ERROR, "Integer type expected"); + delete this; + return nullptr; + } + else if (left->isConstant() && right->isConstant()) + { + int v1 = static_cast(left)->GetValue().GetInt(); + int v2 = static_cast(right)->GetValue().GetInt(); + + FxExpression *e = new FxConstant( + Operator == TK_LShift? v1 << v2 : + Operator == TK_RShift? v1 >> v2 : + Operator == TK_URShift? int((unsigned int)(v1) >> v2) : + Operator == '&'? v1 & v2 : + Operator == '|'? v1 | v2 : + Operator == '^'? v1 ^ v2 : 0, ScriptPosition); + + delete this; + return e; + } + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build) +{ + assert(left->ValueType->GetRegType() == REGT_INT); + assert(right->ValueType->GetRegType() == REGT_INT); + static const VM_UBYTE InstrMap[][4] = + { + { OP_SLL_RR, OP_SLL_KR, OP_SLL_RI }, // TK_LShift + { OP_SRA_RR, OP_SRA_KR, OP_SRA_RI }, // TK_RShift + { OP_SRL_RR, OP_SRL_KR, OP_SRL_RI }, // TK_URShift + { OP_AND_RR, 0, OP_AND_RK }, // '&' + { OP_OR_RR, 0, OP_OR_RK }, // '|' + { OP_XOR_RR, 0, OP_XOR_RK }, // '^' + }; + int index, instr, rop; + ExpEmit op1, op2; + + index = Operator == TK_LShift ? 0 : + Operator == TK_RShift ? 1 : + Operator == TK_URShift ? 2 : + Operator == '&' ? 3 : + Operator == '|' ? 4 : + Operator == '^' ? 5 : -1; + assert(index >= 0); + op1 = left->Emit(build); + if (index < 3) + { // Shift instructions use right-hand immediates instead of constant registers. + if (right->isConstant()) + { + rop = static_cast(right)->GetValue().GetInt(); + op2.Konst = true; + } + else + { + op2 = right->Emit(build); + assert(!op2.Konst); + op2.Free(build); + rop = op2.RegNum; + } + } + else + { // The other operators only take a constant on the right-hand side. + op2 = right->Emit(build); + if (op1.Konst) + { + swapvalues(op1, op2); + } + assert(!op1.Konst); + rop = op2.RegNum; + op2.Free(build); + } + if (!op1.Konst) + { + op1.Free(build); + if (!op2.Konst) + { + instr = InstrMap[index][0]; + } + else + { + instr = InstrMap[index][2]; + } + } + else + { + assert(!op2.Konst); + instr = InstrMap[index][1]; + } + assert(instr != 0); + ExpEmit to(build, REGT_INT); + build->Emit(instr, to.RegNum, op1.RegNum, rop); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r) + : FxBinary(TK_LtGtEq, l, r) +{ + ValueType = TypeSInt32; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + if (!ResolveLR(ctx, true)) + return nullptr; + + if (!left->IsNumeric() || !right->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "<>= expects two numeric operands"); + delete this; + return nullptr; + } + if (left->ValueType->GetRegType() != right->ValueType->GetRegType()) + { + if (left->ValueType->GetRegType() == REGT_INT) + { + left = new FxFloatCast(left); + SAFE_RESOLVE(left, ctx); + } + if (right->ValueType->GetRegType() == REGT_INT) + { + right = new FxFloatCast(left); + SAFE_RESOLVE(left, ctx); + } + } + + else if (left->isConstant() && right->isConstant()) + { + // let's cut this short and always compare doubles. For integers the result will be exactly the same as with an integer comparison, either signed or unsigned. + auto v1 = static_cast(left)->GetValue().GetFloat(); + auto v2 = static_cast(right)->GetValue().GetFloat(); + auto e = new FxConstant(v1 < v2 ? -1 : v1 > v2 ? 1 : 0, ScriptPosition); + delete this; + return e; + } + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxLtGtEq::Emit(VMFunctionBuilder *build) +{ + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + + assert(op1.RegType == op2.RegType); + assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT); + assert(!op1.Konst || !op2.Konst); + + ExpEmit to(build, REGT_INT); + + int instr = op1.RegType == REGT_INT ? (left->ValueType == TypeUInt32? OP_LTU_RR : OP_LT_RR) : OP_LTF_RR; + if (op1.Konst) instr += 2; + if (op2.Konst) instr++; + + + build->Emit(OP_LI, to.RegNum, 1); // default to 1 + build->Emit(instr, 0, op1.RegNum, op2.RegNum); // if (left < right) + auto j1 = build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, -1); // result is -1 + auto j2 = build->Emit(OP_JMP, 1); // jump to end + build->BackpatchToHere(j1); + build->Emit(instr + OP_LE_RR - OP_LT_RR, 0, op1.RegNum, op2.RegNum); // if (left == right) + auto j3 = build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 0); // result is 0 + build->BackpatchToHere(j2); + build->BackpatchToHere(j3); + + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxBinaryLogical::FxBinaryLogical(int o, FxExpression *l, FxExpression *r) +: FxExpression(EFX_BinaryLogical, l->ScriptPosition) +{ + Operator=o; + left=l; + right=r; + ValueType = TypeBool; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxBinaryLogical::~FxBinaryLogical() +{ + SAFE_DELETE(left); + SAFE_DELETE(right); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + RESOLVE(left, ctx); + RESOLVE(right, ctx); + ABORT(right && left); + + if (left->ValueType != TypeBool) + { + left = new FxBoolCast(left); + SAFE_RESOLVE(left, ctx); + } + if (right->ValueType != TypeBool) + { + right = new FxBoolCast(right); + SAFE_RESOLVE(right, ctx); + } + + int b_left=-1, b_right=-1; + if (left->isConstant()) b_left = static_cast(left)->GetValue().GetBool(); + if (right->isConstant()) b_right = static_cast(right)->GetValue().GetBool(); + + // Do some optimizations. This will throw out all sub-expressions that are not + // needed to retrieve the final result. + if (Operator == TK_AndAnd) + { + if (b_left==0 || b_right==0) + { + FxExpression *x = new FxConstant(true, ScriptPosition); + delete this; + return x; + } + else if (b_left==1 && b_right==1) + { + FxExpression *x = new FxConstant(false, ScriptPosition); + delete this; + return x; + } + else if (b_left==1) + { + FxExpression *x = right; + right=nullptr; + delete this; + return x; + } + else if (b_right==1) + { + FxExpression *x = left; + left=nullptr; + delete this; + return x; + } + } + else if (Operator == TK_OrOr) + { + if (b_left==1 || b_right==1) + { + FxExpression *x = new FxConstant(true, ScriptPosition); + delete this; + return x; + } + if (b_left==0 && b_right==0) + { + FxExpression *x = new FxConstant(false, ScriptPosition); + delete this; + return x; + } + else if (b_left==0) + { + FxExpression *x = right; + right=nullptr; + delete this; + return x; + } + else if (b_right==0) + { + FxExpression *x = left; + left=nullptr; + delete this; + return x; + } + } + Flatten(); + return this; +} + +//========================================================================== +// +// flatten a list of the same operator into a single node. +// +//========================================================================== + +void FxBinaryLogical::Flatten() +{ + if (left->ExprType == EFX_BinaryLogical && static_cast(left)->Operator == Operator) + { + list = std::move(static_cast(left)->list); + delete left; + } + else + { + list.Push(left); + } + + if (right->ExprType == EFX_BinaryLogical && static_cast(right)->Operator == Operator) + { + auto &rlist = static_cast(right)->list; + auto cnt = rlist.Size(); + auto v = list.Reserve(cnt); + for (unsigned i = 0; i < cnt; i++) + { + list[v + i] = rlist[i]; + rlist[i] = nullptr; + } + delete right; + } + else + { + list.Push(right); + } + left = right = nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) +{ + TArray patchspots; + + int zero = build->GetConstantInt(0); + for (unsigned i = 0; i < list.Size(); i++) + { + assert(list[i]->ValueType->GetRegType() == REGT_INT); + ExpEmit op1 = list[i]->Emit(build); + assert(!op1.Konst); + op1.Free(build); + build->Emit(OP_EQ_K, (Operator == TK_AndAnd) ? 1 : 0, op1.RegNum, zero); + patchspots.Push(build->Emit(OP_JMP, 0, 0, 0)); + } + ExpEmit to(build, REGT_INT); + build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 1 : 0); + build->Emit(OP_JMP, 1); + auto ctarget = build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1); + for (auto addr : patchspots) build->Backpatch(addr, ctarget); + list.Clear(); + list.ShrinkToFit(); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxDotCross::FxDotCross(int o, FxExpression *l, FxExpression *r) + : FxExpression(EFX_DotCross, l->ScriptPosition) +{ + Operator = o; + left = l; + right = r; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxDotCross::~FxDotCross() +{ + SAFE_DELETE(left); + SAFE_DELETE(right); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxDotCross::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + RESOLVE(left, ctx); + RESOLVE(right, ctx); + ABORT(right && left); + + if (!left->IsVector() || left->ValueType != right->ValueType || (Operator == TK_Cross && left->ValueType != TypeVector3)) + { + ScriptPosition.Message(MSG_ERROR, "Incompatible operants for %sproduct", Operator == TK_Cross ? "cross-" : "dot-"); + delete this; + return nullptr; + } + ValueType = Operator == TK_Cross ? (PType*)TypeVector3 : TypeFloat64; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxDotCross::Emit(VMFunctionBuilder *build) +{ + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + int op = Operator == TK_Cross ? OP_CROSSV_RR : left->ValueType == TypeVector3 ? OP_DOTV3_RR : OP_DOTV2_RR; + build->Emit(op, to.RegNum, op1.RegNum, op2.RegNum); + op1.Free(build); + op2.Free(build); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxTypeCheck::FxTypeCheck(FxExpression *l, FxExpression *r) + : FxExpression(EFX_TypeCheck, l->ScriptPosition) +{ + left = new FxTypeCast(l, NewPointer(RUNTIME_CLASS(DObject)), false); + right = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), r); + EmitTail = false; + ValueType = TypeBool; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxTypeCheck::~FxTypeCheck() +{ + SAFE_DELETE(left); + SAFE_DELETE(right); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + RESOLVE(left, ctx); + RESOLVE(right, ctx); + ABORT(right && left); + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +PPrototype *FxTypeCheck::ReturnProto() +{ + EmitTail = true; + return FxExpression::ReturnProto(); +} + + +//========================================================================== +// +// +// +//========================================================================== + +int BuiltinTypeCheck(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +{ + assert(numparam == 2); + PARAM_POINTER_AT(0, obj, DObject); + PARAM_CLASS_AT(1, cls, DObject); + ACTION_RETURN_BOOL(obj && obj->IsKindOf(cls)); +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build) +{ + ExpEmit out(build, REGT_INT); + EmitParameter(build, left, ScriptPosition); + EmitParameter(build, right, ScriptPosition); + + + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + auto callfunc = ((PSymbolVMFunction *)sym)->Function; + + int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); + build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); + + if (EmitTail) + { + ExpEmit call; + call.Final = true; + return call; + } + + build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); + return out; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxDynamicCast::FxDynamicCast(PClass * cls, FxExpression *r) + : FxExpression(EFX_DynamicCast, r->ScriptPosition) +{ + expr = r; + CastType = cls; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxDynamicCast::~FxDynamicCast() +{ + SAFE_DELETE(expr); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(expr, ctx); + bool constflag = expr->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(expr->ValueType)->IsConst; + expr = new FxTypeCast(expr, NewPointer(RUNTIME_CLASS(DObject), constflag), true, true); + expr = expr->Resolve(ctx); + if (expr == nullptr) + { + delete this; + return nullptr; + } + ValueType = NewPointer(CastType, constflag); + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit out = expr->Emit(build); + ExpEmit check(build, REGT_INT); + assert(out.RegType == REGT_POINTER); + + build->Emit(OP_PARAM, 0, REGT_POINTER, out.RegNum); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(CastType, ATAG_OBJECT)); + + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck); + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + auto callfunc = ((PSymbolVMFunction *)sym)->Function; + + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); + build->Emit(OP_RESULT, 0, REGT_INT, check.RegNum); + build->Emit(OP_EQ_K, 0, check.RegNum, build->GetConstantInt(0)); + auto patch = build->Emit(OP_JMP, 0); + build->Emit(OP_LKP, out.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT)); + build->BackpatchToHere(patch); + return out; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f) +: FxExpression(EFX_Conditional, c->ScriptPosition) +{ + condition = c; + truex=t; + falsex=f; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxConditional::~FxConditional() +{ + SAFE_DELETE(condition); + SAFE_DELETE(truex); + SAFE_DELETE(falsex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxConditional::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + RESOLVE(condition, ctx); + RESOLVE(truex, ctx); + RESOLVE(falsex, ctx); + ABORT(condition && truex && falsex); + + if (truex->ValueType == falsex->ValueType) + ValueType = truex->ValueType; + else if (truex->ValueType == TypeBool && falsex->ValueType == TypeBool) + ValueType = TypeBool; + else if (truex->IsInteger() && falsex->IsInteger()) + ValueType = TypeSInt32; + else if (truex->IsNumeric() && falsex->IsNumeric()) + ValueType = TypeFloat64; + else if (truex->IsPointer() && falsex->ValueType == TypeNullPtr) + ValueType = truex->ValueType; + else if (falsex->IsPointer() && truex->ValueType == TypeNullPtr) + ValueType = falsex->ValueType; + else + ValueType = TypeVoid; + //else if (truex->ValueType != falsex->ValueType) + + if (ValueType->GetRegType() == REGT_NIL) + { + ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator"); + delete this; + return nullptr; + } + + if (condition->ValueType != TypeBool) + { + condition = new FxBoolCast(condition); + SAFE_RESOLVE(condition, ctx); + } + + if (condition->isConstant()) + { + ExpVal condval = static_cast(condition)->GetValue(); + bool result = condval.GetBool(); + + FxExpression *e = result? truex:falsex; + delete (result? falsex:truex); + falsex = truex = nullptr; + delete this; + return e; + } + + if (IsFloat()) + { + if (truex->ValueType->GetRegType() != REGT_FLOAT) + { + truex = new FxFloatCast(truex); + RESOLVE(truex, ctx); + } + if (falsex->ValueType->GetRegType() != REGT_FLOAT) + { + falsex = new FxFloatCast(falsex); + RESOLVE(falsex, ctx); + } + } + + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxConditional::Emit(VMFunctionBuilder *build) +{ + size_t truejump, falsejump; + ExpEmit out; + + // The true and false expressions ought to be assigned to the + // same temporary instead of being copied to it. Oh well; good enough + // for now. + ExpEmit cond = condition->Emit(build); + assert(cond.RegType == REGT_INT && !cond.Konst); + + // Test condition. + build->Emit(OP_EQ_K, 1, cond.RegNum, build->GetConstantInt(0)); + falsejump = build->Emit(OP_JMP, 0); + cond.Free(build); + + // Evaluate true expression. + if (truex->isConstant() && truex->ValueType->GetRegType() == REGT_INT) + { + out = ExpEmit(build, REGT_INT); + build->EmitLoadInt(out.RegNum, static_cast(truex)->GetValue().GetInt()); + } + else + { + ExpEmit trueop = truex->Emit(build); + if (trueop.Konst) + { + trueop.Free(build); + if (trueop.RegType == REGT_FLOAT) + { + out = ExpEmit(build, REGT_FLOAT); + build->Emit(OP_LKF, out.RegNum, trueop.RegNum); + } + else if (trueop.RegType == REGT_POINTER) + { + out = ExpEmit(build, REGT_POINTER); + build->Emit(OP_LKP, out.RegNum, trueop.RegNum); + } + else + { + assert(trueop.RegType == REGT_STRING); + out = ExpEmit(build, REGT_STRING); + build->Emit(OP_LKS, out.RegNum, trueop.RegNum); + } + } + else + { + // Use the register returned by the true condition as the + // target for the false condition. + out = trueop; + } + } + // Make sure to skip the false path. + truejump = build->Emit(OP_JMP, 0); + + // Evaluate false expression. + build->BackpatchToHere(falsejump); + if (falsex->isConstant() && falsex->ValueType->GetRegType() == REGT_INT) + { + build->EmitLoadInt(out.RegNum, static_cast(falsex)->GetValue().GetInt()); + } + else + { + ExpEmit falseop = falsex->Emit(build); + if (falseop.Konst) + { + if (falseop.RegType == REGT_FLOAT) + { + build->Emit(OP_LKF, out.RegNum, falseop.RegNum); + } + else if (falseop.RegType == REGT_POINTER) + { + build->Emit(OP_LKP, out.RegNum, falseop.RegNum); + } + else + { + assert(falseop.RegType == REGT_STRING); + build->Emit(OP_LKS, out.RegNum, falseop.RegNum); + } + falseop.Free(build); + } + else + { + // Move result from the register returned by "false" to the one + // returned by "true" so that only one register is returned by + // this tree. + falseop.Free(build); + build->Emit(falsex->ValueType->GetMoveOp(), out.RegNum, falseop.RegNum, 0); + } + } + build->BackpatchToHere(truejump); + + return out; +} + +//========================================================================== +// +// +// +//========================================================================== +FxAbs::FxAbs(FxExpression *v) +: FxExpression(EFX_Abs, v->ScriptPosition) +{ + val = v; + ValueType = v->ValueType; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxAbs::~FxAbs() +{ + SAFE_DELETE(val); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxAbs::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(val, ctx); + + + if (!val->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + else if (val->isConstant()) + { + ExpVal value = static_cast(val)->GetValue(); + switch (value.Type->GetRegType()) + { + case REGT_INT: + value.Int = abs(value.Int); + break; + + case REGT_FLOAT: + value.Float = fabs(value.Float); + break; + + default: + // shouldn't happen + delete this; + return nullptr; + } + FxExpression *x = new FxConstant(value, ScriptPosition); + delete this; + return x; + } + ValueType = val->ValueType; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxAbs::Emit(VMFunctionBuilder *build) +{ + ExpEmit absofsteal = val->Emit(build); + assert(!absofsteal.Konst); + ExpEmit out(build, absofsteal.RegType); + if (absofsteal.RegType == REGT_INT) + { + build->Emit(OP_ABS, out.RegNum, absofsteal.RegNum, 0); + } + else + { + assert(absofsteal.RegType == REGT_FLOAT); + build->Emit(OP_FLOP, out.RegNum, absofsteal.RegNum, FLOP_ABS); + } + return out; +} + +//========================================================================== +// +// +// +//========================================================================== +FxATan2::FxATan2(FxExpression *y, FxExpression *x, const FScriptPosition &pos) +: FxExpression(EFX_ATan2, pos) +{ + yval = y; + xval = x; +} + +//========================================================================== +// +// +// +//========================================================================== +FxATan2::~FxATan2() +{ + SAFE_DELETE(yval); + SAFE_DELETE(xval); +} + +//========================================================================== +// +// +// +//========================================================================== +FxExpression *FxATan2::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(yval, ctx); + SAFE_RESOLVE(xval, ctx); + + if (!yval->IsNumeric() || !xval->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); + delete this; + return nullptr; + } + if (yval->isConstant() && xval->isConstant()) + { + double y = static_cast(yval)->GetValue().GetFloat(); + double x = static_cast(xval)->GetValue().GetFloat(); + FxExpression *z = new FxConstant(g_atan2(y, x) * (180 / M_PI), ScriptPosition); + delete this; + return z; + } + if (yval->ValueType->GetRegType() != REGT_FLOAT && !yval->isConstant()) + { + yval = new FxFloatCast(yval); + } + if (xval->ValueType->GetRegType() != REGT_FLOAT && !xval->isConstant()) + { + xval = new FxFloatCast(xval); + } + ValueType = TypeFloat64; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== +ExpEmit FxATan2::Emit(VMFunctionBuilder *build) +{ + ExpEmit yreg = ToReg(build, yval); + ExpEmit xreg = ToReg(build, xval); + yreg.Free(build); + xreg.Free(build); + ExpEmit out(build, REGT_FLOAT); + build->Emit(OP_ATAN2, out.RegNum, yreg.RegNum, xreg.RegNum); + return out; +} + +//========================================================================== +// +// The atan2 opcode only takes registers as parameters, so any constants +// must be loaded into registers first. +// +//========================================================================== +ExpEmit FxATan2::ToReg(VMFunctionBuilder *build, FxExpression *val) +{ + if (val->isConstant()) + { + ExpEmit reg(build, REGT_FLOAT); + build->Emit(OP_LKF, reg.RegNum, build->GetConstantFloat(static_cast(val)->GetValue().GetFloat())); + return reg; + } + return val->Emit(build); +} + +//========================================================================== +// +// +// +//========================================================================== +FxMinMax::FxMinMax(TArray &expr, FName type, const FScriptPosition &pos) +: FxExpression(EFX_MinMax, pos), Type(type) +{ + assert(expr.Size() > 0); + assert(type == NAME_Min || type == NAME_Max); + + choices.Resize(expr.Size()); + for (unsigned i = 0; i < expr.Size(); ++i) + { + choices[i] = expr[i]; + expr[i] = nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== +FxExpression *FxMinMax::Resolve(FCompileContext &ctx) +{ + unsigned int i; + int intcount, floatcount; + + CHECKRESOLVED(); + + // Determine if float or int + intcount = floatcount = 0; + for (i = 0; i < choices.Size(); ++i) + { + RESOLVE(choices[i], ctx); + ABORT(choices[i]); + + if (choices[i]->IsFloat()) + { + floatcount++; + } + else if (choices[i]->IsInteger()) + { + intcount++; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Arguments must be of type int or float"); + delete this; + return nullptr; + } + } + if (floatcount != 0) + { + ValueType = TypeFloat64; + if (intcount != 0) + { // There are some ints that need to be cast to floats + for (i = 0; i < choices.Size(); ++i) + { + if (choices[i]->ValueType->GetRegType() == REGT_INT) + { + choices[i] = new FxFloatCast(choices[i]); + RESOLVE(choices[i], ctx); + ABORT(choices[i]); + } + } + } + } + else + { + ValueType = TypeSInt32; + } + + // If at least two arguments are constants, they can be solved now. + + // Look for first constant + for (i = 0; i < choices.Size(); ++i) + { + if (choices[i]->isConstant()) + { + ExpVal best = static_cast(choices[i])->GetValue(); + // Compare against remaining constants, which are removed. + // The best value gets stored in this one. + for (unsigned j = i + 1; j < choices.Size(); ) + { + if (!choices[j]->isConstant()) + { + j++; + } + else + { + ExpVal value = static_cast(choices[j])->GetValue(); + assert(value.Type == ValueType); + if (Type == NAME_Min) + { + if (value.Type->GetRegType() == REGT_FLOAT) + { + if (value.Float < best.Float) + { + best.Float = value.Float; + } + } + else + { + if (value.Int < best.Int) + { + best.Int = value.Int; + } + } + } + else + { + if (value.Type->GetRegType() == REGT_FLOAT) + { + if (value.Float > best.Float) + { + best.Float = value.Float; + } + } + else + { + if (value.Int > best.Int) + { + best.Int = value.Int; + } + } + } + delete choices[j]; + choices[j] = nullptr; + choices.Delete(j); + } + } + FxExpression *x = new FxConstant(best, ScriptPosition); + if (i == 0 && choices.Size() == 1) + { // Every choice was constant + delete this; + return x; + } + delete choices[i]; + choices[i] = x; + break; + } + } + return this; +} + +//========================================================================== +// +// +// +//========================================================================== +static void EmitLoad(VMFunctionBuilder *build, const ExpEmit resultreg, const ExpVal &value) +{ + if (resultreg.RegType == REGT_FLOAT) + { + build->Emit(OP_LKF, resultreg.RegNum, build->GetConstantFloat(value.GetFloat())); + } + else + { + build->EmitLoadInt(resultreg.RegNum, value.GetInt()); + } +} + +ExpEmit FxMinMax::Emit(VMFunctionBuilder *build) +{ + unsigned i; + int opcode; + + assert(choices.Size() > 0); + assert(OP_MAXF_RK == OP_MAXF_RR+1); + assert(OP_MAX_RK == OP_MAX_RR+1); + assert(OP_MIN_RK == OP_MIN_RR+1); + assert(OP_MIN_RK == OP_MIN_RR+1); + + if (Type == NAME_Min) + { + opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_MINF_RR : OP_MIN_RR; + } + else + { + opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_MAXF_RR : OP_MAX_RR; + } + + ExpEmit bestreg; + + // Get first value into a register. This will also be the result register. + if (choices[0]->isConstant()) + { + bestreg = ExpEmit(build, ValueType->GetRegType()); + EmitLoad(build, bestreg, static_cast(choices[0])->GetValue()); + } + else + { + bestreg = choices[0]->Emit(build); + } + + // Compare every choice. Better matches get copied to the bestreg. + for (i = 1; i < choices.Size(); ++i) + { + ExpEmit checkreg = choices[i]->Emit(build); + assert(checkreg.RegType == bestreg.RegType); + build->Emit(opcode + checkreg.Konst, bestreg.RegNum, bestreg.RegNum, checkreg.RegNum); + checkreg.Free(build); + } + return bestreg; +} + +//========================================================================== +// +// +// +//========================================================================== +FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos, bool nowarn) +: FxExpression(EFX_Random, pos) +{ + EmitTail = false; + if (mi != nullptr && ma != nullptr) + { + min = new FxIntCast(mi, nowarn); + max = new FxIntCast(ma, nowarn); + } + else min = max = nullptr; + rng = r; + ValueType = TypeSInt32; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxRandom::~FxRandom() +{ + SAFE_DELETE(min); + SAFE_DELETE(max); +} + +//========================================================================== +// +// +// +//========================================================================== + +PPrototype *FxRandom::ReturnProto() +{ + EmitTail = true; + return FxExpression::ReturnProto(); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxRandom::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + if (min && max) + { + RESOLVE(min, ctx); + RESOLVE(max, ctx); + ABORT(min && max); + assert(min->ValueType == ValueType); + assert(max->ValueType == ValueType); + } + return this; +}; + + +//========================================================================== +// +// +// +//========================================================================== + +int BuiltinRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +{ + assert(numparam >= 1 && numparam <= 3); + FRandom *rng = reinterpret_cast(param[0].a); + if (numparam == 1) + { + ACTION_RETURN_INT((*rng)()); + } + else if (numparam == 2) + { + int maskval = param[1].i; + ACTION_RETURN_INT(rng->Random2(maskval)); + } + else if (numparam == 3) + { + int min = param[1].i, max = param[2].i; + if (max < min) + { + swapvalues(max, min); + } + ACTION_RETURN_INT((*rng)(max - min + 1) + min); + } + + // Shouldn't happen + return 0; +} + +ExpEmit FxRandom::Emit(VMFunctionBuilder *build) +{ + // Call DecoRandom to generate a random number. + VMFunction *callfunc; + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + callfunc = ((PSymbolVMFunction *)sym)->Function; + + int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); + + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); + if (min != nullptr && max != nullptr) + { + EmitParameter(build, min, ScriptPosition); + EmitParameter(build, max, ScriptPosition); + build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); + } + else + { + build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1); + } + + if (EmitTail) + { + ExpEmit call; + call.Final = true; + return call; + } + + ExpEmit out(build, REGT_INT); + build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); + return out; +} + +//========================================================================== +// +// +// +//========================================================================== +FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, const FScriptPosition &pos, bool nowarn) +: FxExpression(EFX_RandomPick, pos) +{ + assert(expr.Size() > 0); + choices.Resize(expr.Size()); + for (unsigned int index = 0; index < expr.Size(); index++) + { + if (floaty) + { + choices[index] = new FxFloatCast(expr[index]); + expr[index] = nullptr; + } + else + { + choices[index] = new FxIntCast(expr[index], nowarn); + expr[index] = nullptr; + } + + } + rng = r; + if (floaty) + { + ValueType = TypeFloat64; + } + else + { + ValueType = TypeSInt32; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxRandomPick::~FxRandomPick() +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxRandomPick::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + for (unsigned int index = 0; index < choices.Size(); index++) + { + RESOLVE(choices[index], ctx); + ABORT(choices[index]); + assert(choices[index]->ValueType == ValueType); + } + return this; +}; + + +//========================================================================== +// +// FxPick :: Emit +// +// The expression: +// a = pick[rng](i_0, i_1, i_2, ..., i_n) +// [where i_x is a complete expression and not just a value] +// is syntactic sugar for: +// +// switch(random[rng](0, n)) { +// case 0: a = i_0; +// case 1: a = i_1; +// case 2: a = i_2; +// ... +// case n: a = i_n; +// } +// +//========================================================================== + +ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) +{ + unsigned i; + + assert(choices.Size() > 0); + + // Call BuiltinRandom to generate a random number. + VMFunction *callfunc; + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + callfunc = ((PSymbolVMFunction *)sym)->Function; + + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); + build->EmitParamInt(0); + build->EmitParamInt(choices.Size() - 1); + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); + + ExpEmit resultreg(build, REGT_INT); + build->Emit(OP_RESULT, 0, REGT_INT, resultreg.RegNum); + build->Emit(OP_IJMP, resultreg.RegNum, 0); + + // Free the result register now. The simple code generation algorithm should + // automatically pick it as the destination register for each case. + resultreg.Free(build); + + // For floating point results, we need to get a new register, since we can't + // reuse the integer one used to store the random result. + if (ValueType->GetRegType() == REGT_FLOAT) + { + resultreg = ExpEmit(build, REGT_FLOAT); + resultreg.Free(build); + } + + // Allocate space for the jump table. + size_t jumptable = build->Emit(OP_JMP, 0); + for (i = 1; i < choices.Size(); ++i) + { + build->Emit(OP_JMP, 0); + } + + // Emit each case + TArray finishes(choices.Size() - 1); + for (unsigned i = 0; i < choices.Size(); ++i) + { + build->BackpatchToHere(jumptable + i); + if (choices[i]->isConstant()) + { + EmitLoad(build, resultreg, static_cast(choices[i])->GetValue()); + } + else + { + ExpEmit casereg = choices[i]->Emit(build); + if (casereg.RegNum != resultreg.RegNum) + { // The result of the case is in a different register from what + // was expected. Copy it to the one we wanted. + + resultreg.Reuse(build); // This is really just for the assert in Reuse() + build->Emit(ValueType->GetRegType() == REGT_INT ? OP_MOVE : OP_MOVEF, resultreg.RegNum, casereg.RegNum, 0); + resultreg.Free(build); + } + // Free this register so the remaining cases can use it. + casereg.Free(build); + } + // All but the final case needs a jump to the end of the expression's code. + if (i + 1 < choices.Size()) + { + size_t loc = build->Emit(OP_JMP, 0); + finishes.Push(loc); + } + } + // Backpatch each case (except the last, since it ends here) to jump to here. + for (i = 0; i < choices.Size() - 1; ++i) + { + build->BackpatchToHere(finishes[i]); + } + // The result register needs to be in-use when we return. + // It should have been freed earlier, so restore its in-use flag. + resultreg.Reuse(build); + return resultreg; +} + +//========================================================================== +// +// +// +//========================================================================== +FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) +: FxRandom(r, nullptr, nullptr, pos, true) +{ + if (mi != nullptr && ma != nullptr) + { + min = new FxFloatCast(mi); + max = new FxFloatCast(ma); + } + ValueType = TypeFloat64; + ExprType = EFX_FRandom; +} + +//========================================================================== +// +// +// +//========================================================================== + +int BuiltinFRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +{ + assert(numparam == 1 || numparam == 3); + FRandom *rng = reinterpret_cast(param[0].a); + + int random = (*rng)(0x40000000); + double frandom = random / double(0x40000000); + + if (numparam == 3) + { + double min = param[1].f, max = param[2].f; + if (max < min) + { + swapvalues(max, min); + } + ACTION_RETURN_FLOAT(frandom * (max - min) + min); + } + else + { + ACTION_RETURN_FLOAT(frandom); + } +} + +ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) +{ + // Call the BuiltinFRandom function to generate a floating point random number.. + VMFunction *callfunc; + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + callfunc = ((PSymbolVMFunction *)sym)->Function; + + int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); + + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); + if (min != nullptr && max != nullptr) + { + EmitParameter(build, min, ScriptPosition); + EmitParameter(build, max, ScriptPosition); + build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); + } + else + { + build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1); + } + + if (EmitTail) + { + ExpEmit call; + call.Final = true; + return call; + } + + ExpEmit out(build, REGT_FLOAT); + build->Emit(OP_RESULT, 0, REGT_FLOAT, out.RegNum); + return out; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos, bool nowarn) +: FxExpression(EFX_Random2, pos) +{ + EmitTail = false; + rng = r; + if (m) mask = new FxIntCast(m, nowarn); + else mask = new FxConstant(-1, pos); + ValueType = TypeSInt32; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxRandom2::~FxRandom2() +{ + SAFE_DELETE(mask); +} + +//========================================================================== +// +// +// +//========================================================================== + +PPrototype *FxRandom2::ReturnProto() +{ + EmitTail = true; + return FxExpression::ReturnProto(); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxRandom2::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(mask, ctx); + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) +{ + // Call the BuiltinRandom function to generate the random number. + VMFunction *callfunc; + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + callfunc = ((PSymbolVMFunction *)sym)->Function; + + int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); + + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); + EmitParameter(build, mask, ScriptPosition); + build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); + + if (EmitTail) + { + ExpEmit call; + call.Final = true; + return call; + } + + ExpEmit out(build, REGT_INT); + build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); + return out; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxIdentifier::FxIdentifier(FName name, const FScriptPosition &pos) +: FxExpression(EFX_Identifier, pos) +{ + Identifier = name; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) +{ + PSymbol * sym; + FxExpression *newex = nullptr; + int num; + + CHECKRESOLVED(); + + // Local variables have highest priority. + FxLocalVariableDeclaration *local = ctx.FindLocalVariable(Identifier); + if (local != nullptr) + { + auto x = new FxLocalVariable(local, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + + if (Identifier == NAME_Default) + { + if (ctx.Function->Variants[0].SelfClass == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Unable to access class defaults from static function"); + delete this; + return nullptr; + } + if (!ctx.Function->Variants[0].SelfClass->IsDescendantOf(RUNTIME_CLASS(AActor))) + { + ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type."); + delete this; + return nullptr; + } + + FxExpression * x = new FxClassDefaults(new FxSelf(ScriptPosition), ScriptPosition); + delete this; + return x->Resolve(ctx); + } + + // Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here... + // see if the current class (if valid) defines something with this name. + PSymbolTable *symtbl; + + // first check fields in self + if ((sym = ctx.FindInSelfClass(Identifier, symtbl)) != nullptr) + { + if (sym->IsKindOf(RUNTIME_CLASS(PField))) + { + FxExpression *self = new FxSelf(ScriptPosition); + self = self->Resolve(ctx); + newex = ResolveMember(ctx, ctx.Function->Variants[0].SelfClass, self, ctx.Function->Variants[0].SelfClass); + ABORT(newex); + } + } + + // now check in the owning class. + if (newex == nullptr && (sym = ctx.FindInClass(Identifier, symtbl)) != nullptr) + { + if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) + { + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars()); + newex = FxConstant::MakeConstant(sym, ScriptPosition); + delete this; + return newex->Resolve(ctx); + } + // Do this check for ZScript as well, so that a clearer error message can be printed. MSG_OPTERROR will default to MSG_ERROR there. + else if (ctx.Function->Variants[0].SelfClass != ctx.Class && sym->IsKindOf(RUNTIME_CLASS(PField))) + { + FxExpression *self = new FxSelf(ScriptPosition, true); + self = self->Resolve(ctx); + newex = ResolveMember(ctx, ctx.Class, self, ctx.Class); + ABORT(newex); + ScriptPosition.Message(MSG_OPTERROR, "Self pointer used in ambiguous context; VM execution may abort!"); + ctx.Unsafe = true; + } + else + { + if (sym->IsKindOf(RUNTIME_CLASS(PFunction))) + { + ScriptPosition.Message(MSG_ERROR, "Function '%s' used without ().\n", Identifier.GetChars()); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'.\n", Identifier.GetChars()); + } + delete this; + return nullptr; + } + } + + // now check the global identifiers. + if (newex == nullptr && (sym = ctx.FindGlobal(Identifier)) != nullptr) + { + if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) + { + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global constant\n", Identifier.GetChars()); + newex = FxConstant::MakeConstant(sym, ScriptPosition); + } + else if (sym->IsKindOf(RUNTIME_CLASS(PField))) + { + // internally defined global variable + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global variable\n", Identifier.GetChars()); + newex = new FxGlobalVariable(static_cast(sym), ScriptPosition); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid global identifier '%s'\n", Identifier.GetChars()); + } + } + + // and line specials + if (newex == nullptr && (num = P_FindLineSpecial(Identifier, nullptr, nullptr))) + { + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num); + newex = new FxConstant(num, ScriptPosition); + } + + if (newex == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); + delete this; + return nullptr; + } + delete this; + return newex? newex->Resolve(ctx) : nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PClass *classctx, FxExpression *&object, PStruct *objtype) +{ + PSymbol *sym; + PSymbolTable *symtbl; + bool isclass = objtype->IsKindOf(RUNTIME_CLASS(PClass)); + if ((sym = objtype->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr) + { + if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) + { + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as %s constant\n", Identifier.GetChars(), isclass ? "class" : "struct"); + delete object; + object = nullptr; + return FxConstant::MakeConstant(sym, ScriptPosition); + } + else if (sym->IsKindOf(RUNTIME_CLASS(PField))) + { + PField *vsym = static_cast(sym); + + // We have 4 cases to consider here: + // 1. The symbol is a static/meta member (not implemented yet) which is always accessible. + // 2. This is a static function + // 3. This is an action function with a restricted self pointer + // 4. This is a normal member or unrestricted action function. + if (vsym->Flags & VARF_Deprecated && !ctx.FromDecorate) + { + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); + } + if ((vsym->Flags & VARF_Private) && symtbl != &classctx->Symbols) + { + ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars()); + return nullptr; + } + + if (vsym->Flags & VARF_Static) + { + // todo. For now these cannot be defined so let's just exit. + ScriptPosition.Message(MSG_ERROR, "Static members not implemented yet."); + return nullptr; + } + auto x = isclass ? new FxClassMember(object, vsym, ScriptPosition) : new FxStructMember(object, vsym, ScriptPosition); + object = nullptr; + return x->Resolve(ctx); + } + else + { + if (sym->IsKindOf(RUNTIME_CLASS(PFunction))) + { + ScriptPosition.Message(MSG_ERROR, "Function '%s' used without ().\n", Identifier.GetChars()); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'.\n", Identifier.GetChars()); + } + delete object; + object = nullptr; + return nullptr; + } + } + else + { + ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); + delete object; + object = nullptr; + return nullptr; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMemberIdentifier::FxMemberIdentifier(FxExpression *left, FName name, const FScriptPosition &pos) + : FxIdentifier(name, pos) +{ + Object = left; + ExprType = EFX_MemberIdentifier; +} + +FxMemberIdentifier::~FxMemberIdentifier() +{ + SAFE_DELETE(Object); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + + SAFE_RESOLVE(Object, ctx); + + if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + { + auto ptype = static_cast(Object->ValueType)->PointedType; + if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) + { + auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast(ptype)); + delete this; + return ret; + } + } + else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct))) + { + auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast(Object->ValueType)); + delete this; + return ret; + } + + ScriptPosition.Message(MSG_ERROR, "Left side of %s is not a struct or class", Identifier.GetChars()); + delete this; + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptPosition &sc) + : FxExpression(EFX_LocalVariable, sc) +{ + Variable = var; + ValueType = var->ValueType; + AddressRequested = false; + RegOffset = 0; +} + +FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + return this; +} + +bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = !ctx.CheckReadOnly(Variable->VarFlags); + return true; +} + +ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) +{ + ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); + ret.RegCount = ValueType->GetRegCount(); + if (AddressRequested) ret.Target = true; + return ret; +} + + + +//========================================================================== +// +// +// +//========================================================================== + +FxSelf::FxSelf(const FScriptPosition &pos, bool deccheck) +: FxExpression(EFX_Self, pos) +{ + check = deccheck; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxSelf::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + if (ctx.Function == nullptr || ctx.Function->Variants[0].SelfClass == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "self used outside of a member function"); + delete this; + return nullptr; + } + ValueType = NewPointer(ctx.Function->Variants[0].SelfClass); + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxSelf::Emit(VMFunctionBuilder *build) +{ + if (check) + { + build->Emit(OP_EQA_R, 1, 0, 1); + build->Emit(OP_JMP, 1); + build->Emit(OP_THROW, 2, X_BAD_SELF); + } + // self is always the first pointer passed to the function + return ExpEmit(0, REGT_POINTER, false, true); +} + + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxSuper::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + if (ctx.Function == nullptr || ctx.Function->Variants[0].SelfClass == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "super used outside of a member function"); + delete this; + return nullptr; + } + ValueType = TypeError; // this intentionally resolves to an invalid type so that it cannot be used outside of super calls. + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxClassDefaults::FxClassDefaults(FxExpression *X, const FScriptPosition &pos) + : FxExpression(EFX_ClassDefaults, pos) +{ + obj = X; + EmitTail = false; +} + +FxClassDefaults::~FxClassDefaults() +{ + SAFE_DELETE(obj); +} + + +//========================================================================== +// +// +// +//========================================================================== + +PPrototype *FxClassDefaults::ReturnProto() +{ + EmitTail = true; + return FxExpression::ReturnProto(); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxClassDefaults::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(obj, ctx); + assert(obj->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))); + ValueType = NewPointer(static_cast(obj->ValueType)->PointedType, true); + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +int BuiltinGetDefault(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +{ + assert(numparam == 1); + PARAM_POINTER_AT(0, obj, DObject); + ACTION_RETURN_OBJECT(obj->GetClass()->Defaults); +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build) +{ + EmitParameter(build, obj, ScriptPosition); + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinGetDefault, BuiltinGetDefault); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + auto callfunc = ((PSymbolVMFunction *)sym)->Function; + int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); + build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1); + + if (EmitTail) + { + ExpEmit call; + call.Final = true; + return call; + } + + ExpEmit out(build, REGT_POINTER); + build->Emit(OP_RESULT, 0, REGT_POINTER, out.RegNum); + return out; + +} + +//========================================================================== +// +// +// +//========================================================================== + +FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos) + : FxExpression(EFX_GlobalVariable, pos) +{ + membervar = mem; + AddressRequested = false; + AddressWritable = true; // must be true unless classx tells us otherwise if requested. +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FxGlobalVariable::RequestAddress(FCompileContext &ctx, bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = AddressWritable && !ctx.CheckReadOnly(membervar->Flags); + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxGlobalVariable::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + ValueType = membervar->Type; + return this; +} + +ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build) +{ + ExpEmit obj(build, REGT_POINTER); + + build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset, ATAG_GENERIC)); + if (AddressRequested) + { + return obj; + } + + ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); + + if (membervar->BitValue == -1) + { + int offsetreg = build->GetConstantInt(0); + build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg); + } + else + { + build->Emit(OP_LBIT, loc.RegNum, obj.RegNum, 1 << membervar->BitValue); + } + obj.Free(build); + return loc; +} + + +//========================================================================== +// +// +// +//========================================================================== + +FxStructMember::FxStructMember(FxExpression *x, PField* mem, const FScriptPosition &pos) + : FxExpression(EFX_StructMember, pos) +{ + classx = x; + membervar = mem; + AddressRequested = false; + AddressWritable = true; // must be true unless classx tells us otherwise if requested. +} + +//========================================================================== +// +// +// +//========================================================================== + +FxStructMember::~FxStructMember() +{ + SAFE_DELETE(classx); +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = (AddressWritable && !ctx.CheckReadOnly(membervar->Flags) && + (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast(classx->ValueType)->IsConst)); + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxStructMember::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(classx, ctx); + + if (membervar->SymbolName == NAME_Default) + { + if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) + || !static_cast(classx->ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(AActor))) + { + ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type."); + delete this; + return nullptr; + } + FxExpression * x = new FxClassDefaults(classx, ScriptPosition); + classx = nullptr; + delete this; + return x->Resolve(ctx); + } + + if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + { + PPointer *ptrtype = dyn_cast(classx->ValueType); + if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PStruct))) + { + ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object."); + delete this; + return nullptr; + } + } + else if (classx->ValueType->IsA(RUNTIME_CLASS(PStruct))) // Classes can never be used as value types so we do not have to consider that case. + { + // if this is a struct within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. + if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember) + { + auto parentfield = static_cast(classx)->membervar; + // PFields are garbage collected so this will be automatically taken care of later. + auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset, membervar->BitValue); + static_cast(classx)->membervar = newfield; + classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. + auto x = classx->Resolve(ctx); + classx = nullptr; + return x; + } + else if (classx->ExprType == EFX_GlobalVariable) + { + auto parentfield = static_cast(classx)->membervar; + auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset, membervar->BitValue); + static_cast(classx)->membervar = newfield; + classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. + auto x = classx->Resolve(ctx); + classx = nullptr; + return x; + } + else if (classx->ExprType == EFX_LocalVariable && classx->IsVector()) // vectors are a special case because they are held in registers + { + // since this is a vector, all potential things that may get here are single float or an xy-vector. + auto locvar = static_cast(classx); + locvar->RegOffset = int(membervar->Offset / 8); + locvar->ValueType = membervar->Type; + classx = nullptr; + delete this; + return locvar; + } + else + { + if (!(classx->RequestAddress(ctx, &AddressWritable))) + { + ScriptPosition.Message(MSG_ERROR, "unable to dereference left side of %s", membervar->SymbolName.GetChars()); + delete this; + return nullptr; + } + } + } + ValueType = membervar->Type; + return this; +} + +ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) +{ + ExpEmit obj = classx->Emit(build); + assert(obj.RegType == REGT_POINTER); + + if (obj.Konst) + { + // If the situation where we are dereferencing a constant + // pointer is common, then it would probably be worthwhile + // to add new opcodes for those. But as of right now, I + // don't expect it to be a particularly common case. + ExpEmit newobj(build, REGT_POINTER); + build->Emit(OP_LKP, newobj.RegNum, obj.RegNum); + obj = newobj; + } + + if (AddressRequested) + { + if (membervar->Offset == 0) + { + return obj; + } + obj.Free(build); + ExpEmit out(build, REGT_POINTER); + build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->Offset)); + return out; + } + + int offsetreg = build->GetConstantInt((int)membervar->Offset); + ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); + + if (membervar->BitValue == -1) + { + build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg); + } + else + { + ExpEmit out(build, REGT_POINTER); + build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, offsetreg); + build->Emit(OP_LBIT, loc.RegNum, out.RegNum, 1 << membervar->BitValue); + out.Free(build); + } + obj.Free(build); + return loc; +} + + +//========================================================================== +// +// not really needed at the moment but may become useful with meta properties +// and some other class-specific extensions. +// +//========================================================================== + +FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition &pos) +: FxStructMember(x, mem, pos) +{ + ExprType = EFX_ClassMember; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index) +:FxExpression(EFX_ArrayElement, base->ScriptPosition) +{ + Array=base; + index = _index; + AddressRequested = false; + AddressWritable = false; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxArrayElement::~FxArrayElement() +{ + SAFE_DELETE(Array); + SAFE_DELETE(index); +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FxArrayElement::RequestAddress(FCompileContext &ctx, bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = AddressWritable; + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Array,ctx); + SAFE_RESOLVE(index,ctx); + + if (index->ValueType->GetRegType() == REGT_FLOAT /* lax */) + { + // DECORATE allows floats here so cast them to int. + index = new FxIntCast(index, ctx.FromDecorate); + index = index->Resolve(ctx); + if (index == nullptr) + { + delete this; + return nullptr; + } + } + if (index->ValueType->GetRegType() != REGT_INT && index->ValueType != TypeName) + { + ScriptPosition.Message(MSG_ERROR, "Array index must be integer"); + delete this; + return nullptr; + } + + PArray *arraytype = dyn_cast(Array->ValueType); + if (arraytype == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); + delete this; + return nullptr; + } + if (index->isConstant()) + { + unsigned indexval = static_cast(index)->GetValue().GetInt(); + if (indexval >= arraytype->ElementCount) + { + ScriptPosition.Message(MSG_ERROR, "Array index out of bounds"); + delete this; + return nullptr; + } + } + + ValueType = arraytype->ElementType; + if (ValueType->GetRegType() != REGT_INT && ValueType->GetRegType() != REGT_FLOAT) + { + // int arrays only for now + ScriptPosition.Message(MSG_ERROR, "Only numeric arrays are supported."); + delete this; + return nullptr; + } + if (!Array->RequestAddress(ctx, &AddressWritable)) + { + ScriptPosition.Message(MSG_ERROR, "Unable to dereference array."); + delete this; + return nullptr; + } + return this; +} + +//========================================================================== +// +// in its current state this won't be able to do more than handle the args array. +// +//========================================================================== + +ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) +{ + ExpEmit start = Array->Emit(build); + PArray *const arraytype = static_cast(Array->ValueType); + ExpEmit dest(build, arraytype->ElementType->GetRegType()); + + if (start.Konst) + { + ExpEmit tmpstart(build, REGT_POINTER); + build->Emit(OP_LKP, tmpstart.RegNum, start.RegNum); + start.Free(build); + start = tmpstart; + } + if (index->isConstant()) + { + unsigned indexval = static_cast(index)->GetValue().GetInt(); + assert(indexval < arraytype->ElementCount && "Array index out of bounds"); + indexval *= arraytype->ElementSize; + + if (AddressRequested) + { + if (indexval != 0) + { + build->Emit(OP_ADDA_RK, start.RegNum, start.RegNum, build->GetConstantInt(indexval)); + } + } + else + { + build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum, + start.RegNum, build->GetConstantInt(indexval)); + } + } + else + { + ExpEmit indexv(index->Emit(build)); + int shiftbits = 0; + while (1u << shiftbits < arraytype->ElementSize) + { + shiftbits++; + } + assert(1u << shiftbits == arraytype->ElementSize && "Element sizes other than power of 2 are not implemented"); + build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); + if (shiftbits > 0) + { + build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, shiftbits); + } + + if (AddressRequested) + { + build->Emit(OP_ADDA_RR, start.RegNum, start.RegNum, indexv.RegNum); + } + else + { + build->Emit(arraytype->ElementType->GetLoadOp() + 1, // added 1 to use the *_R version that + dest.RegNum, start.RegNum, indexv.RegNum); // takes the offset from a register + } + indexv.Free(build); + } + if (AddressRequested) + { + dest.Free(build); + return start; + } + + start.Free(build); + return dest; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos) +: FxExpression(EFX_FunctionCall, pos) +{ + MethodName = methodname; + RNG = &pr_exrandom; + ArgList = std::move(args); + if (rngname != NAME_None) + { + switch (MethodName) + { + case NAME_Random: + case NAME_FRandom: + case NAME_RandomPick: + case NAME_FRandomPick: + case NAME_Random2: + RNG = FRandom::StaticFindRNG(rngname.GetChars()); + break; + + default: + pos.Message(MSG_ERROR, "Cannot use named RNGs with %s", MethodName.GetChars()); + break; + + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFunctionCall::~FxFunctionCall() +{ +} + +//========================================================================== +// +// Check function that gets called +// +//========================================================================== + +static bool CheckArgSize(FName fname, FArgumentList &args, int min, int max, FScriptPosition &sc) +{ + int s = args.Size(); + if (s < min) + { + sc.Message(MSG_ERROR, "Insufficient arguments in call to %s, expected %d, got %d", fname.GetChars(), min, s); + return false; + } + else if (s > max && max >= 0) + { + sc.Message(MSG_ERROR, "Too many arguments in call to %s, expected %d, got %d", fname.GetChars(), min, s); + return false; + } + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) +{ + ABORT(ctx.Class); + bool error = false; + + PFunction *afd = FindClassMemberFunction(ctx.Class, ctx.Class, MethodName, ScriptPosition, &error); + + // Action functions in state providers need special treatment because self is of type Actor here. + if (afd != nullptr && ctx.Class->IsDescendantOf(RUNTIME_CLASS(AStateProvider)) && (ctx.Function->Variants[0].Flags & VARF_Action)) + { + // Only accept static and action functions from the current class. Calling a member function will require explicit use of 'invoker'. + if ((afd->Variants[0].Flags & (VARF_Method|VARF_Action)) == VARF_Method) + { + // Everything else that may be used here must pass the selfclass check, i.e. it must be reachable from Actor. + // Note that FuncClass is still the current item because for symbol privacy checks this is relevant. + afd = FindClassMemberFunction(ctx.Function->Variants[0].SelfClass, ctx.Class, MethodName, ScriptPosition, &error); + if (afd == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Unable to call non-action function %s from here. Please use 'invoker.%s' to call it.", MethodName.GetChars(), MethodName.GetChars()); + delete this; + return nullptr; + } + } + } + + if (error) + { + delete this; + return nullptr; + } + + if (afd != nullptr) + { + if (ctx.Function->Variants[0].Flags & VARF_Static && !(afd->Variants[0].Flags & VARF_Static)) + { + ScriptPosition.Message(MSG_ERROR, "Call to non-static function %s from a static context", MethodName.GetChars()); + delete this; + return nullptr; + } + auto self = !(afd->Variants[0].Flags & VARF_Static)? new FxSelf(ScriptPosition) : nullptr; + auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, false); + delete this; + return x->Resolve(ctx); + } + + for (size_t i = 0; i < countof(FxFlops); ++i) + { + if (MethodName == FxFlops[i].Name) + { + FxExpression *x = new FxFlopFunctionCall(i, ArgList, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + } + + int min, max, special; + if (MethodName == NAME_ACS_NamedExecuteWithResult || MethodName == NAME_CallACS) + { + special = -ACS_ExecuteWithResult; + min = 1; + max = 5; + } + else + { + special = P_FindLineSpecial(MethodName.GetChars(), &min, &max); + } + if (special != 0 && min >= 0) + { + int paramcount = ArgList.Size(); + if (paramcount < min) + { + ScriptPosition.Message(MSG_ERROR, "Not enough parameters for '%s' (expected %d, got %d)", + MethodName.GetChars(), min, paramcount); + delete this; + return nullptr; + } + else if (paramcount > max) + { + ScriptPosition.Message(MSG_ERROR, "too many parameters for '%s' (expected %d, got %d)", + MethodName.GetChars(), max, paramcount); + delete this; + return nullptr; + } + FxExpression *self = (ctx.Function && ctx.Function->Variants[0].Flags & VARF_Method) ? new FxSelf(ScriptPosition) : nullptr; + FxExpression *x = new FxActionSpecialCall(self, special, ArgList, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + + PClass *cls = PClass::FindClass(MethodName); + if (cls != nullptr && cls->bExported) + { + if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) + { + FxExpression *x = new FxDynamicCast(cls, ArgList[0]); + ArgList[0] = nullptr; + delete this; + return x->Resolve(ctx); + } + else + { + delete this; + return nullptr; + } + } + + + // Last but not least: Check builtins and type casts. The random functions can take a named RNG if specified. + // Note that for all builtins the used arguments have to be nulled in the ArgList so that they won't get deleted before they get used. + FxExpression *func = nullptr; + + switch (MethodName) + { + case NAME_Bool: + case NAME_Int: + case NAME_uInt: + case NAME_Float: + case NAME_Double: + case NAME_Name: + case NAME_Color: + case NAME_Sound: + case NAME_State: + if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) + { + PType *type = + MethodName == NAME_Bool ? TypeBool : + MethodName == NAME_Int ? TypeSInt32 : + MethodName == NAME_uInt ? TypeUInt32 : + MethodName == NAME_Float ? TypeFloat64 : + MethodName == NAME_Double ? TypeFloat64 : + MethodName == NAME_Name ? TypeName : + MethodName == NAME_State ? TypeState : + MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; + + func = new FxTypeCast(ArgList[0], type, true, true); + ArgList[0] = nullptr; + } + break; + + case NAME_Random: + // allow calling Random without arguments to default to (0, 255) + if (ArgList.Size() == 0) + { + func = new FxRandom(RNG, new FxConstant(0, ScriptPosition), new FxConstant(255, ScriptPosition), ScriptPosition, ctx.FromDecorate); + } + else if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) + { + func = new FxRandom(RNG, ArgList[0], ArgList[1], ScriptPosition, ctx.FromDecorate); + ArgList[0] = ArgList[1] = nullptr; + } + break; + + case NAME_FRandom: + if (CheckArgSize(NAME_FRandom, ArgList, 2, 2, ScriptPosition)) + { + func = new FxFRandom(RNG, ArgList[0], ArgList[1], ScriptPosition); + ArgList[0] = ArgList[1] = nullptr; + } + break; + + case NAME_RandomPick: + case NAME_FRandomPick: + if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition)) + { + func = new FxRandomPick(RNG, ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); + } + break; + + case NAME_Random2: + if (CheckArgSize(NAME_Random2, ArgList, 0, 1, ScriptPosition)) + { + func = new FxRandom2(RNG, ArgList.Size() == 0? nullptr : ArgList[0], ScriptPosition, ctx.FromDecorate); + if (ArgList.Size() > 0) ArgList[0] = nullptr; + } + break; + + case NAME_Min: + case NAME_Max: + if (CheckArgSize(MethodName, ArgList, 2, -1, ScriptPosition)) + { + func = new FxMinMax(ArgList, MethodName, ScriptPosition); + } + break; + + case NAME_Clamp: + if (CheckArgSize(MethodName, ArgList, 3, 3, ScriptPosition)) + { + TArray pass; + pass.Resize(2); + pass[0] = ArgList[0]; + pass[1] = ArgList[1]; + pass[0] = new FxMinMax(pass, NAME_Max, ScriptPosition); + pass[1] = ArgList[2]; + func = new FxMinMax(pass, NAME_Min, ScriptPosition); + ArgList[0] = ArgList[1] = ArgList[2] = nullptr; + } + break; + + case NAME_Abs: + if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) + { + func = new FxAbs(ArgList[0]); + ArgList[0] = nullptr; + } + break; + + case NAME_ATan2: + case NAME_VectorAngle: + if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition)) + { + func = MethodName == NAME_ATan2 ? new FxATan2(ArgList[0], ArgList[1], ScriptPosition) : new FxATan2(ArgList[1], ArgList[0], ScriptPosition); + ArgList[0] = ArgList[1] = nullptr; + } + break; + + default: + ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); + break; + } + if (func != nullptr) + { + delete this; + return func->Resolve(ctx); + } + delete this; + return nullptr; +} + + +//========================================================================== +// +// +// +//========================================================================== + +FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &args, const FScriptPosition &pos) + : FxExpression(EFX_MemberFunctionCall, pos) +{ + Self = self; + MethodName = methodname; + ArgList = std::move(args); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMemberFunctionCall::~FxMemberFunctionCall() +{ + SAFE_DELETE(Self); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) +{ + ABORT(ctx.Class); + PClass *cls; + bool staticonly = false; + bool novirtual = false; + + if (Self->ExprType == EFX_Identifier) + { + // If the left side is a class name for a static member function call it needs to be resolved manually + // because the resulting value type would cause problems in nearly every other place where identifiers are being used. + cls = PClass::FindClass(static_cast(Self)->Identifier); + if (cls != nullptr && cls->bExported) + { + staticonly = true; + goto isresolved; + } + } + SAFE_RESOLVE(Self, ctx); + + if (Self->ExprType == EFX_Super) + { + // give the node the proper value type now that we know it's properly used. + cls = ctx.Function->Variants[0].SelfClass->ParentClass; + Self->ValueType = NewPointer(cls); + Self->ExprType = EFX_Self; + novirtual = true; // super calls are always non-virtual + } + + if (Self->IsVector()) + { + // handle builtins: Vectors got 2: Length and Unit. + if (MethodName == NAME_Length || MethodName == NAME_Unit) + { + auto x = new FxVectorBuiltin(Self, MethodName); + Self = nullptr; + delete this; + return x->Resolve(ctx); + } + } + + if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + { + auto ptype = static_cast(Self->ValueType)->PointedType; + if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) + { + cls = static_cast(ptype); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Left hand side of %s must point to a class object\n", MethodName.GetChars()); + delete this; + return nullptr; + } + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s\n", MethodName.GetChars()); + delete this; + return nullptr; + } + +isresolved: + bool error = false; + PFunction *afd = FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error); + if (error) + { + delete this; + return nullptr; + } + + if (afd == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Unknown function %s\n", MethodName.GetChars()); + delete this; + return nullptr; + } + if (staticonly && (afd->Variants[0].Flags & VARF_Method)) + { + if (!ctx.Class->IsDescendantOf(cls)) + { + ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here\n", cls->TypeName.GetChars(), MethodName.GetChars()); + delete this; + return nullptr; + } + else + { + // Todo: If this is a qualified call to a parent class function, let it through (but this needs to disable virtual calls later.) + ScriptPosition.Message(MSG_ERROR, "Qualified member call to parent class not yet implemented\n", cls->TypeName.GetChars(), MethodName.GetChars()); + delete this; + return nullptr; + } + } + + // do not pass the self pointer to static functions. + auto self = (afd->Variants[0].Flags & VARF_Method) ? Self : nullptr; + auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly|novirtual); + if (Self == self) Self = nullptr; + delete this; + return x->Resolve(ctx); +} + + +//========================================================================== +// +// FxActionSpecialCall +// +// If special is negative, then the first argument will be treated as a +// name for ACS_NamedExecuteWithResult. +// +//========================================================================== + +FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgumentList &args, const FScriptPosition &pos) +: FxExpression(EFX_ActionSpecialCall, pos) +{ + Self = self; + Special = special; + ArgList = std::move(args); + EmitTail = false; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxActionSpecialCall::~FxActionSpecialCall() +{ + SAFE_DELETE(Self); +} + +//========================================================================== +// +// +// +//========================================================================== + +PPrototype *FxActionSpecialCall::ReturnProto() +{ + EmitTail = true; + return FxExpression::ReturnProto(); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + bool failed = false; + + SAFE_RESOLVE_OPT(Self, ctx); + for (unsigned i = 0; i < ArgList.Size(); i++) + { + ArgList[i] = ArgList[i]->Resolve(ctx); + if (ArgList[i] == nullptr) + { + failed = true; + } + else if (Special < 0 && i == 0) + { + if (ArgList[i]->ValueType == TypeString) + { + ArgList[i] = new FxNameCast(ArgList[i]); + ArgList[i] = ArgList[i]->Resolve(ctx); + if (ArgList[i] == nullptr) + { + failed = true; + } + } + else if (ArgList[i]->ValueType != TypeName) + { + ScriptPosition.Message(MSG_ERROR, "Name expected for parameter %d", i); + failed = true; + } + } + else if (!ArgList[i]->IsInteger()) + { + if (ArgList[i]->ValueType->GetRegType() == REGT_FLOAT /* lax */) + { + ArgList[i] = new FxIntCast(ArgList[i], ctx.FromDecorate); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Integer expected for parameter %d", i); + failed = true; + } + } + } + if (failed) + { + delete this; + return nullptr; + } + ValueType = TypeSInt32; + return this; +} + + +//========================================================================== +// +// +// +//========================================================================== + +int BuiltinCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +{ + assert(numparam > 2 && numparam < 8); + assert(param[0].Type == REGT_INT); + assert(param[1].Type == REGT_POINTER); + int v[5] = { 0 }; + + for (int i = 2; i < numparam; ++i) + { + v[i - 2] = param[i].i; + } + ACTION_RETURN_INT(P_ExecuteSpecial(param[0].i, nullptr, reinterpret_cast(param[1].a), false, v[0], v[1], v[2], v[3], v[4])); +} + +ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) +{ + unsigned i = 0; + + build->Emit(OP_PARAMI, abs(Special)); // pass special number + // fixme: This really should use the Self pointer that got passed to this class instead of just using the first argument from the function. + // Once static functions are possible, or specials can be called through a member access operator this won't work anymore. + build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self + for (; i < ArgList.Size(); ++i) + { + FxExpression *argex = ArgList[i]; + if (Special < 0 && i == 0) + { + assert(argex->ValueType == TypeName); + assert(argex->isConstant()); + build->EmitParamInt(-static_cast(argex)->GetValue().GetName()); + } + else + { + assert(argex->ValueType->GetRegType() == REGT_INT); + if (argex->isConstant()) + { + build->EmitParamInt(static_cast(argex)->GetValue().GetInt()); + } + else + { + ExpEmit arg(argex->Emit(build)); + build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum); + arg.Free(build); + } + } + } + // Call the BuiltinCallLineSpecial function to perform the desired special. + VMFunction *callfunc; + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + callfunc = ((PSymbolVMFunction *)sym)->Function; + ArgList.Clear(); + ArgList.ShrinkToFit(); + + if (EmitTail) + { + build->Emit(OP_TAIL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2 + i, 0); + ExpEmit call; + call.Final = true; + return call; + } + + ExpEmit dest(build, REGT_INT); + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2 + i, 1); + build->Emit(OP_RESULT, 0, REGT_INT, dest.RegNum); + return dest; +} + +//========================================================================== +// +// FxVMFunctionCall +// +//========================================================================== + +FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual) +: FxExpression(EFX_VMFunctionCall, pos) +{ + Self = self; + Function = func; + ArgList = std::move(args); + EmitTail = false; + NoVirtual = novirtual; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxVMFunctionCall::~FxVMFunctionCall() +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +PPrototype *FxVMFunctionCall::ReturnProto() +{ + EmitTail = true; + return Function->Variants[0].Proto; +} + +//========================================================================== +// +// +// +//========================================================================== + +VMFunction *FxVMFunctionCall::GetDirectFunction() +{ + // If this return statement calls a non-virtual 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 (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) + { + return Function->Variants[0].Implementation; + } + + return nullptr; +} + +//========================================================================== +// +// FxVMFunctionCall :: Resolve +// +//========================================================================== + +FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE_OPT(Self, ctx); + bool failed = false; + auto proto = Function->Variants[0].Proto; + auto argtypes = proto->ArgumentTypes; + + int implicit = Function->GetImplicitArgs(); + + // This should never happen. + if (Self == nullptr && (Function->Variants[0].Flags & VARF_Method)) + { + ScriptPosition.Message(MSG_ERROR, "Call to non-static function without a self pointer"); + delete this; + return nullptr; + } + + if (ArgList.Size() > 0) + { + bool foundvarargs = false; + PType * type = nullptr; + if (argtypes.Last() != nullptr && ArgList.Size() + implicit > argtypes.Size()) + { + ScriptPosition.Message(MSG_ERROR, "Too many arguments in call to %s", Function->SymbolName.GetChars()); + delete this; + return nullptr; + } + + for (unsigned i = 0; i < ArgList.Size(); i++) + { + // Varargs must all have the same type as the last typed argument. A_Jump is the only function using it. + if (!foundvarargs) + { + if (argtypes[i + implicit] == nullptr) foundvarargs = true; + else type = argtypes[i + implicit]; + } + assert(type != nullptr); + + FxExpression *x = new FxTypeCast(ArgList[i], type, false); + x = x->Resolve(ctx); + failed |= (x == nullptr); + ArgList[i] = x; + } + int numargs = ArgList.Size() + implicit; + if ((unsigned)numargs < argtypes.Size() && argtypes[numargs] != nullptr) + { + auto flags = Function->Variants[0].ArgFlags[numargs]; + if (!(flags & VARF_Optional)) + { + ScriptPosition.Message(MSG_ERROR, "Insufficient arguments in call to %s", Function->SymbolName.GetChars()); + delete this; + return nullptr; + } + } + } + else + { + if ((unsigned)implicit < argtypes.Size() && argtypes[implicit] != nullptr) + { + auto flags = Function->Variants[0].ArgFlags[implicit]; + if (!(flags & VARF_Optional)) + { + ScriptPosition.Message(MSG_ERROR, "Insufficient arguments in call to %s", Function->SymbolName.GetChars()); + delete this; + return nullptr; + } + } + } + if (failed) + { + delete this; + return nullptr; + } + TArray &rets = proto->ReturnTypes; + if (rets.Size() > 0) + { + ValueType = rets[0]; + } + else + { + ValueType = TypeVoid; + } + + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) +{ + assert(build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits); + int count = 0; + + if (count == 1) + { + ExpEmit reg; + if (CheckEmitCast(build, EmitTail, reg)) + { + ArgList.Clear(); + ArgList.ShrinkToFit(); + return reg; + } + } + + VMFunction *vmfunc = Function->Variants[0].Implementation; + bool staticcall = (vmfunc->Final || vmfunc->VirtualIndex == -1 || NoVirtual); + + count = 0; + // Emit code to pass implied parameters + ExpEmit selfemit; + if (Function->Variants[0].Flags & VARF_Method) + { + assert(Self != nullptr); + selfemit = Self->Emit(build); + assert(selfemit.RegType == REGT_POINTER); + build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); + count += 1; + if (Function->Variants[0].Flags & VARF_Action) + { + static_assert(NAP == 3, "This code needs to be updated if NAP changes"); + if (build->NumImplicits == NAP && selfemit.RegNum == 0) // only pass this function's stateowner and stateinfo if the subfunction is run in self's context. + { + build->Emit(OP_PARAM, 0, REGT_POINTER, 1); + build->Emit(OP_PARAM, 0, REGT_POINTER, 2); + } + else + { + // pass self as stateowner, otherwise all attempts of the subfunction to retrieve a state from a name would fail. + build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr, ATAG_GENERIC)); + } + count += 2; + } + if (staticcall) selfemit.Free(build); + } + else staticcall = true; + // Emit code to pass explicit parameters + for (unsigned i = 0; i < ArgList.Size(); ++i) + { + count += EmitParameter(build, ArgList[i], ScriptPosition); + } + ArgList.Clear(); + ArgList.ShrinkToFit(); + + // Get a constant register for this function + if (staticcall) + { + int funcaddr = build->GetConstantAddress(vmfunc, ATAG_OBJECT); + // Emit the call + if (EmitTail) + { // Tail call + build->Emit(OP_TAIL_K, funcaddr, count, 0); + ExpEmit call; + call.Final = true; + return call; + } + else if (vmfunc->Proto->ReturnTypes.Size() > 0) + { // Call, expecting one result + ExpEmit reg(build, vmfunc->Proto->ReturnTypes[0]->GetRegType(), vmfunc->Proto->ReturnTypes[0]->GetRegCount()); + build->Emit(OP_CALL_K, funcaddr, count, 1); + build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum); + return reg; + } + else + { // Call, expecting no results + build->Emit(OP_CALL_K, funcaddr, count, 0); + return ExpEmit(); + } + } + else + { + selfemit.Free(build); + ExpEmit funcreg(build, REGT_POINTER); + build->Emit(OP_VTBL, funcreg.RegNum, selfemit.RegNum, vmfunc->VirtualIndex); + if (EmitTail) + { // Tail call + build->Emit(OP_TAIL, funcreg.RegNum, count, 0); + ExpEmit call; + call.Final = true; + return call; + } + else if (vmfunc->Proto->ReturnTypes.Size() > 0) + { // Call, expecting one result + ExpEmit reg(build, vmfunc->Proto->ReturnTypes[0]->GetRegType(), vmfunc->Proto->ReturnTypes[0]->GetRegCount()); + build->Emit(OP_CALL, funcreg.RegNum, count, 1); + build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum); + return reg; + } + else + { // Call, expecting no results + build->Emit(OP_CALL, funcreg.RegNum, count, 0); + return ExpEmit(); + } + + + } +} + +//========================================================================== +// +// If calling one of the casting kludge functions, don't bother calling the +// function; just use the parameter directly. Returns true if this was a +// kludge function, false otherwise. +// +//========================================================================== + +bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, ExpEmit ®) +{ + FName funcname = Function->SymbolName; + if (funcname == NAME___decorate_internal_int__ || + funcname == NAME___decorate_internal_bool__ || + funcname == NAME___decorate_internal_float__) + { + FxExpression *arg = ArgList[0]; + if (returnit) + { + if (arg->isConstant() && + (funcname == NAME___decorate_internal_int__ || + funcname == NAME___decorate_internal_bool__)) + { // Use immediate version for integers in range + build->EmitRetInt(0, true, static_cast(arg)->GetValue().Int); + } + else + { + ExpEmit where = arg->Emit(build); + build->Emit(OP_RET, RET_FINAL, EncodeRegType(where), where.RegNum); + where.Free(build); + } + reg = ExpEmit(); + reg.Final = true; + } + else + { + reg = arg->Emit(build); + } + return true; + } + return false; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFlopFunctionCall::FxFlopFunctionCall(size_t index, FArgumentList &args, const FScriptPosition &pos) +: FxExpression(EFX_FlopFunctionCall, pos) +{ + assert(index < countof(FxFlops) && "FLOP index out of range"); + Index = (int)index; + ArgList = std::move(args); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFlopFunctionCall::~FxFlopFunctionCall() +{ +} + +FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + + if (ArgList.Size() != 1) + { + ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", FName(FxFlops[Index].Name).GetChars()); + delete this; + return nullptr; + } + + ArgList[0] = ArgList[0]->Resolve(ctx); + if (ArgList[0] == nullptr) + { + delete this; + return nullptr; + } + + if (!ArgList[0]->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); + delete this; + return nullptr; + } + if (ArgList[0]->isConstant()) + { + double v = static_cast(ArgList[0])->GetValue().GetFloat(); + v = FxFlops[Index].Evaluate(v); + FxExpression *x = new FxConstant(v, ScriptPosition); + delete this; + return x; + } + if (ArgList[0]->ValueType->GetRegType() == REGT_INT) + { + ArgList[0] = new FxFloatCast(ArgList[0]); + } + ValueType = TypeFloat64; + return this; +} + +//========================================================================== +// +// +//========================================================================== + +ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) +{ + ExpEmit v = ArgList[0]->Emit(build); + assert(!v.Konst && v.RegType == REGT_FLOAT); + + build->Emit(OP_FLOP, v.RegNum, v.RegNum, FxFlops[Index].Flop); + ArgList.Clear(); + ArgList.ShrinkToFit(); + return v; +} + + +//========================================================================== +// +// +//========================================================================== + +FxVectorBuiltin::FxVectorBuiltin(FxExpression *self, FName name) + :FxExpression(EFX_VectorBuiltin, self->ScriptPosition) +{ + Self = self; + Function = name; +} + +FxVectorBuiltin::~FxVectorBuiltin() +{ + SAFE_DELETE(Self); +} + +FxExpression *FxVectorBuiltin::Resolve(FCompileContext &ctx) +{ + SAFE_RESOLVE(Self, ctx); + assert(Self->IsVector()); // should never be created for anything else. + ValueType = Function == NAME_Length ? TypeFloat64 : Self->ValueType; + return this; +} + +ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build) +{ + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + ExpEmit op = Self->Emit(build); + if (Function == NAME_Length) + { + build->Emit(Self->ValueType == TypeVector2 ? OP_LENV2 : OP_LENV3, to.RegNum, op.RegNum); + } + else + { + ExpEmit len(build, REGT_FLOAT); + build->Emit(Self->ValueType == TypeVector2 ? OP_LENV2 : OP_LENV3, len.RegNum, op.RegNum); + build->Emit(Self->ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR, to.RegNum, op.RegNum, len.RegNum); + len.Free(build); + } + op.Free(build); + return to; +} + +//========================================================================== +// +// FxSequence :: Resolve +// +//========================================================================== + +FxExpression *FxSequence::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + bool fail = false; + for (unsigned i = 0; i < Expressions.Size(); ++i) + { + if (nullptr == (Expressions[i] = Expressions[i]->Resolve(ctx))) + { + fail = true; + } + else if (Expressions[i]->ValueType == TypeError) + { + ScriptPosition.Message(MSG_ERROR, "Invalid statement"); + fail = true; + } + } + if (fail) + { + delete this; + return nullptr; + } + return this; +} + +//========================================================================== +// +// FxSequence :: CheckReturn +// +//========================================================================== + +bool FxSequence::CheckReturn() +{ + // a sequence always returns when its last element returns. + return Expressions.Size() > 0 && Expressions.Last()->CheckReturn(); +} + +//========================================================================== +// +// FxSequence :: Emit +// +//========================================================================== + +ExpEmit FxSequence::Emit(VMFunctionBuilder *build) +{ + for (unsigned i = 0; i < Expressions.Size(); ++i) + { + ExpEmit v = Expressions[i]->Emit(build); + // Throw away any result. We don't care about it. + v.Free(build); + } + return ExpEmit(); +} + +//========================================================================== +// +// FxSequence :: GetDirectFunction +// +//========================================================================== + +VMFunction *FxSequence::GetDirectFunction() +{ + if (Expressions.Size() == 1) + { + return Expressions[0]->GetDirectFunction(); + } + return nullptr; +} + +//========================================================================== +// +// FxCompoundStatement :: Resolve +// +//========================================================================== + +FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx) +{ + auto outer = ctx.Block; + Outer = ctx.Block; + ctx.Block = this; + auto x = FxSequence::Resolve(ctx); + ctx.Block = outer; + return x; +} + +//========================================================================== +// +// FxCompoundStatement :: Emit +// +//========================================================================== + +ExpEmit FxCompoundStatement::Emit(VMFunctionBuilder *build) +{ + auto e = FxSequence::Emit(build); + // Release all local variables in this block. + for (auto l : LocalVars) + { + l->Release(build); + } + return e; +} + +//========================================================================== +// +// FxCompoundStatement :: FindLocalVariable +// +// Looks for a variable name in any of the containing compound statements +// This does a simple linear search on each block's variables. +// The lists here normally don't get large enough to justify something more complex. +// +//========================================================================== + +FxLocalVariableDeclaration *FxCompoundStatement::FindLocalVariable(FName name, FCompileContext &ctx) +{ + auto block = this; + while (block != nullptr) + { + for (auto l : block->LocalVars) + { + if (l->Name == name) + { + return l; + } + } + block = block->Outer; + } + // finally check the context for function arguments + for (auto arg : ctx.FunctionArgs) + { + if (arg->Name == name) + { + return arg; + } + } + return nullptr; +} + +//========================================================================== +// +// FxCompoundStatement :: CheckLocalVariable +// +// Checks if the current block already contains a local variable +// of the given name. +// +//========================================================================== + +bool FxCompoundStatement::CheckLocalVariable(FName name) +{ + for (auto l : LocalVars) + { + if (l->Name == name) + { + return true; + } + } + return false; +} + +//========================================================================== +// +// FxSwitchStatement +// +//========================================================================== + +FxSwitchStatement::FxSwitchStatement(FxExpression *cond, FArgumentList &content, const FScriptPosition &pos) + : FxExpression(EFX_SwitchStatement, pos) +{ + Condition = new FxIntCast(cond, false); + Content = std::move(content); +} + +FxSwitchStatement::~FxSwitchStatement() +{ + SAFE_DELETE(Condition); +} + +FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Condition, ctx); + + if (Content.Size() == 0) + { + ScriptPosition.Message(MSG_WARNING, "Empty switch statement"); + if (Condition->isConstant()) + { + return new FxNop(ScriptPosition); + } + else + { + // The condition may have a side effect so it should be processed (possible to-do: Analyze all nodes in there and delete if not.) + auto x = Condition; + Condition = nullptr; + delete this; + x->NeedResult = false; + return x; + } + } + + for (auto &line : Content) + { + // Do not resolve breaks, they need special treatment inside switch blocks. + if (line->ExprType != EFX_JumpStatement || static_cast(line)->Token != TK_Break) + { + SAFE_RESOLVE(line, ctx); + line->NeedResult = false; + } + } + + if (Condition->isConstant()) + { + ScriptPosition.Message(MSG_WARNING, "Case expression is constant"); + auto &content = Content; + int defaultindex = -1; + int defaultbreak = -1; + int caseindex = -1; + int casebreak = -1; + // look for a case label with a matching value + for (unsigned i = 0; i < content.Size(); i++) + { + if (content[i] != nullptr) + { + if (content[i]->ExprType == EFX_CaseStatement) + { + auto casestmt = static_cast(content[i]); + if (casestmt->Condition == nullptr) defaultindex = i; + else if (casestmt->CaseValue == static_cast(Condition)->GetValue().GetInt()) caseindex = i; + } + if (content[i]->ExprType == EFX_JumpStatement && static_cast(content[i])->Token == TK_Break) + { + if (defaultindex >= 0 && defaultbreak < 0) defaultbreak = i; + if (caseindex >= 0 && casebreak < 0) + { + casebreak = i; + break; // when we find this we do not need to look any further. + } + } + } + } + if (caseindex < 0) + { + caseindex = defaultindex; + casebreak = defaultbreak; + } + if (caseindex > 0 && casebreak - caseindex > 1) + { + auto seq = new FxSequence(ScriptPosition); + for (int i = caseindex + 1; i < casebreak; i++) + { + if (content[i] != nullptr && content[i]->ExprType != EFX_CaseStatement) + { + seq->Add(content[i]); + content[i] = nullptr; + } + } + delete this; + return seq->Resolve(ctx); + } + delete this; + return new FxNop(ScriptPosition); + } + + int mincase = INT_MAX; + int maxcase = INT_MIN; + for (auto line : Content) + { + if (line->ExprType == EFX_CaseStatement) + { + auto casestmt = static_cast(line); + if (casestmt->Condition != nullptr) + { + CaseAddr ca = { casestmt->CaseValue, 0 }; + CaseAddresses.Push(ca); + if (ca.casevalue < mincase) mincase = ca.casevalue; + if (ca.casevalue > maxcase) maxcase = ca.casevalue; + } + } + } + return this; +} + +ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) +{ + assert(Condition != nullptr); + ExpEmit emit = Condition->Emit(build); + assert(emit.RegType == REGT_INT); + // todo: + // - sort jump table by value. + // - optimize the switch dispatcher to run in native code instead of executing each single branch instruction on its own. + // e.g.: build->Emit(OP_SWITCH, emit.RegNum, build->GetConstantInt(CaseAddresses.Size()); + for (auto &ca : CaseAddresses) + { + if (ca.casevalue >= 0 && ca.casevalue <= 0xffff) + { + build->Emit(OP_TEST, emit.RegNum, (VM_SHALF)ca.casevalue); + } + else if (ca.casevalue < 0 && ca.casevalue >= -0xffff) + { + build->Emit(OP_TESTN, emit.RegNum, (VM_SHALF)-ca.casevalue); + } + else + { + build->Emit(OP_EQ_K, 1, emit.RegNum, build->GetConstantInt(ca.casevalue)); + } + ca.jumpaddress = build->Emit(OP_JMP, 0); + } + size_t DefaultAddress = build->Emit(OP_JMP, 0); + TArray BreakAddresses; + + for (auto line : Content) + { + switch (line->ExprType) + { + case EFX_CaseStatement: + if (static_cast(line)->Condition != nullptr) + { + for (auto &ca : CaseAddresses) + { + if (ca.casevalue == static_cast(line)->CaseValue) + { + build->BackpatchToHere(ca.jumpaddress); + break; + } + } + } + else + { + build->BackpatchToHere(DefaultAddress); + } + break; + + case EFX_JumpStatement: + if (static_cast(line)->Token == TK_Break) + { + BreakAddresses.Push(build->Emit(OP_JMP, 0)); + break; + } + // fall through for continue. + + default: + line->Emit(build); + break; + } + } + for (auto addr : BreakAddresses) + { + build->BackpatchToHere(addr); + } + Content.Clear(); + Content.ShrinkToFit(); + return ExpEmit(); +} + +//========================================================================== +// +// FxSequence :: CheckReturn +// +//========================================================================== + +bool FxSwitchStatement::CheckReturn() +{ + //A switch statement returns when it contains no breaks and ends with a return + for (auto line : Content) + { + if (line->ExprType == EFX_JumpStatement) + { + return false; // Break means that the end of the statement will be reached, Continue cannot happen in the last statement of the last block. + } + } + return Content.Size() > 0 && Content.Last()->CheckReturn(); +} + +//========================================================================== +// +// FxCaseStatement +// +//========================================================================== + +FxCaseStatement::FxCaseStatement(FxExpression *cond, const FScriptPosition &pos) + : FxExpression(EFX_CaseStatement, pos) +{ + Condition = cond? new FxIntCast(cond, false) : nullptr; +} + +FxCaseStatement::~FxCaseStatement() +{ + SAFE_DELETE(Condition); +} + +FxExpression *FxCaseStatement::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE_OPT(Condition, ctx); + + if (Condition != nullptr) + { + if (!Condition->isConstant()) + { + ScriptPosition.Message(MSG_ERROR, "Case label must be a constant value"); + delete this; + return nullptr; + } + CaseValue = static_cast(Condition)->GetValue().GetInt(); + } + return this; +} + +//========================================================================== +// +// FxIfStatement +// +//========================================================================== + +FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part, + FxExpression *false_part, const FScriptPosition &pos) +: FxExpression(EFX_IfStatement, pos) +{ + Condition = cond; + WhenTrue = true_part; + WhenFalse = false_part; + if (WhenTrue != nullptr) WhenTrue->NeedResult = false; + if (WhenFalse != nullptr) WhenFalse->NeedResult = false; + assert(cond != nullptr); +} + +FxIfStatement::~FxIfStatement() +{ + SAFE_DELETE(Condition); + SAFE_DELETE(WhenTrue); + SAFE_DELETE(WhenFalse); +} + +FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + + if (WhenTrue == nullptr && WhenFalse == nullptr) + { // We don't do anything either way, so disappear + delete this; + return nullptr; + } + + SAFE_RESOLVE(Condition, ctx); + + if (Condition->ValueType != TypeBool) + { + Condition = new FxBoolCast(Condition, false); + SAFE_RESOLVE(Condition, ctx); + } + + if (WhenTrue != nullptr) + { + WhenTrue = WhenTrue->Resolve(ctx); + ABORT(WhenTrue); + } + if (WhenFalse != nullptr) + { + WhenFalse = WhenFalse->Resolve(ctx); + ABORT(WhenFalse); + } + + ValueType = TypeVoid; + + if (Condition->isConstant()) + { + ExpVal condval = static_cast(Condition)->GetValue(); + bool result = condval.GetBool(); + + FxExpression *e = result ? WhenTrue : WhenFalse; + delete (result ? WhenFalse : WhenTrue); + WhenTrue = WhenFalse = nullptr; + if (e == nullptr) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts. + delete this; + return e; + } + + return this; +} + +ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) +{ + ExpEmit v; + size_t jumpspot; + FxExpression *path1, *path2; + int condcheck; + + // This is pretty much copied from FxConditional, except we don't + // keep any results. + ExpEmit cond = Condition->Emit(build); + assert(cond.RegType != REGT_STRING && !cond.Konst); + + if (WhenTrue != nullptr) + { + path1 = WhenTrue; + path2 = WhenFalse; + condcheck = 1; + } + else + { + // When there is only a false path, reverse the condition so we can + // treat it as a true path. + assert(WhenFalse != nullptr); + path1 = WhenFalse; + path2 = nullptr; + condcheck = 0; + } + + // Test condition. + + switch (cond.RegType) + { + default: + case REGT_INT: + build->Emit(OP_EQ_K, condcheck, cond.RegNum, build->GetConstantInt(0)); + break; + + case REGT_FLOAT: + build->Emit(OP_EQF_K, condcheck, cond.RegNum, build->GetConstantFloat(0)); + break; + + case REGT_POINTER: + build->Emit(OP_EQA_K, condcheck, cond.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC)); + break; + } + jumpspot = build->Emit(OP_JMP, 0); + cond.Free(build); + + // Evaluate first path + v = path1->Emit(build); + v.Free(build); + if (path2 != nullptr) + { + size_t path1jump; + + // if the branch ends with a return we do not need a terminating jmp. + if (!path1->CheckReturn()) path1jump = build->Emit(OP_JMP, 0); + else path1jump = 0xffffffff; + // Evaluate second path + build->BackpatchToHere(jumpspot); + v = path2->Emit(build); + v.Free(build); + jumpspot = path1jump; + } + if (jumpspot != 0xffffffff) build->BackpatchToHere(jumpspot); + return ExpEmit(); +} + + +//========================================================================== +// +// FxIfStatement :: CheckReturn +// +//========================================================================== + +bool FxIfStatement::CheckReturn() +{ + //An if statement returns if both branches return. Both branches must be present. + return WhenTrue != nullptr && WhenTrue->CheckReturn() && + WhenFalse != nullptr && WhenFalse->CheckReturn(); +} + +//========================================================================== +// +// FxLoopStatement :: Resolve +// +// saves the loop pointer in the context and sets this object as the current loop +// so that continues and breaks always resolve to the innermost loop. +// +//========================================================================== + +FxExpression *FxLoopStatement::Resolve(FCompileContext &ctx) +{ + auto outer = ctx.Loop; + ctx.Loop = this; + auto x = DoResolve(ctx); + ctx.Loop = outer; + return x; +} + +void FxLoopStatement::Backpatch(VMFunctionBuilder *build, size_t loopstart, size_t loopend) +{ + // Give a proper address to any break/continue statement within this loop. + for (unsigned int i = 0; i < Jumps.Size(); i++) + { + if (Jumps[i]->Token == TK_Break) + { + build->Backpatch(Jumps[i]->Address, loopend); + } + else + { // Continue statement. + build->Backpatch(Jumps[i]->Address, loopstart); + } + } +} + +//========================================================================== +// +// FxWhileLoop +// +//========================================================================== + +FxWhileLoop::FxWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) +: FxLoopStatement(EFX_WhileLoop, pos), Condition(condition), Code(code) +{ + ValueType = TypeVoid; +} + +FxWhileLoop::~FxWhileLoop() +{ + SAFE_DELETE(Condition); + SAFE_DELETE(Code); +} + +FxExpression *FxWhileLoop::DoResolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Condition, ctx); + SAFE_RESOLVE_OPT(Code, ctx); + + if (Condition->ValueType != TypeBool) + { + Condition = new FxBoolCast(Condition); + SAFE_RESOLVE(Condition, ctx); + } + + if (Condition->isConstant()) + { + if (static_cast(Condition)->GetValue().GetBool() == false) + { // Nothing happens + FxExpression *nop = new FxNop(ScriptPosition); + delete this; + return nop; + } + else if (Code == nullptr) + { // "while (true) { }" + // Someone could be using this for testing. + ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); + } + } + + return this; +} + +ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) +{ + assert(Condition->ValueType == TypeBool); + + size_t loopstart, loopend; + size_t jumpspot; + + // Evaluate the condition and execute/break out of the loop. + loopstart = build->GetAddress(); + if (!Condition->isConstant()) + { + ExpEmit cond = Condition->Emit(build); + build->Emit(OP_TEST, cond.RegNum, 0); + jumpspot = build->Emit(OP_JMP, 0); + cond.Free(build); + } + else assert(static_cast(Condition)->GetValue().GetBool() == true); + + // Execute the loop's content. + if (Code != nullptr) + { + ExpEmit code = Code->Emit(build); + code.Free(build); + } + + // Loop back. + build->Backpatch(build->Emit(OP_JMP, 0), loopstart); + loopend = build->GetAddress(); + + if (!Condition->isConstant()) + { + build->Backpatch(jumpspot, loopend); + } + + Backpatch(build, loopstart, loopend); + return ExpEmit(); +} + +//========================================================================== +// +// FxDoWhileLoop +// +//========================================================================== + +FxDoWhileLoop::FxDoWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) +: FxLoopStatement(EFX_DoWhileLoop, pos), Condition(condition), Code(code) +{ + ValueType = TypeVoid; +} + +FxDoWhileLoop::~FxDoWhileLoop() +{ + SAFE_DELETE(Condition); + SAFE_DELETE(Code); +} + +FxExpression *FxDoWhileLoop::DoResolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Condition, ctx); + SAFE_RESOLVE_OPT(Code, ctx); + + if (Condition->ValueType != TypeBool) + { + Condition = new FxBoolCast(Condition); + SAFE_RESOLVE(Condition, ctx); + } + + if (Condition->isConstant()) + { + if (static_cast(Condition)->GetValue().GetBool() == false) + { // The code executes once, if any. + if (Jumps.Size() == 0) + { // We would still have to handle the jumps however. + FxExpression *e = Code; + if (e == nullptr) e = new FxNop(ScriptPosition); + Code = nullptr; + delete this; + return e; + } + } + else if (Code == nullptr) + { // "do { } while (true);" + // Someone could be using this for testing. + ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); + } + } + + return this; +} + +ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) +{ + assert(Condition->ValueType == TypeBool); + + size_t loopstart, loopend; + size_t codestart; + + // Execute the loop's content. + codestart = build->GetAddress(); + if (Code != nullptr) + { + ExpEmit code = Code->Emit(build); + code.Free(build); + } + + // Evaluate the condition and execute/break out of the loop. + loopstart = build->GetAddress(); + if (!Condition->isConstant()) + { + ExpEmit cond = Condition->Emit(build); + build->Emit(OP_TEST, cond.RegNum, 1); + cond.Free(build); + build->Backpatch(build->Emit(OP_JMP, 0), codestart); + } + else if (static_cast(Condition)->GetValue().GetBool() == true) + { // Always looping + build->Backpatch(build->Emit(OP_JMP, 0), codestart); + } + loopend = build->GetAddress(); + + Backpatch(build, loopstart, loopend); + + return ExpEmit(); +} + +//========================================================================== +// +// FxForLoop +// +//========================================================================== + +FxForLoop::FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos) +: FxLoopStatement(EFX_ForLoop, pos), Init(init), Condition(condition), Iteration(iteration), Code(code) +{ + ValueType = TypeVoid; + if (Iteration != nullptr) Iteration->NeedResult = false; + if (Code != nullptr) Code->NeedResult = false; +} + +FxForLoop::~FxForLoop() +{ + SAFE_DELETE(Init); + SAFE_DELETE(Condition); + SAFE_DELETE(Iteration); + SAFE_DELETE(Code); +} + +FxExpression *FxForLoop::DoResolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE_OPT(Init, ctx); + SAFE_RESOLVE_OPT(Condition, ctx); + SAFE_RESOLVE_OPT(Iteration, ctx); + SAFE_RESOLVE_OPT(Code, ctx); + + if (Condition != nullptr) + { + if (Condition->ValueType != TypeBool) + { + Condition = new FxBoolCast(Condition); + SAFE_RESOLVE(Condition, ctx); + } + + if (Condition->isConstant()) + { + if (static_cast(Condition)->GetValue().GetBool() == false) + { // Nothing happens + FxExpression *nop = new FxNop(ScriptPosition); + delete this; + return nop; + } + else + { // "for (..; true; ..)" + delete Condition; + Condition = nullptr; + } + } + } + if (Condition == nullptr && Code == nullptr) + { // "for (..; ; ..) { }" + // Someone could be using this for testing. + ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); + } + + return this; +} + +ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) +{ + assert((Condition && Condition->ValueType == TypeBool && !Condition->isConstant()) || Condition == nullptr); + + size_t loopstart, loopend; + size_t codestart; + size_t jumpspot; + + // Init statement (only used by DECORATE. ZScript is pulling it before the loop statement and enclosing the entire loop in a compound statement so that Init can have local variables.) + if (Init != nullptr) + { + ExpEmit init = Init->Emit(build); + init.Free(build); + } + + // Evaluate the condition and execute/break out of the loop. + codestart = build->GetAddress(); + if (Condition != nullptr) + { + ExpEmit cond = Condition->Emit(build); + build->Emit(OP_TEST, cond.RegNum, 0); + cond.Free(build); + jumpspot = build->Emit(OP_JMP, 0); + } + + // Execute the loop's content. + if (Code != nullptr) + { + ExpEmit code = Code->Emit(build); + code.Free(build); + } + + // Iteration statement. + loopstart = build->GetAddress(); + if (Iteration != nullptr) + { + ExpEmit iter = Iteration->Emit(build); + iter.Free(build); + } + build->Backpatch(build->Emit(OP_JMP, 0), codestart); + + // End of loop. + loopend = build->GetAddress(); + if (Condition != nullptr) + { + build->Backpatch(jumpspot, loopend); + } + + Backpatch(build, loopstart, loopend); + return ExpEmit(); +} + +//========================================================================== +// +// FxJumpStatement +// +//========================================================================== + +FxJumpStatement::FxJumpStatement(int token, const FScriptPosition &pos) +: FxExpression(EFX_JumpStatement, pos), Token(token) +{ + ValueType = TypeVoid; +} + +FxExpression *FxJumpStatement::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + + if (ctx.Loop != nullptr) + { + ctx.Loop->Jumps.Push(this); + return this; + } + else + { + ScriptPosition.Message(MSG_ERROR, "'%s' outside of a loop", Token == TK_Break ? "break" : "continue"); + delete this; + return nullptr; + } +} + +ExpEmit FxJumpStatement::Emit(VMFunctionBuilder *build) +{ + Address = build->Emit(OP_JMP, 0); + + return ExpEmit(); +} + +//========================================================================== +// +//========================================================================== + +FxReturnStatement::FxReturnStatement(FxExpression *value, const FScriptPosition &pos) +: FxExpression(EFX_ReturnStatement, pos), Value(value) +{ + ValueType = TypeVoid; +} + +FxReturnStatement::~FxReturnStatement() +{ + SAFE_DELETE(Value); +} + +FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE_OPT(Value, ctx); + + PPrototype *retproto; + if (Value == nullptr) + { + TArray none(0); + retproto = NewPrototype(none, none); + } + else + { + // If we already know the real return type we need at least try to cast the value to its proper type (unless in an anonymous function.) + if (ctx.ReturnProto != nullptr && ctx.Function->SymbolName != NAME_None) + { + Value = new FxTypeCast(Value, ctx.ReturnProto->ReturnTypes[0], false, false); + Value = Value->Resolve(ctx); + ABORT(Value); + } + retproto = Value->ReturnProto(); + } + + ctx.CheckReturn(retproto, ScriptPosition); + + return this; +} + +ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build) +{ + ExpEmit out(0, REGT_NIL); + + // If we return nothing, use a regular RET opcode. + // Otherwise just return the value we're given. + if (Value == nullptr) + { + build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0); + } + else + { + out = Value->Emit(build); + + // Check if it is a function call that simplified itself + // into a tail call in which case we don't emit anything. + if (!out.Final) + { + if (Value->ValueType == TypeVoid) + { // Nothing is returned. + build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0); + } + else + { + build->Emit(OP_RET, RET_FINAL, EncodeRegType(out), out.RegNum); + } + } + } + + out.Final = true; + return out; +} + +VMFunction *FxReturnStatement::GetDirectFunction() +{ + if (Value != nullptr) + { + return Value->GetDirectFunction(); + } + return nullptr; +} + +//========================================================================== +// +//========================================================================== + +FxClassTypeCast::FxClassTypeCast(PClassPointer *dtype, FxExpression *x) +: FxExpression(EFX_ClassTypeCast, x->ScriptPosition) +{ + ValueType = dtype; + desttype = dtype->ClassRestriction; + basex=x; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxClassTypeCast::~FxClassTypeCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType == TypeNullPtr) + { + basex->ValueType = ValueType; + auto x = basex; + basex = nullptr; + delete this; + return x; + } + auto to = static_cast(ValueType); + if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer)) + { + auto from = static_cast(basex->ValueType); + if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction)) + { + basex->ValueType = to; + auto x = basex; + basex = nullptr; + delete this; + return x; + } + ScriptPosition.Message(MSG_ERROR, "Cannot convert from %s to %s: Incompatible class types", from->ClassRestriction->TypeName.GetChars(), to->ClassRestriction->TypeName.GetChars()); + delete this; + return nullptr; + } + + if (basex->ValueType != TypeName && basex->ValueType != TypeString) + { + ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to class type", basex->ValueType->DescriptiveName()); + delete this; + return nullptr; + } + + if (basex->isConstant()) + { + FName clsname = static_cast(basex)->GetValue().GetName(); + PClass *cls = nullptr; + + if (clsname != NAME_None) + { + cls = PClass::FindClass(clsname); + if (cls == nullptr) + { + /* lax */ + // Since this happens in released WADs it must pass without a terminal error... :( + ScriptPosition.Message(MSG_OPTERROR, + "Unknown class name '%s'", + clsname.GetChars(), desttype->TypeName.GetChars()); + } + else + { + if (!cls->IsDescendantOf(desttype)) + { + ScriptPosition.Message(MSG_ERROR, "class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); + delete this; + return nullptr; + } + ScriptPosition.Message(MSG_DEBUGLOG, "resolving '%s' as class name", clsname.GetChars()); + } + } + FxExpression *x = new FxConstant(cls, to, ScriptPosition); + delete this; + return x; + } + if (basex->ValueType == TypeString) + { + basex = new FxNameCast(basex); + } + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +{ + assert(numparam == 2); + assert(numret == 1); + assert(param[0].Type == REGT_INT); + assert(param[1].Type == REGT_POINTER); + assert(ret->RegType == REGT_POINTER); + + FName clsname = ENamedName(param[0].i); + const PClass *cls = PClass::FindClass(clsname); + const PClass *desttype = reinterpret_cast(param[1].a); + + if (!cls->IsDescendantOf(desttype)) + { + Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); + cls = nullptr; + } + ret->SetPointer(const_cast(cls), ATAG_OBJECT); + return 1; +} + +ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) +{ + if (basex->ValueType != TypeName) + { + return ExpEmit(build->GetConstantAddress(nullptr, ATAG_OBJECT), REGT_POINTER, true); + } + ExpEmit clsname = basex->Emit(build); + assert(!clsname.Konst); + ExpEmit dest(build, REGT_POINTER); + build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast(desttype), ATAG_OBJECT)); + + // Call the BuiltinNameToClass function to convert from 'name' to class. + VMFunction *callfunc; + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + callfunc = ((PSymbolVMFunction *)sym)->Function; + + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); + build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); + clsname.Free(build); + return dest; +} + +//========================================================================== +// +// Symbolic state labels. +// Conversion will not happen inside the compiler anymore because it causes +// just too many problems. +// +//========================================================================== + +FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + ABORT(ctx.Class); + auto aclass = dyn_cast(ctx.Class); + + // This expression type can only be used from actors, for everything else it has already produced a compile error. + assert(aclass != nullptr && aclass->NumOwnedStates > 0); + + if (aclass->NumOwnedStates <= index) + { + ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d", + ctx.Class->TypeName.GetChars(), index); + delete this; + return nullptr; + } + int symlabel = StateLabels.AddPointer(aclass->OwnedStates + index); + FxExpression *x = new FxConstant(symlabel, ScriptPosition); + x->ValueType = TypeStateLabel; + delete this; + return x; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxRuntimeStateIndex::FxRuntimeStateIndex(FxExpression *index) +: FxExpression(EFX_RuntimeStateIndex, index->ScriptPosition), Index(index) +{ + ValueType = TypeStateLabel; +} + +FxRuntimeStateIndex::~FxRuntimeStateIndex() +{ + SAFE_DELETE(Index); +} + +FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Index, ctx); + + if (!Index->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + else if (Index->isConstant()) + { + int index = static_cast(Index)->GetValue().GetInt(); + if (index < 0 || (index == 0 && !ctx.FromDecorate)) + { + ScriptPosition.Message(MSG_ERROR, "State index must be positive"); + delete this; + return nullptr; + } + else if (index == 0) + { + int symlabel = StateLabels.AddPointer(nullptr); + auto x = new FxConstant(symlabel, ScriptPosition); + delete this; + x->ValueType = TypeStateLabel; + return x; + } + else + { + auto x = new FxStateByIndex(ctx.StateIndex + index, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + } + else if (Index->ValueType->GetRegType() != REGT_INT) + { // Float. + Index = new FxIntCast(Index, ctx.FromDecorate); + SAFE_RESOLVE(Index, ctx); + } + auto aclass = dyn_cast(ctx.Class); + assert(aclass != nullptr && aclass->NumOwnedStates > 0); + symlabel = StateLabels.AddPointer(aclass->OwnedStates + ctx.StateIndex); + ValueType = TypeStateLabel; + return this; +} + +ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build) +{ + ExpEmit out = Index->Emit(build); + // out = (clamp(Index, 0, 32767) << 16) | symlabel | 0x80000000; 0x80000000 is here to make it negative. + build->Emit(OP_MAX_RK, out.RegNum, out.RegNum, build->GetConstantInt(0)); + build->Emit(OP_MIN_RK, out.RegNum, out.RegNum, build->GetConstantInt(32767)); + build->Emit(OP_SLL_RI, out.RegNum, out.RegNum, 16); + build->Emit(OP_OR_RK, out.RegNum, out.RegNum, build->GetConstantInt(symlabel|0x80000000)); + return out; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPosition &pos) + :FxExpression(EFX_MultiNameState, pos) +{ + FName scopename; + FString statestring = _statestring; + int scopeindex = statestring.IndexOf("::"); + + if (scopeindex >= 0) + { + scopename = FName(statestring, scopeindex, false); + statestring = statestring.Right(statestring.Len() - scopeindex - 2); + } + else + { + scopename = NAME_None; + } + names = MakeStateNameList(statestring); + names.Insert(0, scopename); + scope = nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + ABORT(ctx.Class); + int symlabel; + + if (names[0] == NAME_None) + { + scope = nullptr; + } + else if (names[0] == NAME_Super) + { + scope = dyn_cast(ctx.Class->ParentClass); + } + else + { + scope = PClass::FindActor(names[0]); + if (scope == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Unknown class '%s' in state label", names[0].GetChars()); + delete this; + return nullptr; + } + else if (!scope->IsAncestorOf(ctx.Class)) + { + ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars()); + delete this; + return nullptr; + } + } + if (scope != nullptr) + { + FState *destination = nullptr; + // If the label is class specific we can resolve it right here + if (names[1] != NAME_None) + { + destination = scope->FindState(names.Size()-1, &names[1], false); + if (destination == nullptr) + { + ScriptPosition.Message(MSG_OPTERROR, "Unknown state jump destination"); + /* lax */ + return this; + } + } + symlabel = StateLabels.AddPointer(destination); + } + else + { + names.Delete(0); + symlabel = StateLabels.AddNames(names); + } + FxExpression *x = new FxConstant(symlabel, ScriptPosition); + x->ValueType = TypeStateLabel; + delete this; + return x; +} + +//========================================================================== +// +// declares a single local variable (no arrays) +// +//========================================================================== + +FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p) + :FxExpression(EFX_LocalVariableDeclaration, p) +{ + ValueType = type; + VarFlags = varflags; + Name = name; + RegCount = type == TypeVector2 ? 2 : type == TypeVector3 ? 3 : 1; + Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false); +} + +FxLocalVariableDeclaration::~FxLocalVariableDeclaration() +{ + SAFE_DELETE(Init); +} + +FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE_OPT(Init, ctx); + if (ctx.Block == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Variable declaration outside compound statement"); + delete this; + return nullptr; + } + ctx.Block->LocalVars.Push(this); + return this; +} + +ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) +{ + if (Init == nullptr) + { + RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); + } + else + { + ExpEmit emitval = Init->Emit(build); + + int regtype = emitval.RegType; + if (regtype < REGT_INT || regtype > REGT_TYPE) + { + ScriptPosition.Message(MSG_ERROR, "Attempted to assign a non-value"); + return ExpEmit(); + } + if (emitval.Konst) + { + auto constval = static_cast(Init); + RegNum = build->Registers[regtype].Get(1); + switch (regtype) + { + default: + case REGT_INT: + build->Emit(OP_LK, RegNum, build->GetConstantInt(constval->GetValue().GetInt())); + break; + + case REGT_FLOAT: + build->Emit(OP_LKF, RegNum, build->GetConstantFloat(constval->GetValue().GetFloat())); + break; + + case REGT_POINTER: + build->Emit(OP_LKP, RegNum, build->GetConstantAddress(constval->GetValue().GetPointer(), ATAG_GENERIC)); + break; + + case REGT_STRING: + build->Emit(OP_LKS, RegNum, build->GetConstantString(constval->GetValue().GetString())); + } + emitval.Free(build); + } + else if (Init->ExprType != EFX_LocalVariable) + { + // take over the register that got allocated while emitting the Init expression. + RegNum = emitval.RegNum; + } + else + { + ExpEmit out(build, emitval.RegType, emitval.RegCount); + build->Emit(ValueType->GetMoveOp(), out.RegNum, emitval.RegNum); + RegNum = out.RegNum; + } + } + return ExpEmit(); +} + +void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) +{ + // Release the register after the containing block gets closed + assert(RegNum != -1); + build->Registers[ValueType->GetRegType()].Return(RegNum, RegCount); +} diff --git a/src/thingdef/thingdef_exp.h b/src/scripting/codegeneration/codegen.h similarity index 60% rename from src/thingdef/thingdef_exp.h rename to src/scripting/codegeneration/codegen.h index 5fe8f252f..f1778512f 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/scripting/codegeneration/codegen.h @@ -41,6 +41,9 @@ */ #include "m_random.h" +#include "sc_man.h" +#include "s_sound.h" +#include "actor.h" #define CHECKRESOLVED() if (isresolved) return this; isresolved=true; @@ -53,25 +56,43 @@ class VMFunctionBuilder; class FxJumpStatement; +extern FMemArena FxAlloc; + //========================================================================== // // // //========================================================================== +struct FScriptPosition; +class FxLoopStatement; +class FxCompoundStatement; +class FxLocalVariableDeclaration; struct FCompileContext { - TArray Jumps; + FxLoopStatement *Loop = nullptr; + FxCompoundStatement *Block = nullptr; PPrototype *ReturnProto; - PClassActor *Class; + PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) + PClass *Class; // The type of the owning class. + bool FromDecorate; // DECORATE must silence some warnings and demote some errors. + int StateIndex; // index in actor's state table for anonymous functions, otherwise -1 (not used by DECORATE which pre-resolves state indices) + int StateCount; // amount of states an anoymous function is being used on (must be 1 for state indices to be allowed.) + int Lump; + bool Unsafe = false; + TDeletingArray FunctionArgs; - FCompileContext(PClassActor *cls = nullptr, PPrototype *ret = nullptr); + FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump); + FCompileContext(PClass *cls, bool fromdecorate); // only to be used to resolve constants! - PSymbol *FindInClass(FName identifier); + PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); + PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); PSymbol *FindGlobal(FName identifier); void HandleJumps(int token, FxExpression *handler); void CheckReturn(PPrototype *proto, FScriptPosition &pos); + bool CheckReadOnly(int flags); + FxLocalVariableDeclaration *FindLocalVariable(FName name); }; //========================================================================== @@ -153,6 +174,12 @@ struct ExpVal return regtype == REGT_INT ? double(Int) : regtype == REGT_FLOAT ? Float : 0; } + void *GetPointer() const + { + int regtype = Type->GetRegType(); + return regtype == REGT_POINTER ? pointer : nullptr; + } + const FString GetString() const { return Type == TypeString ? *(FString *)&pointer : Type == TypeName ? FString(FName(ENamedName(Int)).GetChars()) : ""; @@ -166,20 +193,96 @@ struct ExpVal FName GetName() const { + if (Type == TypeString) + { + if (((FString *)&pointer)->Len() == 0) return NAME_None; + return FName(*(FString *)&pointer); + } return Type == TypeName ? ENamedName(Int) : NAME_None; } }; struct ExpEmit { - ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false), Final(false) {} - ExpEmit(int reg, int type) : RegNum(reg), RegType(type), Konst(false), Fixed(false), Final(false) {} - ExpEmit(int reg, int type, bool konst) : RegNum(reg), RegType(type), Konst(konst), Fixed(false), Final(false) {} - ExpEmit(VMFunctionBuilder *build, int type); + ExpEmit() : RegNum(0), RegType(REGT_NIL), RegCount(1), Konst(false), Fixed(false), Final(false), Target(false) {} + ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), RegCount(1), Konst(konst), Fixed(fixed), Final(false), Target(false) {} + ExpEmit(VMFunctionBuilder *build, int type, int count = 1); void Free(VMFunctionBuilder *build); void Reuse(VMFunctionBuilder *build); - BYTE RegNum, RegType, Konst:1, Fixed:1, Final:1; + BYTE RegNum, RegType, RegCount, Konst:1, Fixed:1, Final:1, Target:1; +}; + +enum EFxType +{ + EFX_Expression, + EFX_Identifier, + EFX_MemberIdentifier, + EFX_ClassDefaults, + EFX_Constant, + EFX_BoolCast, + EFX_IntCast, + EFX_FloatCast, + EFX_NameCast, + EFX_StringCast, + EFX_ColorCast, + EFX_SoundCast, + EFX_TypeCast, + EFX_PlusSign, + EFX_MinusSign, + EFX_UnaryNotBitwise, + EFX_UnaryNotBoolean, + EFX_SizeAlign, + EFX_PreIncrDecr, + EFX_PostIncrDecr, + EFX_Assign, + EFX_AssignSelf, + EFX_Binary, // one token fits all, the operator is enough to distinguish them. + EFX_BinaryLogical, + EFX_DotCross, + EFX_Conditional, + EFX_Abs, + EFX_ATan2, + EFX_MinMax, + EFX_Random, + EFX_RandomPick, + EFX_FRandom, + EFX_Random2, + EFX_ClassMember, + EFX_StructMember, + EFX_LocalVariable, + EFX_Self, + EFX_ArrayElement, + EFX_FunctionCall, + EFX_MemberFunctionCall, + EFX_ActionSpecialCall, + EFX_FlopFunctionCall, + EFX_VMFunctionCall, + EFX_Sequence, + EFX_CompoundStatement, + EFX_IfStatement, + EFX_LoopStatement, + EFX_WhileLoop, + EFX_DoWhileLoop, + EFX_ForLoop, + EFX_JumpStatement, + EFX_ReturnStatement, + EFX_ClassTypeCast, + EFX_StateByIndex, + EFX_RuntimeStateIndex, + EFX_MultiNameState, + EFX_DamageValue, + EFX_Nop, + EFX_LocalVariableDeclaration, + EFX_SwitchStatement, + EFX_CaseStatement, + EFX_VectorValue, + EFX_VectorBuiltin, + EFX_TypeCheck, + EFX_DynamicCast, + EFX_GlobalVariable, + EFX_Super, + EFX_COUNT }; //========================================================================== @@ -191,32 +294,45 @@ struct ExpEmit class FxExpression { protected: - FxExpression(const FScriptPosition &pos) - : ScriptPosition(pos) + FxExpression(EFxType type, const FScriptPosition &pos) + : ScriptPosition(pos), ExprType(type) { - isresolved = false; - ScriptPosition = pos; - ValueType = NULL; } -public: + +public: + FxExpression *CheckIntForName(); + virtual ~FxExpression() {} virtual FxExpression *Resolve(FCompileContext &ctx); virtual bool isConstant() const; - virtual bool RequestAddress(); + virtual bool RequestAddress(FCompileContext &ctx, bool *writable); virtual PPrototype *ReturnProto(); virtual VMFunction *GetDirectFunction(); - bool IsNumeric() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } + virtual bool CheckReturn() { return false; } + bool IsNumeric() const { return ValueType->isNumeric(); } + bool IsFloat() const { return ValueType->GetRegType() == REGT_FLOAT && ValueType->GetRegCount() == 1; } + bool IsInteger() const { return ValueType->isNumeric() && (ValueType->GetRegType() == REGT_INT); } bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; } + bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; }; + bool IsBoolCompat() const { return ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT || ValueType->GetRegType() == REGT_POINTER); } virtual ExpEmit Emit(VMFunctionBuilder *build); - TArray JumpAddresses; - FScriptPosition ScriptPosition; - PType *ValueType; + PType *ValueType = nullptr; - bool isresolved; + bool isresolved = false; + bool NeedResult = true; // should be set to false if not needed and properly handled by all nodes for their subnodes to eliminate redundant code + EFxType ExprType; + + void *operator new(size_t size) + { + return FxAlloc.Alloc(size); + } + + void operator delete(void *block) {} + void operator delete[](void *block) {} }; //========================================================================== @@ -227,31 +343,32 @@ public: class FxIdentifier : public FxExpression { +public: FName Identifier; -public: FxIdentifier(FName i, const FScriptPosition &p); FxExpression *Resolve(FCompileContext&); + FxExpression *ResolveMember(FCompileContext&, PClass*, FxExpression*&, PStruct*); }; //========================================================================== // -// FxDotIdentifier +// FxMemberIdentifier // //========================================================================== -class FxDotIdentifier : public FxExpression +class FxMemberIdentifier : public FxIdentifier { - FxExpression *container; - FName Identifier; + FxExpression *Object; public: - FxDotIdentifier(FxExpression*, FName, const FScriptPosition &); - ~FxDotIdentifier(); + FxMemberIdentifier(FxExpression *obj, FName i, const FScriptPosition &p); + ~FxMemberIdentifier(); FxExpression *Resolve(FCompileContext&); }; + //========================================================================== // // FxClassDefaults @@ -261,12 +378,14 @@ public: class FxClassDefaults : public FxExpression { FxExpression *obj; + bool EmitTail; public: - FxClassDefaults(FxExpression*, const FScriptPosition &); + FxClassDefaults(FxExpression *, const FScriptPosition &); ~FxClassDefaults(); + PPrototype *ReturnProto(); FxExpression *Resolve(FCompileContext&); - bool IsDefaultObject() const; + ExpEmit Emit(VMFunctionBuilder *build); }; //========================================================================== @@ -280,69 +399,75 @@ class FxConstant : public FxExpression ExpVal value; public: - FxConstant(bool val, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(bool val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { ValueType = value.Type = TypeBool; value.Int = val; isresolved = true; } - FxConstant(int val, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(int val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { ValueType = value.Type = TypeSInt32; value.Int = val; isresolved = true; } - FxConstant(double val, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(double val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { ValueType = value.Type = TypeFloat64; value.Float = val; isresolved = true; } - FxConstant(FSoundID val, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(FSoundID val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { ValueType = value.Type = TypeSound; value.Int = val; isresolved = true; } - FxConstant(FName val, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(FName val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { ValueType = value.Type = TypeName; value.Int = val; isresolved = true; } - FxConstant(const FString &str, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(const FString &str, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { ValueType = TypeString; value = ExpVal(str); isresolved = true; } - FxConstant(ExpVal cv, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(ExpVal cv, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { value = cv; ValueType = cv.Type; isresolved = true; } - FxConstant(PClass *val, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(PClass *val, PClassPointer *valtype, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { value.pointer = (void*)val; - ValueType = val; - value.Type = NewClassPointer(RUNTIME_CLASS(AActor)); + value.Type = ValueType = valtype; isresolved = true; } - FxConstant(FState *state, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(FState *state, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { value.pointer = state; ValueType = value.Type = TypeState; isresolved = true; } + + FxConstant(const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) + { + value.pointer = nullptr; + ValueType = value.Type = TypeNullPtr; + isresolved = true; + } static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos); @@ -358,6 +483,33 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxVectorValue : public FxExpression +{ + FxExpression *xyz[3]; + bool isConst; // gets set to true if all element are const (used by function defaults parser) + +public: + + friend class ZCCCompiler; + + FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc); + ~FxVectorValue(); + FxExpression *Resolve(FCompileContext&); + bool isConstVector(int dim) + { + if (!isConst) return false; + return dim == 2 ? xyz[2] == nullptr : xyz[2] != nullptr; + } + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // @@ -368,10 +520,11 @@ public: class FxBoolCast : public FxExpression { FxExpression *basex; + bool NeedValue; public: - FxBoolCast(FxExpression *x); + FxBoolCast(FxExpression *x, bool needvalue = true); ~FxBoolCast(); FxExpression *Resolve(FCompileContext&); @@ -381,10 +534,12 @@ public: class FxIntCast : public FxExpression { FxExpression *basex; + bool NoWarn; + bool Explicit; public: - FxIntCast(FxExpression *x); + FxIntCast(FxExpression *x, bool nowarn, bool explicitly = false); ~FxIntCast(); FxExpression *Resolve(FCompileContext&); @@ -404,6 +559,79 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +class FxNameCast : public FxExpression +{ + FxExpression *basex; + +public: + + FxNameCast(FxExpression *x); + ~FxNameCast(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + +class FxStringCast : public FxExpression +{ + FxExpression *basex; + +public: + + FxStringCast(FxExpression *x); + ~FxStringCast(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + +class FxColorCast : public FxExpression +{ + FxExpression *basex; + +public: + + FxColorCast(FxExpression *x); + ~FxColorCast(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + +class FxSoundCast : public FxExpression +{ + FxExpression *basex; + +public: + + FxSoundCast(FxExpression *x); + ~FxSoundCast(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// FxTypeCast +// +//========================================================================== + +class FxTypeCast : public FxExpression +{ + FxExpression *basex; + bool NoWarn; + bool Explicit; + +public: + + FxTypeCast(FxExpression *x, PType *type, bool nowarn, bool explicitly = false); + ~FxTypeCast(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxSign @@ -472,6 +700,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxSign +// +//========================================================================== + +class FxSizeAlign : public FxExpression +{ + FxExpression *Operand; + int Which; + +public: + FxSizeAlign(FxExpression*, int which); + ~FxSizeAlign(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxPreIncrDecr @@ -489,7 +735,7 @@ public: FxPreIncrDecr(FxExpression *base, int token); ~FxPreIncrDecr(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(); + bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -521,14 +767,18 @@ class FxAssign : public FxExpression { FxExpression *Base; FxExpression *Right; + int IsBitWrite; bool AddressRequested; bool AddressWritable; + bool IsModifyAssign; + + friend class FxAssignSelf; public: - FxAssign(FxExpression *base, FxExpression *right); + FxAssign(FxExpression *base, FxExpression *right, bool ismodify = false); ~FxAssign(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(); + //bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Address; @@ -605,6 +855,21 @@ public: // //========================================================================== +class FxPow : public FxBinary +{ +public: + + FxPow(FxExpression*, FxExpression*); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// FxBinary +// +//========================================================================== + class FxCompareRel : public FxBinary { public: @@ -644,6 +909,21 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxLtGtEq : public FxBinary +{ +public: + FxLtGtEq(FxExpression*, FxExpression*); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxBinaryLogical @@ -656,9 +936,71 @@ public: int Operator; FxExpression *left; FxExpression *right; + TDeletingArray list; FxBinaryLogical(int, FxExpression*, FxExpression*); ~FxBinaryLogical(); + void Flatten(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// FxBinaryLogical +// +//========================================================================== + +class FxDotCross : public FxExpression +{ +public: + int Operator; + FxExpression *left; + FxExpression *right; + + FxDotCross(int, FxExpression*, FxExpression*); + ~FxDotCross(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// +// +//========================================================================== + +class FxTypeCheck : public FxExpression +{ +public: + FxExpression *left; + FxExpression *right; + bool EmitTail; + + FxTypeCheck(FxExpression*, FxExpression*); + ~FxTypeCheck(); + FxExpression *Resolve(FCompileContext&); + PPrototype *ReturnProto(); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// +// +//========================================================================== + +class FxDynamicCast : public FxExpression +{ + PClass *CastType; +public: + FxExpression *expr; + + FxDynamicCast(PClass*, FxExpression*); + ~FxDynamicCast(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); @@ -757,7 +1099,7 @@ protected: public: - FxRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos); + FxRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos, bool nowarn); ~FxRandom(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); @@ -778,7 +1120,7 @@ protected: public: - FxRandomPick(FRandom *, TArray &expr, bool floaty, const FScriptPosition &pos); + FxRandomPick(FRandom *, TArray &expr, bool floaty, const FScriptPosition &pos, bool nowarn); ~FxRandomPick(); FxExpression *Resolve(FCompileContext&); @@ -812,7 +1154,7 @@ class FxRandom2 : public FxExpression public: - FxRandom2(FRandom *, FxExpression *m, const FScriptPosition &pos); + FxRandom2(FRandom *, FxExpression *m, const FScriptPosition &pos, bool nowarn); ~FxRandom2(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); @@ -820,23 +1162,75 @@ public: }; +//========================================================================== +// +// FxGlobalVariaböe +// +//========================================================================== + +class FxGlobalVariable : public FxExpression +{ +public: + PField *membervar; + bool AddressRequested; + bool AddressWritable; + + FxGlobalVariable(PField*, const FScriptPosition&); + FxExpression *Resolve(FCompileContext&); + bool RequestAddress(FCompileContext &ctx, bool *writable); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxClassMember // //========================================================================== -class FxClassMember : public FxExpression +class FxStructMember : public FxExpression { public: FxExpression *classx; PField *membervar; bool AddressRequested; + bool AddressWritable; + + FxStructMember(FxExpression*, PField*, const FScriptPosition&); + ~FxStructMember(); + FxExpression *Resolve(FCompileContext&); + bool RequestAddress(FCompileContext &ctx, bool *writable); + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// FxClassMember +// +//========================================================================== + +class FxClassMember : public FxStructMember +{ +public: FxClassMember(FxExpression*, PField*, const FScriptPosition&); - ~FxClassMember(); +}; + +//========================================================================== +// +// FxLocalVariable +// +//========================================================================== + +class FxLocalVariable : public FxExpression +{ +public: + FxLocalVariableDeclaration *Variable; + bool AddressRequested; + int RegOffset; + + FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(); + bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -848,12 +1242,31 @@ public: class FxSelf : public FxExpression { + bool check; + public: - FxSelf(const FScriptPosition&); + FxSelf(const FScriptPosition&, bool deccheck = false); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxSuper +// +//========================================================================== + +class FxSuper : public FxSelf +{ +public: + FxSuper(const FScriptPosition&pos) + : FxSelf(pos) + { + ExprType = EFX_Super; + } + FxExpression *Resolve(FCompileContext&); +}; + //========================================================================== // // FxArrayElement @@ -871,7 +1284,7 @@ public: FxArrayElement(FxExpression*, FxExpression*); ~FxArrayElement(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(); + bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -886,18 +1299,38 @@ typedef TDeletingArray FArgumentList; class FxFunctionCall : public FxExpression { - FxExpression *Self; FName MethodName; - FArgumentList *ArgList; + FRandom *RNG; + FArgumentList ArgList; public: - FxFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos); + FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos); ~FxFunctionCall(); FxExpression *Resolve(FCompileContext&); }; +//========================================================================== +// +// FxFunctionCall +// +//========================================================================== + +class FxMemberFunctionCall : public FxExpression +{ + FxExpression *Self; + FName MethodName; + FArgumentList ArgList; + +public: + + FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &args, const FScriptPosition &pos); + ~FxMemberFunctionCall(); + FxExpression *Resolve(FCompileContext&); +}; + + //========================================================================== // // FxActionSpecialCall @@ -909,11 +1342,11 @@ class FxActionSpecialCall : public FxExpression int Special; bool EmitTail; FxExpression *Self; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxActionSpecialCall(FxExpression *self, int special, FArgumentList *args, const FScriptPosition &pos); + FxActionSpecialCall(FxExpression *self, int special, FArgumentList &args, const FScriptPosition &pos); ~FxActionSpecialCall(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); @@ -929,16 +1362,35 @@ public: class FxFlopFunctionCall : public FxExpression { int Index; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxFlopFunctionCall(size_t index, FArgumentList *args, const FScriptPosition &pos); + FxFlopFunctionCall(size_t index, FArgumentList &args, const FScriptPosition &pos); ~FxFlopFunctionCall(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxFlopFunctionCall +// +//========================================================================== + +class FxVectorBuiltin : public FxExpression +{ + FName Function; + FxExpression *Self; + +public: + + FxVectorBuiltin(FxExpression *self, FName name); + ~FxVectorBuiltin(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxVMFunctionCall @@ -948,11 +1400,13 @@ public: class FxVMFunctionCall : public FxExpression { bool EmitTail; + bool NoVirtual; + FxExpression *Self; PFunction *Function; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos); + FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual); ~FxVMFunctionCall(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); @@ -963,20 +1417,90 @@ public: //========================================================================== // -// FxSequence +// FxSequence (a list of statements with no semantics attached - used to return multiple nodes as one) // //========================================================================== +class FxLocalVariableDeclaration; class FxSequence : public FxExpression { TDeletingArray Expressions; public: - FxSequence(const FScriptPosition &pos) : FxExpression(pos) {} + FxSequence(const FScriptPosition &pos) : FxExpression(EFX_Sequence, pos) {} FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); - void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); } + void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); expr->NeedResult = false; } VMFunction *GetDirectFunction(); + bool CheckReturn(); +}; + +//========================================================================== +// +// FxCompoundStatement (like a list but implements maintenance of local variables) +// +//========================================================================== +class FxLocalVariableDeclaration; + +class FxCompoundStatement : public FxSequence +{ + TArray LocalVars; + FxCompoundStatement *Outer = nullptr; + + friend class FxLocalVariableDeclaration; + +public: + FxCompoundStatement(const FScriptPosition &pos) : FxSequence(pos) {} + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); + FxLocalVariableDeclaration *FindLocalVariable(FName name, FCompileContext &ctx); + bool CheckLocalVariable(FName name); +}; + +//========================================================================== +// +// FxSwitchStatement +// +//========================================================================== + +class FxSwitchStatement : public FxExpression +{ + FxExpression *Condition; + FArgumentList Content; + + struct CaseAddr + { + int casevalue; + size_t jumpaddress; + }; + + TArray CaseAddresses; + +public: + FxSwitchStatement(FxExpression *cond, FArgumentList &content, const FScriptPosition &pos); + ~FxSwitchStatement(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); + bool CheckReturn(); +}; + +//========================================================================== +// +// FxSwitchStatement +// +//========================================================================== + +class FxCaseStatement : public FxExpression +{ + FxExpression *Condition; + int CaseValue; // copy the value to here for easier access. + + friend class FxSwitchStatement; + +public: + FxCaseStatement(FxExpression *cond, const FScriptPosition &pos); + ~FxCaseStatement(); + FxExpression *Resolve(FCompileContext&); }; //========================================================================== @@ -996,6 +1520,29 @@ public: ~FxIfStatement(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); + bool CheckReturn(); +}; + +//========================================================================== +// +// Base class for loops +// +//========================================================================== + +class FxLoopStatement : public FxExpression +{ +protected: + FxLoopStatement(EFxType etype, const FScriptPosition &pos) + : FxExpression(etype, pos) + { + } + + void Backpatch(VMFunctionBuilder *build, size_t loopstart, size_t loopend); + FxExpression *Resolve(FCompileContext&) final; + virtual FxExpression *DoResolve(FCompileContext&) = 0; + +public: + TArray Jumps; }; //========================================================================== @@ -1004,7 +1551,7 @@ public: // //========================================================================== -class FxWhileLoop : public FxExpression +class FxWhileLoop : public FxLoopStatement { FxExpression *Condition; FxExpression *Code; @@ -1012,7 +1559,7 @@ class FxWhileLoop : public FxExpression public: FxWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos); ~FxWhileLoop(); - FxExpression *Resolve(FCompileContext&); + FxExpression *DoResolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1022,7 +1569,7 @@ public: // //========================================================================== -class FxDoWhileLoop : public FxExpression +class FxDoWhileLoop : public FxLoopStatement { FxExpression *Condition; FxExpression *Code; @@ -1030,7 +1577,7 @@ class FxDoWhileLoop : public FxExpression public: FxDoWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos); ~FxDoWhileLoop(); - FxExpression *Resolve(FCompileContext&); + FxExpression *DoResolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1040,7 +1587,7 @@ public: // //========================================================================== -class FxForLoop : public FxExpression +class FxForLoop : public FxLoopStatement { FxExpression *Init; FxExpression *Condition; @@ -1050,7 +1597,7 @@ class FxForLoop : public FxExpression public: FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos); ~FxForLoop(); - FxExpression *Resolve(FCompileContext&); + FxExpression *DoResolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1069,7 +1616,6 @@ public: int Token; size_t Address; - FxExpression *AddressResolver; }; //========================================================================== @@ -1088,6 +1634,7 @@ public: FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); VMFunction *GetDirectFunction(); + bool CheckReturn() { return true; } }; //========================================================================== @@ -1103,7 +1650,7 @@ class FxClassTypeCast : public FxExpression public: - FxClassTypeCast(PClass *dtype, FxExpression *x); + FxClassTypeCast(PClassPointer *dtype, FxExpression *x); ~FxClassTypeCast(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); @@ -1121,7 +1668,7 @@ class FxStateByIndex : public FxExpression public: - FxStateByIndex(int i, const FScriptPosition &pos) : FxExpression(pos) + FxStateByIndex(int i, const FScriptPosition &pos) : FxExpression(EFX_StateByIndex, pos) { index = i; } @@ -1137,14 +1684,13 @@ public: class FxRuntimeStateIndex : public FxExpression { - bool EmitTail; FxExpression *Index; + int symlabel; public: FxRuntimeStateIndex(FxExpression *index); ~FxRuntimeStateIndex(); FxExpression *Resolve(FCompileContext&); - PPrototype *ReturnProto(); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1162,29 +1708,6 @@ public: FxMultiNameState(const char *statestring, const FScriptPosition &pos); FxExpression *Resolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build); -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FxDamageValue : public FxExpression -{ - FxExpression *val; - VMScriptFunction *MyFunction; - -public: - - FxDamageValue(FxExpression *v); - ~FxDamageValue(); - FxExpression *Resolve(FCompileContext&); - - ExpEmit Emit(VMFunctionBuilder *build); - VMScriptFunction *GetFunction() const { return MyFunction; } - void SetFunction(VMScriptFunction *func) { MyFunction = func; } }; //========================================================================== @@ -1197,7 +1720,7 @@ class FxNop : public FxExpression { public: FxNop(const FScriptPosition &p) - : FxExpression(p) + : FxExpression(EFX_Nop, p) { isresolved = true; } @@ -1207,7 +1730,30 @@ public: } }; -FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve = false); +//========================================================================== +// +// +// +//========================================================================== +class FxLocalVariableDeclaration : public FxExpression +{ + friend class FxCompoundStatement; + friend class FxLocalVariable; + + FName Name; + FxExpression *Init; + int VarFlags; + int RegCount; +public: + int RegNum = -1; + + FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); + ~FxLocalVariableDeclaration(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); + void Release(VMFunctionBuilder *build); + +}; #endif diff --git a/src/thingdef/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp similarity index 95% rename from src/thingdef/olddecorations.cpp rename to src/scripting/decorate/olddecorations.cpp index 9afbfc965..a4cf20de4 100644 --- a/src/thingdef/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -48,7 +48,7 @@ #include "decallib.h" #include "i_system.h" #include "thingdef.h" -#include "thingdef_exp.h" +#include "codegeneration/codegen.h" #include "r_data/r_translate.h" // TYPES ------------------------------------------------------------------- @@ -95,15 +95,16 @@ public: // The special was already executed by TryPickup, so do nothing here } }; -IMPLEMENT_CLASS (AFakeInventory) + +IMPLEMENT_CLASS(AFakeInventory, false, false, false, false) // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void ParseInsideDecoration (Baggage &bag, AActor *defaults, - FExtraInfo &extra, EDefinitionType def, FScanner &sc, TArray &StateArray); -static void ParseSpriteFrames (PClassActor *info, TArray &states, FScanner &sc); + FExtraInfo &extra, EDefinitionType def, FScanner &sc, TArray &StateArray, TArray &SourceLines); +static void ParseSpriteFrames (PClassActor *info, TArray &states, TArray &SourceLines, FScanner &sc); // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -146,6 +147,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) { Baggage bag; TArray StateArray; + TArray SourceLines; FExtraInfo extra; PClassActor *type; PClassActor *parent; @@ -158,6 +160,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) type = DecoDerivedClass(FScriptPosition(sc), parent, typeName); ResetBaggage(&bag, parent); bag.Info = type; + bag.fromDecorate = true; #ifdef _DEBUG bag.ClassName = type->TypeName; #endif @@ -166,7 +169,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) sc.MustGetStringName("{"); memset (&extra, 0, sizeof(extra)); - ParseInsideDecoration (bag, (AActor *)(type->Defaults), extra, def, sc, StateArray); + ParseInsideDecoration (bag, (AActor *)(type->Defaults), extra, def, sc, StateArray, SourceLines); bag.Info->NumOwnedStates = StateArray.Size(); if (bag.Info->NumOwnedStates == 0) @@ -190,11 +193,14 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) { // Make a copy of the final frozen frame for A_FreezeDeathChunks FState icecopy = StateArray[extra.IceDeathEnd-1]; + FScriptPosition icepos = SourceLines[extra.IceDeathEnd - 1]; StateArray.Push (icecopy); + SourceLines.Push(icepos); type->NumOwnedStates += 1; } type->OwnedStates = new FState[type->NumOwnedStates]; + SaveStateSourceLines(type->OwnedStates, SourceLines); memcpy (type->OwnedStates, &StateArray[0], type->NumOwnedStates * sizeof(type->OwnedStates[0])); if (type->NumOwnedStates == 1) { @@ -351,7 +357,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) //========================================================================== static void ParseInsideDecoration (Baggage &bag, AActor *defaults, - FExtraInfo &extra, EDefinitionType def, FScanner &sc, TArray &StateArray) + FExtraInfo &extra, EDefinitionType def, FScanner &sc, TArray &StateArray, TArray &SourceLines) { AFakeInventory *const inv = static_cast(defaults); char sprite[5] = "TNT1"; @@ -401,7 +407,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, { sc.MustGetString (); extra.SpawnStart = StateArray.Size(); - ParseSpriteFrames (bag.Info, StateArray, sc); + ParseSpriteFrames (bag.Info, StateArray, SourceLines, sc); extra.SpawnEnd = StateArray.Size(); } else if ((def == DEF_BreakableDecoration || def == DEF_Projectile) && @@ -409,21 +415,21 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, { sc.MustGetString (); extra.DeathStart = StateArray.Size(); - ParseSpriteFrames (bag.Info, StateArray, sc); + ParseSpriteFrames (bag.Info, StateArray, SourceLines, sc); extra.DeathEnd = StateArray.Size(); } else if (def == DEF_BreakableDecoration && sc.Compare ("IceDeathFrames")) { sc.MustGetString (); extra.IceDeathStart = StateArray.Size(); - ParseSpriteFrames (bag.Info, StateArray, sc); + ParseSpriteFrames (bag.Info, StateArray, SourceLines, sc); extra.IceDeathEnd = StateArray.Size(); } else if (def == DEF_BreakableDecoration && sc.Compare ("BurnDeathFrames")) { sc.MustGetString (); extra.FireDeathStart = StateArray.Size(); - ParseSpriteFrames (bag.Info, StateArray, sc); + ParseSpriteFrames (bag.Info, StateArray, SourceLines, sc); extra.FireDeathEnd = StateArray.Size(); } else if (def == DEF_BreakableDecoration && sc.Compare ("GenericIceDeath")) @@ -648,12 +654,13 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, // "10:A, 15:B, 8:C, 6:B" //========================================================================== -static void ParseSpriteFrames (PClassActor *info, TArray &states, FScanner &sc) +static void ParseSpriteFrames (PClassActor *info, TArray &states, TArray &SourceLines, FScanner &sc) { FState state; char *token = strtok (sc.String, ",\t\n\r"); memset (&state, 0, sizeof(state)); + state.UseFlags = info->DefaultStateUsage; while (token != NULL) { @@ -703,6 +710,7 @@ static void ParseSpriteFrames (PClassActor *info, TArray &states, FScann if (!firstState) { states.Push (state); + SourceLines.Push(sc); } firstState = false; state.Frame = *token-'A'; @@ -712,6 +720,7 @@ static void ParseSpriteFrames (PClassActor *info, TArray &states, FScann if (!firstState) { states.Push (state); + SourceLines.Push(sc); } token = strtok (NULL, ",\t\n\r"); diff --git a/src/thingdef/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp similarity index 94% rename from src/thingdef/thingdef_exp.cpp rename to src/scripting/decorate/thingdef_exp.cpp index cad6198f0..229c8f1f4 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -48,7 +48,7 @@ #include "thingdef.h" #include "p_lnspec.h" #include "doomstat.h" -#include "thingdef_exp.h" +#include "codegeneration/codegen.h" FRandom pr_exrandom ("EX_Random"); @@ -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); } @@ -170,7 +170,7 @@ static FxExpression *ParseExpressionM (FScanner &sc, PClassActor *cls) exp->right = ParseExpressionM(sc, cls); - FxAssign *ret = new FxAssign(base, exp); + FxAssign *ret = new FxAssign(base, exp, true); left->Assignment = ret; return ret; } @@ -448,7 +448,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) sc.MustGetToken('('); FxExpression *exp = ParseExpressionM(sc, cls); sc.MustGetToken(')'); - return new FxIntCast(exp); + return new FxIntCast(exp, true); } else if (sc.CheckToken(TK_Float)) { @@ -476,13 +476,16 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) { exp = new FxRuntimeStateIndex(ParseExpressionM(sc, cls)); } + // The parsed expression is of type 'statelabel', but we want a real state here so we must convert it. + FArgumentList args; + args.Push(exp); + exp = new FxFunctionCall(NAME_ResolveState, NAME_None, args, sc); sc.MustGetToken(')'); return exp; } else if (sc.CheckToken(TK_Identifier)) { FName identifier = FName(sc.String); - FArgumentList *args; PFunction *func; switch (identifier) @@ -503,19 +506,13 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) // There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work. if (func != nullptr && identifier != NAME_ACS_NamedExecuteWithResult) { - args = new FArgumentList; + FArgumentList args; if (sc.CheckToken('(')) { sc.UnGet(); - ParseFunctionParameters(sc, cls, *args, func, "", nullptr); + ParseFunctionParameters(sc, cls, args, func, "", nullptr); } - if (args->Size() == 0) - { - delete args; - args = nullptr; - } - - return new FxVMFunctionCall(func, args, sc); + return new FxVMFunctionCall(new FxSelf(sc), func, args, sc, false); } } @@ -536,26 +533,17 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) case NAME_VectorAngle: return ParseAtan2(sc, identifier, cls); default: - args = new FArgumentList; - try + FArgumentList args; + if (!sc.CheckToken(')')) { - if (!sc.CheckToken(')')) + do { - do - { - args->Push(ParseExpressionM (sc, cls)); - } - while (sc.CheckToken(',')); - sc.MustGetToken(')'); + args.Push(ParseExpressionM (sc, cls)); } - return new FxFunctionCall(NULL, identifier, args, sc); + while (sc.CheckToken(',')); + sc.MustGetToken(')'); } - catch (...) - { - delete args; - throw; - } - break; + return new FxFunctionCall(identifier, NAME_None, args, sc); } } else @@ -600,7 +588,7 @@ static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cl if (identifier == NAME_Random) { - return new FxRandom(rng, min, max, sc); + return new FxRandom(rng, min, max, sc, true); } else { @@ -627,7 +615,7 @@ static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor break; sc.MustGetToken(','); } - return new FxRandomPick(rng, list, floaty, sc); + return new FxRandomPick(rng, list, floaty, sc, true); } static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls) @@ -642,7 +630,7 @@ static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls) mask = ParseExpressionM(sc, cls); sc.MustGetToken(')'); } - return new FxRandom2(rng, mask, sc); + return new FxRandom2(rng, mask, sc, true); } static FxExpression *ParseAbs(FScanner &sc, PClassActor *cls) diff --git a/src/thingdef/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp similarity index 78% rename from src/thingdef/thingdef_parse.cpp rename to src/scripting/decorate/thingdef_parse.cpp index 963165ab1..490d9cf79 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -49,7 +49,7 @@ #include "v_palette.h" #include "doomerrors.h" #include "i_system.h" -#include "thingdef_exp.h" +#include "codegeneration/codegen.h" #include "w_wad.h" #include "v_video.h" #include "version.h" @@ -57,6 +57,45 @@ #include "m_argv.h" void ParseOldDecoration(FScanner &sc, EDefinitionType def); +EXTERN_CVAR(Bool, strictdecorate); + + +//========================================================================== +// +// DecoDerivedClass +// +// Create a derived class and performs some additional sanity checks +// +//========================================================================== + +PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName) +{ + PClassActor *type = static_cast(parent->CreateDerivedClass(typeName, parent->Size)); + if (type == nullptr) + { + FString newname = typeName.GetChars(); + FString sourcefile = sc.FileName; + + sourcefile.Substitute(":", "@"); + newname << '@' << sourcefile; + if (strictdecorate) + { + sc.Message(MSG_ERROR, "Tried to define class '%s' more than once.", typeName.GetChars()); + } + else + { + // Due to backwards compatibility issues this cannot be an unconditional error. + sc.Message(MSG_WARNING, "Tried to define class '%s' more than once. Renaming class to '%s'", typeName.GetChars(), newname.GetChars()); + } + type = static_cast(parent->CreateDerivedClass(newname, parent->Size)); + if (type == nullptr) + { + // This we cannot handle cleanly anymore. Let's just abort and forget about the odd mod out that was this careless. + sc.Message(MSG_FATAL, "Tried to define class '%s' more than twice in the same file.", typeName.GetChars()); + } + } + return type; +} //========================================================================== // @@ -92,7 +131,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c } else if (type == TypeSInt32) { - x = new FxIntCast(x); + x = new FxIntCast(x, true); } else { @@ -135,22 +174,19 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c val.Int = v; x = new FxConstant(val, sc); } - else if (type == TypeState) + else if (type == TypeStateLabel) { // This forces quotation marks around the state name. if (sc.CheckToken(TK_StringConst)) { if (sc.String[0] == 0 || sc.Compare("None")) { - x = new FxConstant((FState*)NULL, sc); + x = new FxConstant(0, sc); + x->ValueType = TypeStateLabel; } else if (sc.Compare("*")) { - if (constant) - { - x = new FxConstant((FState*)(intptr_t)-1, sc); - } - else sc.ScriptError("Invalid state name '*'"); + sc.ScriptError("Invalid state name '*'"); } else { @@ -168,7 +204,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); - x = new FxClassTypeCast(static_cast(type)->ClassRestriction, new FxConstant(FName(sc.String), sc)); + x = new FxClassTypeCast(static_cast(type), new FxConstant(FName(sc.String), sc)); } else { @@ -295,248 +331,6 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls) sc.MustGetToken(';'); } -//========================================================================== -// -// ParseArgListDef -// -// Parses the argument list from a function declaration. -// -//========================================================================== - -static void ParseArgListDef(FScanner &sc, PClassActor *cls, - TArray &args, TArray &argflags) -{ - if (!sc.CheckToken(')')) - { - while (sc.TokenType != ')') - { - int flags = 0; - PType *type = NULL; - PClass *restrict = NULL; - - // Retrieve flags before type name - for (;;) - { - if (sc.CheckToken(TK_Coerce) || sc.CheckToken(TK_Native)) - { - } - else - { - break; - } - } - // Read the variable type - sc.MustGetAnyToken(); - switch (sc.TokenType) - { - case TK_Bool: - type = TypeBool; - break; - - case TK_Int: - type = TypeSInt32; - break; - - case TK_Float: - type = TypeFloat64; - break; - - case TK_Sound: type = TypeSound; break; - case TK_String: type = TypeString; break; - case TK_Name: type = TypeName; break; - case TK_State: type = TypeState; break; - case TK_Color: type = TypeColor; break; - case TK_Class: - sc.MustGetToken('<'); - sc.MustGetToken(TK_Identifier); // Get class name - restrict = PClass::FindClass(sc.String); - if (restrict == NULL) - { - sc.ScriptMessage("Unknown class type %s", sc.String); - FScriptPosition::ErrorCounter++; - } - else - { - type = NewClassPointer(restrict); - } - sc.MustGetToken('>'); - break; - case TK_Ellipsis: - // Making the final type NULL signals a varargs function. - type = NULL; - sc.MustGetToken(')'); - sc.UnGet(); - break; - default: - sc.ScriptMessage ("Unknown variable type %s", sc.TokenName(sc.TokenType, sc.String).GetChars()); - type = TypeSInt32; - FScriptPosition::ErrorCounter++; - break; - } - // Read the optional variable name - if (!sc.CheckToken(',') && !sc.CheckToken(')')) - { - sc.MustGetToken(TK_Identifier); - } - else - { - sc.UnGet(); - } - - if (sc.CheckToken('=')) - { - flags |= VARF_Optional; - FxExpression *def = ParseParameter(sc, cls, type, true); - delete def; - } - - args.Push(type); - argflags.Push(flags); - sc.MustGetAnyToken(); - if (sc.TokenType != ',' && sc.TokenType != ')') - { - sc.ScriptError ("Expected ',' or ')' but got %s instead", sc.TokenName(sc.TokenType, sc.String).GetChars()); - } - } - } - sc.MustGetToken(';'); -} - -//========================================================================== -// -// SetImplicitArgs -// -// Adds the parameters implied by the function flags. -// -//========================================================================== - -void SetImplicitArgs(TArray *args, TArray *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 -// -// Parses a native function's parameters and adds it to the class, -// if possible. -// -//========================================================================== - -void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname, - TArray &rets, DWORD funcflags) -{ - assert(cls != NULL); - - const AFuncDesc *afd; - TArray args; - TArray argflags; - - afd = FindFunction(funcname); - if (afd == NULL) - { - sc.ScriptMessage ("The function '%s' has not been exported from the executable.", funcname.GetChars()); - FScriptPosition::ErrorCounter++; - } - sc.MustGetToken('('); - - SetImplicitArgs(&args, &argflags, cls, funcflags); - ParseArgListDef(sc, cls, args, argflags); - - if (afd != NULL) - { - PFunction *sym = new PFunction(funcname); - sym->AddVariant(NewPrototype(rets, args), argflags, *(afd->VMPointer)); - sym->Flags = funcflags; - if (cls->Symbols.AddSymbol(sym) == NULL) - { - delete sym; - sc.ScriptMessage ("'%s' is already defined in class '%s'.", - funcname.GetChars(), cls->TypeName.GetChars()); - FScriptPosition::ErrorCounter++; - } - } -} - -//========================================================================== -// -// ParseNativeFunction -// -// Parses a non-action function declaration. -// -//========================================================================== - -static void ParseNativeFunction(FScanner &sc, PClassActor *cls) -{ - TArray rets(1); - - if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0) - { - sc.ScriptMessage ("functions can only be declared by native actors!"); - FScriptPosition::ErrorCounter++; - } - - // Read the type and make sure it's acceptable. - sc.MustGetAnyToken(); - switch (sc.TokenType) - { - case TK_Bool: - rets.Push(TypeBool); - break; - - case TK_Int: - rets.Push(TypeSInt32); - break; - - case TK_Float: - rets.Push(TypeFloat64); - break; - - case TK_State: - rets.Push(TypeState); - break; - - case TK_Void: - break; - - case TK_Identifier: - rets.Push(NewPointer(RUNTIME_CLASS(DObject))); - // Todo: Object type - sc.ScriptError("Object type variables not implemented yet!"); - break; - - default: - sc.ScriptError("Invalid return type %s", sc.String); - return; - } - sc.MustGetToken(TK_Identifier); - ParseFunctionDef(sc, cls, sc.String, rets, VARF_Method); -} - //========================================================================== // // ParseUserVariable @@ -867,7 +661,7 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau { conv.i = -1; params.Push(conv); - x = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info))); + x = ParseExpression(sc, bag.Info); sc.MustGetStringName(")"); conv.exp = x; params.Push(conv); @@ -1063,7 +857,7 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) } else { - sc.ScriptMessage("\"%s\" requires an actor of type \"%s\"\n", propname.GetChars(), (*prop->cls)->TypeName.GetChars()); + sc.ScriptMessage("'%s' requires an actor of type '%s'\n", propname.GetChars(), (*prop->cls)->TypeName.GetChars()); FScriptPosition::ErrorCounter++; } } @@ -1073,57 +867,54 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) } else { - sc.ScriptError("\"%s\" is an unknown actor property\n", propname.GetChars()); + sc.ScriptError("'%s' is an unknown actor property\n", propname.GetChars()); } } //========================================================================== // -// ActorActionDef -// -// Parses an action function definition. A lot of this is essentially -// documentation in the declaration for when I have a proper language -// ready. +// Starts a new actor definition // //========================================================================== - -static void ParseActionDef (FScanner &sc, PClassActor *cls) +PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName) { - unsigned int error = 0; - FName funcname; - TArray rets; - - if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0) - { - sc.ScriptMessage ("Action functions can only be imported by internal class and actor definitions!"); - FScriptPosition::ErrorCounter++; - } + PClassActor *replacee = NULL; + PClassActor *ti = NULL; - sc.MustGetToken(TK_Native); - // check for a return value - do + PClassActor *parent = RUNTIME_CLASS(AActor); + + if (parentName != NAME_None) { - if (sc.CheckToken(TK_Bool)) + parent = PClass::FindActor(parentName); + + PClassActor *p = parent; + while (p != NULL) { - rets.Push(TypeBool); + if (p->TypeName == typeName) + { + sc.Message(MSG_ERROR, "'%s' inherits from a class with the same name", typeName.GetChars()); + break; + } + p = dyn_cast(p->ParentClass); } - else if (sc.CheckToken(TK_Int)) + + if (parent == NULL) { - rets.Push(TypeSInt32); + sc.Message(MSG_ERROR, "Parent type '%s' not found in %s", parentName.GetChars(), typeName.GetChars()); + parent = RUNTIME_CLASS(AActor); } - else if (sc.CheckToken(TK_State)) + else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor))) { - rets.Push(TypeState); - } - else if (sc.CheckToken(TK_Float)) - { - rets.Push(TypeFloat64); + sc.Message(MSG_ERROR, "Parent type '%s' is not an actor in %s", parentName.GetChars(), typeName.GetChars()); + parent = RUNTIME_CLASS(AActor); } } - while (sc.CheckToken(',')); - sc.MustGetToken(TK_Identifier); - funcname = sc.String; - ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action); + ti = DecoDerivedClass(sc, parent, typeName); + ti->bDecorateClass = true; // we only set this for 'modern' DECORATE. The original stuff is so limited that it cannot do anything that may require flagging. + + ti->Replacee = ti->Replacement = NULL; + ti->DoomEdNum = -1; + return ti; } //========================================================================== @@ -1207,16 +998,20 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag) if (sc.CheckString("native")) { - native = true; + sc.ScriptMessage("Cannot define native classes in DECORATE"); + FScriptPosition::ErrorCounter++; } try { - PClassActor *info = CreateNewActor(sc, typeName, parentName, native); + PClassActor *info = CreateNewActor(sc, typeName, parentName); info->DoomEdNum = DoomEdNum > 0 ? DoomEdNum : -1; info->SourceLumpName = Wads.GetLumpFullPath(sc.LumpNum); - SetReplacement(sc, info, replaceName); + if (!info->SetReplacement(replaceName)) + { + sc.ScriptMessage("Replaced type '%s' not found for %s", replaceName.GetChars(), info->TypeName.GetChars()); + } ResetBaggage (bag, info == RUNTIME_CLASS(AActor) ? NULL : static_cast(info->ParentClass)); bag->Info = info; @@ -1243,16 +1038,13 @@ static void ParseActor(FScanner &sc) PClassActor *info = NULL; Baggage bag; + bag.fromDecorate = true; info = ParseActorHeader(sc, &bag); sc.MustGetToken('{'); while (sc.MustGetAnyToken(), sc.TokenType != '}') { switch (sc.TokenType) { - case TK_Action: - ParseActionDef (sc, info); - break; - case TK_Const: ParseConstant (sc, &info->Symbols, info); break; @@ -1261,10 +1053,6 @@ static void ParseActor(FScanner &sc) ParseEnum (sc, &info->Symbols, info); break; - case TK_Native: - ParseNativeFunction (sc, info); - break; - case TK_Var: ParseUserVariable (sc, &info->Symbols, info); break; @@ -1274,11 +1062,6 @@ static void ParseActor(FScanner &sc) break; case TK_States: - if (bag.StateSet) - { - sc.ScriptMessage("'%s' contains multiple state declarations", bag.Info->TypeName.GetChars()); - FScriptPosition::ErrorCounter++; - } ParseStates(sc, bag.Info, (AActor *)bag.Info->Defaults, bag); bag.StateSet = true; break; @@ -1293,7 +1076,18 @@ static void ParseActor(FScanner &sc) break; } } - FinishActor(sc, info, bag); + if (bag.DropItemSet) + { + bag.Info->SetDropItems(bag.DropItemList); + } + try + { + info->Finalize(bag.statedef); + } + catch (CRecoverableError &err) + { + sc.ScriptError("%s", err.GetMessage()); + } sc.SetCMode (false); } @@ -1432,3 +1226,14 @@ void ParseDecorate (FScanner &sc) } } } + +void ParseAllDecorate() +{ + int lastlump = 0, lump; + + while ((lump = Wads.FindLump("DECORATE", &lastlump)) != -1) + { + FScanner sc(lump); + ParseDecorate(sc); + } +} \ No newline at end of file diff --git a/src/thingdef/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp similarity index 87% rename from src/thingdef/thingdef_states.cpp rename to src/scripting/decorate/thingdef_states.cpp index 707de3045..cad542d1b 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -38,7 +38,7 @@ ** */ -#include "actor.h" +#include "a_pickups.h" #include "info.h" #include "sc_man.h" #include "tarray.h" @@ -54,11 +54,10 @@ #include "s_sound.h" #include "i_system.h" #include "colormatcher.h" -#include "thingdef_exp.h" +#include "codegeneration/codegen.h" #include "version.h" #include "templates.h" - -TDeletingArray StateTempCalls; +#include "vmbuilder.h" //========================================================================== //*** @@ -76,8 +75,8 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) if (special > 0 && min_args >= 0) { - FArgumentList *args = new FArgumentList; - args->Push(new FxConstant(special, sc)); + FArgumentList args; + args.Push(new FxConstant(special, sc)); i = 0; // Make this consistent with all other parameter parsing @@ -85,7 +84,7 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) { while (i < 5) { - args->Push(new FxIntCast(ParseExpression(sc, bag.Info))); + args.Push(new FxIntCast(ParseExpression(sc, bag.Info), true)); i++; if (!sc.CheckToken (',')) break; } @@ -100,7 +99,9 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) { sc.ScriptError ("Too many arguments to %s", specname.GetChars()); } - return new FxVMFunctionCall(FindGlobalActionFunction("A_CallSpecial"), args, sc); + auto f = dyn_cast(RUNTIME_CLASS(AActor)->Symbols.FindSymbol("A_CallSpecial", false)); + assert(f != nullptr); + return new FxVMFunctionCall(new FxSelf(sc), f, args, sc, false); } return NULL; } @@ -141,14 +142,33 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage & FString statestring; FState state; char lastsprite[5] = ""; - FStateTempCall *tcall = NULL; - FArgumentList *args = NULL; + FxExpression *ScriptCode; + FArgumentList *args = nullptr; + int flagdef = actor->DefaultStateUsage; + FScriptPosition scp; + + if (sc.CheckString("(")) + { + flagdef = 0; + do + { + sc.MustGetString(); + if (sc.Compare("Actor")) flagdef |= SUF_ACTOR; + else if (sc.Compare("Overlay")) flagdef |= SUF_OVERLAY; + else if (sc.Compare("Weapon")) flagdef |= SUF_WEAPON; + else if (sc.Compare("Item")) flagdef |= SUF_ITEM; + else sc.ScriptError("Unknown state block qualifier %s", sc.String); + } while (sc.CheckString(",")); + sc.MustGetStringName(")"); + } sc.MustGetStringName ("{"); sc.SetEscape(false); // disable escape sequences in the state parser while (!sc.CheckString ("}") && !sc.End) { + ScriptCode = nullptr; memset(&state,0,sizeof(state)); + state.UseFlags = (uint8_t)flagdef; statestring = ParseStateString(sc); if (!statestring.CompareNoCase("GOTO")) { @@ -219,15 +239,12 @@ do_stop: sc.ScriptError ("Sprite names must be exactly 4 characters\n"); } + scp = sc; state.sprite = GetSpriteIndex(statestring); state.Misc1 = state.Misc2 = 0; sc.MustGetString(); statestring = sc.String; - if (tcall == NULL) - { - tcall = new FStateTempCall; - } if (sc.CheckString("RANDOM")) { int min, max; @@ -315,35 +332,28 @@ do_stop: } bool hasfinalret; - tcall->Code = ParseActions(sc, state, statestring, bag, hasfinalret); - if (!hasfinalret && tcall->Code != nullptr) + ScriptCode = ParseActions(sc, state, statestring, bag, hasfinalret); + if (!hasfinalret && ScriptCode != nullptr) { - static_cast(tcall->Code)->Add(new FxReturnStatement(nullptr, sc)); + static_cast(ScriptCode)->Add(new FxReturnStatement(nullptr, sc)); } goto endofstate; } sc.UnGet(); endofstate: - int count = bag.statedef.AddStates(&state, statestring); + if (ScriptCode != nullptr) + { + auto funcsym = CreateAnonymousFunction(actor, nullptr, state.UseFlags); + state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true); + } + int count = bag.statedef.AddStates(&state, statestring, scp); if (count < 0) { - sc.ScriptError ("Invalid frame character string '%s'", statestring.GetChars()); + sc.ScriptError("Invalid frame character string '%s'", statestring.GetChars()); count = -count; } - if (tcall->Code != NULL) - { - tcall->ActorClass = actor; - tcall->FirstState = bag.statedef.GetStateCount() - count; - tcall->NumStates = count; - StateTempCalls.Push(tcall); - tcall = NULL; - } } } - if (tcall != NULL) - { - delete tcall; - } if (args != NULL) { delete args; @@ -485,7 +495,7 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg const FScriptPosition pos(sc); - FxSequence *seq = NULL; + FxCompoundStatement *seq = NULL; bool lastwasret = false; sc.MustGetString(); @@ -547,7 +557,7 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg { if (seq == NULL) { - seq = new FxSequence(pos); + seq = new FxCompoundStatement(pos); } seq->Add(add); } @@ -580,13 +590,9 @@ FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, B PFunction *afd = dyn_cast(bag.Info->Symbols.FindSymbol(symname, true)); if (afd != NULL) { - FArgumentList *args = new FArgumentList; - ParseFunctionParameters(sc, bag.Info, *args, afd, statestring, &bag.statedef); - call = new FxVMFunctionCall(afd, args->Size() > 0 ? args : NULL, sc); - if (args->Size() == 0) - { - delete args; - } + FArgumentList args; + ParseFunctionParameters(sc, bag.Info, args, afd, statestring, &bag.statedef); + call = new FxVMFunctionCall(new FxSelf(sc), afd, args, sc, false); return call; } sc.ScriptError("Invalid parameter '%s'\n", sc.String); @@ -607,22 +613,22 @@ FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, B void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray &out_params, PFunction *afd, FString statestring, FStateDefinitions *statedef) { - const TArray ¶ms = afd->Variants[0].Implementation->Proto->ArgumentTypes; + const TArray ¶ms = afd->Variants[0].Proto->ArgumentTypes; const TArray ¶mflags = afd->Variants[0].ArgFlags; int numparams = (int)params.Size(); int pnum = 0; bool zeroparm; - if (afd->Flags & VARF_Method) + if (afd->Variants[0].Flags & VARF_Action) + { + numparams -= NAP; + pnum += NAP; + } + else if (afd->Variants[0].Flags & VARF_Method) { numparams--; pnum++; } - if (afd->Flags & VARF_Action) - { - numparams -= 2; - pnum += 2; - } assert(numparams >= 0); zeroparm = numparams == 0; if (numparams > 0 && !(paramflags[pnum] & VARF_Optional)) @@ -639,7 +645,7 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray 0) { FxExpression *x; - if (statedef != NULL && params[pnum] == TypeState && sc.CheckNumber()) + if (statedef != NULL && params[pnum] == TypeStateLabel && sc.CheckNumber()) { // Special case: State label as an offset if (sc.Number > 0 && statestring.Len() > 1) @@ -659,7 +665,8 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArrayValueType = TypeStateLabel; } } else @@ -716,7 +723,7 @@ FName CheckCastKludges(FName in) case NAME_Bool: return NAME___decorate_internal_bool__; case NAME_State: - return NAME___decorate_internal_state__; + return NAME_ResolveState; case NAME_Float: return NAME___decorate_internal_float__; default: diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp new file mode 100644 index 000000000..bf6b08ea7 --- /dev/null +++ b/src/scripting/thingdef.cpp @@ -0,0 +1,434 @@ +/* +** thingdef.cpp +** +** Actor definitions +** +**--------------------------------------------------------------------------- +** Copyright 2002-2008 Christoph Oelckers +** Copyright 2004-2008 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be +** covered by the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or (at +** your option) any later version. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "gi.h" +#include "actor.h" +#include "info.h" +#include "sc_man.h" +#include "tarray.h" +#include "w_wad.h" +#include "templates.h" +#include "r_defs.h" +#include "a_pickups.h" +#include "s_sound.h" +#include "cmdlib.h" +#include "p_lnspec.h" +#include "a_action.h" +#include "decallib.h" +#include "m_random.h" +#include "i_system.h" +#include "m_argv.h" +#include "p_local.h" +#include "doomerrors.h" +#include "a_weaponpiece.h" +#include "p_conversation.h" +#include "v_text.h" +#include "thingdef.h" +#include "codegeneration/codegen.h" +#include "a_sharedglobal.h" +#include "vmbuilder.h" +#include "stats.h" + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- +void InitThingdef(); + +// STATIC FUNCTION PROTOTYPES -------------------------------------------- +PClassActor *QuestItemClasses[31]; + + +static TMap StateSourceLines; +static FScriptPosition unknownstatesource("unknown file", 0); + +//========================================================================== +// +// Saves the state's source lines for error messages during postprocessing +// +//========================================================================== + +void SaveStateSourceLines(FState *firststate, TArray &positions) +{ + for (unsigned i = 0; i < positions.Size(); i++) + { + StateSourceLines[firststate + i] = positions[i]; + } +} + +FScriptPosition & GetStateSource(FState *state) +{ + auto check = StateSourceLines.CheckKey(state); + return check ? *check : unknownstatesource; +} + +//========================================================================== +// +// SetImplicitArgs +// +// Adds the parameters implied by the function flags. +// +//========================================================================== + +void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags, int useflags) +{ + // Must be called before adding any other arguments. + assert(args == nullptr || args->Size() == 0); + assert(argflags == nullptr || argflags->Size() == 0); + + if (funcflags & VARF_Method) + { + // implied self pointer + if (args != nullptr) args->Push(NewPointer(cls)); + if (argflags != nullptr) argflags->Push(VARF_Implicit | VARF_ReadOnly); + if (argnames != nullptr) argnames->Push(NAME_self); + } + if (funcflags & VARF_Action) + { + // implied caller and callingstate pointers + if (args != nullptr) + { + // Special treatment for weapons and CustomInventory flagged functions: 'self' is not the defining class but the actual user of the item, so this pointer must be of type 'Actor' + if (useflags & (SUF_WEAPON|SUF_ITEM)) + { + args->Insert(0, NewPointer(RUNTIME_CLASS(AActor))); // this must go in before the real pointer to the containing class. + } + else + { + args->Push(NewPointer(cls)); + } + args->Push(TypeState/*Info*/); // fixme: TypeState is not the correct type here!!! + } + if (argflags != nullptr) + { + argflags->Push(VARF_Implicit | VARF_ReadOnly); + argflags->Push(VARF_Implicit | VARF_ReadOnly); + } + if (argnames != nullptr) + { + argnames->Push(NAME_invoker); + argnames->Push(NAME_stateinfo); + } + } +} + +//========================================================================== +// +// CreateAnonymousFunction +// +// Creates a function symbol for an anonymous function +// This contains actual info about the implied variables which is needed +// during code generation. +// +//========================================================================== + +PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags) +{ + TArray rets(1); + TArray args; + TArray argflags; + TArray argnames; + + // Functions that only get flagged for actors do not need the additional two context parameters. + int fflags = (flags& (SUF_OVERLAY | SUF_WEAPON | SUF_ITEM)) ? VARF_Action | VARF_Method : VARF_Method; + + rets[0] = returntype != nullptr? returntype : TypeError; // Use TypeError as placeholder if we do not know the return type yet. + SetImplicitArgs(&args, &argflags, &argnames, containingclass, fflags, flags); + + PFunction *sym = new PFunction(containingclass, NAME_None); // anonymous functions do not have names. + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, fflags); + return sym; +} + +//========================================================================== +// +// FindClassMemberFunction +// +// Looks for a name in a class's symbol table and outputs appropriate messages +// +//========================================================================== + +PFunction *FindClassMemberFunction(PClass *selfcls, PClass *funccls, FName name, FScriptPosition &sc, bool *error) +{ + // Skip ACS_NamedExecuteWithResult. Anything calling this should use the builtin instead. + if (name == NAME_ACS_NamedExecuteWithResult) return nullptr; + + PSymbolTable *symtable; + auto symbol = selfcls->Symbols.FindSymbolInTable(name, symtable); + auto funcsym = dyn_cast(symbol); + + if (symbol != nullptr) + { + if (funcsym == nullptr) + { + sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars()); + } + else if (funcsym->Variants[0].Flags & VARF_Private && symtable != &funccls->Symbols) + { + // private access is only allowed if the symbol table belongs to the class in which the current function is being defined. + sc.Message(MSG_ERROR, "%s is declared private and not accessible", symbol->SymbolName.GetChars()); + } + else if (funcsym->Variants[0].Flags & VARF_Deprecated) + { + sc.Message(MSG_WARNING, "Call to deprecated function %s", symbol->SymbolName.GetChars()); + } + } + // return nullptr if the name cannot be found in the symbol table so that the calling code can do other checks. + return funcsym; +} + +//========================================================================== +// +// CreateDamageFunction +// +// creates a damage function from the given expression +// +//========================================================================== + +void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate) +{ + if (id == nullptr) + { + defaults->DamageFunc = nullptr; + } + else + { + auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition); + auto funcsym = CreateAnonymousFunction(info, TypeSInt32, 0); + defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate); + } +} + +//========================================================================== +// +// CheckForUnsafeStates +// +// Performs a quick analysis to find potentially bad states. +// This is not perfect because it cannot track jumps by function. +// For such cases a runtime check in the relevant places is also present. +// +//========================================================================== +static void CheckForUnsafeStates(PClassActor *obj) +{ + static ENamedName weaponstates[] = { NAME_Ready, NAME_Deselect, NAME_Select, NAME_Fire, NAME_AltFire, NAME_Hold, NAME_AltHold, NAME_Flash, NAME_AltFlash, NAME_None }; + static ENamedName pickupstates[] = { NAME_Pickup, NAME_Drop, NAME_Use, NAME_None }; + TMap checked; + ENamedName *test; + + if (obj->IsDescendantOf(RUNTIME_CLASS(AWeapon))) + { + if (obj->Size == RUNTIME_CLASS(AWeapon)->Size) return; // This class cannot have user variables. + test = weaponstates; + } + else if (obj->IsDescendantOf(RUNTIME_CLASS(ACustomInventory))) + { + if (obj->Size == RUNTIME_CLASS(ACustomInventory)->Size) return; // This class cannot have user variables. + test = pickupstates; + } + else return; // something else derived from AStateProvider. We do not know what this may be. + + for (; *test != NAME_None; test++) + { + FState *state = obj->FindState(*test); + while (state != nullptr && checked.CheckKey(state) == nullptr) // have we checked this state already. If yes, we can stop checking the current chain. + { + checked[state] = true; + if (state->ActionFunc && state->ActionFunc->Unsafe) + { + // If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash. + auto owner = FState::StaticFindStateOwner(state); + GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "Unsafe state call in state %s.%d which accesses user variables, reached by %s.%s.\n", + owner->TypeName.GetChars(), state - owner->OwnedStates, obj->TypeName.GetChars(), FName(*test).GetChars()); + } + state = state->NextState; + } + } +} + +//========================================================================== +// +// CheckStates +// +// Checks if states link to ones with proper restrictions +// Checks that all base labels refer a string with proper restrictions. +// For these cases a runtime check in the relevant places is also present. +// +//========================================================================== + +static void CheckLabel(PClassActor *obj, FStateLabel *slb, int useflag, FName statename, const char *descript) +{ + auto state = slb->State; + if (state != nullptr) + { + if (!(state->UseFlags & useflag)) + { + auto owner = FState::StaticFindStateOwner(state); + GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "%s references state %s.%d as %s state, but this state is not flagged for use as %s.\n", + obj->TypeName.GetChars(), owner->TypeName.GetChars(), int(state - owner->OwnedStates), statename.GetChars(), descript); + } + } + if (slb->Children != nullptr) + { + for (int i = 0; i < slb->Children->NumLabels; i++) + { + auto state = slb->Children->Labels[i].State; + CheckLabel(obj, &slb->Children->Labels[i], useflag, statename, descript); + } + } +} + +static void CheckStateLabels(PClassActor *obj, ENamedName *test, int useflag, const char *descript) +{ + FStateLabels *labels = obj->StateList; + + for (; *test != NAME_None; test++) + { + auto label = labels->FindLabel(*test); + if (label != nullptr) + { + CheckLabel(obj, label, useflag, *test, descript); + } + } +} + + +static void CheckStates(PClassActor *obj) +{ + static ENamedName actorstates[] = { NAME_Spawn, NAME_See, NAME_Melee, NAME_Missile, NAME_Pain, NAME_Death, NAME_Wound, NAME_Raise, NAME_Yes, NAME_No, NAME_Greetings, NAME_None }; + static ENamedName weaponstates[] = { NAME_Ready, NAME_Deselect, NAME_Select, NAME_Fire, NAME_AltFire, NAME_Hold, NAME_AltHold, NAME_Flash, NAME_AltFlash, NAME_None }; + static ENamedName pickupstates[] = { NAME_Pickup, NAME_Drop, NAME_Use, NAME_None }; + TMap checked; + + CheckStateLabels(obj, actorstates, SUF_ACTOR, "actor sprites"); + + if (obj->IsDescendantOf(RUNTIME_CLASS(AWeapon))) + { + CheckStateLabels(obj, weaponstates, SUF_WEAPON, "weapon sprites"); + } + else if (obj->IsDescendantOf(RUNTIME_CLASS(ACustomInventory))) + { + CheckStateLabels(obj, pickupstates, SUF_ITEM, "CustomInventory state chain"); + } + for (int i = 0; i < obj->NumOwnedStates; i++) + { + auto state = obj->OwnedStates + i; + if (state->NextState && (state->UseFlags & state->NextState->UseFlags) != state->UseFlags) + { + GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "State %s.%d links to a state with incompatible restrictions.\n", + obj->TypeName.GetChars(), int(state - obj->OwnedStates)); + } + } +} + +//========================================================================== +// +// LoadActors +// +// Called from FActor::StaticInit() +// +//========================================================================== +void ParseScripts(); +void ParseAllDecorate(); + +void LoadActors () +{ + cycle_t timer; + + timer.Reset(); timer.Clock(); + FScriptPosition::ResetErrorCounter(); + + InitThingdef(); + FScriptPosition::StrictErrors = true; + ParseScripts(); + + FScriptPosition::StrictErrors = false; + ParseAllDecorate(); + + FunctionBuildList.Build(); + + if (FScriptPosition::ErrorCounter > 0) + { + I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter); + } + FScriptPosition::ResetErrorCounter(); + + for (auto ti : PClassActor::AllActorClasses) + { + if (ti->Size == TentativeClass) + { + Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); + FScriptPosition::ErrorCounter++; + continue; + } + + if (GetDefaultByType(ti) == nullptr) + { + Printf(TEXTCOLOR_RED "No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars()); + FScriptPosition::ErrorCounter++; + continue; + } + + + CheckStates(ti); + + if (ti->bDecorateClass && ti->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) + { + // either a DECORATE based weapon or CustomInventory. + // These are subject to relaxed rules for user variables in states. + // Although there is a runtime check for bogus states, let's do a quick analysis if any of the known entry points + // hits an unsafe state. If we can find something here it can be handled wuth a compile error rather than a runtime error. + CheckForUnsafeStates(ti); + } + + } + if (FScriptPosition::ErrorCounter > 0) + { + I_Error("%d errors during actor postprocessing", FScriptPosition::ErrorCounter); + } + + timer.Unclock(); + if (!batchrun) Printf("script parsing took %.2f ms\n", timer.TimeMS()); + + // Since these are defined in DECORATE now the table has to be initialized here. + for (int i = 0; i < 31; i++) + { + char fmt[20]; + mysnprintf(fmt, countof(fmt), "QuestItem%d", i + 1); + QuestItemClasses[i] = PClass::FindActor(fmt); + } + StateSourceLines.Clear(); +} diff --git a/src/thingdef/thingdef.h b/src/scripting/thingdef.h similarity index 69% rename from src/thingdef/thingdef.h rename to src/scripting/thingdef.h index 565da573a..7218a84e6 100644 --- a/src/thingdef/thingdef.h +++ b/src/scripting/thingdef.h @@ -6,6 +6,7 @@ #include "s_sound.h" #include "sc_man.h" #include "cmdlib.h" +#include "vm.h" class FScanner; @@ -23,9 +24,10 @@ struct FFlagDef const char *name; int structoffset; int fieldsize; + int varflags; }; -FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2); +FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bool strict = false); void HandleDeprecatedFlags(AActor *defaults, PClassActor *info, bool set, int index); bool CheckDeprecatedFlags(const AActor *actor, PClassActor *info, int index); const char *GetFlagName(unsigned int flagnum, int flagoffset); @@ -46,18 +48,6 @@ class FxExpression; struct FStateLabels; -enum EStateDefineFlags -{ - SDF_NEXT = 0, - SDF_STATE = 1, - SDF_STOP = 2, - SDF_WAIT = 3, - SDF_LABEL = 4, - SDF_INDEX = 5, - SDF_MASK = 7, - SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump -}; - struct FStateDefine { FName Label; @@ -73,6 +63,7 @@ class FStateDefinitions FState *laststatebeforelabel; intptr_t lastlabel; TArray StateArray; + TArray SourceLines; static FStateDefine *FindStateLabelInList(TArray &list, FName name, bool create); static FStateLabels *CreateStateLabelList(TArray &statelist); @@ -84,7 +75,6 @@ class FStateDefinitions FState *ResolveGotoLabel(AActor *actor, PClassActor *mytype, char *name); static void FixStatePointers(PClassActor *actor, TArray & list); void ResolveGotoLabels(PClassActor *actor, AActor *defaults, TArray & list); - public: FStateDefinitions() @@ -108,28 +98,13 @@ public: bool SetStop(); bool SetWait(); bool SetLoop(); - int AddStates(FState *state, const char *framechars); + int AddStates(FState *state, const char *framechars, const FScriptPosition &sc); int GetStateCount() const { return StateArray.Size(); } }; -//========================================================================== -// -// -// -//========================================================================== -struct FStateTempCall -{ - FStateTempCall() : ActorClass(NULL), Code(NULL), FirstState(0), NumStates(0) {} - - PClassActor *ActorClass; - class FxExpression *Code; - class PPrototype *Proto; - int FirstState; - int NumStates; -}; -extern TDeletingArray StateTempCalls; -extern TDeletingArray ActorDamageFuncs; +void SaveStateSourceLines(FState *firststate, TArray &positions); +FScriptPosition & GetStateSource(FState *state); //========================================================================== // @@ -146,6 +121,7 @@ struct Baggage PClassActor *Info; bool DropItemSet; bool StateSet; + bool fromDecorate; int CurrentState; int Lumpnum; FStateDefinitions statedef; @@ -160,6 +136,7 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) bag->DropItemList = NULL; bag->DropItemSet = false; bag->CurrentState = 0; + bag->fromDecorate = true; bag->StateSet = false; bag->statedef.MakeStateDefines(stateclass); } @@ -170,25 +147,20 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) // //========================================================================== -struct AFuncDesc -{ - const char *Name; - actionf_p Function; - VMNativeFunction **VMPointer; -}; - AFuncDesc *FindFunction(const char * string); +FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, bool mustresolve = false); void ParseStates(FScanner &sc, PClassActor *actor, AActor *defaults, Baggage &bag); void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray &out_params, PFunction *afd, FString statestring, FStateDefinitions *statedef); FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, bool &endswithret); class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag); FName CheckCastKludges(FName in); -void SetImplicitArgs(TArray *args, TArray *argflags, PClassActor *cls, DWORD funcflags); - -PFunction *FindGlobalActionFunction(const char *name); +void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags, int useflags); +PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); +PFunction *FindClassMemberFunction(PClass *cls, PClass *funccls, FName name, FScriptPosition &sc, bool *error); +void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate); //========================================================================== // @@ -196,11 +168,7 @@ PFunction *FindGlobalActionFunction(const char *name); // //========================================================================== -PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native); -void SetReplacement(FScanner &sc, PClassActor *info, FName replaceName); - void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod); -void FinishActor(const FScriptPosition &sc, PClassActor *info, Baggage &bag); FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant); @@ -231,23 +199,13 @@ enum EDefinitionType }; #if defined(_MSC_VER) -#pragma section(".areg$u",read) #pragma section(".greg$u",read) -#pragma section(".mreg$u",read) -#define MSVC_ASEG __declspec(allocate(".areg$u")) -#define GCC_ASEG #define MSVC_PSEG __declspec(allocate(".greg$u")) #define GCC_PSEG -#define MSVC_MSEG __declspec(allocate(".mreg$u")) -#define GCC_MSEG #else -#define MSVC_ASEG -#define GCC_ASEG __attribute__((section(SECTION_AREG))) __attribute__((used)) #define MSVC_PSEG #define GCC_PSEG __attribute__((section(SECTION_GREG))) __attribute__((used)) -#define MSVC_MSEG -#define GCC_MSEG __attribute__((section(SECTION_MREG))) __attribute__((used)) #endif @@ -264,7 +222,7 @@ typedef void (*PropHandler)(AActor *defaults, PClassActor *info, Baggage &bag, F enum ECategory { CAT_PROPERTY, // Inheritable property - CAT_INFO // non-inheritable info (spawn ID, Doomednum, game filter, conversation ID) + CAT_INFO // non-inheritable info (spawn ID, Doomednum, game filter, conversation ID, not usable in ZScript) }; struct FPropertyInfo @@ -321,39 +279,4 @@ int MatchString (const char *in, const char **strings); #define PROP_COLOR_PARM(var, no) \ int var = params[(no)+1].i== 0? params[(no)+2].i : V_GetColor(NULL, params[(no)+2].s); - -// Macros to handle action functions. These are here so that I don't have to -// change every single use in case the parameters change. -#define DECLARE_ACTION(name) extern VMNativeFunction *name##_VMPtr; - -// This distinction is here so that CALL_ACTION produces errors when trying to -// access a function that requires parameters. -#define DEFINE_ACTION_FUNCTION(cls, name) \ - static int AF_##name(VM_ARGS); \ - VMNativeFunction *name##_VMPtr; \ - static const AFuncDesc cls##_##name##_Hook = { #name, AF_##name, &name##_VMPtr }; \ - extern AFuncDesc const *const cls##_##name##_HookPtr; \ - MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \ - static int AF_##name(VM_ARGS) - -#define DEFINE_ACTION_FUNCTION_PARAMS(cls, name) DEFINE_ACTION_FUNCTION(cls, name) - -//#define DECLARE_PARAMINFO AActor *self, AActor *stateowner, FState *CallingState, int ParameterIndex, StateCallData *statecall -//#define PUSH_PARAMINFO self, stateowner, CallingState, ParameterIndex, statecall - -#define CALL_ACTION(name,self) { /*AF_##name(self, self, NULL, 0, NULL)*/ \ - VMValue params[3] = { self, self, VMValue(NULL, ATAG_STATEINFO) }; \ - stack->Call(name##_VMPtr, params, countof(params), NULL, 0, NULL); \ - } - - -#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0) -#define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0) -#define ACTION_RETURN_INT(v) do { int u = v; if (numret > 0) { assert(ret != NULL); ret->SetInt(u); return 1; } return 0; } while(0) -#define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v) - -// Checks to see what called the current action function -#define ACTION_CALL_FROM_ACTOR() (stateinfo == nullptr || stateinfo->mStateType == STATE_Actor) -#define ACTION_CALL_FROM_PSPRITE() (self->player && stateinfo != nullptr && stateinfo->mStateType == STATE_Psprite) -#define ACTION_CALL_FROM_INVENTORY() (stateinfo != nullptr && stateinfo->mStateType == STATE_StateChain) #endif diff --git a/src/thingdef/thingdef_data.cpp b/src/scripting/thingdef_data.cpp similarity index 80% rename from src/thingdef/thingdef_data.cpp rename to src/scripting/thingdef_data.cpp index efdd64921..4ccc72748 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -54,19 +54,53 @@ static TArray AFTable; //========================================================================== // [RH] Keep GCC quiet by not using offsetof on Actor types. -#define DEFINE_FLAG(prefix, name, type, variable) { (unsigned int)prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable) } -#define DEFINE_FLAG2(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable) } -#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1, 0 } -#define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1, 0 } +#define DEFINE_FLAG(prefix, name, type, variable) { (unsigned int)prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), VARF_Native } +#define DEFINE_PROTECTED_FLAG(prefix, name, type, variable) { (unsigned int)prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), VARF_Native|VARF_ReadOnly|VARF_InternalAccess } +#define DEFINE_FLAG2(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), VARF_Native } +#define DEFINE_FLAG2_DEPRECATED(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), VARF_Native|VARF_Deprecated } +#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1, 0, true } +#define DEFINE_DUMMY_FLAG(name, deprec) { DEPF_UNUSED, #name, -1, 0, deprec? VARF_Deprecated:0 } -static FFlagDef ActorFlagDefs[]= +// internal flags. These do not get exposed to actor definitions but scripts need to be able to access them as variables. +FFlagDef InternalActorFlagDefs[]= +{ + DEFINE_FLAG(MF, INCHASE, AActor, flags), + DEFINE_FLAG(MF, UNMORPHED, AActor, flags), + DEFINE_FLAG(MF2, FLY, AActor, flags2), + DEFINE_FLAG(MF2, ONMOBJ, AActor, flags2), + DEFINE_FLAG(MF2, ARGSDEFINED, AActor, flags2), + DEFINE_FLAG(MF3, NOSIGHTCHECK, AActor, flags3), + DEFINE_FLAG(MF3, CRASHED, AActor, flags3), + DEFINE_FLAG(MF3, WARNBOT, AActor, flags3), + DEFINE_FLAG(MF3, HUNTPLAYERS, AActor, flags3), + DEFINE_FLAG(MF4, NOHATEPLAYERS, AActor, flags4), + DEFINE_FLAG(MF4, SCROLLMOVE, AActor, flags4), + DEFINE_FLAG(MF4, VFRICTION, AActor, flags4), + DEFINE_FLAG(MF4, BOSSSPAWNED, AActor, flags4), + DEFINE_FLAG(MF5, AVOIDINGDROPOFF, AActor, flags5), + DEFINE_FLAG(MF5, CHASEGOAL, AActor, flags5), + DEFINE_FLAG(MF5, INCONVERSATION, AActor, flags5), + DEFINE_FLAG(MF6, ARMED, AActor, flags6), + DEFINE_FLAG(MF6, FALLING, AActor, flags6), + DEFINE_FLAG(MF6, LINEDONE, AActor, flags6), + DEFINE_FLAG(MF6, SHATTERING, AActor, flags6), + DEFINE_FLAG(MF6, KILLED, AActor, flags6), + DEFINE_FLAG(MF6, BOSSCUBE, AActor, flags6), + DEFINE_FLAG(MF6, INTRYMOVE, AActor, flags6), + DEFINE_FLAG(MF7, HANDLENODELAY, AActor, flags7), + DEFINE_FLAG(MF7, FLYCHEAT, AActor, flags7), + { 0xffffffff } +}; + + +FFlagDef ActorFlagDefs[]= { DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags), DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags), DEFINE_FLAG(MF, SOLID, AActor, flags), DEFINE_FLAG(MF, SHOOTABLE, AActor, flags), - DEFINE_FLAG(MF, NOSECTOR, AActor, flags), - DEFINE_FLAG(MF, NOBLOCKMAP, AActor, flags), + DEFINE_PROTECTED_FLAG(MF, NOSECTOR, AActor, flags), + DEFINE_PROTECTED_FLAG(MF, NOBLOCKMAP, AActor, flags), DEFINE_FLAG(MF, AMBUSH, AActor, flags), DEFINE_FLAG(MF, JUSTHIT, AActor, flags), DEFINE_FLAG(MF, JUSTATTACKED, AActor, flags), @@ -171,7 +205,6 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF4, SYNCHRONIZED, AActor, flags4), DEFINE_FLAG(MF4, NOTARGETSWITCH, AActor, flags4), DEFINE_FLAG(MF4, DONTHARMCLASS, AActor, flags4), - DEFINE_FLAG2(MF4_DONTHARMCLASS, DONTHURTSPECIES, AActor, flags4), // Deprecated name as an alias DEFINE_FLAG(MF4, SHIELDREFLECT, AActor, flags4), DEFINE_FLAG(MF4, DEFLECT, AActor, flags4), DEFINE_FLAG(MF4, ALLOWPARTICLES, AActor, flags4), @@ -294,6 +327,12 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG2(BOUNCE_MBF, MBFBOUNCER, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_AutoOffFloorOnly, BOUNCEAUTOOFFFLOORONLY, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_UseBounceState, USEBOUNCESTATE, AActor, BounceFlags), + { 0xffffffff } +}; + +// These won't be accessible through bitfield variables +static FFlagDef MoreFlagDefs[] = +{ // Deprecated flags. Handling must be performed in HandleDeprecatedFlags DEFINE_DEPRECATED_FLAG(FIREDAMAGE), @@ -308,15 +347,16 @@ static FFlagDef ActorFlagDefs[]= DEFINE_DEPRECATED_FLAG(DOOMBOUNCE), // Deprecated flags with no more existing functionality. - DEFINE_DUMMY_FLAG(FASTER), // obsolete, replaced by 'Fast' state flag - DEFINE_DUMMY_FLAG(FASTMELEE), // obsolete, replaced by 'Fast' state flag + DEFINE_DUMMY_FLAG(FASTER, true), // obsolete, replaced by 'Fast' state flag + DEFINE_DUMMY_FLAG(FASTMELEE, true), // obsolete, replaced by 'Fast' state flag // Various Skulltag flags that are quite irrelevant to ZDoom - DEFINE_DUMMY_FLAG(NONETID), // netcode-based - DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN), // netcode-based - DEFINE_DUMMY_FLAG(CLIENTSIDEONLY), // netcode-based - DEFINE_DUMMY_FLAG(SERVERSIDEONLY), // netcode-based - DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless + DEFINE_DUMMY_FLAG(NONETID, false), // netcode-based + DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN, false), // netcode-based + DEFINE_DUMMY_FLAG(CLIENTSIDEONLY, false), // netcode-based + DEFINE_DUMMY_FLAG(SERVERSIDEONLY, false), // netcode-based + DEFINE_DUMMY_FLAG(EXPLODEONDEATH, true), // seems useless + DEFINE_FLAG2_DEPRECATED(MF4_DONTHARMCLASS, DONTHURTSPECIES, AActor, flags4), // Deprecated name as an alias }; static FFlagDef InventoryFlagDefs[] = @@ -372,9 +412,9 @@ static FFlagDef WeaponFlagDefs[] = DEFINE_FLAG(WIF, NODEATHDESELECT, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, NODEATHINPUT, AWeapon, WeaponFlags), - DEFINE_DUMMY_FLAG(NOLMS), + DEFINE_DUMMY_FLAG(NOLMS, false), DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags), - DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL), + DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false), }; static FFlagDef PlayerPawnFlagDefs[] = @@ -393,7 +433,8 @@ static FFlagDef PowerSpeedFlagDefs[] = static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] = { - { &RUNTIME_CLASS_CASTLESS(AActor), ActorFlagDefs, countof(ActorFlagDefs) }, + { &RUNTIME_CLASS_CASTLESS(AActor), ActorFlagDefs, countof(ActorFlagDefs)-1 }, // -1 to account for the terminator + { &RUNTIME_CLASS_CASTLESS(AActor), MoreFlagDefs, countof(MoreFlagDefs) }, { &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs) }, { &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs) }, { &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs) }, @@ -436,14 +477,14 @@ static FFlagDef *FindFlag (FFlagDef *flags, int numflags, const char *flag) // //========================================================================== -FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2) +FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bool strict) { FFlagDef *def; - size_t i; if (part2 == NULL) { // Search all lists - for (i = 0; i < NUM_FLAG_LISTS; ++i) + int max = strict ? 2 : NUM_FLAG_LISTS; + for (int i = 0; i < max; ++i) { if (type->IsDescendantOf (*FlagLists[i].Type)) { @@ -457,7 +498,7 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2) } else { // Search just the named list - for (i = 0; i < NUM_FLAG_LISTS; ++i) + for (size_t i = 0; i < NUM_FLAG_LISTS; ++i) { if (stricmp ((*FlagLists[i].Type)->TypeName.GetChars(), part1) == 0) { @@ -561,9 +602,10 @@ AFuncDesc *FindFunction(const char * string) // //========================================================================== -PFunction *FindGlobalActionFunction(const char *name) +VMFunction *FindVMFunction(PClass *cls, const char *name) { - return dyn_cast(RUNTIME_CLASS(AActor)->Symbols.FindSymbol(name, false)); + auto f = dyn_cast(cls->Symbols.FindSymbol(name, true)); + return f == nullptr ? nullptr : f->Variants[0].Implementation; } @@ -593,6 +635,7 @@ static int funccmp(const void * a, const void * b) // Initialization // //========================================================================== +void G_InitLevelLocalsForScript(); void InitThingdef() { @@ -632,46 +675,20 @@ void InitThingdef() qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp); } - // Define some member variables we feel like exposing to the user - PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols; - PType *array5 = NewArray(TypeSInt32, 5); - symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor, Alpha))); - symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw))); - symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor, args))); - symt.AddSymbol(new PField(NAME_CeilingZ, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, ceilingz))); - symt.AddSymbol(new PField(NAME_FloorZ, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, floorz))); - symt.AddSymbol(new PField(NAME_Health, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, health))); - symt.AddSymbol(new PField(NAME_Mass, TypeSInt32, VARF_Native, myoffsetof(AActor, Mass))); - symt.AddSymbol(new PField(NAME_Pitch, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Pitch))); - symt.AddSymbol(new PField(NAME_Roll, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Roll))); - symt.AddSymbol(new PField(NAME_Special, TypeSInt32, VARF_Native, myoffsetof(AActor, special))); - symt.AddSymbol(new PField(NAME_TID, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, tid))); - symt.AddSymbol(new PField(NAME_TIDtoHate, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, TIDtoHate))); - symt.AddSymbol(new PField(NAME_WaterLevel, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, waterlevel))); - symt.AddSymbol(new PField(NAME_X, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos.X))); // must remain read-only! - symt.AddSymbol(new PField(NAME_Y, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos.Y))); // must remain read-only! - symt.AddSymbol(new PField(NAME_Z, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos.Z))); // must remain read-only! - symt.AddSymbol(new PField(NAME_VelX, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Vel.X))); - symt.AddSymbol(new PField(NAME_VelY, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Vel.Y))); - symt.AddSymbol(new PField(NAME_VelZ, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Vel.Z))); - symt.AddSymbol(new PField(NAME_MomX, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Vel.X))); - symt.AddSymbol(new PField(NAME_MomY, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Vel.Y))); - symt.AddSymbol(new PField(NAME_MomZ, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Vel.Z))); - symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native, myoffsetof(AActor, Scale.X))); - symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native, 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))); - symt.AddSymbol(new PField(NAME_Height, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Height))); - symt.AddSymbol(new PField(NAME_Radius, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, radius))); - symt.AddSymbol(new PField(NAME_ReactionTime, TypeSInt32, VARF_Native, myoffsetof(AActor, reactiontime))); - symt.AddSymbol(new PField(NAME_MeleeRange, TypeFloat64, VARF_Native, myoffsetof(AActor, meleerange))); - symt.AddSymbol(new PField(NAME_Speed, TypeFloat64, VARF_Native, myoffsetof(AActor, Speed))); - symt.AddSymbol(new PField(NAME_Threshold, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, threshold))); - symt.AddSymbol(new PField(NAME_DefThreshold, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, DefThreshold))); - symt.AddSymbol(new PField(NAME_Damage, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, DamageVal))); - symt.AddSymbol(new PField(NAME_VisibleStartAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartAngle))); - symt.AddSymbol(new PField(NAME_VisibleStartPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartPitch))); - symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle))); - symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch))); + PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); + + PStruct *sstruct = NewStruct("Sector", nullptr); + auto sptr = NewPointer(sstruct); + sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); + + G_InitLevelLocalsForScript(); + + FAutoSegIterator probe(CRegHead, CRegTail); + + while (*++probe != NULL) + { + if (((ClassReg *)*probe)->InitNatives) + ((ClassReg *)*probe)->InitNatives(); + } + } diff --git a/src/thingdef/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp similarity index 98% rename from src/thingdef/thingdef_properties.cpp rename to src/scripting/thingdef_properties.cpp index 6321ebfe9..7faab937b 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -69,6 +69,7 @@ #include "teaminfo.h" #include "v_video.h" #include "r_data/colormaps.h" +#include "vmbuilder.h" //========================================================================== @@ -514,10 +515,11 @@ DEFINE_INFO_PROPERTY(conversationid, IiI, Actor) //========================================================================== DEFINE_PROPERTY(skip_super, 0, Actor) { - if (info->IsDescendantOf(RUNTIME_CLASS(AInventory))) + auto actorclass = RUNTIME_CLASS(AActor); + if (info->Size != actorclass->Size) { - bag.ScriptPosition.Message(MSG_WARNING, - "'skip_super' in definition of inventory item '%s' ignored.", info->TypeName.GetChars() ); + bag.ScriptPosition.Message(MSG_OPTERROR, + "'skip_super' is only allowed in subclasses of AActor with no additional fields and will be ignored.", info->TypeName.GetChars()); return; } if (bag.StateSet) @@ -531,6 +533,15 @@ DEFINE_PROPERTY(skip_super, 0, Actor) ResetBaggage (&bag, RUNTIME_CLASS(AActor)); } +//========================================================================== +// for internal use only - please do not document! +//========================================================================== +DEFINE_PROPERTY(defaultstateusage, I, Actor) +{ + PROP_INT_PARM(use, 0); + static_cast(bag.Info)->DefaultStateUsage = use; + +} //========================================================================== // //========================================================================== @@ -645,18 +656,18 @@ DEFINE_PROPERTY(damage, X, Actor) // compatibility reasons, expressions must be enclosed within // parentheses. - // Store this expression here for now. It will be converted to a function - // later once all actors have been processed. defaults->DamageVal = dmgval; + // Only DECORATE can get here with a valid expression. + CreateDamageFunction(bag.Info, defaults, id, true); +} - if (id == nullptr) - { - defaults->DamageFunc = nullptr; - } - else - { - defaults->DamageFunc = (VMFunction *)(uintptr_t)(ActorDamageFuncs.Push(id) + 1); - } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(damagemultiply, F, Actor) +{ + PROP_FLOAT_PARM(dmgm, 0); + defaults->DamageMultiply = dmgm; } //========================================================================== @@ -2429,11 +2440,18 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver) // Yuck! What was I thinking when I decided to prepend "Power" to the name? // Now it's too late to change it... PClassActor *cls = PClass::FindActor(str); - if (cls == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(APowerup))) + if (cls == nullptr || !cls->IsDescendantOf(RUNTIME_CLASS(APowerup))) { - FString st; - st.Format("%s%s", strnicmp(str, "power", 5)? "Power" : "", str); - cls = FindClassTentativePowerup(st); + if (bag.fromDecorate) + { + FString st; + st.Format("%s%s", strnicmp(str, "power", 5) ? "Power" : "", str); + cls = FindClassTentativePowerup(st); + } + else + { + I_Error("Unknown powerup type %s", str); + } } defaults->PowerupType = cls; @@ -2484,7 +2502,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, face, S, PlayerPawn) ); if (!valid) { - bag.ScriptPosition.Message(MSG_WARNING, + bag.ScriptPosition.Message(MSG_OPTERROR, "Invalid face '%s' for '%s';\nSTF replacement codes must be 3 alphanumeric characters.\n", tmp.GetChars(), info->TypeName.GetChars ()); } @@ -2551,13 +2569,13 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorset, ISIIIiiiiiiiiiiiiiiiiiiiiiiii, Pl } if (count != 0) { - bag.ScriptPosition.Message(MSG_WARNING, "Extra ranges require 4 parameters each.\n"); + bag.ScriptPosition.Message(MSG_OPTERROR, "Extra ranges require 4 parameters each.\n"); } } if (setnum < 0) { - bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n"); + bag.ScriptPosition.Message(MSG_OPTERROR, "Color set number must not be negative.\n"); } else { @@ -2584,7 +2602,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorsetfile, ISSI, PlayerPawn) if (setnum < 0) { - bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n"); + bag.ScriptPosition.Message(MSG_OPTERROR, "Color set number must not be negative.\n"); } else if (color.Lump >= 0) { @@ -2602,7 +2620,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, clearcolorset, I, PlayerPawn) if (setnum < 0) { - bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n"); + bag.ScriptPosition.Message(MSG_OPTERROR, "Color set number must not be negative.\n"); } else { diff --git a/src/zscript/vm.h b/src/scripting/vm/vm.h similarity index 66% rename from src/zscript/vm.h rename to src/scripting/vm/vm.h index a000e9533..2f98c8d81 100644 --- a/src/zscript/vm.h +++ b/src/scripting/vm/vm.h @@ -3,6 +3,8 @@ #include "zstring.h" #include "dobject.h" +#include "autosegs.h" +#include "vectors.h" #define MAX_RETURNS 8 // Maximum number of results a function called by script code can return #define MAX_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function @@ -16,7 +18,7 @@ typedef unsigned int VM_UWORD; typedef signed int VM_SWORD; typedef VM_UBYTE VM_ATAG; -#define VM_EPSILON (1/1024.0) +#define VM_EPSILON (1/65536.0) union VMOP { @@ -115,6 +117,12 @@ enum CAST_P2S, CAST_S2I, CAST_S2F, + CAST_S2N, + CAST_N2S, + CAST_S2Co, + CAST_S2So, + CAST_Co2S, + CAST_So2S, }; // Register types for VMParam @@ -127,10 +135,12 @@ enum REGT_TYPE = 3, REGT_KONST = 4, - REGT_MULTIREG = 8, // (e.g. a vector) + REGT_MULTIREG2 = 8, + REGT_MULTIREG3 = 16, // (e.g. a vector) + REGT_MULTIREG = 24, REGT_ADDROF = 32, // used with PARAM: pass address of this register - REGT_NIL = 255 // parameter was omitted + REGT_NIL = 128 // parameter was omitted }; #define RET_FINAL (0x80) // Used with RET and RETI in the destination slot: this is the final return value @@ -151,9 +161,8 @@ enum ATAG_SREGISTER, // pointer to a string register ATAG_AREGISTER, // pointer to an address register - ATAG_STATE, // pointer to FState - ATAG_STATEINFO, // FState plus some info. ATAG_RNG, // pointer to FRandom + ATAG_STATE = ATAG_GENERIC, // pointer to FState (cannot have its own type because there's no means to track inside the VM.) }; enum EVMAbortException @@ -166,20 +175,6 @@ enum EVMAbortException X_BAD_SELF, }; -class VMFunction : public DObject -{ - DECLARE_ABSTRACT_CLASS(VMFunction, DObject); - HAS_OBJECT_POINTERS; -public: - bool Native; - FName Name; - - class PPrototype *Proto; - - VMFunction() : Native(false), Name(NAME_None), Proto(NULL) {} - VMFunction(FName name) : Native(false), Name(name), Proto(NULL) {} -}; - enum EVMOpMode { MODE_ASHIFT = 0, @@ -297,11 +292,30 @@ struct VMReturn } void SetVector(const double val[3]) { - //assert(RegType == REGT_FLOAT); + assert(RegType == (REGT_FLOAT|REGT_MULTIREG3)); ((double *)Location)[0] = val[0]; ((double *)Location)[1] = val[1]; ((double *)Location)[2] = val[2]; } + void SetVector(const DVector3 &val) + { + assert(RegType == (REGT_FLOAT | REGT_MULTIREG3)); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + ((double *)Location)[2] = val[2]; + } + void SetVector2(const double val[2]) + { + assert(RegType == (REGT_FLOAT|REGT_MULTIREG2)); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + } + void SetVector2(const DVector2 &val) + { + assert(RegType == (REGT_FLOAT | REGT_MULTIREG2)); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + } void SetString(const FString &val) { assert(RegType == REGT_STRING); @@ -635,6 +649,24 @@ do_double: if (inexact) } }; +class VMFunction : public DObject +{ + DECLARE_ABSTRACT_CLASS(VMFunction, DObject); + HAS_OBJECT_POINTERS; +public: + bool Native; + bool Final = false; // cannot be overridden + bool Unsafe = false; // Contains references to class fields that are unsafe for psp and item state calls. + BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action + int VirtualIndex = -1; + FName Name; + TArray DefaultArgs; + + 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 @@ -782,6 +814,7 @@ public: VM_UBYTE NumKonstA; VM_UHALF MaxParam; // Maximum number of parameters this function has on the stack at once VM_UBYTE NumArgs; // Number of arguments this function takes + FString PrintableName; // so that the VM can print meaningful info if something in this function goes wrong. }; class VMFrameStack @@ -821,7 +854,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; } @@ -892,8 +925,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

@@ -905,30 +938,35 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FSoundID x = param[p].i; #define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); PalEntry x; x.d = param[p].i; #define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); double x = param[p].f; -#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); DAngle x = param[p].f; +#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); DAngle x = param[p].f; #define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s(); -#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); FState *x = (FState *)param[p].a; +#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, self->GetClass()); +#define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass()); #define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a; #define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type))); #define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base))); -// For optional paramaters. These have dangling elses for you to fill in the default assignment. e.g.: -// 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_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 -#define PARAM_SOUND_OPT_AT(p,x) FSoundID x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = FSoundID(param[p].i); } else -#define PARAM_COLOR_OPT_AT(p,x) PalEntry x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x.d = param[p].i; } else -#define PARAM_FLOAT_OPT_AT(p,x) double x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = param[p].f; } else -#define PARAM_ANGLE_OPT_AT(p,x) DAngle x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = param[p].f; } else -#define PARAM_STRING_OPT_AT(p,x) FString x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_STRING); x = param[p].s(); } else -#define PARAM_STATE_OPT_AT(p,x) FState *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); x = (FState *)param[p].a; } else -#define PARAM_STATEINFO_OPT_AT(p,x) FStateParamInfo *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATEINFO || param[p].a == NULL)); x = (FStateParamInfo *)param[p].a; } else -#define PARAM_POINTER_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER); x = (type *)param[p].a; } else -#define PARAM_OBJECT_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type))); } else -#define PARAM_CLASS_OPT_AT(p,x,base) base::MetaClass *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base))); } else +#define PARAM_EXISTS(p) ((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 || (p).a == nullptr)) +#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(p)) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; } +#define PARAM_BOOL_DEF_AT(p,x) bool x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = !!param[p].i; } else { ASSERTINT(defaultparam[p]); x = !!defaultparam[p].i; } +#define PARAM_NAME_DEF_AT(p,x) FName x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = ENamedName(param[p].i); } else { ASSERTINT(defaultparam[p]); x = ENamedName(defaultparam[p].i); } +#define PARAM_SOUND_DEF_AT(p,x) FSoundID x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = FSoundID(param[p].i); } else { ASSERTINT(defaultparam[p]); x = FSoundID(defaultparam[p].i); } +#define PARAM_COLOR_DEF_AT(p,x) PalEntry x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; } +#define PARAM_FLOAT_DEF_AT(p,x) double x; if (PARAM_EXISTS(p)) { ASSERTFLOAT(param[p]); x = param[p].f; } else { ASSERTFLOAT(defaultparam[p]); x = defaultparam[p].f; } +#define PARAM_ANGLE_DEF_AT(p,x) DAngle x; if (PARAM_EXISTS(p)) { ASSERTFLOAT(param[p]); x = param[p].f; } else { ASSERTFLOAT(defaultparam[p]); x = defaultparam[p].f; } +#define PARAM_STRING_DEF_AT(p,x) FString x; if (PARAM_EXISTS(p)) { ASSERTSTRING(param[p]); x = param[p].s; } else { ASSERTSTRING(defaultparam[p]); x = defaultparam[p].s; } +#define PARAM_STATE_DEF_AT(p,x) FState *x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = (FState*)StateLabels.GetState(param[p].i, self->GetClass()); } else { ASSERTINT(defaultparam[p]); x = (FState*)StateLabels.GetState(defaultparam[p].i, self->GetClass()); } +#define PARAM_STATE_ACTION_DEF_AT(p,x) FState *x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = (FState*)StateLabels.GetState(param[p].i, stateowner->GetClass()); } else { ASSERTINT(defaultparam[p]); x = (FState*)StateLabels.GetState(defaultparam[p].i, stateowner->GetClass()); } +#define PARAM_POINTER_DEF_AT(p,x,t) t *x; if (PARAM_EXISTS(p)) { ASSERTPOINTER(param[p]); x = (t*)param[p].a; } else { ASSERTPOINTER(defaultparam[p]); x = (t*)defaultparam[p].a; } +#define PARAM_OBJECT_DEF_AT(p,x,t) t *x; if (PARAM_EXISTS(p)) { ASSERTOBJECT(param[p]); x = (t*)param[p].a; } else { ASSERTOBJECT(defaultparam[p]); x = (t*)defaultparam[p].a; } +#define PARAM_CLASS_DEF_AT(p,x,t) t::MetaClass *x; if (PARAM_EXISTS(p)) { ASSERTOBJECT(param[p]); x = (t::MetaClass*)param[p].a; } else { ASSERTOBJECT(defaultparam[p]); x = (t::MetaClass*)defaultparam[p].a; } // The above, but with an automatically increasing position index. #define PARAM_PROLOGUE int paramnum = -1; @@ -942,22 +980,103 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_ANGLE(x) ++paramnum; PARAM_ANGLE_AT(paramnum,x) #define PARAM_STRING(x) ++paramnum; PARAM_STRING_AT(paramnum,x) #define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x) +#define PARAM_STATE_ACTION(x) ++paramnum; PARAM_STATE_ACTION_AT(paramnum,x) #define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type) #define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type) #define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base) -#define PARAM_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) -#define PARAM_SOUND_OPT(x) ++paramnum; PARAM_SOUND_OPT_AT(paramnum,x) -#define PARAM_COLOR_OPT(x) ++paramnum; PARAM_COLOR_OPT_AT(paramnum,x) -#define PARAM_FLOAT_OPT(x) ++paramnum; PARAM_FLOAT_OPT_AT(paramnum,x) -#define PARAM_ANGLE_OPT(x) ++paramnum; PARAM_ANGLE_OPT_AT(paramnum,x) -#define PARAM_STRING_OPT(x) ++paramnum; PARAM_STRING_OPT_AT(paramnum,x) -#define PARAM_STATE_OPT(x) ++paramnum; PARAM_STATE_OPT_AT(paramnum,x) -#define PARAM_STATEINFO_OPT(x) ++paramnum; PARAM_STATEINFO_OPT_AT(paramnum,x) -#define PARAM_POINTER_OPT(x,type) ++paramnum; PARAM_POINTER_OPT_AT(paramnum,x,type) -#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) +#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_STATE_ACTION_DEF(x) ++paramnum; PARAM_STATE_ACTION_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) + +typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ + +struct AFuncDesc +{ + const char *Name; + actionf_p Function; + VMNativeFunction **VMPointer; +}; + +#if defined(_MSC_VER) +#pragma section(".areg$u",read) + +#define MSVC_ASEG __declspec(allocate(".areg$u")) +#define GCC_ASEG +#else +#define MSVC_ASEG +#define GCC_ASEG __attribute__((section(SECTION_AREG))) __attribute__((used)) +#endif + +// Macros to handle action functions. These are here so that I don't have to +// change every single use in case the parameters change. +#define DECLARE_ACTION(name) extern VMNativeFunction *name##_VMPtr; + +// This distinction is here so that CALL_ACTION produces errors when trying to +// access a function that requires parameters. +#define DEFINE_ACTION_FUNCTION(cls, name) \ + static int AF_##name(VM_ARGS); \ + VMNativeFunction *name##_VMPtr; \ + static const AFuncDesc cls##_##name##_Hook = { #name, AF_##name, &name##_VMPtr }; \ + extern AFuncDesc const *const cls##_##name##_HookPtr; \ + MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \ + static int AF_##name(VM_ARGS) + +#define DEFINE_ACTION_FUNCTION_PARAMS(cls, name) DEFINE_ACTION_FUNCTION(cls, name) + +//#define DECLARE_PARAMINFO AActor *self, AActor *stateowner, FState *CallingState, int ParameterIndex, StateCallData *statecall +//#define PUSH_PARAMINFO self, stateowner, CallingState, ParameterIndex, statecall + +class AActor; +void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); +#define CALL_ACTION(name, self) CallAction(stack, name##_VMPtr, self); + + +#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0) +#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_OBJECT); return 1; } return 0; } while(0) +#define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0) +#define ACTION_RETURN_VEC3(v) do { DVector3 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector(u); return 1; } return 0; } while(0) +#define ACTION_RETURN_INT(v) do { int u = v; if (numret > 0) { assert(ret != NULL); ret->SetInt(u); return 1; } return 0; } while(0) +#define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v) + +// Checks to see what called the current action function +#define ACTION_CALL_FROM_ACTOR() (stateinfo == nullptr || stateinfo->mStateType == STATE_Actor) +#define ACTION_CALL_FROM_PSPRITE() (self->player && stateinfo != nullptr && stateinfo->mStateType == STATE_Psprite) +#define ACTION_CALL_FROM_INVENTORY() (stateinfo != nullptr && stateinfo->mStateType == STATE_StateChain) + +// Standard parameters for all action functons +// self - Actor this action is to operate on (player if a weapon) +// stateowner - Actor this action really belongs to (may be an item) +// callingstate - State this action was called from +#define PARAM_ACTION_PROLOGUE(type) \ + PARAM_PROLOGUE; \ + PARAM_OBJECT (self, type); \ + PARAM_OBJECT (stateowner, AActor) \ + PARAM_POINTER (stateinfo, FStateParamInfo) \ + +// Number of action paramaters +#define NAP 3 + +#define PARAM_SELF_PROLOGUE(type) \ + PARAM_PROLOGUE; \ + PARAM_OBJECT(self, type); + + +class PFunction; + +VMFunction *FindVMFunction(PClass *cls, const char *name); +#define DECLARE_VMFUNC(cls, name) static VMFunction *name; if (name == nullptr) name = FindVMFunction(RUNTIME_CLASS(cls), #name); + + #endif diff --git a/src/zscript/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp similarity index 69% rename from src/zscript/vmbuilder.cpp rename to src/scripting/vm/vmbuilder.cpp index 8d7b5a8c1..19d89fc6f 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -1,4 +1,41 @@ +/* +** vmbuilder.cpp +** +**--------------------------------------------------------------------------- +** Copyright -2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include "vmbuilder.h" +#include "codegeneration/codegen.h" +#include "info.h" +#include "m_argv.h" +#include "thingdef.h" //========================================================================== // @@ -6,7 +43,7 @@ // //========================================================================== -VMFunctionBuilder::VMFunctionBuilder(bool selfcheck) +VMFunctionBuilder::VMFunctionBuilder(int numimplicits) { NumIntConstants = 0; NumFloatConstants = 0; @@ -14,7 +51,7 @@ VMFunctionBuilder::VMFunctionBuilder(bool selfcheck) NumStringConstants = 0; MaxParam = 0; ActiveParam = 0; - IsActionFunc = selfcheck; + NumImplicits = numimplicits; } //========================================================================== @@ -35,10 +72,8 @@ VMFunctionBuilder::~VMFunctionBuilder() // //========================================================================== -VMScriptFunction *VMFunctionBuilder::MakeFunction() +void VMFunctionBuilder::MakeFunction(VMScriptFunction *func) { - VMScriptFunction *func = new VMScriptFunction; - func->Alloc(Code.Size(), NumIntConstants, NumFloatConstants, NumStringConstants, NumAddressConstants); // Copy code block. @@ -73,8 +108,6 @@ VMScriptFunction *VMFunctionBuilder::MakeFunction() // entries on the parameter stack, but it means the caller probably // did something wrong. assert(ActiveParam == 0); - - return func; } //========================================================================== @@ -303,10 +336,10 @@ int VMFunctionBuilder::RegAvailability::Get(int count) { return -1; } - + mask = count == 32 ? ~0u : (1 << count) - 1; - for (i = 0; i < 256/32; ++i) + for (i = 0; i < 256 / 32; ++i) { // Find the first word with free registers VM_UWORD bits = Used[i]; @@ -329,9 +362,9 @@ int VMFunctionBuilder::RegAvailability::Get(int count) { if (firstbit + count <= 32) { // Needed bits all fit in one word, so we got it. - if (firstbit + count > MostUsed) + if (i * 32 + firstbit + count > MostUsed) { - MostUsed = firstbit + count; + MostUsed = i * 32 + firstbit + count; } Used[i] |= mask << firstbit; return i * 32 + firstbit; @@ -341,9 +374,9 @@ int VMFunctionBuilder::RegAvailability::Get(int count) { // There is a next word. if (((Used[i + 1]) & (mask >> (32 - firstbit))) == 0) { // The next word has the needed open space, too. - if (firstbit + count > MostUsed) + if (i * 32 + firstbit + count > MostUsed) { - MostUsed = firstbit + count; + MostUsed = i * 32 + firstbit + count; } Used[i] |= mask << firstbit; Used[i + 1] |= mask >> (32 - firstbit); @@ -465,7 +498,11 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc) assert(opc >= 0 && opc <= 255); if (opcode == OP_PARAM) { - ParamChange(1); + int chg; + if (opb & REGT_MULTIREG2) chg = 2; + else if (opb®T_MULTIREG3) chg = 3; + else chg = 1; + ParamChange(chg); } else if (opcode == OP_CALL || opcode == OP_CALL_K || opcode == OP_TAIL || opcode == OP_TAIL_K) { @@ -601,3 +638,144 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc) { Backpatch(loc, Code.Size()); } + +//========================================================================== +// +// FFunctionBuildList +// +// This list contains all functions yet to build. +// All adding functions return a VMFunction - either a complete one +// for native functions or an empty VMScriptFunction for scripted ones +// This VMScriptFunction object later gets filled in with the actual +// info, but we get the pointer right after registering the function +// with the builder. +// +//========================================================================== +FFunctionBuildList FunctionBuildList; + +VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount, int lumpnum) +{ + auto func = code->GetDirectFunction(); + if (func != nullptr) + { + delete code; + return func; + } + + //Printf("Adding %s\n", name.GetChars()); + + Item it; + it.Func = functype; + it.Code = code; + it.PrintableName = name; + it.Function = new VMScriptFunction; + it.Function->Name = functype->SymbolName; + it.Function->ImplicitArgs = functype->GetImplicitArgs(); + it.Proto = nullptr; + it.FromDecorate = fromdecorate; + it.StateIndex = stateindex; + it.StateCount = statecount; + it.Lump = lumpnum; + + // set prototype for named functions. + if (it.Func->SymbolName != NAME_None) + { + it.Function->Proto = it.Func->Variants[0].Proto; + } + + mItems.Push(it); + return it.Function; +} + + +void FFunctionBuildList::Build() +{ + int errorcount = 0; + int codesize = 0; + FILE *dump = nullptr; + + if (Args->CheckParm("-dumpdisasm")) dump = fopen("disasm.txt", "w"); + + for (auto &item : mItems) + { + assert(item.Code != NULL); + + // We don't know the return type in advance for anonymous functions. + FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate, item.StateIndex, item.StateCount, item.Lump); + + // Allocate registers for the function's arguments and create local variable nodes before starting to resolve it. + VMFunctionBuilder buildit(item.Func->GetImplicitArgs()); + for(unsigned i=0;iVariants[0].Proto->ArgumentTypes.Size();i++) + { + auto type = item.Func->Variants[0].Proto->ArgumentTypes[i]; + auto name = item.Func->Variants[0].ArgNames[i]; + auto flags = item.Func->Variants[0].ArgFlags[i]; + // this won't get resolved and won't get emitted. It is only needed so that the code generator can retrieve the necessary info about this argument to do its work. + auto local = new FxLocalVariableDeclaration(type, name, nullptr, flags, FScriptPosition()); + local->RegNum = buildit.Registers[type->GetRegType()].Get(type->GetRegCount()); + ctx.FunctionArgs.Push(local); + } + + FScriptPosition::StrictErrors = !item.FromDecorate; + item.Code = item.Code->Resolve(ctx); + + // Make sure resolving it didn't obliterate it. + if (item.Code != nullptr) + { + if (!item.Code->CheckReturn()) + { + auto newcmpd = new FxCompoundStatement(item.Code->ScriptPosition); + newcmpd->Add(item.Code); + newcmpd->Add(new FxReturnStatement(nullptr, item.Code->ScriptPosition)); + item.Code = newcmpd->Resolve(ctx); + } + + item.Proto = ctx.ReturnProto; + if (item.Proto == nullptr) + { + item.Code->ScriptPosition.Message(MSG_ERROR, "Function %s without prototype", item.PrintableName.GetChars()); + continue; + } + + // Generate prototype for anonymous functions. + VMScriptFunction *sfunc = item.Function; + // create a new prototype from the now known return type and the argument list of the function's template prototype. + if (sfunc->Proto == nullptr) + { + sfunc->Proto = NewPrototype(item.Proto->ReturnTypes, item.Func->Variants[0].Proto->ArgumentTypes); + } + + // Emit code + item.Code->Emit(&buildit); + buildit.MakeFunction(sfunc); + sfunc->NumArgs = 0; + // NumArgs for the VMFunction must be the amount of stack elements, which can differ from the amount of logical function arguments if vectors are in the list. + // For the VM a vector is 2 or 3 args, depending on size. + for (auto s : item.Func->Variants[0].Proto->ArgumentTypes) + { + sfunc->NumArgs += s->GetRegCount(); + } + + if (dump != nullptr) + { + DumpFunction(dump, sfunc, item.PrintableName.GetChars(), (int)item.PrintableName.Len()); + codesize += sfunc->CodeSize; + } + sfunc->PrintableName = item.PrintableName; + sfunc->Unsafe = ctx.Unsafe; + } + delete item.Code; + if (dump != nullptr) + { + fflush(dump); + } + } + if (dump != nullptr) + { + fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4); + fclose(dump); + } + FScriptPosition::StrictErrors = false; + mItems.Clear(); + FxAlloc.FreeAllBlocks(); +} \ No newline at end of file diff --git a/src/zscript/vmbuilder.h b/src/scripting/vm/vmbuilder.h similarity index 67% rename from src/zscript/vmbuilder.h rename to src/scripting/vm/vmbuilder.h index ed2516c2a..5394dec32 100644 --- a/src/zscript/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -23,10 +23,10 @@ public: friend class VMFunctionBuilder; }; - VMFunctionBuilder(bool checkself = false); + VMFunctionBuilder(int numimplicits); ~VMFunctionBuilder(); - VMScriptFunction *MakeFunction(); + void MakeFunction(VMScriptFunction *func); // Returns the constant register holding the value. int GetConstantInt(int val); @@ -60,8 +60,8 @@ public: // Track available registers. RegAvailability Registers[4]; - // For use by DECORATE's self/stateowner sanitizer. - bool IsActionFunc; + // amount of implicit parameters so that proper code can be emitted for method calls + int NumImplicits; private: struct AddrKonst @@ -87,4 +87,37 @@ private: }; +void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen); + + +//========================================================================== +// +// +// +//========================================================================== +class FxExpression; + +class FFunctionBuildList +{ + struct Item + { + PFunction *Func = nullptr; + FxExpression *Code = nullptr; + PPrototype *Proto = nullptr; + VMScriptFunction *Function = nullptr; + FString PrintableName; + int StateIndex; + int StateCount; + int Lump; + bool FromDecorate; + }; + + TArray mItems; + +public: + VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate = -1, int statecnt = 0, int lumpnum = -1); + void Build(); +}; + +extern FFunctionBuildList FunctionBuildList; #endif diff --git a/src/zscript/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp similarity index 83% rename from src/zscript/vmdisasm.cpp rename to src/scripting/vm/vmdisasm.cpp index 4e6f33ec7..49c929f05 100644 --- a/src/zscript/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -1,5 +1,39 @@ +/* +** vmdisasm.cpp +** +**--------------------------------------------------------------------------- +** Copyright -2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include "vm.h" #include "c_console.h" +#include "templates.h" #define NOP MODE_AUNUSED | MODE_BUNUSED | MODE_CUNUSED @@ -50,6 +84,7 @@ #define RPI8 MODE_AP | MODE_BIMMZ | MODE_CUNUSED #define KPI8 MODE_AKP | MODE_BIMMZ | MODE_CUNUSED #define RPI8I8 MODE_AP | MODE_BIMMZ | MODE_CIMMZ +#define RPRPI8 MODE_AP | MODE_BP | MODE_CIMMZ #define KPI8I8 MODE_AKP | MODE_BIMMZ | MODE_CIMMZ #define I8BCP MODE_AIMMZ | MODE_BCJOINT | MODE_BCPARAM #define THROW MODE_AIMMZ | MODE_BCTHROW @@ -83,6 +118,9 @@ #define RVRVRV MODE_AV | MODE_BV | MODE_CV #define RVRVKV MODE_AV | MODE_BV | MODE_CKV #define RVKVRV MODE_AV | MODE_BKV | MODE_CV +#define RVRVRF MODE_AV | MODE_BV | MODE_CF +#define RVRVKF MODE_AV | MODE_BV | MODE_CKF +#define RVKVRF MODE_AV | MODE_BKV | MODE_CF #define RFRV MODE_AF | MODE_BV | MODE_CUNUSED #define I8RVRV MODE_AIMMZ | MODE_BV | MODE_CV #define I8RVKV MODE_AIMMZ | MODE_BV | MODE_CKV @@ -162,7 +200,7 @@ static int printf_wrapper(FILE *f, const char *fmt, ...) void VMDumpConstants(FILE *out, const VMScriptFunction *func) { - char tmp[21]; + char tmp[30]; int i, j, k, kk; if (func->KonstD != NULL && func->NumKonstD != 0) @@ -202,7 +240,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func) for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk) { mysnprintf(tmp, countof(tmp), "%3d. %p:%d", k, func->KonstA[k].v, func->KonstATags()[k]); - printf_wrapper(out, "%-20s", tmp); + printf_wrapper(out, "%-22s", tmp); } printf_wrapper(out, "\n"); } @@ -345,6 +383,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction case CAST_I2F: mode = MODE_AF | MODE_BI | MODE_CUNUSED; break; + case CAST_Co2S: + case CAST_So2S: + case CAST_N2S: case CAST_I2S: mode = MODE_AS | MODE_BI | MODE_CUNUSED; break; @@ -357,6 +398,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction case CAST_P2S: mode = MODE_AS | MODE_BP | MODE_CUNUSED; break; + case CAST_S2Co: + case CAST_S2So: + case CAST_S2N: case CAST_S2I: mode = MODE_AI | MODE_BS | MODE_CUNUSED; break; @@ -535,8 +579,10 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const return col+printf_wrapper(out, "s%d", regnum); case REGT_POINTER: return col+printf_wrapper(out, "a%d", regnum); - case REGT_FLOAT | REGT_MULTIREG: - return col+printf_wrapper(out, "v%d", regnum); + case REGT_FLOAT | REGT_MULTIREG2: + return col+printf_wrapper(out, "v%d.2", regnum); + case REGT_FLOAT | REGT_MULTIREG3: + return col+printf_wrapper(out, "v%d.3", regnum); case REGT_INT | REGT_KONST: return col+print_reg(out, 0, regnum, MODE_KI, 0, func); case REGT_FLOAT | REGT_KONST: @@ -565,3 +611,21 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const } return col; } + +//========================================================================== +// +// Do some postprocessing after everything has been defined +// +//========================================================================== + +void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen) +{ + const char *marks = "======================================================="; + fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks); + fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n", + sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam); + VMDumpConstants(dump, sfunc); + fprintf(dump, "\nDisassembly @ %p:\n", sfunc->Code); + VMDisasm(dump, sfunc->Code, sfunc->CodeSize, sfunc); +} + diff --git a/src/zscript/vmexec.cpp b/src/scripting/vm/vmexec.cpp similarity index 67% rename from src/zscript/vmexec.cpp rename to src/scripting/vm/vmexec.cpp index 7ee89329a..57ce48a95 100644 --- a/src/zscript/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -1,4 +1,39 @@ +/* +** vmexec.cpp +** +**--------------------------------------------------------------------------- +** Copyright -2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include +#include +#include #include "vm.h" #include "xs_Float.h" #include "math/cmath.h" @@ -153,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->DefaultArgs.Size() == calleefunc->NumArgs)); 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->DefaultArgs[i]; if (p.Type < REGT_STRING) { if (p.Type == REGT_INT) diff --git a/src/zscript/vmexec.h b/src/scripting/vm/vmexec.h similarity index 82% rename from src/zscript/vmexec.h rename to src/scripting/vm/vmexec.h index 3637f2c1c..02e0db3de 100644 --- a/src/zscript/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -175,13 +175,13 @@ begin: OP(LO): ASSERTA(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); - reg.a[a] = *(void **)ptr; + reg.a[a] = *(DObject **)ptr; reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(LO_R): ASSERTA(a); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); - reg.a[a] = *(void **)ptr; + reg.a[a] = GC::ReadBarrier(*(DObject **)ptr); reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(LP): @@ -196,21 +196,39 @@ begin: reg.a[a] = *(void **)ptr; reg.atag[a] = ATAG_GENERIC; NEXTOP; - OP(LV): + OP(LV2): ASSERTF(a+2); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); { - float *v = (float *)ptr; + auto v = (double *)ptr; + reg.f[a] = v[0]; + reg.f[a+1] = v[1]; + } + NEXTOP; + OP(LV2_R): + ASSERTF(a+2); ASSERTA(B); ASSERTD(C); + GETADDR(PB,RC,X_READ_NIL); + { + auto v = (double *)ptr; + reg.f[a] = v[0]; + reg.f[a+1] = v[1]; + } + NEXTOP; + OP(LV3): + ASSERTF(a+2); ASSERTA(B); ASSERTKD(C); + GETADDR(PB,KC,X_READ_NIL); + { + auto v = (double *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; reg.f[a+2] = v[2]; } NEXTOP; - OP(LV_R): + OP(LV3_R): ASSERTF(a+2); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); { - float *v = (float *)ptr; + auto v = (double *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; reg.f[a+2] = v[2]; @@ -292,24 +310,42 @@ begin: GETADDR(PA,RC,X_WRITE_NIL); *(void **)ptr = reg.a[B]; NEXTOP; - OP(SV): + OP(SV2): ASSERTA(a); ASSERTF(B+2); ASSERTKD(C); GETADDR(PA,KC,X_WRITE_NIL); { - float *v = (float *)ptr; - v[0] = (float)reg.f[B]; - v[1] = (float)reg.f[B+1]; - v[2] = (float)reg.f[B+2]; + auto v = (double *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; } NEXTOP; - OP(SV_R): + OP(SV2_R): ASSERTA(a); ASSERTF(B+2); ASSERTD(C); GETADDR(PA,RC,X_WRITE_NIL); { - float *v = (float *)ptr; - v[0] = (float)reg.f[B]; - v[1] = (float)reg.f[B+1]; - v[2] = (float)reg.f[B+2]; + auto v = (double *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + } + NEXTOP; + OP(SV3): + ASSERTA(a); ASSERTF(B+2); ASSERTKD(C); + GETADDR(PA,KC,X_WRITE_NIL); + { + auto v = (double *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + v[2] = reg.f[B+2]; + } + NEXTOP; + OP(SV3_R): + ASSERTA(a); ASSERTF(B+2); ASSERTD(C); + GETADDR(PA,RC,X_WRITE_NIL); + { + auto v = (double *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + v[2] = reg.f[B+2]; } NEXTOP; OP(SBIT): @@ -342,6 +378,17 @@ begin: reg.a[a] = reg.a[B]; reg.atag[a] = reg.atag[B]; NEXTOP; + OP(MOVEV2): + ASSERTF(a); ASSERTF(B); + reg.f[a] = reg.f[B]; + reg.f[a+1] = reg.f[B+1]; + NEXTOP; + OP(MOVEV3): + ASSERTF(a); ASSERTF(B); + reg.f[a] = reg.f[B]; + reg.f[a+1] = reg.f[B+1]; + reg.f[a+2] = reg.f[B+2]; + NEXTOP; OP(CAST): if (C == CAST_I2F) { @@ -372,6 +419,13 @@ begin: pc++; } NEXTOP; + OP(TESTN): + ASSERTD(a); + if (-reg.d[a] != BC) + { + pc++; + } + NEXTOP; OP(JMP): pc += JMPOFS(pc); NEXTOP; @@ -399,7 +453,7 @@ begin: } else { - switch(b & (REGT_TYPE | REGT_KONST | REGT_ADDROF)) + switch(b) { case REGT_INT: assert(C < f->NumRegD); @@ -438,40 +492,31 @@ begin: ::new(param) VMValue(konsta[C].v, konstatag[C]); break; case REGT_FLOAT: - if (b & REGT_MULTIREG) - { - assert(C < f->NumRegF - 2); - assert(f->NumParam < sfunc->MaxParam - 1); - ::new(param) VMValue(reg.f[C]); - ::new(param+1) VMValue(reg.f[C+1]); - ::new(param+2) VMValue(reg.f[C+2]); - f->NumParam += 2; - } - else - { - assert(C < f->NumRegF); - ::new(param) VMValue(reg.f[C]); - } + assert(C < f->NumRegF); + ::new(param) VMValue(reg.f[C]); + break; + case REGT_FLOAT | REGT_MULTIREG2: + assert(C < f->NumRegF - 1); + assert(f->NumParam < sfunc->MaxParam); + ::new(param) VMValue(reg.f[C]); + ::new(param + 1) VMValue(reg.f[C + 1]); + f->NumParam++; + break; + case REGT_FLOAT | REGT_MULTIREG3: + assert(C < f->NumRegF - 2); + assert(f->NumParam < sfunc->MaxParam - 1); + ::new(param) VMValue(reg.f[C]); + ::new(param + 1) VMValue(reg.f[C + 1]); + ::new(param + 2) VMValue(reg.f[C + 2]); + f->NumParam += 2; break; case REGT_FLOAT | REGT_ADDROF: assert(C < f->NumRegF); ::new(param) VMValue(®.f[C], ATAG_FREGISTER); break; case REGT_FLOAT | REGT_KONST: - if (b & REGT_MULTIREG) - { - assert(C < sfunc->NumKonstF - 2); - assert(f->NumParam < sfunc->MaxParam - 1); - ::new(param) VMValue(konstf[C]); - ::new(param+1) VMValue(konstf[C+1]); - ::new(param+2) VMValue(konstf[C+2]); - f->NumParam += 2; - } - else - { - assert(C < sfunc->NumKonstF); - ::new(param) VMValue(konstf[C]); - } + assert(C < sfunc->NumKonstF); + ::new(param) VMValue(konstf[C]); break; default: assert(0); @@ -480,6 +525,15 @@ begin: } } NEXTOP; + OP(VTBL): + ASSERTA(a); ASSERTA(B); + { + auto o = (DObject*)reg.a[B]; + auto p = o->GetClass(); + assert(C < p->Virtuals.Size()); + reg.a[a] = p->Virtuals[C]; + } + NEXTOP; OP(CALL_K): ASSERTKA(a); assert(konstatag[a] == ATAG_OBJECT); @@ -499,7 +553,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->DefaultArgs, B, returns, C); } else { @@ -543,7 +597,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->DefaultArgs, B, ret, numret); } else { // FIXME: Not a true tail call @@ -819,6 +873,31 @@ begin: reg.d[a] = konstd[B] / reg.d[C]; NEXTOP; + OP(DIVU_RR): + ASSERTD(a); ASSERTD(B); ASSERTD(C); + if (reg.d[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } + reg.d[a] = int((unsigned)reg.d[B] / (unsigned)reg.d[C]); + NEXTOP; + OP(DIVU_RK): + ASSERTD(a); ASSERTD(B); ASSERTKD(C); + if (konstd[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } + reg.d[a] = int((unsigned)reg.d[B] / (unsigned)konstd[C]); + NEXTOP; + OP(DIVU_KR): + ASSERTD(a); ASSERTKD(B); ASSERTD(C); + if (reg.d[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } + reg.d[a] = int((unsigned)konstd[B] / (unsigned)reg.d[C]); + NEXTOP; + OP(MOD_RR): ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) @@ -844,6 +923,31 @@ begin: reg.d[a] = konstd[B] % reg.d[C]; NEXTOP; + OP(MODU_RR): + ASSERTD(a); ASSERTD(B); ASSERTD(C); + if (reg.d[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } + reg.d[a] = int((unsigned)reg.d[B] % (unsigned)reg.d[C]); + NEXTOP; + OP(MODU_RK): + ASSERTD(a); ASSERTD(B); ASSERTKD(C); + if (konstd[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } + reg.d[a] = int((unsigned)reg.d[B] % (unsigned)konstd[C]); + NEXTOP; + OP(MODU_KR): + ASSERTD(a); ASSERTKD(B); ASSERTD(C); + if (reg.d[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } + reg.d[a] = int((unsigned)konstd[B] % (unsigned)reg.d[C]); + NEXTOP; + OP(AND_RR): ASSERTD(a); ASSERTD(B); ASSERTD(C); reg.d[a] = reg.d[B] & reg.d[C]; @@ -867,7 +971,7 @@ begin: reg.d[a] = reg.d[B] ^ reg.d[C]; NEXTOP; OP(XOR_RK): - ASSERTD(a); ASSERTD(B); ASSERTD(C); + ASSERTD(a); ASSERTD(B); ASSERTKD(C); reg.d[a] = reg.d[B] ^ konstd[C]; NEXTOP; @@ -1061,15 +1165,15 @@ begin: OP(POWF_RR): ASSERTF(a); ASSERTF(B); ASSERTF(C); - reg.f[a] = pow(reg.f[B], reg.f[C]); + reg.f[a] = g_pow(reg.f[B], reg.f[C]); NEXTOP; OP(POWF_RK): ASSERTF(a); ASSERTF(B); ASSERTKF(C); - reg.f[a] = pow(reg.f[B], konstf[C]); + reg.f[a] = g_pow(reg.f[B], konstf[C]); NEXTOP; OP(POWF_KR): ASSERTF(a); ASSERTKF(B); ASSERTF(C); - reg.f[a] = pow(konstf[B], reg.f[C]); + reg.f[a] = g_pow(konstf[B], reg.f[C]); NEXTOP; OP(MINF_RR): @@ -1189,51 +1293,149 @@ begin: } NEXTOP; - OP(NEGV): + OP(NEGV2): + ASSERTF(a+1); ASSERTF(B+1); + reg.f[a] = -reg.f[B]; + reg.f[a+1] = -reg.f[B+1]; + NEXTOP; + + OP(ADDV2_RR): + ASSERTF(a+1); ASSERTF(B+1); ASSERTF(C+1); + fcp = ®.f[C]; + Do_ADDV2: + fbp = ®.f[B]; + reg.f[a] = fbp[0] + fcp[0]; + reg.f[a+1] = fbp[1] + fcp[1]; + NEXTOP; + OP(ADDV2_RK): + fcp = &konstf[C]; + goto Do_ADDV2; + + OP(SUBV2_RR): + ASSERTF(a+1); ASSERTF(B+1); ASSERTF(C+1); + fbp = ®.f[B]; + fcp = ®.f[C]; + Do_SUBV2: + reg.f[a] = fbp[0] - fcp[0]; + reg.f[a+1] = fbp[1] - fcp[1]; + NEXTOP; + OP(SUBV2_RK): + ASSERTF(a+1); ASSERTF(B+1); ASSERTKF(C+1); + fbp = ®.f[B]; + fcp = &konstf[C]; + goto Do_SUBV2; + OP(SUBV2_KR): + ASSERTF(A+1); ASSERTKF(B+1); ASSERTF(C+1); + fbp = &konstf[B]; + fcp = ®.f[C]; + goto Do_SUBV2; + + OP(DOTV2_RR): + ASSERTF(a); ASSERTF(B+1); ASSERTF(C+1); + reg.f[a] = reg.f[B] * reg.f[C] + reg.f[B+1] * reg.f[C+1]; + NEXTOP; + OP(DOTV2_RK): + ASSERTF(a); ASSERTF(B+1); ASSERTKF(C+1); + reg.f[a] = reg.f[B] * konstf[C] + reg.f[B+1] * konstf[C+1]; + NEXTOP; + + OP(MULVF2_RR): + ASSERTF(a+1); ASSERTF(B+1); ASSERTF(C); + fc = reg.f[C]; + fbp = ®.f[B]; + Do_MULV2: + reg.f[a] = fbp[0] * fc; + reg.f[a+1] = fbp[1] * fc; + NEXTOP; + OP(MULVF2_RK): + ASSERTF(a+1); ASSERTF(B+1); ASSERTKF(C); + fc = konstf[C]; + fbp = ®.f[B]; + goto Do_MULV2; + + OP(DIVVF2_RR): + ASSERTF(a+1); ASSERTF(B+1); ASSERTF(C); + fc = reg.f[C]; + fbp = ®.f[B]; + Do_DIVV2: + reg.f[a] = fbp[0] / fc; + reg.f[a+1] = fbp[1] / fc; + NEXTOP; + OP(DIVVF2_RK): + ASSERTF(a+1); ASSERTF(B+1); ASSERTKF(C); + fc = konstf[C]; + fbp = ®.f[B]; + goto Do_DIVV2; + + OP(LENV2): + ASSERTF(a); ASSERTF(B+1); + reg.f[a] = g_sqrt(reg.f[B] * reg.f[B] + reg.f[B+1] * reg.f[B+1]); + NEXTOP; + + OP(EQV2_R): + ASSERTF(B+1); ASSERTF(C+1); + fcp = ®.f[C]; + Do_EQV2: + if (a & CMP_APPROX) + { + CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && + fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON); + } + else + { + CMPJMP(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1]); + } + NEXTOP; + OP(EQV2_K): + ASSERTF(B+1); ASSERTKF(C+1); + fcp = &konstf[C]; + goto Do_EQV2; + + OP(NEGV3): ASSERTF(a+2); ASSERTF(B+2); reg.f[a] = -reg.f[B]; reg.f[a+1] = -reg.f[B+1]; reg.f[a+2] = -reg.f[B+2]; NEXTOP; - OP(ADDV_RR): + OP(ADDV3_RR): ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C+2); fcp = ®.f[C]; - Do_ADDV: + Do_ADDV3: fbp = ®.f[B]; reg.f[a] = fbp[0] + fcp[0]; reg.f[a+1] = fbp[1] + fcp[1]; reg.f[a+2] = fbp[2] + fcp[2]; NEXTOP; - OP(ADDV_RK): + OP(ADDV3_RK): fcp = &konstf[C]; - goto Do_ADDV; + goto Do_ADDV3; - OP(SUBV_RR): + OP(SUBV3_RR): ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C+2); fbp = ®.f[B]; fcp = ®.f[C]; - Do_SUBV: + Do_SUBV3: reg.f[a] = fbp[0] - fcp[0]; reg.f[a+1] = fbp[1] - fcp[1]; reg.f[a+2] = fbp[2] - fcp[2]; NEXTOP; - OP(SUBV_RK): + OP(SUBV3_RK): ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C+2); fbp = ®.f[B]; fcp = &konstf[C]; - goto Do_SUBV; - OP(SUBV_KR): + goto Do_SUBV3; + OP(SUBV3_KR): ASSERTF(A+2); ASSERTKF(B+2); ASSERTF(C+2); fbp = &konstf[B]; fcp = ®.f[C]; - goto Do_SUBV; + goto Do_SUBV3; - OP(DOTV_RR): + OP(DOTV3_RR): ASSERTF(a); ASSERTF(B+2); ASSERTF(C+2); reg.f[a] = reg.f[B] * reg.f[C] + reg.f[B+1] * reg.f[C+1] + reg.f[B+2] * reg.f[C+2]; NEXTOP; - OP(DOTV_RK): + OP(DOTV3_RK): ASSERTF(a); ASSERTF(B+2); ASSERTKF(C+2); reg.f[a] = reg.f[B] * konstf[C] + reg.f[B+1] * konstf[C+1] + reg.f[B+2] * konstf[C+2]; NEXTOP; @@ -1262,35 +1464,45 @@ begin: fcp = &konstf[C]; goto Do_CROSSV; - OP(MULVF_RR): + OP(MULVF3_RR): ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C); fc = reg.f[C]; fbp = ®.f[B]; - Do_MULV: + Do_MULV3: reg.f[a] = fbp[0] * fc; reg.f[a+1] = fbp[1] * fc; reg.f[a+2] = fbp[2] * fc; NEXTOP; - OP(MULVF_RK): + OP(MULVF3_RK): ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C); fc = konstf[C]; fbp = ®.f[B]; - goto Do_MULV; - OP(MULVF_KR): - ASSERTF(a+2); ASSERTKF(B+2); ASSERTF(C); - fc = reg.f[C]; - fbp = &konstf[B]; - goto Do_MULV; + goto Do_MULV3; - OP(LENV): + OP(DIVVF3_RR): + ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C); + fc = reg.f[C]; + fbp = ®.f[B]; + Do_DIVV3: + reg.f[a] = fbp[0] / fc; + reg.f[a+1] = fbp[1] / fc; + reg.f[a+2] = fbp[2] / fc; + NEXTOP; + OP(DIVVF3_RK): + ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C); + fc = konstf[C]; + fbp = ®.f[B]; + goto Do_DIVV3; + + OP(LENV3): ASSERTF(a); ASSERTF(B+2); reg.f[a] = g_sqrt(reg.f[B] * reg.f[B] + reg.f[B+1] * reg.f[B+1] + reg.f[B+2] * reg.f[B+2]); NEXTOP; - OP(EQV_R): + OP(EQV3_R): ASSERTF(B+2); ASSERTF(C+2); fcp = ®.f[C]; - Do_EQV: + Do_EQV3: if (a & CMP_APPROX) { CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && @@ -1302,10 +1514,10 @@ begin: CMPJMP(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1] && reg.f[B+2] == fcp[2]); } NEXTOP; - OP(EQV_K): + OP(EQV3_K): ASSERTF(B+2); ASSERTKF(C+2); fcp = &konstf[C]; - goto Do_EQV; + goto Do_EQV3; OP(ADDA_RR): ASSERTA(a); ASSERTA(B); ASSERTD(C); @@ -1472,6 +1684,39 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c reg.f[a] = reg.s[b].ToDouble(); break; + case CAST_S2N: + ASSERTD(a); ASSERTS(b); + reg.d[a] = reg.s[b].Len() == 0? FName(NAME_None) : FName(reg.s[b]); + break; + + case CAST_N2S: + { + ASSERTS(a); ASSERTD(b); + FName name = FName(ENamedName(reg.d[b])); + reg.s[a] = name.IsValidName() ? name.GetChars() : ""; + break; + } + + case CAST_S2Co: + ASSERTD(a); ASSERTS(b); + reg.d[a] = V_GetColor(NULL, reg.s[b]); + break; + + case CAST_Co2S: + ASSERTS(a); ASSERTD(b); + reg.s[a].Format("%02x %02x %02x", PalEntry(reg.d[b]).r, PalEntry(reg.d[b]).g, PalEntry(reg.d[b]).b); + break; + + case CAST_S2So: + ASSERTD(a); ASSERTS(b); + reg.d[a] = FSoundID(reg.s[b]); + break; + + case CAST_So2S: + ASSERTS(a); ASSERTD(b); + reg.s[a] = S_sfx[reg.d[b]].name; + break; + default: assert(0); } @@ -1572,10 +1817,14 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_ assert(regnum + ((regtype & REGT_KONST) ? 2u : 0u) < frame->NumRegF); src = ®.f[regnum]; } - if (regtype & REGT_MULTIREG) + if (regtype & REGT_MULTIREG3) { ret->SetVector((double *)src); } + else if (regtype & REGT_MULTIREG2) + { + ret->SetVector2((double *)src); + } else { ret->SetFloat(*(double *)src); diff --git a/src/zscript/vmframe.cpp b/src/scripting/vm/vmframe.cpp similarity index 81% rename from src/zscript/vmframe.cpp rename to src/scripting/vm/vmframe.cpp index 50c7d78d9..3a593861c 100644 --- a/src/zscript/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -1,12 +1,48 @@ +/* +** vmframe.cpp +** +**--------------------------------------------------------------------------- +** Copyright -2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include #include "vm.h" -IMPLEMENT_CLASS(VMException) -IMPLEMENT_ABSTRACT_POINTY_CLASS(VMFunction) - DECLARE_POINTER(Proto) -END_POINTERS -IMPLEMENT_CLASS(VMScriptFunction) -IMPLEMENT_CLASS(VMNativeFunction) +IMPLEMENT_CLASS(VMException, false, false, false, false) +IMPLEMENT_CLASS(VMFunction, true, true, false, false) + +IMPLEMENT_POINTERS_START(VMFunction) + IMPLEMENT_POINTER(Proto) +IMPLEMENT_POINTERS_END + +IMPLEMENT_CLASS(VMScriptFunction, false, false, false, false) +IMPLEMENT_CLASS(VMNativeFunction, false, false, false, false) VMScriptFunction::VMScriptFunction(FName name) { @@ -382,7 +418,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->DefaultArgs, numparams, results, numresults); } else { @@ -458,3 +494,11 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur throw; } } + +class AActor; +void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self) +{ + // Without the type cast this picks the 'void *' assignment... + VMValue params[3] = { (DObject*)self, (DObject*)self, VMValue(nullptr, ATAG_GENERIC) }; + stack->Call(vmfunc, params, vmfunc->ImplicitArgs, nullptr, 0, nullptr); +} diff --git a/src/zscript/vmops.h b/src/scripting/vm/vmops.h similarity index 78% rename from src/zscript/vmops.h rename to src/scripting/vm/vmops.h index 39d224f5c..368f143bd 100644 --- a/src/zscript/vmops.h +++ b/src/scripting/vm/vmops.h @@ -33,8 +33,10 @@ xx(LO, lo, RPRPKI), // load object xx(LO_R, lo, RPRPRI), xx(LP, lp, RPRPKI), // load pointer xx(LP_R, lp, RPRPRI), -xx(LV, lv, RVRPKI), // load vector -xx(LV_R, lv, RVRPRI), +xx(LV2, lv2, RVRPKI), // load vector2 +xx(LV2_R, lv2, RVRPRI), +xx(LV3, lv3, RVRPKI), // load vector3 +xx(LV3_R, lv3, RVRPRI), xx(LBIT, lbit, RIRPI8), // rA = !!(*rB & C) -- *rB is a byte @@ -53,8 +55,10 @@ xx(SS, ss, RPRSKI), // store string xx(SS_R, ss, RPRSRI), xx(SP, sp, RPRPKI), // store pointer xx(SP_R, sp, RPRPRI), -xx(SV, sv, RPRVKI), // store vector -xx(SV_R, sv, RPRVRI), +xx(SV2, sv2, RPRVKI), // store vector2 +xx(SV2_R, sv2, RPRVRI), +xx(SV3, sv3, RPRVKI), // store vector3 +xx(SV3_R, sv3, RPRVRI), xx(SBIT, sbit, RPRII8), // *rA |= C if rB is true, *rA &= ~C otherwise @@ -63,18 +67,22 @@ xx(MOVE, mov, RIRI), // dA = dB xx(MOVEF, mov, RFRF), // fA = fB xx(MOVES, mov, RSRS), // sA = sB xx(MOVEA, mov, RPRP), // aA = aB +xx(MOVEV2, mov2, RFRF), // fA = fB (2 elements) +xx(MOVEV3, mov3, RFRF), // fA = fB (3 elements) xx(CAST, cast, CAST), // xA = xB, conversion specified by C xx(DYNCAST_R, dyncast,RPRPRP), // aA = aB after casting to rkC (specifying a class) xx(DYNCAST_K, dyncast,RPRPKP), // Control flow. xx(TEST, test, RII16), // if (dA != BC) then pc++ +xx(TESTN, testn, RII16), // if (dA != -BC) then pc++ xx(JMP, jmp, I24), // pc += ABC -- The ABC fields contain a signed 24-bit offset. xx(IJMP, ijmp, RII16), // pc += dA + BC -- BC is a signed offset. The target instruction must be a JMP. xx(PARAM, param, __BCP), // push parameter encoded in BC for function call (B=regtype, C=regnum) xx(PARAMI, parami, I24), // push immediate, signed integer for function call xx(CALL, call, RPI8I8), // Call function pkA with parameter count B and expected result count C xx(CALL_K, call, KPI8I8), +xx(VTBL, vtbl, RPRPI8), // dereferences a virtual method table. xx(TAIL, tail, RPI8), // Call+Ret in a single instruction xx(TAIL_K, tail, KPI8), xx(RESULT, result, __BCP), // Result should go in register encoded in BC (in caller, after CALL) @@ -115,12 +123,18 @@ xx(SUB_RK, sub, RIRIKI), xx(SUB_KR, sub, RIKIRI), xx(MUL_RR, mul, RIRIRI), // dA = dB * dkC xx(MUL_RK, mul, RIRIKI), -xx(DIV_RR, div, RIRIRI), // dA = dkB / dkC +xx(DIV_RR, div, RIRIRI), // dA = dkB / dkC (signed) xx(DIV_RK, div, RIRIKI), xx(DIV_KR, div, RIKIRI), -xx(MOD_RR, mod, RIRIRI), // dA = dkB % dkC +xx(DIVU_RR, divu, RIRIRI), // dA = dkB / dkC (unsigned) +xx(DIVU_RK, divu, RIRIKI), +xx(DIVU_KR, divu, RIKIRI), +xx(MOD_RR, mod, RIRIRI), // dA = dkB % dkC (signed) xx(MOD_RK, mod, RIRIKI), xx(MOD_KR, mod, RIKIRI), +xx(MODU_RR, modu, RIRIRI), // dA = dkB % dkC (unsigned) +xx(MODU_RK, modu, RIRIKI), +xx(MODU_KR, modu, RIKIRI), xx(AND_RR, and, RIRIRI), // dA = dB & dkC xx(AND_RK, and, RIRIKI), xx(OR_RR, or, RIRIRI), // dA = dB | dkC @@ -186,24 +200,42 @@ xx(LEF_RR, ble, CFRR), // if ((fkb <= fkC) != (A & 1)) then pc++ xx(LEF_RK, ble, CFRK), xx(LEF_KR, ble, CFKR), -// Vector math. -xx(NEGV, negv, RVRV), // vA = -vB -xx(ADDV_RR, addv, RVRVRV), // vA = vB + vkC -xx(ADDV_RK, addv, RVRVKV), -xx(SUBV_RR, subv, RVRVRV), // vA = vkB - vkC -xx(SUBV_RK, subv, RVRVKV), -xx(SUBV_KR, subv, RVKVRV), -xx(DOTV_RR, dotv, RVRVRV), // va = vB dot vkC -xx(DOTV_RK, dotv, RVRVKV), +// Vector math. (2D) +xx(NEGV2, negv2, RVRV), // vA = -vB +xx(ADDV2_RR, addv2, RVRVRV), // vA = vB + vkC +xx(ADDV2_RK, addv2, RVRVKV), +xx(SUBV2_RR, subv2, RVRVRV), // vA = vkB - vkC +xx(SUBV2_RK, subv2, RVRVKV), +xx(SUBV2_KR, subv2, RVKVRV), +xx(DOTV2_RR, dotv2, RVRVRV), // va = vB dot vkC +xx(DOTV2_RK, dotv2, RVRVKV), +xx(MULVF2_RR, mulv2, RVRVRF), // vA = vkB * fkC +xx(MULVF2_RK, mulv2, RVRVKF), +xx(DIVVF2_RR, divv2, RVRVRF), // vA = vkB / fkC +xx(DIVVF2_RK, divv2, RVRVKF), +xx(LENV2, lenv2, RFRV), // fA = vB.Length +xx(EQV2_R, beqv2, CVRR), // if ((vB == vkC) != A) then pc++ (inexact if A & 32) +xx(EQV2_K, beqv2, CVRK), + +// Vector math (3D) +xx(NEGV3, negv3, RVRV), // vA = -vB +xx(ADDV3_RR, addv3, RVRVRV), // vA = vB + vkC +xx(ADDV3_RK, addv3, RVRVKV), +xx(SUBV3_RR, subv3, RVRVRV), // vA = vkB - vkC +xx(SUBV3_RK, subv3, RVRVKV), +xx(SUBV3_KR, subv3, RVKVRV), +xx(DOTV3_RR, dotv3, RVRVRV), // va = vB dot vkC +xx(DOTV3_RK, dotv3, RVRVKV), xx(CROSSV_RR, crossv, RVRVRV), // vA = vkB cross vkC xx(CROSSV_RK, crossv, RVRVKV), xx(CROSSV_KR, crossv, RVKVRV), -xx(MULVF_RR, mulv, RVRVRV), // vA = vkB * fkC -xx(MULVF_RK, mulv, RVRVKV), -xx(MULVF_KR, mulv, RVKVRV), -xx(LENV, lenv, RFRV), // fA = vB.Length -xx(EQV_R, beqv, CVRR), // if ((vB == vkC) != A) then pc++ (inexact if A & 32) -xx(EQV_K, beqv, CVRK), +xx(MULVF3_RR, mulv3, RVRVRF), // vA = vkB * fkC +xx(MULVF3_RK, mulv3, RVRVKF), +xx(DIVVF3_RR, divv3, RVRVRF), // vA = vkB / fkC +xx(DIVVF3_RK, divv3, RVRVKF), +xx(LENV3, lenv3, RFRV), // fA = vB.Length +xx(EQV3_R, beqv3, CVRR), // if ((vB == vkC) != A) then pc++ (inexact if A & 33) +xx(EQV3_K, beqv3, CVRK), // Pointer math. xx(ADDA_RR, add, RPRPRI), // pA = pB + dkC diff --git a/src/zscript/ast.cpp b/src/scripting/zscript/ast.cpp similarity index 84% rename from src/zscript/ast.cpp rename to src/scripting/zscript/ast.cpp index a68b1c69f..c24867837 100644 --- a/src/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -1,3 +1,36 @@ +/* +** ast.cpp +** +**--------------------------------------------------------------------------- +** Copyright -2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include "dobject.h" #include "sc_man.h" #include "memarena.h" @@ -19,9 +52,13 @@ static const char *BuiltInTypeNames[] = "string", "vector2", "vector3", - "vector4", "name", - "usertype" + "color", + "state", + "sound", + + "usertype", + }; class FLispString @@ -32,7 +69,7 @@ public: FLispString() { NestDepth = Column = 0; - WrapWidth = 72; + WrapWidth = 200; NeedSpace = false; ConsecOpens = 0; } @@ -321,6 +358,7 @@ static void PrintStates(FLispString &out, ZCC_TreeNode *node) ZCC_States *snode = (ZCC_States *)node; out.Break(); out.Open("states"); + PrintNodes(out, snode->Flags, false, true); PrintNodes(out, snode->Body, false, true); out.Close(); } @@ -367,6 +405,7 @@ static void PrintStateGoto(FLispString &out, ZCC_TreeNode *node) { ZCC_StateGoto *snode = (ZCC_StateGoto *)node; out.Open("state-goto"); + PrintNodes(out, snode->Qualifier); PrintNodes(out, snode->Label); PrintNodes(out, snode->Offset); out.Close(); @@ -376,7 +415,8 @@ static void PrintStateLine(FLispString &out, ZCC_TreeNode *node) { ZCC_StateLine *snode = (ZCC_StateLine *)node; out.Open("state-line"); - out.Add(snode->Sprite, 4); + out.Add(*(snode->Sprite)); + PrintNodes(out, snode->Duration); if (snode->bNoDelay) out.Add("nodelay", 7); if (snode->bBright) out.Add("bright", 6); if (snode->bFast) out.Add("fast", 4); @@ -397,6 +437,17 @@ static void PrintVarName(FLispString &out, ZCC_TreeNode *node) out.Close(); } +static void PrintVarInit(FLispString &out, ZCC_TreeNode *node) +{ + ZCC_VarInit *vnode = (ZCC_VarInit *)node; + out.Open("var-init"); + PrintNodes(out, vnode->ArraySize); + PrintNodes(out, vnode->Init); + if (vnode->InitIsArray) out.Add("array", 5); + out.AddName(vnode->Name); + out.Close(); +} + static void PrintType(FLispString &out, ZCC_TreeNode *node) { ZCC_Type *tnode = (ZCC_Type *)node; @@ -571,6 +622,16 @@ static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node) out.Close(); } +static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node) +{ + ZCC_VectorValue *enode = (ZCC_VectorValue *)node; + OpenExprType(out, enode->Operation); + PrintNodes(out, enode->X); + PrintNodes(out, enode->Y); + PrintNodes(out, enode->Z); + out.Close(); +} + static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node) { ZCC_FuncParm *pnode = (ZCC_FuncParm *)node; @@ -596,6 +657,15 @@ static void PrintCompoundStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } +static void PrintDefault(FLispString &out, ZCC_TreeNode *node) +{ + ZCC_Default *snode = (ZCC_Default *)node; + out.Break(); + out.Open("default"); + PrintNodes(out, snode->Content, false, true); + out.Close(); +} + static void PrintContinueStmt(FLispString &out, ZCC_TreeNode *node) { out.Break(); @@ -687,21 +757,6 @@ static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node) { ZCC_AssignStmt *snode = (ZCC_AssignStmt *)node; out.Open("assign-stmt"); - switch (snode->AssignOp) - { - case ZCC_EQ: out.AddChar('='); break; - case ZCC_MULEQ: out.Add("*=", 2); break; - case ZCC_DIVEQ: out.Add("/=", 2); break; - case ZCC_MODEQ: out.Add("%=", 2); break; - case ZCC_ADDEQ: out.Add("+=", 2); break; - case ZCC_SUBEQ: out.Add("-=", 2); break; - case ZCC_LSHEQ: out.Add("<<=", 2); break; - case ZCC_RSHEQ: out.Add(">>=", 2); break; - case ZCC_ANDEQ: out.Add("&=", 2); break; - case ZCC_OREQ: out.Add("|=", 2); break; - case ZCC_XOREQ: out.Add("^=", 2); break; - default: BadAssignOp(out, snode->AssignOp); break; - } PrintNodes(out, snode->Dests); PrintNodes(out, snode->Sources); out.Close(); @@ -713,7 +768,6 @@ static void PrintLocalVarStmt(FLispString &out, ZCC_TreeNode *node) out.Open("local-var-stmt"); PrintNodes(out, snode->Type); PrintNodes(out, snode->Vars); - PrintNodes(out, snode->Inits); out.Close(); } @@ -725,6 +779,7 @@ static void PrintFuncParamDecl(FLispString &out, ZCC_TreeNode *node) PrintNodes(out, dnode->Type); out.AddName(dnode->Name); out.AddHex(dnode->Flags); + PrintNodes(out, dnode->Default); out.Close(); } @@ -772,6 +827,26 @@ static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node) out.Close(); } +static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node) +{ + auto dnode = (ZCC_FlagStmt *)node; + out.Break(); + out.Open("flag-stmt"); + PrintNodes(out, dnode->name, false); + out.AddInt(dnode->set); + out.Close(); +} + +static void PrintPropertyStmt(FLispString &out, ZCC_TreeNode *node) +{ + auto dnode = (ZCC_PropertyStmt *)node; + out.Break(); + out.Open("property-stmt"); + PrintNodes(out, dnode->Prop, false); + PrintNodes(out, dnode->Values, false); + out.Close(); +} + void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *) = { PrintIdentifier, @@ -789,6 +864,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintStateGoto, PrintStateLine, PrintVarName, + PrintVarInit, PrintType, PrintBasicType, PrintMapType, @@ -820,7 +896,11 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintConstantDef, PrintDeclarator, PrintVarDeclarator, - PrintFuncDeclarator + PrintFuncDeclarator, + PrintDefault, + PrintFlagStmt, + PrintPropertyStmt, + PrintVectorInitializer, }; FString ZCC_PrintAST(ZCC_TreeNode *root) diff --git a/src/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon similarity index 76% rename from src/zscript/zcc-parse.lemon rename to src/scripting/zscript/zcc-parse.lemon index 12cbb6625..a29d3d943 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -40,6 +40,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) struct StateOpts { ZCC_Expression *Offset; + ZCC_ExprConstant *Lights; bool Bright; bool Fast; bool Slow; @@ -47,7 +48,8 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) bool CanRaise; void Zero() { - Offset = NULL; + Offset = nullptr; + Lights = nullptr; Bright = false; Fast = false; Slow = false; @@ -96,12 +98,13 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) } } } - stat->sc.ScriptMessage("%s\n%s\n", unexpected.GetChars(), expecting.GetChars()); + stat->sc->ScriptMessage("%s\n%s\n", unexpected.GetChars(), expecting.GetChars()); + FScriptPosition::ErrorCounter++; } -%parse_accept { stat->sc.ScriptMessage("input accepted\n"); } +%parse_accept { DPrintf(DMSG_SPAMMY, "Input accepted\n"); } %parse_failure { /**failed = true;*/ } -%nonassoc EQ MULEQ DIVEQ MODEQ ADDEQ SUBEQ LSHEQ RSHEQ ANDEQ OREQ XOREQ. +%right EQ MULEQ DIVEQ MODEQ ADDEQ SUBEQ LSHEQ RSHEQ ANDEQ OREQ XOREQ URSHEQ. %right QUESTION COLON. %left OROR. %left ANDAND. @@ -111,7 +114,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) %left OR. /* Note that this is like the Ruby precedence for these */ %left XOR. /* three operators and not the C precedence, since */ %left AND. /* they are higher priority than the comparisons. */ -%left LSH RSH. +%left LSH RSH URSH. %left SUB ADD. %left MUL DIV MOD CROSSPROD DOTPROD. %left POW. @@ -124,7 +127,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) %type opt_func_body {ZCC_CompoundStmt *} %type function_body {ZCC_CompoundStmt *} -main ::= translation_unit(A). { stat->TopNode = A; stat->sc.ScriptMessage("Parse complete\n"); } +main ::= translation_unit(A). { stat->TopNode = A; DPrintf(DMSG_SPAMMY, "Parse complete\n"); } %type translation_unit {ZCC_TreeNode *} translation_unit(X) ::= . { X = NULL; } @@ -168,6 +171,18 @@ class_definition(X) ::= class_head(A) class_body(B). X = A; /*X-overwrites-A*/ } +class_head(X) ::= EXTEND CLASS(T) IDENTIFIER(A). +{ + NEW_AST_NODE(Class,head,T); + head->NodeName = A.Name(); + head->ParentName = nullptr; + head->Flags = ZCC_Extension; + head->Replaces = nullptr; + head->Type = nullptr; + head->Symbol = nullptr; + X = head; +} + class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C). { NEW_AST_NODE(Class,head,T); @@ -175,6 +190,8 @@ class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C). head->ParentName = B; head->Flags = C.Flags; head->Replaces = C.Replaces; + head->Type = nullptr; + head->Symbol = nullptr; X = head; } @@ -184,8 +201,9 @@ class_ancestry(X) ::= COLON dottable_id(A). { X = A; /*X-overwrites-A*/ } %type class_flags{ClassFlagsBlock} class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; } -class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | 0/*FIXME*/; X.Replaces = A.Replaces; } -class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | 0/*FIXME*/; X.Replaces = A.Replaces; } +class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | ZCC_Abstract; X.Replaces = A.Replaces; } +class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Replaces = A.Replaces; } +class_flags(X) ::= class_flags(A) ACTION. { X.Flags = A.Flags | ZCC_Action; X.Replaces = A.Replaces; } class_flags(X) ::= class_flags(A) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; } /*----- Dottable Identifier -----*/ @@ -206,6 +224,24 @@ dottable_id(X) ::= dottable_id(A) DOT IDENTIFIER(B). A->AppendSibling(id2); X = A; /*X-overwrites-A*/ } +dottable_id(X) ::= dottable_id(A) DOT DEFAULT. +{ + NEW_AST_NODE(Identifier,id2,A); + id2->Id = NAME_Default; + A->AppendSibling(id2); + X = A; /*X-overwrites-A*/ +} + +// a bit of a hack to allow the 'color' token to be used inside default properties. +// as a variable name it is practically meaningless because it cannot defined +// as such anywhere so it will always produce an error during processing. +dottable_id(X) ::= dottable_id(A) DOT COLOR. +{ + NEW_AST_NODE(Identifier,id2,A); + id2->Id = NAME_Color; + A->AppendSibling(id2); + X = A; /*X-overwrites-A*/ +} /*------ Class Body ------*/ // Body is a list of: @@ -247,6 +283,8 @@ struct_def(X) ::= STRUCT(T) IDENTIFIER(A) LBRACE opt_struct_body(B) RBRACE opt_s NEW_AST_NODE(Struct,def,T); def->NodeName = A.Name(); def->Body = B; + def->Type = nullptr; + def->Symbol = nullptr; X = def; } @@ -286,6 +324,7 @@ enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRAC def->NodeName = A.Name(); def->EnumType = (EZCCBuiltinType)B.Int; def->Elements = C; + def->Symbol = nullptr; // If the first element does not have an explicit value, make it 0. if (C != NULL) @@ -339,7 +378,7 @@ enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRAC X = def; } -enum_type(X) ::= . { X.Int = ZCC_IntAuto; X.SourceLoc = stat->sc.GetMessageLine(); } +enum_type(X) ::= . { X.Int = ZCC_IntAuto; X.SourceLoc = stat->sc->GetMessageLine(); } enum_type(X) ::= COLON int_type(A). { X = A; /*X-overwrites-A*/ } enum_list(X) ::= error. { X = NULL; } @@ -379,14 +418,36 @@ enumerator(X) ::= IDENTIFIER(A) EQ expr(B). /* Expression must be constant. */ %type state_call_params {ZCC_FuncParm *} %type state_opts {StateOpts} +%type states_opts { ZCC_Identifier *} +%type states_opt { ZCC_Identifier *} -states_def(X) ::= STATES(T) scanner_mode LBRACE states_body(A) RBRACE. +states_def(X) ::= STATES(T) states_opts(B) scanner_mode LBRACE states_body(A) RBRACE. { NEW_AST_NODE(States,def,T); + def->Flags = B; def->Body = A; X = def; } +states_opts(X) ::= . { X = nullptr; } +states_opts(X) ::= LPAREN states_opt(A) RPAREN. { X = A; /*X-overwrites-A*/ } + +states_opt(X) ::= IDENTIFIER(A). +{ + NEW_AST_NODE(Identifier,id,A); + id->Id = A.Name(); + X = id; +} + +states_opt(X) ::= states_opt(A) COMMA IDENTIFIER(B). +{ + NEW_AST_NODE(Identifier,id,B); + id->Id = B.Name(); + X = A; /*X-overwrites-A*/ + X->AppendSibling(id); +} + + /* We use a special scanner mode to allow for sprite names and frame characters * to not be quoted even if they contain special characters. The scanner_mode * nonterminal is used to enter this mode. The scanner automatically leaves it @@ -398,7 +459,7 @@ states_def(X) ::= STATES(T) scanner_mode LBRACE states_body(A) RBRACE. * set immediately after LBRACE is consumed, rather than immediately after * STATES is consumed. */ -scanner_mode ::= . { stat->sc.SetStateMode(true); } +scanner_mode ::= . { stat->sc->SetStateMode(true); } states_body(X) ::= . { X = NULL; } states_body(X) ::= error. { X = NULL; } @@ -424,31 +485,50 @@ state_flow_type(X) ::= GOTO(T) dottable_id(A) state_goto_offset(B). NEW_AST_NODE(StateGoto, flow, T); flow->Label = A; flow->Offset = B; + flow->Qualifier = nullptr; + X = flow; +} + +state_flow_type(X) ::= GOTO(T) IDENTIFIER(C) SCOPE dottable_id(A) state_goto_offset(B). +{ + NEW_AST_NODE(StateGoto, flow, T); + flow->Label = A; + flow->Offset = B; + + NEW_AST_NODE(Identifier,id,C); + id->Id = C.Name(); + flow->Qualifier =id; + X = flow; +} + +state_flow_type(X) ::= GOTO(T) SUPER(C) SCOPE dottable_id(A) state_goto_offset(B). +{ + NEW_AST_NODE(StateGoto, flow, T); + flow->Label = A; + flow->Offset = B; + + NEW_AST_NODE(Identifier,id,C); + id->Id = NAME_Super; + flow->Qualifier =id; X = flow; } state_goto_offset(X) ::= . { X = NULL; } -state_goto_offset(X) ::= PLUS expr(A). { X = A; /*X-overwrites-A*/ } /* Must evaluate to a non-negative integer constant. */ +state_goto_offset(X) ::= ADD expr(A). { X = A; /*X-overwrites-A*/ } /* Must evaluate to a non-negative integer constant. */ -state_line(X) ::= NWS(A) NWS(B) expr state_opts(C) state_action(D). +state_line(X) ::= NWS(A) NWS(B) expr(E) state_opts(C) state_action(D). { NEW_AST_NODE(StateLine, line, A); - const char *sprite = FName(A.Name()).GetChars(); - if (strlen(sprite) != 4) - { - Printf("Sprite name '%s' must be four characters", sprite); - } - else - { - memcpy(line->Sprite, sprite, 4); - } + line->Sprite = stat->Strings.Alloc(FName(A.Name()).GetChars()); line->Frames = stat->Strings.Alloc(FName(B.Name()).GetChars()); + line->Duration = E; line->bBright = C.Bright; line->bFast = C.Fast; line->bSlow = C.Slow; line->bNoDelay = C.NoDelay; line->bCanRaise = C.CanRaise; line->Offset = C.Offset; + line->Lights = C.Lights; line->Action = D; X = line; } @@ -460,13 +540,40 @@ state_opts(X) ::= state_opts(A) SLOW. { A.Slow = true; X = A; /*X-overwri state_opts(X) ::= state_opts(A) NODELAY. { A.NoDelay = true; X = A; /*X-overwrites-A*/ } state_opts(X) ::= state_opts(A) CANRAISE. { A.CanRaise = true; X = A; /*X-overwrites-A*/ } state_opts(X) ::= state_opts(A) OFFSET LPAREN expr(B) COMMA expr(C) RPAREN. { A.Offset = B; B->AppendSibling(C); X = A; /*X-overwrites-A*/ } -state_opts(X) ::= state_opts(A) LIGHT LPAREN light_list RPAREN. { X = A; /*X-overwrites-A*/ } ///FIXME: GZDoom would want to know this +state_opts(X) ::= state_opts(A) LIGHT LPAREN light_list(B) RPAREN. { X = A; /*X-overwrites-A*/ X.Lights = B; } -light_list ::= STRCONST. -light_list ::= light_list COMMA STRCONST. +%type light_list {ZCC_ExprConstant *} + +light_list(X) ::= STRCONST(A). +{ + NEW_AST_NODE(ExprConstant, strconst, A); + strconst->Operation = PEX_ConstValue; + strconst->Type = TypeString; + strconst->StringVal = A.String; + X = strconst; +} + +light_list(X) ::= light_list(A) COMMA STRCONST(B). +{ + NEW_AST_NODE(ExprConstant, strconst, B); + strconst->Operation = PEX_ConstValue; + strconst->Type = TypeString; + strconst->StringVal = B.String; + A->AppendSibling(strconst); + X = A; /*X-overwrites-A*/ +} /* A state action can be either a compound statement or a single action function call. */ -state_action(X) ::= LBRACE statement_list(A) scanner_mode RBRACE. { X = A; /*X-overwrites-A*/ } +state_action(X) ::= LBRACE(T) statement_list(A) scanner_mode RBRACE. +{ + NEW_AST_NODE(CompoundStmt,stmt,T); + stmt->Content = A; + X = stmt; +} +state_action(X) ::= LBRACE scanner_mode RBRACE. +{ + X = NULL; +} state_action(X) ::= LBRACE error scanner_mode RBRACE. { X = NULL; } state_action(X) ::= state_call(A) scanner_mode SEMICOLON. { X = A; /*X-overwrites-A*/ } @@ -488,8 +595,81 @@ state_call_params(X) ::= . { X = NULL; } state_call_params(X) ::= LPAREN func_expr_list(A) RPAREN. { X = A; /*X-overwrites-A*/ } /* Definition of a default class instance. */ -%type default_def {ZCC_CompoundStmt *} -default_def(X) ::= DEFAULT compound_statement(A). { X = A; /*X-overwrites-A*/ } +%type default_def {ZCC_Default *} +%type default_statement_list{ZCC_Statement *} +%type default_statement{ZCC_Statement *} + +default_def(X) ::= DEFAULT LBRACE(T) RBRACE. +{ + NEW_AST_NODE(Default,stmt,T); + stmt->Content = NULL; + X = stmt; +} +default_def(X) ::= DEFAULT LBRACE(T) default_statement_list(A) RBRACE. +{ + NEW_AST_NODE(Default,stmt,T); + stmt->Content = A; + X = stmt; +} +default_def(X) ::= DEFAULT LBRACE(T) error RBRACE. +{ + NEW_AST_NODE(Default,stmt,T); + stmt->Content = NULL; + X = stmt; +} + +default_statement_list(X) ::= default_statement(A). +{ + X = A; /*X-overwrites-A*/ +} +default_statement_list(X) ::= default_statement_list(X) default_statement(B). +{ + SAFE_APPEND(X,B); +} + + +default_statement(X) ::= SEMICOLON. { X = NULL; } +default_statement(X) ::= error SEMICOLON. { X = NULL; } +//default_statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } +default_statement(X) ::= property_statement(A). { X = A; /*X-overwrites-A*/ } +default_statement(X) ::= flag_statement(A). { X = A; /*X-overwrites-A*/ } + +%type flag_statement { ZCC_FlagStmt *} + +flag_statement(X) ::= ADD dottable_id(A). +{ + NEW_AST_NODE(FlagStmt, type, A); + type->set = true; + type->name = A; + X = type; +} +flag_statement(X) ::= SUB dottable_id(A). +{ + NEW_AST_NODE(FlagStmt, type, A); + type->set = false; + type->name = A; + X = type; +} + +%type property_statement{ZCC_PropertyStmt *} + +property_statement(X) ::= dottable_id(A) expr_list(B) SEMICOLON. +{ + NEW_AST_NODE(PropertyStmt,stmt,A); + stmt->Prop = A; + stmt->Values = B; + X = stmt; +} + +property_statement(X) ::= dottable_id(A) SEMICOLON. +{ + NEW_AST_NODE(PropertyStmt,stmt,A); + stmt->Prop = A; + stmt->Values = nullptr; + X = stmt; +} + + /* Type names */ %type type_name {ZCC_BasicType *} @@ -506,14 +686,19 @@ type_name1(X) ::= int_type(X). type_name1(X) ::= FLOAT(T). { X.Int = ZCC_FloatAuto; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= DOUBLE(T). { X.Int = ZCC_Float64; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= STRING(T). { X.Int = ZCC_String; X.SourceLoc = T.SourceLoc; } -type_name1(X) ::= VECTOR(T) vector_size(A). { X.Int = A.Int; X.SourceLoc = T.SourceLoc; } +type_name1(X) ::= VECTOR2(T). { X.Int = ZCC_Vector2; X.SourceLoc = T.SourceLoc; } +type_name1(X) ::= VECTOR3(T). { X.Int = ZCC_Vector3; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= NAME(T). { X.Int = ZCC_Name; X.SourceLoc = T.SourceLoc; } +type_name1(X) ::= SOUND(T). { X.Int = ZCC_Sound; X.SourceLoc = T.SourceLoc; } +type_name1(X) ::= STATE(T). { X.Int = ZCC_State; X.SourceLoc = T.SourceLoc; } +type_name1(X) ::= COLOR(T). { X.Int = ZCC_Color; X.SourceLoc = T.SourceLoc; } type_name(X) ::= type_name1(A). { NEW_AST_NODE(BasicType, type, A); type->Type = (EZCCBuiltinType)A.Int; type->UserType = NULL; + type->isconst = false; X = type; } type_name(X) ::= IDENTIFIER(A). /* User-defined type (struct, enum, or class) */ @@ -522,41 +707,34 @@ type_name(X) ::= IDENTIFIER(A). /* User-defined type (struct, enum, or class) NEW_AST_NODE(Identifier, id, A); type->Type = ZCC_UserType; type->UserType = id; + type->isconst = false; id->Id = A.Name(); X = type; } +type_name(X) ::= READONLY LT IDENTIFIER(A) GT. +{ + NEW_AST_NODE(BasicType, type, A); + NEW_AST_NODE(Identifier, id, A); + type->Type = ZCC_UserType; + type->UserType = id; + type->isconst = true; + id->Id = A.Name(); + X = type; +} + type_name(X) ::= DOT dottable_id(A). { NEW_AST_NODE(BasicType, type, A); type->Type = ZCC_UserType; type->UserType = A; + type->isconst = false; X = type; } -/* Vectors can be 2, 3, or 4 entries long. Default is a 3D vector. - * (Well, actually, I'm not sure if 4D ones are going to happen - * straight away.) - */ -%token_class intconst INTCONST|UINTCONST. -vector_size(X) ::= . { X.Int = ZCC_Vector3; X.SourceLoc = stat->sc.GetMessageLine(); } -vector_size(X) ::= LT intconst(A) GT. -{ - if (A.Int >= 2 && A.Int <= 4) - { - X.Int = ZCC_Vector2 + A.Int - 2; - } - else - { - X.Int = ZCC_Vector3; - stat->sc.ScriptMessage("Invalid vector size %d\n", A.Int); - } - X.SourceLoc = A.SourceLoc; -} - /* Type names can also be used as identifiers in contexts where type names * are not normally allowed. */ %fallback IDENTIFIER - SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR NAME MAP ARRAY VOID. + SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 NAME MAP ARRAY VOID STATE. /* Aggregate types */ %type aggregate_type {ZCC_Type *} @@ -564,7 +742,7 @@ vector_size(X) ::= LT intconst(A) GT. %type type_list {ZCC_Type *} %type type_list_or_void {ZCC_Type *} %type type_or_array {ZCC_Type *} -%type class_restrictor {ZCC_Identifier *} + %type class_restrictor {ZCC_Identifier *} %type array_size{ZCC_Expression *} %type array_size_expr{ZCC_Expression *} @@ -656,11 +834,11 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C). { // An invalid if (B == NULL) { - stat->sc.ScriptMessage("Variables may not be of type void.\n"); + stat->sc->ScriptMessage("Variables may not be of type void.\n"); } else { - stat->sc.ScriptMessage("Variables may be of only one type.\n"); + stat->sc->ScriptMessage("Variables may be of only one type.\n"); } X = NULL; } @@ -749,8 +927,10 @@ decl_flags(X) ::= decl_flags(A) META(T). { X.Int = A.Int | ZCC_Meta; X.SourceLo decl_flags(X) ::= decl_flags(A) ACTION(T). { X.Int = A.Int | ZCC_Action; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } decl_flags(X) ::= decl_flags(A) READONLY(T). { X.Int = A.Int | ZCC_ReadOnly; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } decl_flags(X) ::= decl_flags(A) DEPRECATED(T). { X.Int = A.Int | ZCC_Deprecated; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } +decl_flags(X) ::= decl_flags(A) VIRTUAL(T). { X.Int = A.Int | ZCC_Virtual; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } +decl_flags(X) ::= decl_flags(A) OVERRIDE(T). { X.Int = A.Int | ZCC_Override; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -func_const(X) ::= . { X.Int = 0; X.SourceLoc = stat->sc.GetMessageLine(); } +func_const(X) ::= . { X.Int = 0; X.SourceLoc = stat->sc->GetMessageLine(); } func_const(X) ::= CONST(T). { X.Int = ZCC_FuncConst; X.SourceLoc = T.SourceLoc; } opt_func_body(X) ::= SEMICOLON. { X = NULL; } @@ -764,6 +944,17 @@ func_params(X) ::= . /* empty */ { X = NULL; } func_params(X) ::= VOID. { X = NULL; } func_params(X) ::= func_param_list(X). +func_params(X) ::= func_param_list(A) COMMA ELLIPSIS. +{ + NEW_AST_NODE(FuncParamDecl,parm,stat->sc->GetMessageLine()); + parm->Type = nullptr; + parm->Name = NAME_None; + parm->Flags = 0; + parm->Default = nullptr; + X = A; /*X-overwrites-A*/ + X->AppendSibling(parm); +} + func_param_list(X) ::= func_param(X). func_param_list(X) ::= func_param_list(A) COMMA func_param(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); } @@ -773,6 +964,17 @@ func_param(X) ::= func_param_flags(A) type(B) IDENTIFIER(C). parm->Type = B; parm->Name = C.Name(); parm->Flags = A.Int; + parm->Default = nullptr; + X = parm; +} + +func_param(X) ::= func_param_flags(A) type(B) IDENTIFIER(C) EQ expr(D). +{ + NEW_AST_NODE(FuncParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc); + parm->Type = B; + parm->Name = C.Name(); + parm->Flags = A.Int; + parm->Default = D; X = parm; } @@ -810,12 +1012,25 @@ primary(X) ::= SUPER(T). X = expr; } primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ } -primary(X) ::= SELF(T). +primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. [DOT] { - NEW_AST_NODE(Expression, expr, T); - expr->Operation = PEX_Self; - expr->Type = NULL; - X = expr; + NEW_AST_NODE(VectorValue, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector3; + expr->X = A; + expr->Y = B; + expr->Z = C; + XX = expr; +} +primary(XX) ::= LPAREN expr(A) COMMA expr(B) RPAREN. [DOT] +{ + NEW_AST_NODE(VectorValue, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector2; + expr->X = A; + expr->Y = B; + expr->Z = nullptr; + XX = expr; } primary(X) ::= LPAREN expr(A) RPAREN. { @@ -866,6 +1081,7 @@ primary(X) ::= SCOPE primary(B). X = expr2; } */ + /*----- Unary Expressions -----*/ unary_expr(X) ::= primary(X). @@ -994,6 +1210,11 @@ expr(X) ::= expr(A) RSH expr(B). /* a >> b */ BINARY_EXPR(A,B,PEX_RightShift); X = expr2; } +expr(X) ::= expr(A) URSH expr(B). /* a >>> b */ +{ + BINARY_EXPR(A,B,PEX_URightShift); + X = expr2; +} expr(X) ::= expr(A) DOTDOT expr(B). /* a .. b */ { BINARY_EXPR(A,B,PEX_Concat); @@ -1007,9 +1228,8 @@ expr(X) ::= expr(A) LT expr(B). /* a < b */ } expr(X) ::= expr(A) GT expr(B). /* a > b */ { - BINARY_EXPR(A,B,PEX_LTEQ); - UNARY_EXPR(expr2,PEX_BoolNot); - X = expr1; + BINARY_EXPR(A,B,PEX_GT); + X = expr2; } expr(X) ::= expr(A) LTEQ expr(B). /* a <= b */ { @@ -1018,9 +1238,8 @@ expr(X) ::= expr(A) LTEQ expr(B). /* a <= b */ } expr(X) ::= expr(A) GTEQ expr(B). /* a >= b */ { - BINARY_EXPR(A,B,PEX_LT); - UNARY_EXPR(expr1,PEX_BoolNot); - X = expr1; + BINARY_EXPR(A,B,PEX_GTEQ); + X = expr2; } expr(X) ::= expr(A) LTGTEQ expr(B). /* a <>= b */ { @@ -1040,9 +1259,8 @@ expr(X) ::= expr(A) EQEQ expr(B). /* a == b */ } expr(X) ::= expr(A) NEQ expr(B). /* a != b */ { - BINARY_EXPR(A,B,PEX_EQEQ); - UNARY_EXPR(expr2,PEX_BoolNot); - X = expr1; + BINARY_EXPR(A,B,PEX_NEQ); + X = expr2; } expr(X) ::= expr(A) APPROXEQ expr(B). /* a ~== b */ { @@ -1075,6 +1293,67 @@ expr(X) ::= expr(A) OROR expr(B). /* a || b */ BINARY_EXPR(A,B,PEX_BoolOr); X = expr2; } +expr(X) ::= expr(A) EQ expr(B). /* a = b */ +{ + BINARY_EXPR(A,B,PEX_Assign); + X = expr2; +} +expr(X) ::= expr(A) ADDEQ expr(B). /* a += b */ +{ + BINARY_EXPR(A,B,PEX_AddAssign); + X = expr2; +} +expr(X) ::= expr(A) SUBEQ expr(B). /* a -= b */ +{ + BINARY_EXPR(A,B,PEX_SubAssign); + X = expr2; +} +expr(X) ::= expr(A) MULEQ expr(B). /* a *= b */ +{ + BINARY_EXPR(A,B,PEX_MulAssign); + X = expr2; +} +expr(X) ::= expr(A) DIVEQ expr(B). /* a /= b */ +{ + BINARY_EXPR(A,B,PEX_DivAssign); + X = expr2; +} +expr(X) ::= expr(A) MODEQ expr(B). /* a %= b */ +{ + BINARY_EXPR(A,B,PEX_ModAssign); + X = expr2; +} +expr(X) ::= expr(A) LSHEQ expr(B). /* a <<= b */ +{ + BINARY_EXPR(A,B,PEX_LshAssign); + X = expr2; +} +expr(X) ::= expr(A) RSHEQ expr(B). /* a >>= b */ +{ + BINARY_EXPR(A,B,PEX_RshAssign); + X = expr2; +} +expr(X) ::= expr(A) URSHEQ expr(B). /* a >>>= b */ +{ + BINARY_EXPR(A,B,PEX_URshAssign); + X = expr2; +} +expr(X) ::= expr(A) ANDEQ expr(B). /* a &= b */ +{ + BINARY_EXPR(A,B,PEX_AndAssign); + X = expr2; +} +expr(X) ::= expr(A) OREQ expr(B). /* a |= b */ +{ + BINARY_EXPR(A,B,PEX_OrAssign); + X = expr2; +} +expr(X) ::= expr(A) XOREQ expr(B). /* a ^= b */ +{ + BINARY_EXPR(A,B,PEX_XorAssign); + X = expr2; +} + expr(X) ::= expr(A) SCOPE expr(B). { @@ -1217,6 +1496,14 @@ constant(X) ::= TRUE(A). NEW_INTCONST_NODE(boolconst, TypeBool, true, A); X = boolconst; } +constant(X) ::= NULLPTR(A). +{ + NEW_AST_NODE(ExprConstant, nullptrconst, A); + nullptrconst->Operation = PEX_ConstValue; + nullptrconst->Type = TypeNullPtr; + nullptrconst->StringVal = nullptr; + X = nullptrconst; +} /************ Statements ************/ @@ -1230,7 +1517,7 @@ statement(X) ::= expression_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ statement(X) ::= selection_statement(X). statement(X) ::= iteration_statement(X). statement(X) ::= jump_statement(X). -statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } +//statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } statement(X) ::= local_var(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } statement(X) ::= error SEMICOLON. { X = NULL; } @@ -1381,7 +1668,6 @@ for_init(X) ::= for_bump(A). { X = A /*X-overwrites-A*/; } %type for_bump{ZCC_Statement *} for_bump(X) ::= . { X = NULL; } for_bump(X) ::= expression_statement(A). { X = A; /*X-overwrites-A*/ } -for_bump(X) ::= assign_statement(A). { X = A; /*X-overwrites-A*/ } /*----- If Statements -----*/ @@ -1442,42 +1728,93 @@ labeled_statement(X) ::= DEFAULT(T) COLON. /*----- Assignment Statements -----*/ +/* This is no longer being used, in favor of handling assignments as expressions, just like C and C++ do. + Keep this here in case some other parts require assignment syntax or Lua-style multi-assignments become a thing. %type assign_statement{ZCC_AssignStmt *} -assign_statement(X) ::= expr_list(A) assign_op(OP) expr_list(B). [EQ] +assign_statement(X) ::= expr_list(A) EQ expr_list(B). [EQ] { - NEW_AST_NODE(AssignStmt,stmt,OP); - stmt->AssignOp = OP.Int; + NEW_AST_NODE(AssignStmt,stmt,A); + stmt->AssignOp = ZCC_EQ; stmt->Dests = A; stmt->Sources = B; X = stmt; } - -assign_op(X) ::= EQ(T). { X.Int = ZCC_EQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= MULEQ(T). { X.Int = ZCC_MULEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= DIVEQ(T). { X.Int = ZCC_DIVEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= MODEQ(T). { X.Int = ZCC_MODEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= ADDEQ(T). { X.Int = ZCC_ADDEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= SUBEQ(T). { X.Int = ZCC_SUBEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= LSHEQ(T). { X.Int = ZCC_LSHEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= RSHEQ(T). { X.Int = ZCC_RSHEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= ANDEQ(T). { X.Int = ZCC_ANDEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= OREQ(T). { X.Int = ZCC_OREQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= XOREQ(T). { X.Int = ZCC_XOREQ; X.SourceLoc = T.SourceLoc; } +*/ /*----- Local Variable Definition "Statements" -----*/ %type local_var{ZCC_LocalVarStmt *} -local_var(X) ::= type(A) variable_list(B) var_init(C). +local_var(X) ::= type(A) variable_list_with_init(B). { NEW_AST_NODE(LocalVarStmt,vardef,A); vardef->Type = A; vardef->Vars = B; - vardef->Inits = C; X = vardef; } -%type var_init{ZCC_Expression *} -var_init(X) ::= . { X = NULL; } -var_init(X) ::= EQ expr_list(A). { X = A; /*X-overwrites-A*/ } +%type var_init{ZCC_VarInit *} +var_init(X) ::= IDENTIFIER(A). +{ + NEW_AST_NODE(VarInit,var,A); + var->Name = ENamedName(A.Int); + var->ArraySize = NULL; + var->Init = NULL; + var->InitIsArray = false; + X = var; +} + +var_init(X) ::= IDENTIFIER(A) array_size(B). +{ + NEW_AST_NODE(VarInit,var,A); + var->Name = ENamedName(A.Int); + var->ArraySize = B; + var->Init = NULL; + var->InitIsArray = false; + X = var; +} + +var_init(X) ::= IDENTIFIER(A) EQ expr(B). +{ + NEW_AST_NODE(VarInit,var,A); + var->Name = ENamedName(A.Int); + var->ArraySize = NULL; + var->Init = B; + var->InitIsArray = false; + X = var; +} + +var_init(X) ::= IDENTIFIER(A) EQ LBRACE expr_list(C) RBRACE. // this is for arrays which declare the size with the type +{ + NEW_AST_NODE(VarInit,var,A); + var->Name = ENamedName(A.Int); + var->ArraySize = NULL; + var->Init = C; + var->InitIsArray = true; + X = var; +} + +var_init(X) ::= IDENTIFIER(A) array_size(B) EQ LBRACE expr_list(C) RBRACE. +{ + NEW_AST_NODE(VarInit,var,A); + var->Name = ENamedName(A.Int); + var->ArraySize = B; + var->Init = C; + var->InitIsArray = true; + X = var; +} + +var_init(X) ::= IDENTIFIER EQ LBRACE error RBRACE. +{ + X = NULL; +} + +%type variable_list_with_init{ZCC_VarInit *} + +variable_list_with_init(X) ::= var_init(X). +variable_list_with_init(X) ::= variable_list_with_init(A) COMMA var_init(B). +{ + A->AppendSibling(B); + X = A; /*X-overwrites-A*/ +} diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp new file mode 100644 index 000000000..57475c50e --- /dev/null +++ b/src/scripting/zscript/zcc_compile.cpp @@ -0,0 +1,3079 @@ +/* +** zcc_compile.cpp +** +**--------------------------------------------------------------------------- +** Copyright -2016 Randy Heit +** Copyright 2016 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "a_pickups.h" +#include "thingdef.h" +#include "sc_man.h" +#include "c_console.h" +#include "c_dispatch.h" +#include "doomerrors.h" +#include "w_wad.h" +#include "cmdlib.h" +#include "m_alloc.h" +#include "zcc_parser.h" +#include "zcc-parse.h" +#include "zcc_compile.h" +#include "v_text.h" +#include "p_lnspec.h" +#include "i_system.h" +#include "gdtoa.h" +#include "codegeneration/codegen.h" +#include "vmbuilder.h" + +#define DEFAULTS_VMEXPORT ((BYTE *)(void *)1) + +//========================================================================== +// +// ZCCCompiler :: ProcessClass +// +//========================================================================== + +void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) +{ + ZCC_ClassWork *cls = nullptr; + // If this is a class extension, put the new node directly into the existing class. + if (cnode->Flags == ZCC_Extension) + { + for (auto clss : Classes) + { + if (clss->NodeName() == cnode->NodeName) + { + cls = clss; + break; + } + } + if (cls == nullptr) + { + Error(cnode, "Class %s cannot be found in the current translation unit."); + return; + } + } + else + { + Classes.Push(new ZCC_ClassWork(static_cast(cnode), treenode)); + cls = Classes.Last(); + } + + auto node = cnode->Body; + PSymbolTreeNode *childnode; + ZCC_Enum *enumType = nullptr; + + // Need to check if the class actually has a body. + if (node != nullptr) do + { + switch (node->NodeType) + { + case AST_Struct: + case AST_ConstantDef: + case AST_Enum: + if ((childnode = AddTreeNode(static_cast(node)->NodeName, node, &cls->TreeNodes))) + { + switch (node->NodeType) + { + case AST_Enum: + enumType = static_cast(node); + cls->Enums.Push(enumType); + break; + + case AST_Struct: + ProcessStruct(static_cast(node), childnode, cls->cls); + break; + + case AST_ConstantDef: + cls->Constants.Push(static_cast(node)); + cls->Constants.Last()->Type = enumType; + break; + + default: + assert(0 && "Default case is just here to make GCC happy. It should never be reached"); + } + } + break; + + case AST_VarDeclarator: + cls->Fields.Push(static_cast(node)); + break; + + case AST_EnumTerminator: + enumType = nullptr; + break; + + case AST_States: + cls->States.Push(static_cast(node)); + break; + + case AST_FuncDeclarator: + cls->Functions.Push(static_cast(node)); + break; + + case AST_Default: + cls->Defaults.Push(static_cast(node)); + break; + + default: + assert(0 && "Unhandled AST node type"); + break; + } + node = node->SiblingNext; + } + while (node != cnode->Body); +} + +//========================================================================== +// +// ZCCCompiler :: ProcessStruct +// +//========================================================================== + +void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZCC_Class *outer) +{ + Structs.Push(new ZCC_StructWork(static_cast(cnode), treenode, outer)); + ZCC_StructWork *cls = Structs.Last(); + + auto node = cnode->Body; + PSymbolTreeNode *childnode; + ZCC_Enum *enumType = nullptr; + + // Need to check if the struct actually has a body. + if (node != nullptr) do + { + switch (node->NodeType) + { + case AST_ConstantDef: + case AST_Enum: + if ((childnode = AddTreeNode(static_cast(node)->NodeName, node, &cls->TreeNodes))) + { + switch (node->NodeType) + { + case AST_Enum: + enumType = static_cast(node); + cls->Enums.Push(enumType); + break; + + case AST_ConstantDef: + cls->Constants.Push(static_cast(node)); + cls->Constants.Last()->Type = enumType; + break; + + default: + assert(0 && "Default case is just here to make GCC happy. It should never be reached"); + } + } + break; + + case AST_VarDeclarator: + cls->Fields.Push(static_cast(node)); + break; + + case AST_EnumTerminator: + enumType = nullptr; + break; + + default: + assert(0 && "Unhandled AST node type"); + break; + } + node = node->SiblingNext; + } + while (node != cnode->Body); +} + +//========================================================================== +// +// ZCCCompiler Constructor +// +//========================================================================== + +ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PSymbolTable &_outsymbols, int lumpnum) + : Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), Lump(lumpnum) +{ + FScriptPosition::ResetErrorCounter(); + // Group top-level nodes by type + if (ast.TopNode != NULL) + { + ZCC_TreeNode *node = ast.TopNode; + PSymbolTreeNode *tnode; + PType *enumType = nullptr; + ZCC_Enum *zenumType = nullptr; + + do + { + switch (node->NodeType) + { + case AST_Class: + // a class extension should not check the tree node symbols. + if (static_cast(node)->Flags == ZCC_Extension) + { + ProcessClass(static_cast(node), tnode); + break; + } + case AST_Struct: + case AST_ConstantDef: + case AST_Enum: + if ((tnode = AddTreeNode(static_cast(node)->NodeName, node, GlobalTreeNodes))) + { + switch (node->NodeType) + { + case AST_Enum: + zenumType = static_cast(node); + enumType = NewEnum(zenumType->NodeName, nullptr); + GlobalSymbols.AddSymbol(new PSymbolType(zenumType->NodeName, enumType)); + break; + + case AST_Class: + ProcessClass(static_cast(node), tnode); + break; + + case AST_Struct: + ProcessStruct(static_cast(node), tnode, nullptr); + break; + + case AST_ConstantDef: + Constants.Push(static_cast(node)); + Constants.Last()->Type = zenumType; + break; + + default: + assert(0 && "Default case is just here to make GCC happy. It should never be reached"); + } + } + break; + + case AST_EnumTerminator: + zenumType = nullptr; + break; + + default: + assert(0 && "Unhandled AST node type"); + break; + } + node = node->SiblingNext; + } while (node != ast.TopNode); + } +} + +ZCCCompiler::~ZCCCompiler() +{ + for (auto s : Structs) + { + delete s; + } + for (auto c : Classes) + { + delete c; + } + Structs.Clear(); + Classes.Clear(); +} + +//========================================================================== +// +// ZCCCompiler :: AddTreeNode +// +// Keeps track of definition nodes by their names. Ensures that all names +// in this scope are unique. +// +//========================================================================== + +PSymbolTreeNode *ZCCCompiler::AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents) +{ + PSymbol *check = treenodes->FindSymbol(name, searchparents); + if (check != NULL) + { + assert(check->IsA(RUNTIME_CLASS(PSymbolTreeNode))); + Error(node, "Attempt to redefine '%s'", name.GetChars()); + Error(static_cast(check)->Node, " Original definition is here"); + return nullptr; + } + else + { + auto sy = new PSymbolTreeNode(name, node); + FString name; + treenodes->AddSymbol(sy); + return sy; + } +} + +//========================================================================== +// +// ZCCCompiler :: Warn +// +// Prints a warning message, and increments WarnCount. +// +//========================================================================== + +void ZCCCompiler::Warn(ZCC_TreeNode *node, const char *msg, ...) +{ + va_list argptr; + va_start(argptr, msg); + MessageV(node, TEXTCOLOR_ORANGE, msg, argptr); + va_end(argptr); + + FScriptPosition::WarnCounter++; +} + +//========================================================================== +// +// ZCCCompiler :: Error +// +// Prints an error message, and increments ErrorCount. +// +//========================================================================== + +void ZCCCompiler::Error(ZCC_TreeNode *node, const char *msg, ...) +{ + va_list argptr; + va_start(argptr, msg); + MessageV(node, TEXTCOLOR_RED, msg, argptr); + va_end(argptr); + + FScriptPosition::ErrorCounter++; +} + +//========================================================================== +// +// ZCCCompiler :: MessageV +// +// Prints a message, annotated with the source location for the tree node. +// +//========================================================================== + +void ZCCCompiler::MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr) +{ + FString composed; + + composed.Format("%s%s, line %d: ", txtcolor, node->SourceName->GetChars(), node->SourceLoc); + composed.VAppendFormat(msg, argptr); + composed += '\n'; + PrintString(PRINT_HIGH, composed); +} + +//========================================================================== +// +// ZCCCompiler :: Compile +// +// Compile everything defined at this level. +// +//========================================================================== + +int ZCCCompiler::Compile() +{ + CreateClassTypes(); + CreateStructTypes(); + CompileAllConstants(); + CompileAllFields(); + InitDefaults(); + InitFunctions(); + CompileStates(); + return FScriptPosition::ErrorCounter; +} + +//========================================================================== +// +// ZCCCompiler :: CreateStructTypes +// +// Creates a PStruct for every struct. +// +//========================================================================== + +void ZCCCompiler::CreateStructTypes() +{ + for(auto s : Structs) + { + s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->Type; + s->strct->Type = NewStruct(s->NodeName(), s->Outer); + s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type()); + GlobalSymbols.AddSymbol(s->strct->Symbol); + + for (auto e : s->Enums) + { + auto etype = NewEnum(e->NodeName, s->Type()); + s->Type()->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + } + } +} + +//========================================================================== +// +// ZCCCompiler :: CreateClassTypes +// +// Creates a PClass for every class so that we get access to the symbol table +// These will be created with unknown size because for that we need to +// process all fields first, but to do that we need the PClass and some +// other info depending on the PClass. +// +//========================================================================== + +void ZCCCompiler::CreateClassTypes() +{ + // we are going to sort the classes array so that entries are sorted in order of inheritance. + + auto OrigClasses = std::move(Classes); + Classes.Clear(); + bool donesomething = true; + while (donesomething) + { + donesomething = false; + for (unsigned i = 0; icls->ParentName; + + if (ParentName != nullptr && ParentName->SiblingNext == ParentName) parent = PClass::FindClass(ParentName->Id); + else if (ParentName == nullptr) parent = RUNTIME_CLASS(DObject); + else + { + // The parent is a dotted name which the type system currently does not handle. + // Once it does this needs to be implemented here. + auto p = ParentName; + FString build; + + do + { + if (build.IsNotEmpty()) build += '.'; + build += FName(p->Id); + p = static_cast(p->SiblingNext); + } while (p != ParentName); + Error(c->cls, "Qualified name '%s' for base class not supported in '%s'", build.GetChars(), FName(c->NodeName()).GetChars()); + parent = RUNTIME_CLASS(DObject); + } + + if (parent != nullptr) + { + // The parent exists, we may create a type for this class + if (c->cls->Flags & ZCC_Native) + { + // If this is a native class, its own type must also already exist and not be a runtime class. + auto me = PClass::FindClass(c->NodeName()); + if (me == nullptr) + { + Error(c->cls, "Unknown native class %s", c->NodeName().GetChars()); + // Create a placeholder so that the compiler can continue looking for errors. + me = parent->FindClassTentative(c->NodeName()); + } + else if (me->bRuntimeClass) + { + Error(c->cls, "%s is not a native class", c->NodeName().GetChars()); + } + else + { + DPrintf(DMSG_SPAMMY, "Registered %s as native with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars()); + } + c->cls->Type = me; + auto ac = dyn_cast(me); + if (ac != nullptr) ac->SourceLumpName = *c->cls->SourceName; + } + else + { + // The parent was the last native class in the inheritance tree. + // There is probably a better place for this somewhere else + // TODO: Do this somewhere else or find a less hackish way to do it + if (!parent->bRuntimeClass) + { + //assert(parent->VMExported != nullptr); // Ideally the macro would be used on all inheritable-native classes + /**/ if (parent->VMExported != nullptr) { /**/ // remove the if condition when all done + + parent = parent->VMExported; + assert(parent->bRuntimeClass == false); + + if (parent->Defaults == nullptr) + { + // We have to manually do that since zscript knows nothing about these + parent->Defaults = DEFAULTS_VMEXPORT; + } + + /**/ } /**/ + } + + // We will never get here if the name is a duplicate, so we can just do the assignment. + try + { + c->cls->Type = parent->CreateDerivedClass(c->NodeName(), TentativeClass); + if (c->Type() == nullptr) + { + Error(c->cls, "Class name %s already exists", c->NodeName().GetChars()); + } + } + catch (CRecoverableError &err) + { + Error(c->cls, "%s", err.GetMessage()); + // create a placeholder so that the compiler can continue looking for errors. + c->cls->Type = nullptr; + } + } + if (c->Type() == nullptr) c->cls->Type = parent->FindClassTentative(c->NodeName()); + c->Type()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.) + c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); + GlobalSymbols.AddSymbol(c->cls->Symbol); + Classes.Push(c); + OrigClasses.Delete(i--); + donesomething = true; + } + else + { + // No base class found. Now check if something in the unprocessed classes matches. + // If not, print an error. If something is found let's retry again in the next iteration. + bool found = false; + for (auto d : OrigClasses) + { + if (d->NodeName() == c->cls->ParentName->Id) + { + found = true; + break; + } + } + if (!found) + { + Error(c->cls, "Class %s has unknown base class %s", c->NodeName().GetChars(), FName(c->cls->ParentName->Id).GetChars()); + // create a placeholder so that the compiler can continue looking for errors. + c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()); + c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); + GlobalSymbols.AddSymbol(c->cls->Symbol); + Classes.Push(c); + OrigClasses.Delete(i--); + donesomething = true; + } + } + } + } + + // What's left refers to some other class in the list but could not be resolved. + // This normally means a circular reference. + for (auto c : OrigClasses) + { + Error(c->cls, "Class %s has circular inheritance", FName(c->NodeName()).GetChars()); + c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()); + c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); + GlobalSymbols.AddSymbol(c->cls->Symbol); + Classes.Push(c); + } + + // Last but not least: Now that all classes have been created, we can create the symbols for the internal enums and link the treenode symbol tables and set up replacements + for (auto cd : Classes) + { + for (auto e : cd->Enums) + { + auto etype = NewEnum(e->NodeName, cd->Type()); + cd->Type()->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + } + // Link the tree node tables. We only can do this after we know the class relations. + for (auto cc : Classes) + { + if (cc->Type() == cd->Type()->ParentClass) + { + cd->TreeNodes.SetParentTable(&cc->TreeNodes); + break; + } + } + + if (cd->cls->Replaces != nullptr && !static_cast(cd->Type())->SetReplacement(cd->cls->Replaces->Id)) + { + Warn(cd->cls, "Replaced type '%s' not found for %s", FName(cd->cls->Replaces->Id).GetChars(), cd->Type()->TypeName.GetChars()); + } + + } +} + +//========================================================================== +// +// ZCCCompiler :: AddConstants +// +// Helper for CompileAllConstants +// +//========================================================================== + +void ZCCCompiler::CopyConstants(TArray &dest, TArray &Constants, PSymbolTable *ot) +{ + for (auto c : Constants) + { + dest.Push({ c, ot }); + } +} + +//========================================================================== +// +// ZCCCompiler :: CompileAllConstants +// +// Make symbols from every constant defined at all levels. +// Since constants may only depend on other constants this can be done +// without any more involved processing of the AST as a first step. +// +//========================================================================== + +void ZCCCompiler::CompileAllConstants() +{ + // put all constants in one list to make resolving this easier. + TArray constantwork; + + CopyConstants(constantwork, Constants, OutputSymbols); + for (auto c : Classes) + { + CopyConstants(constantwork, c->Constants, &c->Type()->Symbols); + } + for (auto s : Structs) + { + CopyConstants(constantwork, s->Constants, &s->Type()->Symbols); + } + + // Before starting to resolve the list, let's create symbols for all already resolved ones first (i.e. all literal constants), to reduce work. + for (unsigned i = 0; iValue->NodeType == AST_ExprConstant) + { + AddConstant(constantwork[i]); + // Remove the constant from the list + constantwork.Delete(i); + i--; + } + } + bool donesomething = true; + // Now go through this list until no more constants can be resolved. The remaining ones will be non-constant values. + while (donesomething && constantwork.Size() > 0) + { + donesomething = false; + for (unsigned i = 0; i < constantwork.Size(); i++) + { + if (CompileConstant(constantwork[i].node, constantwork[i].outputtable)) + { + AddConstant(constantwork[i]); + // Remove the constant from the list + constantwork.Delete(i); + i--; + donesomething = true; + } + } + } + for (unsigned i = 0; i < constantwork.Size(); i++) + { + Error(constantwork[i].node, "%s is not a constant", FName(constantwork[i].node->NodeName).GetChars()); + } +} + +//========================================================================== +// +// ZCCCompiler :: AddConstant +// +// Adds a constant to its assigned symbol table +// +//========================================================================== + +void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) +{ + auto def = constant.node; + auto val = def->Value; + if (val->NodeType == AST_ExprConstant) + { + ZCC_ExprConstant *cval = static_cast(val); + if (cval->Type == TypeString) + { + def->Symbol = new PSymbolConstString(def->NodeName, *(cval->StringVal)); + } + else if (cval->Type->IsA(RUNTIME_CLASS(PInt))) + { + // How do we get an Enum type in here without screwing everything up??? + //auto type = def->Type != nullptr ? def->Type : cval->Type; + def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal); + } + else if (cval->Type->IsA(RUNTIME_CLASS(PFloat))) + { + if (def->Type != nullptr) + { + Error(def, "Enum members must be integer values"); + } + def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->DoubleVal); + } + else + { + Error(def->Value, "Bad type for constant definiton"); + def->Symbol = nullptr; + } + + if (def->Symbol == nullptr) + { + // Create a dummy constant so we don't make any undefined value warnings. + def->Symbol = new PSymbolConstNumeric(def->NodeName, TypeError, 0); + } + constant.outputtable->ReplaceSymbol(def->Symbol); + } +} + +//========================================================================== +// +// ZCCCompiler :: CompileConstant +// +// For every constant definition, evaluate its value (which should result +// in a constant), and create a symbol for it. +// +//========================================================================== + +bool ZCCCompiler::CompileConstant(ZCC_ConstantDef *def, PSymbolTable *sym) +{ + assert(def->Symbol == nullptr); + + ZCC_Expression *val = Simplify(def->Value, sym, true); + def->Value = val; + return (val->NodeType == AST_ExprConstant); +} + + +//========================================================================== +// +// ZCCCompiler :: Simplify +// +// For an expression, +// Evaluate operators whose arguments are both constants, replacing it +// with a new constant. +// For a binary operator with one constant argument, put it on the right- +// hand operand, where permitted. +// Perform automatic type promotion. +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root, PSymbolTable *sym, bool wantconstant) +{ + SimplifyingConstant = wantconstant; + return DoSimplify(root, sym); +} + +ZCC_Expression *ZCCCompiler::DoSimplify(ZCC_Expression *root, PSymbolTable *sym) +{ + if (root->NodeType == AST_ExprUnary) + { + return SimplifyUnary(static_cast(root), sym); + } + else if (root->NodeType == AST_ExprBinary) + { + return SimplifyBinary(static_cast(root), sym); + } + else if (root->Operation == PEX_ID) + { + return IdentifyIdentifier(static_cast(root), sym); + } + else if (root->Operation == PEX_MemberAccess) + { + return SimplifyMemberAccess(static_cast(root), sym); + } + else if (root->Operation == PEX_FuncCall) + { + return SimplifyFunctionCall(static_cast(root), sym); + } + return root; +} + +//========================================================================== +// +// ZCCCompiler :: SimplifyUnary +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *sym) +{ + unary->Operand = DoSimplify(unary->Operand, sym); + if (unary->Operand->Type == nullptr) + { + return unary; + } + ZCC_OpProto *op = PromoteUnary(unary->Operation, unary->Operand); + if (op == NULL) + { // Oh, poo! + unary->Type = TypeError; + } + else if (unary->Operand->Operation == PEX_ConstValue) + { + return op->EvalConst1(static_cast(unary->Operand)); + } + return unary; +} + +//========================================================================== +// +// ZCCCompiler :: SimplifyBinary +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary, PSymbolTable *sym) +{ + binary->Left = DoSimplify(binary->Left, sym); + binary->Right = DoSimplify(binary->Right, sym); + if (binary->Left->Type == nullptr || binary->Right->Type == nullptr) + { + // We do not know yet what this is so we cannot promote it (yet.) + return binary; + } + ZCC_OpProto *op = PromoteBinary(binary->Operation, binary->Left, binary->Right); + if (op == NULL) + { + binary->Type = TypeError; + } + else if (binary->Left->Operation == PEX_ConstValue && + binary->Right->Operation == PEX_ConstValue) + { + return op->EvalConst2(static_cast(binary->Left), + static_cast(binary->Right), AST.Strings); + } + return binary; +} + +//========================================================================== +// +// ZCCCompiler :: SimplifyMemberAccess +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop, PSymbolTable *symt) +{ + PSymbolTable *symtable; + + // TBD: Is it safe to simplify the left side here when not processing a constant? + dotop->Left = DoSimplify(dotop->Left, symt); + + if (dotop->Left->Operation == PEX_TypeRef) + { // Type refs can be evaluated now. + PType *ref = static_cast(dotop->Left)->RefType; + PSymbol *sym = ref->Symbols.FindSymbolInTable(dotop->Right, symtable); + if (sym != nullptr) + { + ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable); + if (expr != nullptr) + { + return expr; + } + } + } + else if (dotop->Left->Operation == PEX_Super) + { + symt = symt->GetParentTable(); + if (symt != nullptr) + { + PSymbol *sym = symt->FindSymbolInTable(dotop->Right, symtable); + if (sym != nullptr) + { + ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable); + if (expr != nullptr) + { + return expr; + } + } + } + } + return dotop; +} + +//========================================================================== +// +// ZCCCompiler :: SimplifyFunctionCall +// +// This may replace a function call with cast(s), since they look like the +// same thing to the parser. +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSymbolTable *sym) +{ + ZCC_FuncParm *parm; + int parmcount = 0; + + parm = callop->Parameters; + if (parm != NULL) + { + do + { + parmcount++; + assert(parm->NodeType == AST_FuncParm); + parm->Value = DoSimplify(parm->Value, sym); + parm = static_cast(parm->SiblingNext); + } + while (parm != callop->Parameters); + } + // Only simplify the 'function' part if we want to retrieve a constant. + // This is necessary to evaluate the type casts, but for actual functions + // the simplification process is destructive and has to be avoided. + if (SimplifyingConstant) + { + callop->Function = DoSimplify(callop->Function, sym); + } + // If the left side is a type ref, then this is actually a cast + // and not a function call. + if (callop->Function->Operation == PEX_TypeRef) + { + if (parmcount != 1) + { + Error(callop, "Type cast requires one parameter"); + callop->ToErrorNode(); + } + else + { + PType *dest = static_cast(callop->Function)->RefType; + const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; + int routelen = parm->Value->Type->FindConversion(dest, route, countof(route)); + if (routelen < 0) + { + ///FIXME: Need real type names + Error(callop, "Cannot convert %s to %s", parm->Value->Type->DescriptiveName(), dest->DescriptiveName()); + callop->ToErrorNode(); + } + else + { + ZCC_Expression *val = ApplyConversion(parm->Value, route, routelen); + assert(val->Type == dest); + return val; + } + } + } + return callop; +} + +//========================================================================== +// +// ZCCCompiler :: PromoteUnary +// +// Converts the operand into a format preferred by the operator. +// +//========================================================================== + +ZCC_OpProto *ZCCCompiler::PromoteUnary(EZCCExprType op, ZCC_Expression *&expr) +{ + if (expr->Type == TypeError) + { + return NULL; + } + const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; + int routelen = countof(route); + ZCC_OpProto *proto = ZCC_OpInfo[op].FindBestProto(expr->Type, route, routelen); + + if (proto != NULL) + { + expr = ApplyConversion(expr, route, routelen); + } + return proto; +} + +//========================================================================== +// +// ZCCCompiler :: PromoteBinary +// +// Converts the operands into a format (hopefully) compatible with the +// operator. +// +//========================================================================== + +ZCC_OpProto *ZCCCompiler::PromoteBinary(EZCCExprType op, ZCC_Expression *&left, ZCC_Expression *&right) +{ + // If either operand is of type 'error', the result is also 'error' + if (left->Type == TypeError || right->Type == TypeError) + { + return NULL; + } + const PType::Conversion *route1[CONVERSION_ROUTE_SIZE], *route2[CONVERSION_ROUTE_SIZE]; + int route1len = countof(route1), route2len = countof(route2); + ZCC_OpProto *proto = ZCC_OpInfo[op].FindBestProto(left->Type, route1, route1len, right->Type, route2, route2len); + if (proto != NULL) + { + left = ApplyConversion(left, route1, route1len); + right = ApplyConversion(right, route2, route2len); + } + return proto; +} + +//========================================================================== +// +// ZCCCompiler :: ApplyConversion +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::ApplyConversion(ZCC_Expression *expr, const PType::Conversion **route, int routelen) +{ + for (int i = 0; i < routelen; ++i) + { + if (expr->Operation != PEX_ConstValue) + { + expr = AddCastNode(route[i]->TargetType, expr); + } + else + { + route[i]->ConvertConstant(static_cast(expr), AST.Strings); + } + } + return expr; +} + +//========================================================================== +// +// ZCCCompiler :: AddCastNode +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::AddCastNode(PType *type, ZCC_Expression *expr) +{ + assert(expr->Operation != PEX_ConstValue && "Expression must not be constant"); + // TODO: add a node here + return expr; +} + +//========================================================================== +// +// ZCCCompiler :: IdentifyIdentifier +// +// Returns a node that represents what the identifer stands for. +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable *symt) +{ + // Check the symbol table for the identifier. + PSymbolTable *table; + PSymbol *sym = symt->FindSymbolInTable(idnode->Identifier, table); + // GlobalSymbols cannot be the parent of a class's symbol table so we have to look for global symbols explicitly. + if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(idnode->Identifier, table); + if (sym != nullptr) + { + ZCC_Expression *node = NodeFromSymbol(sym, idnode, table); + if (node != NULL) + { + return node; + } + } + else if (SimplifyingConstant) // leave unknown identifiers alone when simplifying non-constants. It is impossible to know what they are here. + { + // Also handle line specials. + // To call this like a function this needs to be done differently, but for resolving constants this is ok. + int spec = P_FindLineSpecial(FName(idnode->Identifier).GetChars()); + if (spec != 0) + { + ZCC_ExprConstant *val = static_cast(AST.InitNode(sizeof(*val), AST_ExprConstant, idnode)); + val->Operation = PEX_ConstValue; + val->Type = TypeSInt32; + val->IntVal = spec; + return val; + } + + Error(idnode, "Unknown identifier '%s'", FName(idnode->Identifier).GetChars()); + idnode->ToErrorNode(); + } + return idnode; +} + +//========================================================================== +// +// ZCCCompiler :: NodeFromSymbol +// +//========================================================================== + +ZCC_Expression *ZCCCompiler::NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table) +{ + assert(sym != nullptr); + + if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) + { + return NodeFromSymbolConst(static_cast(sym), source); + } + else if (sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) + { + return NodeFromSymbolType(static_cast(sym), source); + } + return NULL; +} + +//========================================================================== +// +// ZCCCompiler :: NodeFromSymbolConst +// +// Returns a new AST constant node with the symbol's content. +// +//========================================================================== + +ZCC_ExprConstant *ZCCCompiler::NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode) +{ + ZCC_ExprConstant *val = static_cast(AST.InitNode(sizeof(*val), AST_ExprConstant, idnode)); + val->Operation = PEX_ConstValue; + if (sym == NULL) + { + val->Type = TypeError; + val->IntVal = 0; + } + else if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConstString))) + { + val->StringVal = AST.Strings.Alloc(static_cast(sym)->Str); + val->Type = TypeString; + } + else + { + val->Type = sym->ValueType; + if (val->Type != TypeError) + { + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric))); + if (sym->ValueType->IsKindOf(RUNTIME_CLASS(PInt))) + { + val->IntVal = static_cast(sym)->Value; + } + else + { + assert(sym->ValueType->IsKindOf(RUNTIME_CLASS(PFloat))); + val->DoubleVal = static_cast(sym)->Float; + } + } + } + return val; +} + +//========================================================================== +// +// ZCCCompiler :: NodeFromSymbolType +// +// Returns a new AST type ref node with the symbol's content. +// +//========================================================================== + +ZCC_ExprTypeRef *ZCCCompiler::NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode) +{ + ZCC_ExprTypeRef *ref = static_cast(AST.InitNode(sizeof(*ref), AST_ExprTypeRef, idnode)); + ref->Operation = PEX_TypeRef; + ref->RefType = sym->Type; + ref->Type = NewClassPointer(RUNTIME_CLASS(PType)); + return ref; +} + +//========================================================================== +// +// ZCCCompiler :: CompileAllFields +// +// builds the internal structure of all classes and structs +// +//========================================================================== + +void ZCCCompiler::CompileAllFields() +{ + // Create copies of the arrays which can be altered + auto Classes = this->Classes; + auto Structs = this->Structs; + + // first step: Look for native classes with native children. + // These may not have any variables added to them because it'd clash with the native definitions. + for (unsigned i = 0; i < Classes.Size(); i++) + { + auto c = Classes[i]; + + if (c->Type()->Size != TentativeClass && c->Fields.Size() > 0) + { + // We need to search the global class table here because not all children may have a scripted definition attached. + for (auto ac : PClass::AllClasses) + { + if (ac->ParentClass == c->Type() && ac->Size != TentativeClass) + { + Error(c->cls, "Trying to add fields to class '%s' with native children", c->Type()->TypeName.GetChars()); + Classes.Delete(i--); + break; + } + } + } + } + bool donesomething = true; + while (donesomething && (Structs.Size() > 0 || Classes.Size() > 0)) + { + donesomething = false; + for (unsigned i = 0; i < Structs.Size(); i++) + { + if (CompileFields(Structs[i]->Type(), Structs[i]->Fields, Structs[i]->Outer, &Structs[i]->TreeNodes, true)) + { + // Remove from the list if all fields got compiled. + Structs.Delete(i--); + donesomething = true; + } + } + for (unsigned i = 0; i < Classes.Size(); i++) + { + auto type = Classes[i]->Type(); + if (type->Size == TentativeClass) + { + if (type->ParentClass->Size == TentativeClass) + { + // we do not know the parent class's size yet, so skip this class for now. + continue; + } + else + { + // Inherit the size of the parent class + type->Size = Classes[i]->Type()->ParentClass->Size; + } + } + if (CompileFields(type, Classes[i]->Fields, nullptr, &Classes[i]->TreeNodes, false)) + { + // Remove from the list if all fields got compiled. + Classes.Delete(i--); + donesomething = true; + } + } + } + // This really should never happen, but if it does, let's better print an error. + for (auto s : Structs) + { + Error(s->strct, "Unable to resolve all fields for struct %s", FName(s->NodeName()).GetChars()); + } + for (auto s : Classes) + { + Error(s->cls, "Unable to resolve all fields for class %s", FName(s->NodeName()).GetChars()); + } +} + +//========================================================================== +// +// ZCCCompiler :: CompileFields +// +// builds the internal structure of a single class or struct +// +//========================================================================== + +bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct) +{ + while (Fields.Size() > 0) + { + auto field = Fields[0]; + + PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, true, true); + + // For structs only allow 'deprecated', for classes exclude function qualifiers. + int notallowed = forstruct? ~ZCC_Deprecated : ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract | ZCC_Virtual | ZCC_Override; + + if (field->Flags & notallowed) + { + Error(field, "Invalid qualifiers for %s (%s not allowed)", FName(field->Names->Name).GetChars(), FlagsToString(field->Flags & notallowed).GetChars()); + field->Flags &= notallowed; + } + uint32_t varflags = 0; + + // These map directly to implementation flags. + if (field->Flags & ZCC_Private) varflags |= VARF_Private; + if (field->Flags & ZCC_Protected) varflags |= VARF_Protected; + if (field->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated; + if (field->Flags & ZCC_ReadOnly) varflags |= VARF_ReadOnly; + + if (field->Flags & ZCC_Native) + { + // todo: get the native address of this field. + } + if (field->Flags & ZCC_Meta) + { + varflags |= VARF_ReadOnly; // metadata implies readonly + // todo: this needs to go into the metaclass and needs some handling + } + + if (field->Type->ArraySize != nullptr) + { + fieldtype = ResolveArraySize(fieldtype, field->Type->ArraySize, &type->Symbols); + } + + auto name = field->Names; + do + { + if (AddTreeNode(name->Name, name, TreeNodes, !forstruct)) + { + auto thisfieldtype = fieldtype; + if (name->ArraySize != nullptr) + { + thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, &type->Symbols); + } + + type->AddField(name->Name, thisfieldtype, varflags); + } + name = static_cast(name->SiblingNext); + } while (name != field->Names); + Fields.Delete(0); + } + return Fields.Size() == 0; +} + +//========================================================================== +// +// ZCCCompiler :: FieldFlagsToString +// +// creates a string for a field's flags +// +//========================================================================== + +FString ZCCCompiler::FlagsToString(uint32_t flags) +{ + const char *flagnames[] = { "native", "static", "private", "protected", "latent", "final", "meta", "action", "deprecated", "readonly", "funcconst", "abstract" }; + FString build; + + for (int i = 0; i < 12; i++) + { + if (flags & (1 << i)) + { + if (build.IsNotEmpty()) build += ", "; + build += flagnames[i]; + } + } + return build; +} + +//========================================================================== +// +// ZCCCompiler :: DetermineType +// +// retrieves the type for this field, for arrays the type of a single entry. +// +//========================================================================== + +PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember) +{ + PType *retval = TypeError; + if (!allowarraytypes && ztype->ArraySize != nullptr) + { + Error(field, "%s: Array type not allowed", name.GetChars()); + return TypeError; + } + switch (ztype->NodeType) + { + case AST_BasicType: + { + auto btype = static_cast(ztype); + switch (btype->Type) + { + case ZCC_SInt8: + retval = TypeSInt8; + break; + + case ZCC_UInt8: + retval = TypeUInt8; + break; + + case ZCC_SInt16: + retval = TypeSInt16; + break; + + case ZCC_UInt16: + retval = TypeUInt16; + break; + + case ZCC_SInt32: + case ZCC_IntAuto: // todo: for enums, autoselect appropriately sized int + retval = TypeSInt32; + break; + + case ZCC_UInt32: + retval = TypeUInt32; + break; + + case ZCC_Bool: + retval = TypeBool; + break; + + // Do we really want to allow single precision floats, despite all the problems they cause? + // These are nearly guaranteed to desync between MSVC and GCC on x87, because GCC does not implement an IEEE compliant mode + case ZCC_Float32: + case ZCC_FloatAuto: + //return TypeFloat32; + case ZCC_Float64: + retval = TypeFloat64; + break; + + case ZCC_String: + retval = TypeString; + break; + + case ZCC_Name: + retval = TypeName; + break; + + case ZCC_Vector2: + retval = TypeVector2; + break; + + case ZCC_Vector3: + retval = TypeVector3; + break; + + case ZCC_State: + retval = TypeState; + break; + + case ZCC_Color: + retval = TypeColor; + break; + + case ZCC_Sound: + retval = TypeSound; + break; + + case ZCC_UserType: + // statelabel is not a token - there really is no need to, it works just as well as an identifier. Maybe the same should be done for some other types, too? + if (btype->UserType->Id == NAME_StateLabel) + { + retval = TypeStateLabel; + } + else + { + retval = ResolveUserType(btype, &outertype->Symbols); + } + break; + } + break; + } + + case AST_MapType: + if (allowarraytypes) + { + Error(field, "%s: Map types not implemented yet", name.GetChars()); + // Todo: Decide what we allow here and if it makes sense to allow more complex constructs. + auto mtype = static_cast(ztype); + retval = NewMap(DetermineType(outertype, field, name, mtype->KeyType, false, false), DetermineType(outertype, field, name, mtype->ValueType, false, false)); + break; + } + break; + + case AST_DynArrayType: + if (allowarraytypes) + { + Error(field, "%s: Dynamic array types not implemented yet", name.GetChars()); + auto atype = static_cast(ztype); + retval = NewDynArray(DetermineType(outertype, field, name, atype->ElementType, false, false)); + break; + } + break; + + case AST_ClassType: + { + auto ctype = static_cast(ztype); + if (ctype->Restriction == nullptr) + { + retval = NewClassPointer(RUNTIME_CLASS(DObject)); + } + else + { + auto sym = outertype->Symbols.FindSymbol(ctype->Restriction->Id, true); + if (sym == nullptr) sym = GlobalSymbols.FindSymbol(ctype->Restriction->Id, false); + if (sym == nullptr) + { + Error(field, "%s: Unknown identifier", FName(ctype->Restriction->Id).GetChars()); + return TypeError; + } + auto typesym = dyn_cast(sym); + if (typesym == nullptr || !typesym->Type->IsKindOf(RUNTIME_CLASS(PClass))) + { + Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars()); + return TypeError; + } + retval = NewClassPointer(static_cast(typesym->Type)); + } + break; + } + } + if (retval != TypeError && retval->MemberOnly && !formember) + { + Error(field, "Invalid type %s", retval->DescriptiveName()); + return TypeError; + } + return retval; +} + +//========================================================================== +// +// ZCCCompiler :: ResolveUserType +// +// resolves a user type and returns a matching PType +// +//========================================================================== + +PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) +{ + // Check the symbol table for the identifier. + PSymbolTable *table; + PSymbol *sym = symt->FindSymbolInTable(type->UserType->Id, table); + // GlobalSymbols cannot be the parent of a class's symbol table so we have to look for global symbols explicitly. + if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(type->UserType->Id, table); + if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) + { + auto ptype = static_cast(sym)->Type; + if (ptype->IsKindOf(RUNTIME_CLASS(PEnum))) + { + return TypeSInt32; // hack this to an integer until we can resolve the enum mess. + } + if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) + { + return NewPointer(ptype, type->isconst); + } + return ptype; + } + Error(type, "Unable to resolve %s as type.", FName(type->UserType->Id).GetChars()); + return TypeError; +} + + +//========================================================================== +// +// ZCCCompiler :: ResolveArraySize +// +// resolves the array size and returns a matching type. +// +//========================================================================== + +PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym) +{ + // The duplicate Simplify call is necessary because if the head node gets replaced there is no way to detect the end of the list otherwise. + arraysize = Simplify(arraysize, sym, true); + ZCC_Expression *val; + do + { + val = Simplify(arraysize, sym, true); + if (val->Operation != PEX_ConstValue || !val->Type->IsA(RUNTIME_CLASS(PInt))) + { + Error(arraysize, "Array index must be an integer constant"); + return TypeError; + } + int size = static_cast(val)->IntVal; + if (size < 1) + { + Error(arraysize, "Array size must be positive"); + return TypeError; + } + baseType = NewArray(baseType, size); + val = static_cast(val->SiblingNext); + } while (val != arraysize); + return baseType; +} + +//========================================================================== +// +// ZCCCompiler :: GetInt - Input must be a constant expression +// +//========================================================================== + +int ZCCCompiler::GetInt(ZCC_Expression *expr) +{ + if (expr->Type == TypeError) + { + return 0; + } + const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; + int routelen = expr->Type->FindConversion(TypeSInt32, route, countof(route)); + if (routelen < 0) + { + Error(expr, "Cannot convert to integer"); + return 0; + } + else + { + if (expr->Type->IsKindOf(RUNTIME_CLASS(PFloat))) + { + Warn(expr, "Truncation of floating point value"); + } + auto ex = static_cast(ApplyConversion(expr, route, routelen)); + return ex->IntVal; + } +} + +double ZCCCompiler::GetDouble(ZCC_Expression *expr) +{ + if (expr->Type == TypeError) + { + return 0; + } + const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; + int routelen = expr->Type->FindConversion(TypeFloat64, route, countof(route)); + if (routelen < 0) + { + Error(expr, "Cannot convert to float"); + return 0; + } + else + { + auto ex = static_cast(ApplyConversion(expr, route, routelen)); + return ex->DoubleVal; + } +} + +const char *ZCCCompiler::GetString(ZCC_Expression *expr, bool silent) +{ + if (expr->Type == TypeError) + { + return nullptr; + } + else if (expr->Type->IsKindOf(RUNTIME_CLASS(PString))) + { + return static_cast(expr)->StringVal->GetChars(); + } + else if (expr->Type->IsKindOf(RUNTIME_CLASS(PName))) + { + // Ugh... What a mess... + return FName(ENamedName(static_cast(expr)->IntVal)).GetChars(); + } + else + { + if (!silent) Error(expr, "Cannot convert to string"); + return nullptr; + } +} + +//========================================================================== +// +// Parses an actor property's parameters and calls the handler +// +//========================================================================== + +void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *property, AActor *defaults, Baggage &bag) +{ + static TArray params; + static TArray strings; + + params.Clear(); + strings.Clear(); + params.Reserve(1); + params[0].i = 0; + if (prop->params[0] != '0') + { + if (property->Values == nullptr) + { + Error(property, "%s: arguments missing", prop->name); + return; + } + property->Values = Simplify(property->Values, &bag.Info->Symbols, true); // need to do this before the loop so that we can find the head node again. + const char * p = prop->params; + auto exp = property->Values; + + while (true) + { + FPropParam conv; + FPropParam pref; + + if (exp->NodeType != AST_ExprConstant) + { + // If we get TypeError, there has already been a message from deeper down so do not print another one. + if (exp->Type != TypeError) Error(exp, "%s: non-constant parameter", prop->name); + return; + } + conv.s = nullptr; + pref.s = nullptr; + pref.i = -1; + switch ((*p) & 223) + { + + case 'X': // Expression in parentheses or number. We only support the constant here. The function will have to be handled by a separate property to get past the parser. + conv.i = GetInt(exp); + params.Push(conv); + conv.exp = nullptr; + break; + + case 'I': + case 'M': // special case for morph styles in DECORATE . This expression-aware parser will not need this. + case 'N': // special case for thing activations in DECORATE. This expression-aware parser will not need this. + conv.i = GetInt(exp); + break; + + case 'F': + conv.d = GetDouble(exp); + break; + + case 'Z': // an optional string. Does not allow any numeric value. + if (!GetString(exp, true)) + { + // apply this expression to the next argument on the list. + params.Push(conv); + params[0].i++; + p++; + continue; + } + conv.s = GetString(exp); + break; + + case 'C': // this parser accepts colors only in string form. + pref.i = 1; + case 'S': + case 'T': // a filtered string (ZScript only parses filtered strings so there's nothing to do here.) + conv.s = GetString(exp); + break; + + case 'L': // Either a number or a list of strings + if (!GetString(exp, true)) + { + pref.i = 0; + conv.i = GetInt(exp); + } + else + { + pref.i = 1; + params.Push(pref); + params[0].i++; + + do + { + conv.s = GetString(exp); + if (conv.s != nullptr) + { + params.Push(conv); + params[0].i++; + } + exp = Simplify(static_cast(exp->SiblingNext), &bag.Info->Symbols, true); + } while (exp != property->Values); + goto endofparm; + } + break; + + default: + assert(false); + break; + + } + if (pref.i != -1) + { + params.Push(pref); + params[0].i++; + } + params.Push(conv); + params[0].i++; + exp = Simplify(static_cast(exp->SiblingNext), &bag.Info->Symbols, true); + endofparm: + p++; + // Skip the DECORATE 'no comma' marker + if (*p == '_') p++; + + if (*p == 0) + { + if (exp != property->Values) + { + Error(property, "Too many values for '%s'", prop->name); + return; + } + break; + } + else if (exp == property->Values) + { + if (*p < 'a') + { + Error(property, "Insufficient parameters for %s", prop->name); + return; + } + break; + } + } + } + // call the handler + try + { + prop->Handler(defaults, bag.Info, bag, ¶ms[0]); + } + catch (CRecoverableError &error) + { + Error(property, "%s", error.GetMessage()); + } +} + +//========================================================================== +// +// Parses an actor property +// +//========================================================================== + +void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *prop, Baggage &bag) +{ + auto namenode = prop->Prop; + FString propname; + + if (namenode->SiblingNext == namenode) + { + if (namenode->Id == NAME_DamageFunction) + { + auto x = ConvertNode(prop->Values); + CreateDamageFunction(cls, (AActor *)bag.Info->Defaults, x, false); + ((AActor *)bag.Info->Defaults)->DamageVal = -1; + return; + } + + // a one-name property + propname = FName(namenode->Id); + + } + else if (namenode->SiblingNext->SiblingNext == namenode) + { + // a two-name property + propname << FName(namenode->Id) << "." << FName(static_cast(namenode->SiblingNext)->Id); + } + else + { + Error(prop, "Property name may at most contain two parts"); + return; + } + + + FPropertyInfo *property = FindProperty(propname); + + if (property != nullptr && property->category != CAT_INFO) + { + if (cls->IsDescendantOf(*property->cls)) + { + DispatchProperty(property, prop, (AActor *)bag.Info->Defaults, bag); + } + else + { + Error(prop, "'%s' requires an actor of type '%s'\n", propname.GetChars(), (*property->cls)->TypeName.GetChars()); + } + } + else + { + Error(prop, "'%s' is an unknown actor property\n", propname.GetChars()); + } +} + +//========================================================================== +// +// Finds a flag and sets or clears it +// +//========================================================================== + +void ZCCCompiler::ProcessDefaultFlag(PClassActor *cls, ZCC_FlagStmt *flg) +{ + auto namenode = flg->name; + const char *n1 = FName(namenode->Id).GetChars(), *n2; + + if (namenode->SiblingNext == namenode) + { + // a one-name flag + n2 = nullptr; + } + else if (namenode->SiblingNext->SiblingNext == namenode) + { + // a two-name flag + n2 = FName(static_cast(namenode->SiblingNext)->Id).GetChars(); + } + else + { + Error(flg, "Flag name may at most contain two parts"); + return; + } + + auto fd = FindFlag(cls, n1, n2, true); + if (fd != nullptr) + { + if (fd->varflags & VARF_Deprecated) + { + Warn(flg, "Deprecated flag '%s%s%s' used", n1, n2 ? "." : "", n2 ? n2 : ""); + } + if (fd->structoffset == -1) + { + HandleDeprecatedFlags((AActor*)cls->Defaults, cls, flg->set, fd->flagbit); + } + else + { + ModActorFlag((AActor*)cls->Defaults, fd, flg->set); + } + } + else + { + Error(flg, "Unknown flag '%s%s%s'", n1, n2 ? "." : "", n2 ? n2 : ""); + } +} + +//========================================================================== +// +// Parses the default list +// +//========================================================================== + +void ZCCCompiler::InitDefaults() +{ + for (auto c : Classes) + { + // This may be removed if the conditions change, but right now only subclasses of Actor can define a Default block. + if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor))) + { + if (c->Defaults.Size()) Error(c->cls, "%s: Non-actor classes may not have defaults", c->Type()->TypeName.GetChars()); + if (c->Type()->ParentClass) c->Type()->ParentClass->DeriveData(c->Type()); + } + else + { + // This should never happen. + if (c->Type()->Defaults != nullptr) + { + Error(c->cls, "%s already has defaults", c->Type()->TypeName.GetChars()); + } + // This can only occur if a native parent is not initialized. In all other cases the sorting of the class list should prevent this from ever happening. + else if (c->Type()->ParentClass->Defaults == nullptr && c->Type() != RUNTIME_CLASS(AActor)) + { + Error(c->cls, "Parent class %s of %s is not initialized", c->Type()->ParentClass->TypeName.GetChars(), c->Type()->TypeName.GetChars()); + } + else + { + // Copy the parent's defaults and meta data. + auto ti = static_cast(c->Type()); + + // Hack for the DVMObjects as they weren't in the list originally + // TODO: process them in a non hackish way obviously + if (ti->ParentClass->Defaults == DEFAULTS_VMEXPORT) + { + ti->ParentClass->Defaults = nullptr; + ti->ParentClass->InitializeDefaults(); + ti->ParentClass->ParentClass->DeriveData(ti->ParentClass); + } + + ti->InitializeDefaults(); + ti->ParentClass->DeriveData(ti); + + // We need special treatment for this one field in AActor's defaults which cannot be made visible to DECORATE as a property. + // It's better to do this here under controlled conditions than deeper down in the class type classes. + if (ti == RUNTIME_CLASS(AActor)) + { + ((AActor*)ti->Defaults)->ConversationRoot = 1; + } + + Baggage bag; + #ifdef _DEBUG + bag.ClassName = c->Type()->TypeName; + #endif + bag.Info = ti; + bag.DropItemSet = false; + bag.StateSet = false; + bag.fromDecorate = false; + bag.CurrentState = 0; + bag.Lumpnum = c->cls->SourceLump; + bag.DropItemList = nullptr; + // The actual script position needs to be set per property. + + for (auto d : c->Defaults) + { + auto content = d->Content; + if (content != nullptr) do + { + switch (content->NodeType) + { + case AST_PropertyStmt: + bag.ScriptPosition.FileName = *content->SourceName; + bag.ScriptPosition.ScriptLine = content->SourceLoc; + ProcessDefaultProperty(ti, static_cast(content), bag); + break; + + case AST_FlagStmt: + ProcessDefaultFlag(ti, static_cast(content)); + break; + } + content = static_cast(content->SiblingNext); + } while (content != d->Content); + } + if (bag.DropItemSet) + { + bag.Info->SetDropItems(bag.DropItemList); + } + } + } + } +} + +//========================================================================== +// +// Parses the functions list +// +//========================================================================== + +void ZCCCompiler::InitFunctions() +{ + TArray rets(1); + TArray args; + TArray argflags; + TArray argdefaults; + TArray argnames; + + for (auto c : Classes) + { + // cannot be done earlier because it requires the parent class to be processed by this code, too. + if (c->Type()->ParentClass != nullptr) + { + if (c->Type()->ParentClass->Virtuals.Size() == 0) + { + // This a VMClass which didn't get processed here. + c->Type()->ParentClass->Virtuals = c->Type()->ParentClass->ParentClass->Virtuals; + } + c->Type()->Virtuals = c->Type()->ParentClass->Virtuals; + } + for (auto f : c->Functions) + { + 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)) + { + auto t = f->Type; + if (t != nullptr) + { + do + { + auto type = DetermineType(c->Type(), f, f->Name, t, false, false); + if (type->IsKindOf(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) + { + // structs and classes only get passed by pointer. + type = NewPointer(type); + } + // TBD: disallow certain types? For now, let everything pass that isn't an array. + rets.Push(type); + t = static_cast(t->SiblingNext); + } while (t != f->Type); + } + + int notallowed = ZCC_Latent | ZCC_Meta | ZCC_ReadOnly | ZCC_FuncConst | ZCC_Abstract; + + if (f->Flags & notallowed) + { + Error(f, "Invalid qualifiers for %s (%s not allowed)", FName(f->Name).GetChars(), FlagsToString(f->Flags & notallowed).GetChars()); + f->Flags &= notallowed; + } + uint32_t varflags = VARF_Method; + int implicitargs = 1; + AFuncDesc *afd = nullptr; + + // map to implementation flags. + if (f->Flags & ZCC_Private) varflags |= VARF_Private; + if (f->Flags & ZCC_Protected) varflags |= VARF_Protected; + if (f->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated; + if (f->Flags & ZCC_Virtual) varflags |= VARF_Virtual; + if (f->Flags & ZCC_Override) varflags |= VARF_Override; + if (f->Flags & ZCC_Action) varflags |= VARF_Action|VARF_Final, implicitargs = 3; // Action implies Final. + if (f->Flags & ZCC_Static) varflags = (varflags & ~VARF_Method) | VARF_Final, implicitargs = 0; // Static implies Final. + + if (varflags & VARF_Override) varflags &= ~VARF_Virtual; // allow 'virtual override'. + // Only one of these flags may be used. + static int exclude[] = { ZCC_Virtual, ZCC_Override, ZCC_Action, ZCC_Static }; + static const char * print[] = { "virtual", "override", "action", "static" }; + int fc = 0; + FString build; + for (int i = 0; i < 4; i++) + { + if (f->Flags & exclude[i]) + { + fc++; + if (build.Len() > 0) build += ", "; + build += print[i]; + } + } + if (fc > 1) + { + Error(f, "Invalid combination of qualifiers %s on function %s.", FName(f->Name).GetChars(), build.GetChars() ); + varflags |= VARF_Method; + } + if (varflags & VARF_Override) varflags |= VARF_Virtual; // Now that the flags are checked, make all override functions virtual as well. + + if (f->Flags & ZCC_Native) + { + varflags |= VARF_Native; + afd = FindFunction(FName(f->Name).GetChars()); + if (afd == nullptr) + { + Error(f, "The function '%s' has not been exported from the executable.", FName(f->Name).GetChars()); + } + else + { + (*afd->VMPointer)->ImplicitArgs = BYTE(implicitargs); + } + } + // Todo: parse these values from the definition + int tempuseflags = (varflags & VARF_Action) ? SUF_WEAPON | SUF_ITEM | SUF_OVERLAY | SUF_ACTOR : SUF_ACTOR; + SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags, tempuseflags); + argdefaults.Resize(argnames.Size()); + auto p = f->Params; + bool hasoptionals = false; + if (p != nullptr) + { + do + { + int elementcount = 1; + VMValue vmval[3]; // 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 ((type->IsA(RUNTIME_CLASS(PStruct))) || (flags & VARF_Out)) + { + // 'out' parameters and all structs except vectors are passed by reference + if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3)) + { + type = NewPointer(type); + } + else if (type == TypeVector2) + { + elementcount = 2; + } + else if (type == TypeVector3) + { + elementcount = 3; + } + } + 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; + hasoptionals = true; + // 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) + { + // Vectors need special treatment because they use more than one entry in the Defaults and do not report as actual constants + if (type == TypeVector2 && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(2)) + { + auto vx = static_cast(x); + vmval[0] = static_cast(vx->xyz[0])->GetValue().GetFloat(); + vmval[1] = static_cast(vx->xyz[1])->GetValue().GetFloat(); + } + else if (type == TypeVector3 && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(3)) + { + auto vx = static_cast(x); + vmval[0] = static_cast(vx->xyz[0])->GetValue().GetFloat(); + vmval[1] = static_cast(vx->xyz[1])->GetValue().GetFloat(); + vmval[2] = static_cast(vx->xyz[2])->GetValue().GetFloat(); + } + else 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[0] = cnst->GetValue().GetInt(); + break; + + case REGT_FLOAT: + vmval[0] = cnst->GetValue().GetFloat(); + break; + + case REGT_POINTER: + if (type->IsKindOf(RUNTIME_CLASS(PClassPointer))) + vmval[0] = (DObject*)cnst->GetValue().GetPointer(); + else + vmval[0] = cnst->GetValue().GetPointer(); + break; + + case REGT_STRING: + vmval[0] = cnst->GetValue().GetString(); + break; + + default: + assert(0 && "no valid type for constant"); + break; + } + } + } + if (x != nullptr) delete x; + } + else if (hasoptionals) + { + Error(p, "All arguments after the first optional one need also be optional."); + } + // TBD: disallow certain types? For now, let everything pass that isn't an array. + args.Push(type); + argflags.Push(flags); + argnames.Push(p->Name); + + } + else + { + args.Push(nullptr); + argflags.Push(0); + argnames.Push(NAME_None); + } + for(int i=0;i(p->SiblingNext); + } while (p != f->Params); + } + + PFunction *sym = new PFunction(c->Type(), f->Name); + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr? nullptr : *(afd->VMPointer), varflags); + c->Type()->Symbols.ReplaceSymbol(sym); + + if (!(f->Flags & ZCC_Native)) + { + auto code = ConvertAST(c->Type(), f->Body); + if (code != nullptr) + { + sym->Variants[0].Implementation = FunctionBuildList.AddFunction(sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump); + } + } + if (sym->Variants[0].Implementation != nullptr && hasdefault) // do not copy empty default lists, they only waste space and processing time. + { + sym->Variants[0].Implementation->DefaultArgs = std::move(argdefaults); + } + + if (varflags & VARF_Virtual) + { + if (varflags & VARF_Final) + { + sym->Variants[0].Implementation->Final = true; + } + int vindex = c->Type()->FindVirtualIndex(sym->SymbolName, sym->Variants[0].Proto); + // specifying 'override' is necessary to prevent one of the biggest problem spots with virtual inheritance: Mismatching argument types. + if (varflags & VARF_Override) + { + if (vindex == -1) + { + Error(p, "Attempt to override non-existent virtual function %s", FName(f->Name).GetChars()); + } + else + { + auto oldfunc = c->Type()->Virtuals[vindex]; + if (oldfunc->Final) + { + Error(p, "Attempt to override final function %s", FName(f->Name).GetChars()); + } + c->Type()->Virtuals[vindex] = sym->Variants[0].Implementation; + sym->Variants[0].Implementation->VirtualIndex = vindex; + } + } + else + { + if (vindex != -1) + { + Error(p, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); + } + sym->Variants[0].Implementation->VirtualIndex = c->Type()->Virtuals.Push(sym->Variants[0].Implementation); + } + } + } + } + } +} + +//========================================================================== +// +// very complicated check for random duration. +// +//========================================================================== + +static bool CheckRandom(ZCC_Expression *duration) +{ + if (duration->NodeType != AST_ExprFuncCall) return false; + auto func = static_cast(duration); + if (func->Function == nullptr) return false; + if (func->Function->NodeType != AST_ExprID) return false; + auto f2 = static_cast(func->Function); + return f2->Identifier == NAME_Random; +} + +//========================================================================== +// +// Sets up the action function call +// +//========================================================================== +FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) +{ + // We have 3 cases to consider here: + // 1. A function without parameters. This can be called directly + // 2. A functon with parameters. This needs to be wrapped into a helper function to set everything up. + // 3. An anonymous function. + + // 1. and 2. are exposed through AST_ExprFunctionCall + if (af->NodeType == AST_ExprFuncCall) + { + auto fc = static_cast(af); + assert(fc->Function->NodeType == AST_ExprID); + auto id = static_cast(fc->Function); + + // We must skip ACS_NamedExecuteWithResult here, because this name both exists as an action function and as a builtin. + // The code which gets called from here can easily make use of the builtin, so let's just pass this name without any checks. + // The actual action function is still needed by DECORATE: + if (id->Identifier != NAME_ACS_NamedExecuteWithResult) + { + PFunction *afd = dyn_cast(cls->Symbols.FindSymbol(id->Identifier, true)); + if (afd != nullptr) + { + if (fc->Parameters == nullptr && !(afd->Variants[0].Flags & VARF_Virtual)) + { + FArgumentList argumentlist; + // We can use this function directly without wrapping it in a caller. + if ((afd->Variants[0].Flags & VARF_Action) || !cls->IsDescendantOf(RUNTIME_CLASS(AStateProvider)) || !afd->Variants[0].SelfClass->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) + { + return new FxVMFunctionCall(new FxSelf(*af), afd, argumentlist, *af, false); + } + else + { + Error(af, "Cannot use non-action function %s here.", FName(id->Identifier).GetChars()); + } + } + } + else + { + // it may also be an action special so check that first before printing an error. + if (!P_FindLineSpecial(FName(id->Identifier).GetChars())) + { + Error(af, "%s: action function not found in %s", FName(id->Identifier).GetChars(), cls->TypeName.GetChars()); + return nullptr; + } + // Action specials fall through to the code generator. + } + } + } + return ConvertAST(cls, af); +} + +//========================================================================== +// +// Compile the states +// +//========================================================================== + +void ZCCCompiler::CompileStates() +{ + for (auto c : Classes) + { + + if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor))) + { + if (c->States.Size()) Error(c->cls, "%s: States can only be defined for actors.", c->Type()->TypeName.GetChars()); + continue; + } + + // Same here, hack in the DVMObject as they weren't in the list originally + // TODO: process them in a non hackish way obviously + if (c->Type()->bRuntimeClass == true && c->Type()->ParentClass->bRuntimeClass == false) + { + auto vmtype = static_cast(c->Type()->ParentClass); + if (vmtype->StateList == nullptr) + { + FStateDefinitions vmstates; + vmstates.MakeStateDefines(dyn_cast(vmtype->ParentClass)); + vmtype->Finalize(vmstates); + } + } + + FString statename; // The state builder wants the label as one complete string, not separated into tokens. + FStateDefinitions statedef; + statedef.MakeStateDefines(dyn_cast(c->Type()->ParentClass)); + int numframes = 0; + + for (auto s : c->States) + { + int flags; + if (s->Flags != nullptr) + { + flags = 0; + auto p = s->Flags; + do + { + switch (p->Id) + { + case NAME_Actor: + flags |= SUF_ACTOR; + break; + case NAME_Overlay: + flags |= SUF_OVERLAY; + break; + case NAME_Weapon: + flags |= SUF_WEAPON; + break; + case NAME_Item: + flags |= SUF_ITEM; + break; + default: + Error(p, "Unknown States qualifier %s", FName(p->Id).GetChars()); + break; + } + + p = static_cast(p->SiblingNext); + } while (p != s->Flags); + } + else + { + flags = static_cast(c->Type())->DefaultStateUsage; + } + auto st = s->Body; + if (st != nullptr) do + { + switch (st->NodeType) + { + case AST_StateLabel: + { + auto sl = static_cast(st); + statename = FName(sl->Label); + statedef.AddStateLabel(statename); + break; + } + case AST_StateLine: + { + auto sl = static_cast(st); + FState state; + memset(&state, 0, sizeof(state)); + state.UseFlags = flags; + if (sl->Sprite->Len() != 4) + { + Error(sl, "Sprite name must be exactly 4 characters. Found '%s'", sl->Sprite->GetChars()); + } + else + { + state.sprite = GetSpriteIndex(sl->Sprite->GetChars()); + } + // It is important to call CheckRandom before Simplify, because Simplify will resolve the function's name to nonsense + if (CheckRandom(sl->Duration)) + { + auto func = static_cast(sl->Duration); + if (func->Parameters == func->Parameters->SiblingNext || func->Parameters != func->Parameters->SiblingNext->SiblingNext) + { + Error(sl, "Random duration requires exactly 2 parameters"); + } + auto p1 = Simplify(func->Parameters->Value, &c->Type()->Symbols, true); + auto p2 = Simplify(static_cast(func->Parameters->SiblingNext)->Value, &c->Type()->Symbols, true); + int v1 = GetInt(p1); + int v2 = GetInt(p2); + if (v1 > v2) std::swap(v1, v2); + state.Tics = (int16_t)clamp(v1, 0, INT16_MAX); + state.TicRange = (uint16_t)clamp(v2 - v1, 0, UINT16_MAX); + } + else + { + auto duration = Simplify(sl->Duration, &c->Type()->Symbols, true); + if (duration->Operation == PEX_ConstValue) + { + state.Tics = (int16_t)clamp(GetInt(duration), -1, INT16_MAX); + state.TicRange = 0; + } + else + { + Error(sl, "Duration is not a constant"); + } + } + state.Fullbright = sl->bBright; + state.Fast = sl->bFast; + state.Slow = sl->bSlow; + state.CanRaise = sl->bCanRaise; + if ((state.NoDelay = sl->bNoDelay)) + { + if (statedef.GetStateLabelIndex(NAME_Spawn) != statedef.GetStateCount()) + { + Warn(sl, "NODELAY only has an effect on the first state after 'Spawn:'"); + } + } + if (sl->Offset != nullptr) + { + auto o1 = static_cast(Simplify(sl->Offset, &c->Type()->Symbols, true)); + auto o2 = static_cast(Simplify(static_cast(o1->SiblingNext), &c->Type()->Symbols, true)); + + if (o1->Operation != PEX_ConstValue || o2->Operation != PEX_ConstValue) + { + Error(o1, "State offsets must be constant"); + } + else + { + state.Misc1 = GetInt(o1); + state.Misc2 = GetInt(o2); + } + } +#ifdef DYNLIGHT + if (sl->Lights != nullptr) + { + auto l = sl->Lights; + do + { + AddStateLight(&state, GetString(l)); + l = static_cast(l->SiblingNext); + } while (l != sl->Lights); + } +#endif + + if (sl->Action != nullptr) + { + auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); + if (code != nullptr) + { + auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, state.UseFlags); + state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len(), Lump); + } + } + + int count = statedef.AddStates(&state, sl->Frames->GetChars(), *sl); + if (count < 0) + { + Error(sl, "Invalid frame character string '%s'", sl->Frames->GetChars()); + count = -count; + } + break; + } + case AST_StateGoto: + { + auto sg = static_cast(st); + statename = ""; + if (sg->Qualifier != nullptr) + { + statename << FName(sg->Qualifier->Id) << "::"; + } + auto part = sg->Label; + do + { + statename << FName(part->Id) << '.'; + part = static_cast(part->SiblingNext); + } while (part != sg->Label); + statename.Truncate((long)statename.Len() - 1); // remove the last '.' in the label name + if (sg->Offset != nullptr) + { + auto ofs = Simplify(sg->Offset, &c->Type()->Symbols, true); + if (ofs->Operation != PEX_ConstValue) + { + Error(sg, "Constant offset expected for GOTO"); + } + else + { + int offset = GetInt(ofs); + if (offset < 0) + { + Error(sg, "GOTO offset must be positive"); + offset = 0; + } + if (offset > 0) + { + statename.AppendFormat("+%d", offset); + } + } + } + if (!statedef.SetGotoLabel(statename)) + { + Error(sg, "GOTO before first state"); + } + break; + } + case AST_StateFail: + case AST_StateWait: + if (!statedef.SetWait()) + { + Error(st, "%s before first state", st->NodeType == AST_StateFail ? "Fail" : "Wait"); + continue; + } + break; + + case AST_StateLoop: + if (!statedef.SetLoop()) + { + Error(st, "LOOP before first state"); + continue; + } + break; + + case AST_StateStop: + if (!statedef.SetStop()) + { + Error(st, "STOP before first state"); + } + break; + + default: + assert(0 && "Bad AST node in state"); + } + st = static_cast(st->SiblingNext); + } while (st != s->Body); + } + try + { + static_cast(c->Type())->Finalize(statedef); + } + catch (CRecoverableError &err) + { + Error(c->cls, "%s", err.GetMessage()); + } + } +} + +//========================================================================== +// +// Convert the AST data for the code generator. +// +//========================================================================== + +FxExpression *ZCCCompiler::ConvertAST(PClass *cls, ZCC_TreeNode *ast) +{ + ConvertClass = cls; + // there are two possibilities here: either a single function call or a compound statement. For a compound statement we also need to check if the last thing added was a return. + if (ast->NodeType == AST_ExprFuncCall) + { + auto cp = new FxCompoundStatement(*ast); + cp->Add(new FxReturnStatement(ConvertNode(ast), *ast)); + return cp; + } + else + { + // This must be done here so that we can check for a trailing return statement. + auto x = new FxCompoundStatement(*ast); + auto compound = static_cast(ast); + //bool isreturn = false; + auto node = compound->Content; + if (node != nullptr) do + { + x->Add(ConvertNode(node)); + //isreturn = node->NodeType == AST_ReturnStmt; + node = static_cast(node->SiblingNext); + } while (node != compound->Content); + //if (!isreturn) x->Add(new FxReturnStatement(nullptr, *ast)); + return x; + } +} + + +#define xx(a,z) z, +static int Pex2Tok[] = { +#include "zcc_exprlist.h" +}; + +//========================================================================== +// +// Helper for modify/assign operators +// +//========================================================================== + +static FxExpression *ModifyAssign(FxBinary *operation, FxExpression *left) +{ + auto assignself = static_cast(operation->left); + auto assignment = new FxAssign(left, operation, true); + assignself->Assignment = assignment; + return assignment; +} + + +//========================================================================== +// +// Convert an AST node and its children +// +//========================================================================== + +FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) +{ + if (ast == nullptr) return nullptr; + + // Note: Do not call 'Simplify' here because that function tends to destroy identifiers due to lack of context in which to resolve them. + // The Fx nodes created here will be better suited for that. + switch (ast->NodeType) + { + case AST_ExprFuncCall: + { + auto fcall = static_cast(ast); + + // function names can either be + // - plain identifiers + // - class members + // - array syntax for random() calls. + // Everything else coming here is a syntax error. + FArgumentList args; + switch (fcall->Function->NodeType) + { + case AST_ExprID: + // The function name is a simple identifier. + return new FxFunctionCall(static_cast(fcall->Function)->Identifier, NAME_None, ConvertNodeList(args, fcall->Parameters), *ast); + + case AST_ExprMemberAccess: + { + auto ema = static_cast(fcall->Function); + return new FxMemberFunctionCall(ConvertNode(ema->Left), ema->Right, ConvertNodeList(args, fcall->Parameters), *ast); + } + + case AST_ExprBinary: + // Array syntax for randoms. They are internally stored as ExprBinary with both an identifier on the left and right side. + if (fcall->Function->Operation == PEX_ArrayAccess) + { + auto binary = static_cast(fcall->Function); + if (binary->Left->NodeType == AST_ExprID && binary->Right->NodeType == AST_ExprID) + { + return new FxFunctionCall(static_cast(binary->Left)->Identifier, static_cast(binary->Right)->Identifier, ConvertNodeList(args, fcall->Parameters), *ast); + } + } + // fall through if this isn't an array access node. + + default: + Error(fcall, "Invalid function identifier"); + return new FxNop(*ast); // return something so that the compiler can continue. + } + break; + } + + case AST_ExprMemberAccess: + { + auto memaccess = static_cast(ast); + return new FxMemberIdentifier(ConvertNode(memaccess->Left), memaccess->Right, *ast); + } + + case AST_FuncParm: + { + auto fparm = static_cast(ast); + // ignore the label for now, that's stuff for far later, when a bit more here is working. + return ConvertNode(fparm->Value); + } + + case AST_ExprID: + { + auto id = static_cast(ast); + return new FxIdentifier(id->Identifier, *ast); + } + + case AST_ExprConstant: + { + auto cnst = static_cast(ast); + if (cnst->Type->IsA(RUNTIME_CLASS(PName))) + { + return new FxConstant(FName(ENamedName(cnst->IntVal)), *ast); + } + else if (cnst->Type->IsA(RUNTIME_CLASS(PInt))) + { + return new FxConstant(cnst->IntVal, *ast); + } + else if (cnst->Type->IsA(RUNTIME_CLASS(PBool))) + { + return new FxConstant(!!cnst->IntVal, *ast); + } + else if (cnst->Type->IsA(RUNTIME_CLASS(PFloat))) + { + return new FxConstant(cnst->DoubleVal, *ast); + } + else if (cnst->Type->IsA(RUNTIME_CLASS(PString))) + { + return new FxConstant(*cnst->StringVal, *ast); + } + else if (cnst->Type == TypeNullPtr) + { + return new FxConstant(*ast); + } + else + { + // can there be other types? + Error(cnst, "Unknown constant type %s", cnst->Type->DescriptiveName()); + return new FxConstant(0, *ast); + } + } + + case AST_ExprUnary: + { + auto unary = static_cast(ast); + auto operand = ConvertNode(unary->Operand); + auto op = unary->Operation; + switch (op) + { + case PEX_PostDec: + case PEX_PostInc: + return new FxPostIncrDecr(operand, Pex2Tok[op]); + + case PEX_PreDec: + case PEX_PreInc: + return new FxPreIncrDecr(operand, Pex2Tok[op]); + + case PEX_Negate: + return new FxMinusSign(operand); + + case PEX_AntiNegate: + return new FxPlusSign(operand); + + case PEX_BitNot: + return new FxUnaryNotBitwise(operand); + + case PEX_BoolNot: + return new FxUnaryNotBoolean(operand); + + case PEX_SizeOf: + case PEX_AlignOf: + return new FxSizeAlign(operand, Pex2Tok[op]); + + default: + assert(0 && "Unknown unary operator."); // should never happen + Error(unary, "Unknown unary operator ID #%d", op); + return new FxNop(*ast); + } + break; + } + + + case AST_ExprBinary: + { + auto binary = static_cast(ast); + auto left = ConvertNode(binary->Left); + auto right = ConvertNode(binary->Right); + auto op = binary->Operation; + auto tok = Pex2Tok[op]; + switch (op) + { + case PEX_Add: + case PEX_Sub: + return new FxAddSub(tok, left, right); + + case PEX_Mul: + case PEX_Div: + case PEX_Mod: + return new FxMulDiv(tok, left, right); + + case PEX_Pow: + return new FxPow(left, right); + + case PEX_LeftShift: + case PEX_RightShift: + case PEX_URightShift: + case PEX_BitAnd: + case PEX_BitOr: + case PEX_BitXor: + return new FxBinaryInt(tok, left, right); + + case PEX_BoolOr: + case PEX_BoolAnd: + return new FxBinaryLogical(tok, left, right); + + case PEX_LT: + case PEX_LTEQ: + case PEX_GT: + case PEX_GTEQ: + return new FxCompareRel(tok, left, right); + + case PEX_EQEQ: + case PEX_NEQ: + case PEX_APREQ: + return new FxCompareEq(tok, left, right); + + case PEX_Assign: + return new FxAssign(left, right); + + case PEX_AddAssign: + case PEX_SubAssign: + return ModifyAssign(new FxAddSub(tok, new FxAssignSelf(*ast), right), left); + + case PEX_MulAssign: + case PEX_DivAssign: + case PEX_ModAssign: + return ModifyAssign(new FxMulDiv(tok, new FxAssignSelf(*ast), right), left); + + case PEX_LshAssign: + case PEX_RshAssign: + case PEX_URshAssign: + case PEX_AndAssign: + case PEX_OrAssign: + case PEX_XorAssign: + return ModifyAssign(new FxBinaryInt(tok, new FxAssignSelf(*ast), right), left); + + case PEX_LTGTEQ: + return new FxLtGtEq(left, right); + + case PEX_ArrayAccess: + return new FxArrayElement(left, right); + + case PEX_CrossProduct: + case PEX_DotProduct: + return new FxDotCross(tok, left, right); + + case PEX_Is: + return new FxTypeCheck(left, right); + + // todo: These do not have representations in DECORATE and no implementation exists yet. + case PEX_Concat: + + default: + I_Error("Binary operator %d not implemented yet", op); + } + break; + } + + case AST_ExprTrinary: + { + auto trinary = static_cast(ast); + auto condition = ConvertNode(trinary->Test); + auto left = ConvertNode(trinary->Left); + auto right = ConvertNode(trinary->Right); + + return new FxConditional(condition, left, right); + } + + case AST_VectorValue: + { + auto vecini = static_cast(ast); + auto xx = ConvertNode(vecini->X); + auto yy = ConvertNode(vecini->Y); + auto zz = ConvertNode(vecini->Z); + return new FxVectorValue(xx, yy, zz, *ast); + } + + case AST_LocalVarStmt: + { + auto loc = static_cast(ast); + auto node = loc->Vars; + FxSequence *list = new FxSequence(*ast); + do + { + // Type determination must be done for each field to properly handle array definitions. + PType *type = DetermineType(ConvertClass, node, node->Name, loc->Type, true, false); + if (type->IsKindOf(RUNTIME_CLASS(PArray))) + { + Error(loc, "Local array variables not implemented yet."); + } + else + { + FxExpression *val; + if (node->InitIsArray) + { + Error(node, "Tried to initialize %s with an array", FName(node->Name).GetChars()); + val = nullptr; + } + else + { + val = node->Init ? ConvertNode(node->Init) : nullptr; + } + list->Add(new FxLocalVariableDeclaration(type, node->Name, val, 0, *node)); // todo: Handle flags in the grammar. + } + + node = static_cast(node->SiblingNext); + } while (node != loc->Vars); + return list; + } + + case AST_Expression: + { + auto ret = static_cast(ast); + if (ret->Operation == PEX_Super) + { + return new FxSuper(*ast); + } + break; + } + + case AST_ExpressionStmt: + return ConvertNode(static_cast(ast)->Expression); + + case AST_ReturnStmt: + { + auto ret = static_cast(ast); + FArgumentList args; + ConvertNodeList(args, ret->Values); + if (args.Size() == 0) + { + return new FxReturnStatement(nullptr, *ast); + } + else if (args.Size() == 1) + { + auto arg = args[0]; + args[0] = nullptr; + return new FxReturnStatement(arg, *ast); + } + else + { + Error(ast, "Return with multiple values not implemented yet."); + return new FxReturnStatement(nullptr, *ast); + } + } + + case AST_BreakStmt: + case AST_ContinueStmt: + return new FxJumpStatement(ast->NodeType == AST_BreakStmt ? TK_Break : TK_Continue, *ast); + + case AST_IfStmt: + { + auto iff = static_cast(ast); + return new FxIfStatement(ConvertNode(iff->Condition), ConvertNode(iff->TruePath), ConvertNode(iff->FalsePath), *ast); + } + + case AST_IterationStmt: + { + auto iter = static_cast(ast); + if (iter->CheckAt == ZCC_IterationStmt::End) + { + assert(iter->LoopBumper == nullptr); + return new FxDoWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast); + } + else if (iter->LoopBumper != nullptr) + { + return new FxForLoop(nullptr, ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopBumper), ConvertNode(iter->LoopStatement), *ast); + } + else + { + return new FxWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast); + } + } + + // not yet done + case AST_SwitchStmt: + { + auto swtch = static_cast(ast); + if (swtch->Content->NodeType != AST_CompoundStmt) + { + Error(ast, "Expecting { after 'switch'"); + return new FxNop(*ast); // allow compiler to continue looking for errors. + } + else + { + // The switch content is wrapped into a compound statement which needs to be unraveled here. + auto cmpnd = static_cast(swtch->Content); + FArgumentList args; + return new FxSwitchStatement(ConvertNode(swtch->Condition), ConvertNodeList(args, cmpnd->Content), *ast); + } + } + + case AST_CaseStmt: + { + auto cases = static_cast(ast); + return new FxCaseStatement(ConvertNode(cases->Condition), *ast); + } + + case AST_CompoundStmt: + { + auto x = new FxCompoundStatement(*ast); + auto compound = static_cast(ast); + auto node = compound->Content; + if (node != nullptr) do + { + x->Add(ConvertNode(node)); + node = static_cast(node->SiblingNext); + } while (node != compound->Content); + return x; + } + } + // only for development. I_Error is more convenient here than a normal error. + I_Error("ConvertNode encountered unsupported node of type %d", ast->NodeType); + return nullptr; +} + + +FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *head) +{ + if (head != nullptr) + { + auto node = head; + do + { + args.Push(ConvertNode(node)); + node = node->SiblingNext; + } while (node != head); + } + return args; +} \ No newline at end of file diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h new file mode 100644 index 000000000..2e8840a46 --- /dev/null +++ b/src/scripting/zscript/zcc_compile.h @@ -0,0 +1,159 @@ +#ifndef ZCC_COMPILE_H +#define ZCC_COMPILE_H + +#include + +struct Baggage; +struct FPropertyInfo; +class AActor; +class FxExpression; +typedef TDeletingArray FArgumentList; + + +struct ZCC_StructWork +{ + PSymbolTable TreeNodes; + ZCC_Struct *strct; + ZCC_Class *OuterDef; + PClass *Outer; + PSymbolTreeNode *node; + TArray Enums; + TArray Constants; + TArray Fields; + + ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n, ZCC_Class *outer) + { + strct = s; + node = n; + OuterDef = outer; + Outer = nullptr; + }; + + FName NodeName() const + { + return strct->NodeName; + } + + PStruct *Type() + { + return strct->Type; + } + +}; + +struct ZCC_ClassWork +{ + ZCC_Class *cls; + PSymbolTable TreeNodes; + PSymbolTreeNode *node; + TArray Enums; + TArray Constants; + TArray Fields; + TArray Defaults; + TArray Functions; + TArray States; + + ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n) + { + cls = s; + node = n; + } + + FName NodeName() const + { + return cls->NodeName; + } + + PClass *Type() + { + return cls->Type; + } + +}; + +struct ZCC_ConstantWork +{ + ZCC_ConstantDef *node; + PSymbolTable *outputtable; +}; + +class ZCCCompiler +{ +public: + ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PSymbolTable &outsymbols, int lumpnum); + ~ZCCCompiler(); + int Compile(); + +private: + void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); + void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer); + void CreateStructTypes(); + void CreateClassTypes(); + void CopyConstants(TArray &dest, TArray &Constants, PSymbolTable *ot); + void CompileAllConstants(); + void AddConstant(ZCC_ConstantWork &constant); + bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols); + + void CompileAllFields(); + bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct); + FString FlagsToString(uint32_t flags); + PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); + PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym); + PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym); + + void InitDefaults(); + void ProcessDefaultFlag(PClassActor *cls, ZCC_FlagStmt *flg); + void ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *flg, Baggage &bag); + void DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *pex, AActor *defaults, Baggage &bag); + int GetInt(ZCC_Expression *expr); + double GetDouble(ZCC_Expression *expr); + const char *GetString(ZCC_Expression *expr, bool silent = false); + + void InitFunctions(); + void CompileStates(); + FxExpression *SetupActionFunction(PClass *cls, ZCC_TreeNode *sl); + + bool SimplifyingConstant; + TArray Constants; + TArray Structs; + TArray Classes; + + PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false); + + ZCC_Expression *Simplify(ZCC_Expression *root, PSymbolTable *Symbols, bool wantconstant); + ZCC_Expression *DoSimplify(ZCC_Expression *root, PSymbolTable *Symbols); + ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *Symbols); + ZCC_Expression *SimplifyBinary(ZCC_ExprBinary *binary, PSymbolTable *Symbols); + ZCC_Expression *SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop, PSymbolTable *Symbols); + ZCC_Expression *SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSymbolTable *Symbols); + ZCC_OpProto *PromoteUnary(EZCCExprType op, ZCC_Expression *&expr); + ZCC_OpProto *PromoteBinary(EZCCExprType op, ZCC_Expression *&left, ZCC_Expression *&right); + + ZCC_Expression *ApplyConversion(ZCC_Expression *expr, const PType::Conversion **route, int routelen); + ZCC_Expression *AddCastNode(PType *type, ZCC_Expression *expr); + + ZCC_Expression *IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable *sym); + ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table); + ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode); + ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode); + + + void Warn(ZCC_TreeNode *node, const char *msg, ...); + void Error(ZCC_TreeNode *node, const char *msg, ...); + void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr); + + FxExpression *ConvertAST(PClass *cclass, ZCC_TreeNode *ast); + FxExpression *ConvertNode(ZCC_TreeNode *node); + FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head); + + DObject *Outer; + PClass *ConvertClass; // class type to be used when resoving symbold while converting an AST + PSymbolTable *GlobalTreeNodes; + PSymbolTable *OutputSymbols; + ZCC_AST &AST; + int Lump; +}; + +void ZCC_InitConversions(); + +#endif diff --git a/src/zscript/zcc_expr.cpp b/src/scripting/zscript/zcc_expr.cpp similarity index 85% rename from src/zscript/zcc_expr.cpp rename to src/scripting/zscript/zcc_expr.cpp index e1a091b18..0c2c6baee 100644 --- a/src/zscript/zcc_expr.cpp +++ b/src/scripting/zscript/zcc_expr.cpp @@ -1,3 +1,36 @@ +/* +** zcc_expr.cpp +** +**--------------------------------------------------------------------------- +** Copyright -2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include #include "dobject.h" #include "sc_man.h" @@ -8,6 +41,7 @@ #include "m_alloc.h" #include "zcc_parser.h" #include "templates.h" +#include "math/cmath.h" #define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) @@ -299,7 +333,7 @@ void ZCC_InitOperators() { PEX_Mod , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal %= r->UIntVal; return l; } }, { PEX_Mod , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = luai_nummod(l->DoubleVal, r->DoubleVal); return l; } }, - { PEX_Pow , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = pow(l->DoubleVal, r->DoubleVal); return l; } }, + { PEX_Pow , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = g_pow(l->DoubleVal, r->DoubleVal); return l; } }, { PEX_Concat , (PType **)&TypeString, (PType **)&TypeString, (PType **)&TypeString, EvalConcat }, @@ -332,6 +366,18 @@ void ZCC_InitOperators() { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal <= r->UIntVal; l->Type = TypeBool; return l; } }, { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal <= r->DoubleVal; l->Type = TypeBool; return l; } }, + { PEX_GT , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal > r->IntVal; l->Type = TypeBool; return l; } }, + { PEX_GT , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal > r->UIntVal; l->Type = TypeBool; return l; } }, + { PEX_GT , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal > r->DoubleVal; l->Type = TypeBool; return l; } }, + + { PEX_GTEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal >= r->IntVal; l->Type = TypeBool; return l; } }, + { PEX_GTEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal >= r->UIntVal; l->Type = TypeBool; return l; } }, + { PEX_GTEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal >= r->DoubleVal; l->Type = TypeBool; return l; } }, + + { PEX_NEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal != r->IntVal; l->Type = TypeBool; return l; } }, + { PEX_NEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal != r->UIntVal; l->Type = TypeBool; return l; } }, + { PEX_NEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal != r->DoubleVal; l->Type = TypeBool; return l; } }, + { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal == r->IntVal; l->Type = TypeBool; return l; } }, { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal == r->UIntVal; l->Type = TypeBool; return l; } }, { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal == r->DoubleVal; l->Type = TypeBool; return l; } }, diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h new file mode 100644 index 000000000..b565c00fb --- /dev/null +++ b/src/scripting/zscript/zcc_exprlist.h @@ -0,0 +1,75 @@ +// Name Token used in the code generator +xx(Nil, TK_None) + +xx(ID, TK_Identifier) +xx(Super, TK_Super) +xx(Null, TK_Null) +xx(ConstValue, TK_Const) +xx(FuncCall, '(') +xx(ArrayAccess, TK_Array) +xx(MemberAccess, '.') +xx(TypeRef, TK_Class) +xx(Vector, TK_Vector2) + +xx(PostInc, TK_Incr) +xx(PostDec, TK_Decr) + +xx(PreInc, TK_Incr) +xx(PreDec, TK_Decr) +xx(Negate, '-') +xx(AntiNegate, '+') +xx(BitNot, '~') +xx(BoolNot, '!') +xx(SizeOf, TK_SizeOf) +xx(AlignOf, TK_AlignOf) + +xx(Add, '+') +xx(Sub, '-') +xx(Mul, '*') +xx(Div, '/') +xx(Mod, '%') +xx(Pow, TK_MulMul) +xx(CrossProduct, TK_Cross) +xx(DotProduct, TK_Dot) +xx(LeftShift, TK_LShift) +xx(RightShift, TK_RShift) +xx(URightShift, TK_URShift) +xx(Concat, TK_DotDot) + +xx(LT, '<') +xx(LTEQ, TK_Leq) +xx(GT, '>') +xx(GTEQ, TK_Geq) +xx(LTGTEQ, TK_LtGtEq) +xx(Is, TK_Is) + +xx(EQEQ, TK_Eq) +xx(NEQ, TK_Neq) +xx(APREQ, TK_ApproxEq) + +xx(BitAnd, '&') +xx(BitOr, '|') +xx(BitXor, '^') +xx(BoolAnd, TK_AndAnd) +xx(BoolOr, TK_OrOr) + +xx(Assign, '=') +xx(AddAssign, '+') // these are what the code generator needs, not what they represent. +xx(SubAssign, '-') +xx(MulAssign, '*') +xx(DivAssign, '/') +xx(ModAssign, '%') +xx(LshAssign, TK_LShift) +xx(RshAssign, TK_RShift) +xx(URshAssign, TK_URShift) +xx(AndAssign, '&') +xx(OrAssign, '|') +xx(XorAssign, '^') + +xx(Scope, TK_ColonColon) + +xx(Trinary, '?') + +xx(Cast, TK_Coerce) + +#undef xx diff --git a/src/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp similarity index 58% rename from src/zscript/zcc_parser.cpp rename to src/scripting/zscript/zcc_parser.cpp index 1f1fa4541..de3d2c7e1 100644 --- a/src/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -1,3 +1,36 @@ +/* +** zcc_expr.cpp +** +**--------------------------------------------------------------------------- +** Copyright -2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + #include "dobject.h" #include "sc_man.h" #include "c_console.h" @@ -5,6 +38,9 @@ #include "w_wad.h" #include "cmdlib.h" #include "m_alloc.h" +#include "i_system.h" +#include "m_argv.h" +#include "v_text.h" #include "zcc_parser.h" #include "zcc_compile.h" @@ -37,6 +73,7 @@ static void InitTokenMap() TOKENDEF (TK_SubEq, ZCC_SUBEQ); TOKENDEF (TK_LShiftEq, ZCC_LSHEQ); TOKENDEF (TK_RShiftEq, ZCC_RSHEQ); + TOKENDEF (TK_URShiftEq, ZCC_URSHEQ); TOKENDEF (TK_AndEq, ZCC_ANDEQ); TOKENDEF (TK_OrEq, ZCC_OREQ); TOKENDEF (TK_XorEq, ZCC_XOREQ); @@ -54,11 +91,13 @@ static void InitTokenMap() TOKENDEF (TK_LtGtEq, ZCC_LTGTEQ); TOKENDEF (TK_Is, ZCC_IS); TOKENDEF (TK_DotDot, ZCC_DOTDOT); + TOKENDEF (TK_Ellipsis, ZCC_ELLIPSIS); TOKENDEF ('|', ZCC_OR); TOKENDEF ('^', ZCC_XOR); TOKENDEF ('&', ZCC_AND); TOKENDEF (TK_LShift, ZCC_LSH); TOKENDEF (TK_RShift, ZCC_RSH); + TOKENDEF (TK_URShift, ZCC_URSH); TOKENDEF ('-', ZCC_SUB); TOKENDEF ('+', ZCC_ADD); TOKENDEF ('*', ZCC_MUL); @@ -78,11 +117,14 @@ static void InitTokenMap() TOKENDEF (TK_Class, ZCC_CLASS); TOKENDEF (TK_Abstract, ZCC_ABSTRACT); TOKENDEF (TK_Native, ZCC_NATIVE); + TOKENDEF (TK_Action, ZCC_ACTION); TOKENDEF (TK_Replaces, ZCC_REPLACES); TOKENDEF (TK_Static, ZCC_STATIC); TOKENDEF (TK_Private, ZCC_PRIVATE); TOKENDEF (TK_Protected, ZCC_PROTECTED); TOKENDEF (TK_Latent, ZCC_LATENT); + TOKENDEF (TK_Virtual, ZCC_VIRTUAL); + TOKENDEF (TK_Override, ZCC_OVERRIDE); TOKENDEF (TK_Final, ZCC_FINAL); TOKENDEF (TK_Meta, ZCC_META); TOKENDEF (TK_Deprecated, ZCC_DEPRECATED); @@ -101,7 +143,8 @@ static void InitTokenMap() TOKENDEF2(TK_Float, ZCC_FLOAT, NAME_Float); TOKENDEF2(TK_Double, ZCC_DOUBLE, NAME_Double); TOKENDEF2(TK_String, ZCC_STRING, NAME_String); - TOKENDEF2(TK_Vector, ZCC_VECTOR, NAME_Vector); + TOKENDEF2(TK_Vector2, ZCC_VECTOR2, NAME_Vector2); + TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3); TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name); TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map); TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array); @@ -114,7 +157,7 @@ static void InitTokenMap() TOKENDEF (TK_Out, ZCC_OUT); TOKENDEF (TK_Optional, ZCC_OPTIONAL); TOKENDEF (TK_Super, ZCC_SUPER); - TOKENDEF (TK_Self, ZCC_SELF); + TOKENDEF (TK_Null, ZCC_NULLPTR); TOKENDEF ('~', ZCC_TILDE); TOKENDEF ('!', ZCC_BANG); TOKENDEF (TK_SizeOf, ZCC_SIZEOF); @@ -138,6 +181,9 @@ static void InitTokenMap() TOKENDEF (TK_Loop, ZCC_LOOP); TOKENDEF (TK_Goto, ZCC_GOTO); TOKENDEF (TK_States, ZCC_STATES); + TOKENDEF2(TK_State, ZCC_STATE, NAME_State); + TOKENDEF2(TK_Color, ZCC_COLOR, NAME_Color); + TOKENDEF2(TK_Sound, ZCC_SOUND, NAME_Sound); TOKENDEF (TK_Identifier, ZCC_IDENTIFIER); TOKENDEF (TK_StringConst, ZCC_STRCONST); @@ -154,51 +200,34 @@ static void InitTokenMap() TOKENDEF (TK_Offset, ZCC_OFFSET); TOKENDEF (TK_CanRaise, ZCC_CANRAISE); TOKENDEF (TK_Light, ZCC_LIGHT); - - ZCC_InitOperators(); - ZCC_InitConversions(); + TOKENDEF (TK_Extend, ZCC_EXTEND); } #undef TOKENDEF #undef TOKENDEF2 -static void DoParse(const char *filename) +static void ParseSingleFile(const char *filename, int lump, void *parser, ZCCParseState &state) { - if (TokenMap.CountUsed() == 0) - { - InitTokenMap(); - } - - FScanner sc; - void *parser; int tokentype; - int lump; - bool failed; + //bool failed; ZCCToken value; + FScanner sc; - lump = Wads.CheckNumForFullName(filename, true); - if (lump >= 0) + if (filename != nullptr) { - sc.OpenLumpNum(lump); + lump = Wads.CheckNumForFullName(filename, true); + if (lump >= 0) + { + sc.OpenLumpNum(lump); + } + else + { + Printf("Could not find script lump '%s'\n", filename); + return; + } } - else if (FileExists(filename)) - { - sc.OpenFile(filename); - } - else - { - Printf("Could not find script lump '%s'\n", filename); - return; - } - - parser = ZCCParseAlloc(malloc); - failed = false; -#ifdef _DEBUG - FILE *f = fopen("trace.txt", "w"); - char prompt = '\0'; - ZCCParseTrace(f, &prompt); -#endif - ZCCParseState state(sc); + else sc.OpenLumpNum(lump); + state.sc = ≻ while (sc.GetToken()) { value.SourceLoc = sc.GetMessageLine(); @@ -241,7 +270,7 @@ static void DoParse(const char *filename) default: TokenMapEntry *zcctoken = TokenMap.CheckKey(sc.TokenType); - if (zcctoken != NULL) + if (zcctoken != nullptr) { tokentype = zcctoken->TokenType; value.Int = zcctoken->TokenName; @@ -254,38 +283,132 @@ static void DoParse(const char *filename) break; } ZCCParse(parser, tokentype, value, &state); - if (failed) - { - sc.ScriptMessage("Parse failed\n"); - goto parse_end; - } } parse_end: value.Int = -1; ZCCParse(parser, ZCC_EOF, value, &state); + state.sc = nullptr; +} + +static void DoParse(int lumpnum) +{ + FScanner sc; + void *parser; + ZCCToken value; + + parser = ZCCParseAlloc(malloc); + ZCCParseState state; +//#define TRACE +#ifdef TRACE // this costs a lot of time and should only be activated when it's really needed. + FILE *f = fopen("trace.txt", "w"); + char prompt = '\0'; + ZCCParseTrace(f, &prompt); +#endif + + sc.OpenLumpNum(lumpnum); + auto saved = sc.SavePos(); + bool parsed = false; + if (sc.GetToken()) + { + if (sc.TokenType == TK_Class || sc.TokenType == TK_Enum || sc.TokenType == TK_Struct || sc.TokenType == TK_Const || sc.TokenType == TK_Native) + { + if (sc.CheckToken(TK_Identifier)) + { + // This looks like an actual definition file and not a file list. + ParseSingleFile(nullptr, lumpnum, parser, state); + parsed = true; + } + } + } + if (!parsed) + { + sc.RestorePos(saved); + // parse all files from this list in one go. + while (sc.GetString()) + { + FixPathSeperator(sc.String); + if (Wads.GetLumpFile(sc.LumpNum) == 0) + { + int includefile = Wads.GetLumpFile(Wads.CheckNumForFullName(sc.String, true)); + if (includefile != 0) + { + I_FatalError("File %s is overriding core lump %s.", + Wads.GetWadFullName(includefile), sc.String); + } + } + + ParseSingleFile(sc.String, 0, parser, state); + } + } + + value.Int = -1; + value.SourceLoc = sc.GetMessageLine(); ZCCParse(parser, 0, value, &state); ZCCParseFree(parser, free); - PSymbolTable symbols(&GlobalSymbols); - ZCCCompiler cc(state, NULL, symbols); - cc.Compile(); -#ifdef _DEBUG - if (f != NULL) + // If the parser fails, there is no point starting the compiler, because it'd only flood the output with endless errors. + if (FScriptPosition::ErrorCounter > 0) { - fclose(f); + I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); } - FString ast = ZCC_PrintAST(state.TopNode); - FString astfile = ExtractFileBase(filename, false); - astfile << ".ast"; - f = fopen(astfile, "w"); + +#ifdef TRACE if (f != NULL) { - fputs(ast.GetChars(), f); fclose(f); } #endif + + // Make a dump of the AST before running the compiler for diagnostic purposes. + if (Args->CheckParm("-dumpast")) + { + FString ast = ZCC_PrintAST(state.TopNode); + FString filename = Wads.GetLumpFullPath(lumpnum); + filename.ReplaceChars(":\\/?|", '.'); + filename << ".ast"; + FILE *ff = fopen(filename, "w"); + if (ff != NULL) + { + fputs(ast.GetChars(), ff); + fclose(ff); + } + } + + PSymbolTable symtable; + ZCCCompiler cc(state, NULL, symtable, GlobalSymbols, lumpnum); + cc.Compile(); + + if (FScriptPosition::ErrorCounter > 0) + { + // Abort if the compiler produced any errors. Also do not compile further lumps, because they very likely miss some stuff. + I_Error("%d errors, %d warnings while compiling %s", FScriptPosition::ErrorCounter, FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); + } + else if (FScriptPosition::WarnCounter > 0) + { + // If we got warnings, but no errors, print the information but continue. + Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s", FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); + } + } +void ParseScripts() +{ + if (TokenMap.CountUsed() == 0) + { + InitTokenMap(); + } + ZCC_InitOperators(); + ZCC_InitConversions(); + + int lump, lastlump = 0; + FScriptPosition::ResetErrorCounter(); + while ((lump = Wads.FindLump("ZSCRIPT", &lastlump)) != -1) + { + DoParse(lump); + } +} + +/* CCMD(parse) { if (argv.argc() == 2) @@ -293,6 +416,7 @@ CCMD(parse) DoParse(argv[1]); } } +*/ static FString ZCCTokenName(int terminal) { @@ -325,6 +449,7 @@ ZCC_TreeNode *ZCC_AST::InitNode(size_t size, EZCCTreeNodeType type, ZCC_TreeNode if (basis != NULL) { node->SourceName = basis->SourceName; + node->SourceLump = basis->SourceLump; node->SourceLoc = basis->SourceLoc; } return node; @@ -333,6 +458,7 @@ ZCC_TreeNode *ZCC_AST::InitNode(size_t size, EZCCTreeNodeType type, ZCC_TreeNode ZCC_TreeNode *ZCCParseState::InitNode(size_t size, EZCCTreeNodeType type) { ZCC_TreeNode *node = ZCC_AST::InitNode(size, type, NULL); - node->SourceName = Strings.Alloc(sc.ScriptName); + node->SourceName = Strings.Alloc(sc->ScriptName); + node->SourceLump = sc->LumpNum; return node; } diff --git a/src/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h similarity index 87% rename from src/zscript/zcc_parser.h rename to src/scripting/zscript/zcc_parser.h index e74b5263e..1a187af82 100644 --- a/src/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -2,6 +2,7 @@ #define ZCC_PARSER_H #include "memarena.h" +#include "sc_man.h" struct ZCCToken { @@ -16,7 +17,7 @@ struct ZCCToken ENamedName Name() { return ENamedName(Int); } }; -// Variable / Function modifiers +// Variable / Function / Class modifiers enum { ZCC_Native = 1 << 0, @@ -30,6 +31,10 @@ enum ZCC_Deprecated = 1 << 8, ZCC_ReadOnly = 1 << 9, ZCC_FuncConst = 1 << 10, + ZCC_Abstract = 1 << 11, + ZCC_Extension = 1 << 12, + ZCC_Virtual = 1 << 13, + ZCC_Override = 1 << 14, }; // Function parameter modifiers @@ -41,7 +46,6 @@ enum }; - // Syntax tree structures. enum EZCCTreeNodeType { @@ -60,6 +64,7 @@ enum EZCCTreeNodeType AST_StateGoto, AST_StateLine, AST_VarName, + AST_VarInit, AST_Type, AST_BasicType, AST_MapType, @@ -92,6 +97,10 @@ enum EZCCTreeNodeType AST_Declarator, AST_VarDeclarator, AST_FuncDeclarator, + AST_Default, + AST_FlagStmt, + AST_PropertyStmt, + AST_VectorValue, NUM_AST_NODE_TYPES }; @@ -113,8 +122,12 @@ enum EZCCBuiltinType ZCC_String, ZCC_Vector2, ZCC_Vector3, - ZCC_Vector4, ZCC_Name, + + ZCC_Color, // special types for ZDoom. + ZCC_State, + ZCC_Sound, + ZCC_UserType, ZCC_NUM_BUILT_IN_TYPES @@ -139,6 +152,7 @@ struct ZCC_TreeNode // can't use FScriptPosition, because the string wouldn't have a chance to // destruct if we did that. FString *SourceName; + int SourceLump; int SourceLoc; // Node type is one of the node types above, which corresponds with @@ -167,6 +181,12 @@ struct ZCC_TreeNode SiblingPrev = siblingend; siblingend->SiblingNext = this; } + + operator FScriptPosition() + { + return FScriptPosition(*SourceName, SourceLoc); + } + }; struct ZCC_Identifier : ZCC_TreeNode @@ -177,6 +197,7 @@ struct ZCC_Identifier : ZCC_TreeNode struct ZCC_NamedNode : ZCC_TreeNode { ENamedName NodeName; + PSymbolType *Symbol; }; struct ZCC_Class : ZCC_NamedNode @@ -185,11 +206,13 @@ struct ZCC_Class : ZCC_NamedNode ZCC_Identifier *Replaces; VM_UWORD Flags; ZCC_TreeNode *Body; + PClass *Type; }; struct ZCC_Struct : ZCC_NamedNode { ZCC_TreeNode *Body; + PStruct *Type; }; struct ZCC_Enum : ZCC_NamedNode @@ -205,6 +228,7 @@ struct ZCC_EnumTerminator : ZCC_TreeNode struct ZCC_States : ZCC_TreeNode { struct ZCC_StatePart *Body; + ZCC_Identifier *Flags; }; struct ZCC_StatePart : ZCC_TreeNode @@ -248,20 +272,23 @@ struct ZCC_Expression : ZCC_TreeNode struct ZCC_StateGoto : ZCC_StatePart { + ZCC_Identifier *Qualifier; ZCC_Identifier *Label; ZCC_Expression *Offset; }; struct ZCC_StateLine : ZCC_StatePart { - char Sprite[4]; + FString *Sprite; BITFIELD bBright : 1; BITFIELD bFast : 1; BITFIELD bSlow : 1; BITFIELD bNoDelay : 1; BITFIELD bCanRaise : 1; FString *Frames; + ZCC_Expression *Duration; ZCC_Expression *Offset; + ZCC_ExprConstant *Lights; ZCC_TreeNode *Action; }; @@ -271,6 +298,12 @@ struct ZCC_VarName : ZCC_TreeNode ZCC_Expression *ArraySize; // NULL if not an array }; +struct ZCC_VarInit : ZCC_VarName +{ + ZCC_Expression *Init; + bool InitIsArray; // this is needed to distinguish one-element arrays from raw elements. +}; + struct ZCC_Type : ZCC_TreeNode { ZCC_Expression *ArraySize; // NULL if not an array @@ -280,6 +313,7 @@ struct ZCC_BasicType : ZCC_Type { EZCCBuiltinType Type; ZCC_Identifier *UserType; + bool isconst; }; struct ZCC_MapType : ZCC_Type @@ -355,6 +389,11 @@ struct ZCC_ExprTrinary : ZCC_Expression ZCC_Expression *Right; }; +struct ZCC_VectorValue : ZCC_Expression +{ + ZCC_Expression *X, *Y, *Z; +}; + struct ZCC_Statement : ZCC_TreeNode { }; @@ -423,13 +462,13 @@ struct ZCC_AssignStmt : ZCC_Statement struct ZCC_LocalVarStmt : ZCC_Statement { ZCC_Type *Type; - ZCC_VarName *Vars; - ZCC_Expression *Inits; + ZCC_VarInit *Vars; }; struct ZCC_FuncParamDecl : ZCC_TreeNode { ZCC_Type *Type; + ZCC_Expression *Default; ENamedName Name; int Flags; }; @@ -438,6 +477,7 @@ struct ZCC_ConstantDef : ZCC_NamedNode { ZCC_Expression *Value; PSymbolConst *Symbol; + ZCC_Enum *Type; // gets set when the constant originates from an enum. }; struct ZCC_Declarator : ZCC_TreeNode @@ -460,6 +500,23 @@ struct ZCC_FuncDeclarator : ZCC_Declarator ZCC_Statement *Body; }; +struct ZCC_Default : ZCC_CompoundStmt +{ +}; + +struct ZCC_PropertyStmt : ZCC_Statement +{ + ZCC_Identifier *Prop; + ZCC_Expression *Values; +}; + + +struct ZCC_FlagStmt : ZCC_Statement +{ + ZCC_Identifier *name; + bool set; +}; + typedef ZCC_ExprConstant *(*EvalConst1op)(ZCC_ExprConstant *); typedef ZCC_ExprConstant *(*EvalConst2op)(ZCC_ExprConstant *, ZCC_ExprConstant *, FSharedStringArena &); @@ -514,10 +571,10 @@ struct ZCC_AST struct ZCCParseState : public ZCC_AST { - ZCCParseState(FScanner &scanner) : sc(scanner) {} + ZCCParseState(FScanner *scanner = nullptr) : sc(scanner) {} ZCC_TreeNode *InitNode(size_t size, EZCCTreeNodeType type); - FScanner ≻ + FScanner *sc; }; #endif diff --git a/src/serializer.cpp b/src/serializer.cpp index 8875b61f9..5f0e6dfce 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -63,6 +63,7 @@ #include "w_zip.h" #include "doomerrors.h" #include "v_text.h" +#include "cmdlib.h" char nulspace[1024 * 1024 * 4]; bool save_full = false; // for testing. Should be removed afterward. diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index c1973780b..53c471a31 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -59,6 +59,7 @@ #include "i_music.h" #include "i_musicinterns.h" #include "tempfiles.h" +#include "cmdlib.h" FModule OpenALModule{"OpenAL"}; diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp deleted file mode 100644 index 9af031b04..000000000 --- a/src/thingdef/thingdef.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/* -** thingdef.cpp -** -** Actor definitions -** -**--------------------------------------------------------------------------- -** Copyright 2002-2008 Christoph Oelckers -** Copyright 2004-2008 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be -** covered by the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or (at -** your option) any later version. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include "gi.h" -#include "actor.h" -#include "info.h" -#include "sc_man.h" -#include "tarray.h" -#include "w_wad.h" -#include "templates.h" -#include "r_defs.h" -#include "a_pickups.h" -#include "s_sound.h" -#include "cmdlib.h" -#include "p_lnspec.h" -#include "a_action.h" -#include "decallib.h" -#include "m_random.h" -#include "i_system.h" -#include "m_argv.h" -#include "p_local.h" -#include "doomerrors.h" -#include "a_weaponpiece.h" -#include "p_conversation.h" -#include "v_text.h" -#include "thingdef.h" -#include "thingdef_exp.h" -#include "a_sharedglobal.h" -#include "vmbuilder.h" -#include "stats.h" - -TDeletingArray ActorDamageFuncs; - - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- -void InitThingdef(); -void ParseDecorate(FScanner &ctx); - -// STATIC FUNCTION PROTOTYPES -------------------------------------------- -PClassActor *QuestItemClasses[31]; - -EXTERN_CVAR(Bool, strictdecorate); - -PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName) -{ - PClassActor *type = static_cast(parent->CreateDerivedClass(typeName, parent->Size)); - if (type == nullptr) - { - FString newname = typeName.GetChars(); - FString sourcefile = sc.FileName; - - sourcefile.Substitute(":", "@"); - newname << '@' << sourcefile; - if (strictdecorate) - { - sc.Message(MSG_ERROR, "Tried to define class '%s' more than once.", typeName.GetChars()); - } - else - { - // Due to backwards compatibility issues this cannot be an unconditional error. - sc.Message(MSG_WARNING, "Tried to define class '%s' more than once. Renaming class to '%s'", typeName.GetChars(), newname.GetChars()); - } - type = static_cast(parent->CreateDerivedClass(newname, parent->Size)); - if (type == nullptr) - { - // This we cannot handle cleanly anymore. Let's just abort and forget about the odd mod out that was this careless. - sc.Message(MSG_FATAL, "Tried to define class '%s' more than twice in the same file.", typeName.GetChars()); - } - } - return type; -} -//========================================================================== -// -// Starts a new actor definition -// -//========================================================================== -PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native) -{ - PClassActor *replacee = NULL; - PClassActor *ti = NULL; - - PClassActor *parent = RUNTIME_CLASS(AActor); - - if (parentName != NAME_None) - { - parent = PClass::FindActor(parentName); - - PClassActor *p = parent; - while (p != NULL) - { - if (p->TypeName == typeName) - { - sc.Message(MSG_ERROR, "'%s' inherits from a class with the same name", typeName.GetChars()); - break; - } - p = dyn_cast(p->ParentClass); - } - - if (parent == NULL) - { - sc.Message(MSG_ERROR, "Parent type '%s' not found in %s", parentName.GetChars(), typeName.GetChars()); - parent = RUNTIME_CLASS(AActor); - } - else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor))) - { - sc.Message(MSG_ERROR, "Parent type '%s' is not an actor in %s", parentName.GetChars(), typeName.GetChars()); - parent = RUNTIME_CLASS(AActor); - } - } - - if (native) - { - ti = PClass::FindActor(typeName); - if (ti == NULL) - { - extern void DumpTypeTable(); - DumpTypeTable(); - sc.Message(MSG_ERROR, "Unknown native actor '%s'", typeName.GetChars()); - goto create; - } - else if (ti != RUNTIME_CLASS(AActor) && ti->ParentClass->NativeClass() != parent->NativeClass()) - { - sc.Message(MSG_ERROR, "Native class '%s' does not inherit from '%s'", typeName.GetChars(), parentName.GetChars()); - parent = RUNTIME_CLASS(AActor); - goto create; - } - else if (ti->Defaults != NULL) - { - sc.Message(MSG_ERROR, "Redefinition of internal class '%s'", typeName.GetChars()); - goto create; - } - ti->InitializeNativeDefaults(); - ti->ParentClass->DeriveData(ti); - } - else - { - create: - ti = DecoDerivedClass(sc, parent, typeName); - } - - ti->Replacee = ti->Replacement = NULL; - ti->DoomEdNum = -1; - return ti; -} - -//========================================================================== -// -// -// -//========================================================================== - -void SetReplacement(FScanner &sc, PClassActor *info, FName replaceName) -{ - // Check for "replaces" - if (replaceName != NAME_None) - { - // Get actor name - PClassActor *replacee = PClass::FindActor(replaceName); - - if (replacee == NULL) - { - sc.ScriptMessage("Replaced type '%s' not found for %s", replaceName.GetChars(), info->TypeName.GetChars()); - return; - } - if (replacee != NULL) - { - replacee->Replacement = info; - info->Replacee = replacee; - } - } - -} - -//========================================================================== -// -// Finalizes an actor definition -// -//========================================================================== - -void FinishActor(const FScriptPosition &sc, PClassActor *info, Baggage &bag) -{ - AActor *defaults = (AActor*)info->Defaults; - - try - { - bag.statedef.FinishStates (info, defaults); - } - catch (CRecoverableError &err) - { - sc.Message(MSG_ERROR, "%s", err.GetMessage()); - bag.statedef.MakeStateDefines(NULL); - return; - } - bag.statedef.InstallStates (info, defaults); - bag.statedef.MakeStateDefines(NULL); - if (bag.DropItemSet) - { - info->DropItems = bag.DropItemList; - GC::WriteBarrier(info, info->DropItems); - } - if (info->IsDescendantOf (RUNTIME_CLASS(AInventory))) - { - defaults->flags |= MF_SPECIAL; - } - - // Weapons must be checked for all relevant states. They may crash the game otherwise. - if (info->IsDescendantOf(RUNTIME_CLASS(AWeapon))) - { - FState *ready = info->FindState(NAME_Ready); - FState *select = info->FindState(NAME_Select); - FState *deselect = info->FindState(NAME_Deselect); - FState *fire = info->FindState(NAME_Fire); - - // Consider any weapon without any valid state abstract and don't output a warning - // This is for creating base classes for weapon groups that only set up some properties. - if (ready || select || deselect || fire) - { - if (!ready) - { - sc.Message(MSG_ERROR, "Weapon %s doesn't define a ready state.\n", info->TypeName.GetChars()); - } - if (!select) - { - sc.Message(MSG_ERROR, "Weapon %s doesn't define a select state.\n", info->TypeName.GetChars()); - } - if (!deselect) - { - sc.Message(MSG_ERROR, "Weapon %s doesn't define a deselect state.\n", info->TypeName.GetChars()); - } - if (!fire) - { - sc.Message(MSG_ERROR, "Weapon %s doesn't define a fire state.\n", info->TypeName.GetChars()); - } - } - } -} - -//========================================================================== -// -// Do some postprocessing after everything has been defined -// -//========================================================================== - -static void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen) -{ - const char *marks = "======================================================="; - fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks); - fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n", - sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam); - VMDumpConstants(dump, sfunc); - fprintf(dump, "\nDisassembly @ %p:\n", sfunc->Code); - VMDisasm(dump, sfunc->Code, sfunc->CodeSize, sfunc); -} - -static void FinishThingdef() -{ - int errorcount = 0; - unsigned i; - int codesize = 0; - FILE *dump = NULL; - - if (Args->CheckParm("-dumpdisasm")) dump = fopen("disasm.txt", "w"); - - for (i = 0; i < StateTempCalls.Size(); ++i) - { - FStateTempCall *tcall = StateTempCalls[i]; - VMFunction *func = nullptr; - - assert(tcall->Code != NULL); - - // We don't know the return type in advance for anonymous functions. - FCompileContext ctx(tcall->ActorClass, nullptr); - tcall->Code = tcall->Code->Resolve(ctx); - tcall->Proto = ctx.ReturnProto; - - // Make sure resolving it didn't obliterate it. - if (tcall->Code != nullptr) - { - // Can we call this function directly without wrapping it in an - // anonymous function? e.g. Are we passing any parameters to it? - func = tcall->Code->GetDirectFunction(); - - if (func == nullptr) - { - VMFunctionBuilder buildit(true); - - assert(tcall->Proto != nullptr); - - // Allocate registers used to pass parameters in. - // self, stateowner, state (all are pointers) - buildit.Registers[REGT_POINTER].Get(3); - - // Emit code - tcall->Code->Emit(&buildit); - - VMScriptFunction *sfunc = buildit.MakeFunction(); - sfunc->NumArgs = NAP; - - // Generate prototype for this anonymous function - TArray args(3); - SetImplicitArgs(&args, NULL, tcall->ActorClass, VARF_Method | VARF_Action); - sfunc->Proto = NewPrototype(tcall->Proto->ReturnTypes, args); - - func = sfunc; - - if (dump != NULL) - { - char label[64]; - int labellen = mysnprintf(label, countof(label), "Function %s.States[%d] (*%d)", - tcall->ActorClass->TypeName.GetChars(), tcall->FirstState, tcall->NumStates); - DumpFunction(dump, sfunc, label, labellen); - codesize += sfunc->CodeSize; - } - } - - delete tcall->Code; - tcall->Code = nullptr; - for (int k = 0; k < tcall->NumStates; ++k) - { - tcall->ActorClass->OwnedStates[tcall->FirstState + k].SetAction(func); - } - } - } - - for (i = 0; i < PClassActor::AllActorClasses.Size(); i++) - { - PClassActor *ti = PClassActor::AllActorClasses[i]; - - if (ti->Size == TentativeClass) - { - Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); - errorcount++; - continue; - } - - AActor *def = GetDefaultByType(ti); - - if (!def) - { - Printf(TEXTCOLOR_RED "No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars()); - errorcount++; - continue; - } - - if (def->DamageFunc != nullptr) - { - FxDamageValue *dmg = (FxDamageValue *)ActorDamageFuncs[(uintptr_t)def->DamageFunc - 1]; - VMScriptFunction *sfunc; - sfunc = dmg->GetFunction(); - if (sfunc == nullptr) - { - FCompileContext ctx(ti); - dmg = static_cast(dmg->Resolve(ctx)); - - if (dmg != nullptr) - { - VMFunctionBuilder buildit; - buildit.Registers[REGT_POINTER].Get(1); // The self pointer - dmg->Emit(&buildit); - sfunc = buildit.MakeFunction(); - sfunc->NumArgs = 1; - sfunc->Proto = nullptr; ///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); - } - } - def->DamageFunc = sfunc; - - if (dump != nullptr && sfunc != nullptr) - { - char label[64]; - int labellen = mysnprintf(label, countof(label), "Function %s.Damage", - ti->TypeName.GetChars()); - DumpFunction(dump, sfunc, label, labellen); - codesize += sfunc->CodeSize; - } - } - } - if (dump != NULL) - { - fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4); - fclose(dump); - } - if (errorcount > 0) - { - I_Error("%d errors during actor postprocessing", errorcount); - } - - ActorDamageFuncs.DeleteAndClear(); - StateTempCalls.DeleteAndClear(); - - // Since these are defined in DECORATE now the table has to be initialized here. - for(int i = 0; i < 31; i++) - { - char fmt[20]; - mysnprintf(fmt, countof(fmt), "QuestItem%d", i+1); - QuestItemClasses[i] = PClass::FindActor(fmt); - } -} - - - -//========================================================================== -// -// LoadActors -// -// Called from FActor::StaticInit() -// -//========================================================================== - -void LoadActors () -{ - int lastlump, lump; - cycle_t timer; - - timer.Reset(); timer.Clock(); - ActorDamageFuncs.Clear(); - FScriptPosition::ResetErrorCounter(); - InitThingdef(); - lastlump = 0; - while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1) - { - FScanner sc(lump); - - if (Wads.GetLumpFile(lump) == 0) - { - // define namespace 'zdoom' - } - else - { - // use namespace 'zdoom' - } - - ParseDecorate (sc); - } - FinishThingdef(); - if (FScriptPosition::ErrorCounter > 0) - { - I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter); - } - timer.Unclock(); - if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); - // Base time: ~52 ms -} diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp deleted file mode 100644 index 7c55e5286..000000000 --- a/src/thingdef/thingdef_expression.cpp +++ /dev/null @@ -1,5259 +0,0 @@ -/* -** thingdef_expression.cpp -** -** Expression evaluation -** -**--------------------------------------------------------------------------- -** Copyright 2008 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be -** covered by the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or (at -** your option) any later version. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include "actor.h" -#include "sc_man.h" -#include "tarray.h" -#include "templates.h" -#include "cmdlib.h" -#include "i_system.h" -#include "m_random.h" -#include "a_pickups.h" -#include "thingdef.h" -#include "p_lnspec.h" -#include "doomstat.h" -#include "thingdef_exp.h" -#include "m_fixed.h" -#include "vmbuilder.h" -#include "v_text.h" -#include "math/cmath.h" - -struct FLOP -{ - ENamedName Name; - int Flop; - double (*Evaluate)(double); -}; - -// Decorate operates on degrees, so the evaluate functions need to convert -// degrees to radians for those that work with angles. -static const FLOP FxFlops[] = -{ - { NAME_Exp, FLOP_EXP, [](double v) { return g_exp(v); } }, - { NAME_Log, FLOP_LOG, [](double v) { return g_log(v); } }, - { NAME_Log10, FLOP_LOG10, [](double v) { return g_log10(v); } }, - { NAME_Sqrt, FLOP_SQRT, [](double v) { return g_sqrt(v); } }, - { NAME_Ceil, FLOP_CEIL, [](double v) { return ceil(v); } }, - { NAME_Floor, FLOP_FLOOR, [](double v) { return floor(v); } }, - - { NAME_ACos, FLOP_ACOS_DEG, [](double v) { return g_acos(v) * (180.0 / M_PI); } }, - { NAME_ASin, FLOP_ASIN_DEG, [](double v) { return g_asin(v) * (180.0 / M_PI); } }, - { NAME_ATan, FLOP_ATAN_DEG, [](double v) { return g_atan(v) * (180.0 / M_PI); } }, - { NAME_Cos, FLOP_COS_DEG, [](double v) { return g_cosdeg(v); } }, - { NAME_Sin, FLOP_SIN_DEG, [](double v) { return g_sindeg(v); } }, - { NAME_Tan, FLOP_TAN_DEG, [](double v) { return g_tan(v * (M_PI / 180.0)); } }, - - { NAME_CosH, FLOP_COSH, [](double v) { return g_cosh(v); } }, - { NAME_SinH, FLOP_SINH, [](double v) { return g_sinh(v); } }, - { NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(v); } }, -}; - -//========================================================================== -// -// FCompileContext -// -//========================================================================== - -FCompileContext::FCompileContext(PClassActor *cls, PPrototype *ret) : ReturnProto(ret), Class(cls) -{ -} - -PSymbol *FCompileContext::FindInClass(FName identifier) -{ - return Class ? Class->Symbols.FindSymbol(identifier, true) : nullptr; -} -PSymbol *FCompileContext::FindGlobal(FName identifier) -{ - return GlobalSymbols.FindSymbol(identifier, true); -} - -void FCompileContext::HandleJumps(int token, FxExpression *handler) -{ - for (unsigned int i = 0; i < Jumps.Size(); i++) - { - if (Jumps[i]->Token == token) - { - Jumps[i]->AddressResolver = handler; - handler->JumpAddresses.Push(Jumps[i]); - Jumps.Delete(i); - i--; - } - } -} - -void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) -{ - assert(proto != nullptr); - bool fail = false; - - if (ReturnProto == nullptr) - { - ReturnProto = proto; - return; - } - - // 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 (ReturnProto->ReturnTypes.Size() < proto->ReturnTypes.Size()) - { // Make proto the shorter one to avoid code duplication below. - swapvalues(proto, ReturnProto); - } - // If one prototype returns nothing, they both must. - if (proto->ReturnTypes.Size() == 0) - { - if (ReturnProto->ReturnTypes.Size() != 0) - { - fail = true; - } - } - else - { - for (unsigned i = 0; i < proto->ReturnTypes.Size(); i++) - { - if (ReturnProto->ReturnTypes[i] != proto->ReturnTypes[i]) - { // Incompatible - fail = true; - break; - } - } - } - - if (fail) - { - pos.Message(MSG_ERROR, "All return expressions must deduce to the same type"); - } -} - -//========================================================================== -// -// ExpEmit -// -//========================================================================== - -ExpEmit::ExpEmit(VMFunctionBuilder *build, int type) -: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false), Final(false) -{ -} - -void ExpEmit::Free(VMFunctionBuilder *build) -{ - if (!Fixed && !Konst && RegType <= REGT_TYPE) - { - build->Registers[RegType].Return(RegNum, 1); - } -} - -void ExpEmit::Reuse(VMFunctionBuilder *build) -{ - if (!Fixed && !Konst) - { - bool success = build->Registers[RegType].Reuse(RegNum); - assert(success && "Attempt to reuse a register that is already in use"); - } -} - -//========================================================================== -// -// FindDecorateBuiltinFunction -// -// Returns the symbol for a decorate utility function. If not found, create -// it and install it in Actor. -// -//========================================================================== - -static PSymbol *FindDecorateBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func) -{ - PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(funcname, false); - if (sym == NULL) - { - PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname); - VMNativeFunction *calldec = new VMNativeFunction(func, funcname); - symfunc->Function = calldec; - sym = symfunc; - RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym); - } - return sym; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxExpression::Emit (VMFunctionBuilder *build) -{ - ScriptPosition.Message(MSG_ERROR, "Unemitted expression found"); - return ExpEmit(); -} - - -//========================================================================== -// -// -// -//========================================================================== - -bool FxExpression::isConstant() const -{ - return false; -} - -//========================================================================== -// -// -// -//========================================================================== - -VMFunction *FxExpression::GetDirectFunction() -{ - return NULL; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxExpression::Resolve(FCompileContext &ctx) -{ - isresolved = true; - return this; -} - -//========================================================================== -// -// Returns true if we can write to the address. -// -//========================================================================== - -bool FxExpression::RequestAddress() -{ - ScriptPosition.Message(MSG_ERROR, "invalid dereference\n"); - return false; -} - -//========================================================================== -// -// Called by return statements. -// -//========================================================================== - -PPrototype *FxExpression::ReturnProto() -{ - assert(ValueType != nullptr); - - TArray ret(0); - TArray none(0); - if (ValueType != TypeVoid) - { - ret.Push(ValueType); - } - - return NewPrototype(ret, none); -} - -//========================================================================== -// -// -// -//========================================================================== - -static void EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const FScriptPosition &pos) -{ - ExpEmit where = operand->Emit(build); - - if (where.RegType == REGT_NIL) - { - pos.Message(MSG_ERROR, "Attempted to pass a non-value"); - build->Emit(OP_PARAM, 0, where.RegType, where.RegNum); - } - else - { - int regtype = where.RegType; - if (where.Konst) - { - regtype |= REGT_KONST; - } - build->Emit(OP_PARAM, 0, regtype, where.RegNum); - where.Free(build); - } -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos) -{ - FxExpression *x; - PSymbolConstNumeric *csym = dyn_cast(sym); - if (csym != NULL) - { - if (csym->ValueType->IsA(RUNTIME_CLASS(PInt))) - { - x = new FxConstant(csym->Value, pos); - } - else if (csym->ValueType->IsA(RUNTIME_CLASS(PFloat))) - { - x = new FxConstant(csym->Float, pos); - } - else - { - pos.Message(MSG_ERROR, "Invalid constant '%s'\n", csym->SymbolName.GetChars()); - return NULL; - } - } - else - { - pos.Message(MSG_ERROR, "'%s' is not a constant\n", sym->SymbolName.GetChars()); - x = NULL; - } - return x; -} - -ExpEmit FxConstant::Emit(VMFunctionBuilder *build) -{ - ExpEmit out; - - out.Konst = true; - int regtype = value.Type->GetRegType(); - out.RegType = regtype; - if (regtype == REGT_INT) - { - out.RegNum = build->GetConstantInt(value.Int); - } - else if (regtype == REGT_FLOAT) - { - out.RegNum = build->GetConstantFloat(value.Float); - } - else if (regtype == REGT_POINTER) - { - VM_ATAG tag = ATAG_GENERIC; - if (value.Type == TypeState) - { - tag = ATAG_STATE; - } - else if (value.Type->GetLoadOp() == OP_LO) - { - tag = ATAG_OBJECT; - } - out.RegNum = build->GetConstantAddress(value.pointer, tag); - } - else if (regtype == REGT_STRING) - { - out.RegNum = build->GetConstantString(value.GetString()); - } - else - { - ScriptPosition.Message(MSG_ERROR, "Cannot emit needed constant"); - out.RegNum = 0; - } - return out; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxBoolCast::FxBoolCast(FxExpression *x) - : FxExpression(x->ScriptPosition) -{ - basex = x; - ValueType = TypeBool; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxBoolCast::~FxBoolCast() -{ - SAFE_DELETE(basex); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxBoolCast::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(basex, ctx); - - if (basex->ValueType == TypeBool) - { - FxExpression *x = basex; - basex = nullptr; - delete this; - return x; - } - else if (basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER) - { - if (basex->isConstant()) - { - assert(basex->ValueType != TypeState && "We shouldn't be able to generate a constant state ref"); - - ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(constval.GetBool(), ScriptPosition); - delete this; - return x; - } - return this; - } - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return nullptr; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) -{ - ExpEmit from = basex->Emit(build); - assert(!from.Konst); - assert(basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER); - ExpEmit to(build, REGT_INT); - from.Free(build); - - // Preload result with 0. - build->Emit(OP_LI, to.RegNum, 0); - - // Check source against 0. - if (from.RegType == REGT_INT) - { - build->Emit(OP_EQ_R, 1, from.RegNum, to.RegNum); - } - else if (from.RegType == REGT_FLOAT) - { - build->Emit(OP_EQF_K, 1, from.RegNum, build->GetConstantFloat(0.)); - } - else if (from.RegType == REGT_POINTER) - { - build->Emit(OP_EQA_K, 1, from.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC)); - } - build->Emit(OP_JMP, 1); - - // Reload result with 1 if the comparison fell through. - build->Emit(OP_LI, to.RegNum, 1); - - return to; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxIntCast::FxIntCast(FxExpression *x) -: FxExpression(x->ScriptPosition) -{ - basex=x; - ValueType = TypeSInt32; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxIntCast::~FxIntCast() -{ - SAFE_DELETE(basex); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxIntCast::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(basex, ctx); - - if (basex->ValueType->GetRegType() == REGT_INT) - { - if (basex->ValueType != TypeName) - { - FxExpression *x = basex; - basex = NULL; - delete this; - return x; - } - else - { - // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( - if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); - else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); - FxExpression * x = new FxConstant(0, ScriptPosition); - delete this; - return x; - } - } - else if (basex->ValueType->GetRegType() == REGT_FLOAT) - { - if (basex->isConstant()) - { - ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(constval.GetInt(), ScriptPosition); - delete this; - return x; - } - return this; - } - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxIntCast::Emit(VMFunctionBuilder *build) -{ - ExpEmit from = basex->Emit(build); - assert(!from.Konst); - assert(basex->ValueType->GetRegType() == REGT_FLOAT); - from.Free(build); - ExpEmit to(build, REGT_INT); - build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_F2I); - return to; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxFloatCast::FxFloatCast(FxExpression *x) -: FxExpression(x->ScriptPosition) -{ - basex=x; - ValueType = TypeFloat64; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxFloatCast::~FxFloatCast() -{ - SAFE_DELETE(basex); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(basex, ctx); - - if (basex->ValueType->GetRegType() == REGT_FLOAT) - { - FxExpression *x = basex; - basex = NULL; - delete this; - return x; - } - else if (basex->ValueType->GetRegType() == REGT_INT) - { - if (basex->ValueType != TypeName) - { - if (basex->isConstant()) - { - ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition); - delete this; - return x; - } - return this; - } - else - { - // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( - if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); - else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); - FxExpression *x = new FxConstant(0.0, ScriptPosition); - delete this; - return x; - } - } - else - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build) -{ - ExpEmit from = basex->Emit(build); - assert(!from.Konst); - assert(basex->ValueType->GetRegType() == REGT_INT); - from.Free(build); - ExpEmit to(build, REGT_FLOAT); - build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_I2F); - return to; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxPlusSign::FxPlusSign(FxExpression *operand) -: FxExpression(operand->ScriptPosition) -{ - Operand=operand; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxPlusSign::~FxPlusSign() -{ - SAFE_DELETE(Operand); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxPlusSign::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Operand, ctx); - - if (Operand->IsNumeric()) - { - FxExpression *e = Operand; - Operand = NULL; - delete this; - return e; - } - else - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } -} - -ExpEmit FxPlusSign::Emit(VMFunctionBuilder *build) -{ - return Operand->Emit(build); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxMinusSign::FxMinusSign(FxExpression *operand) -: FxExpression(operand->ScriptPosition) -{ - Operand=operand; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxMinusSign::~FxMinusSign() -{ - SAFE_DELETE(Operand); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxMinusSign::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Operand, ctx); - - if (Operand->IsNumeric()) - { - if (Operand->isConstant()) - { - ExpVal val = static_cast(Operand)->GetValue(); - FxExpression *e = val.Type->GetRegType() == REGT_INT ? - new FxConstant(-val.Int, ScriptPosition) : - new FxConstant(-val.Float, ScriptPosition); - delete this; - return e; - } - ValueType = Operand->ValueType; - return this; - } - else - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) -{ - assert(ValueType == Operand->ValueType); - ExpEmit from = Operand->Emit(build); - assert(from.Konst == 0); - // Do it in-place. - if (ValueType->GetRegType() == REGT_INT) - { - build->Emit(OP_NEG, from.RegNum, from.RegNum, 0); - } - else - { - assert(ValueType->GetRegType() == REGT_FLOAT); - build->Emit(OP_FLOP, from.RegNum, from.RegNum, FLOP_NEG); - } - return from; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxUnaryNotBitwise::FxUnaryNotBitwise(FxExpression *operand) -: FxExpression(operand->ScriptPosition) -{ - Operand=operand; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxUnaryNotBitwise::~FxUnaryNotBitwise() -{ - SAFE_DELETE(Operand); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Operand, ctx); - - if (Operand->ValueType->GetRegType() == REGT_FLOAT /* lax */) - { - // DECORATE allows floats here so cast them to int. - Operand = new FxIntCast(Operand); - Operand = Operand->Resolve(ctx); - if (Operand == NULL) - { - delete this; - return NULL; - } - } - - if (Operand->ValueType->GetRegType() != REGT_INT) - { - ScriptPosition.Message(MSG_ERROR, "Integer type expected"); - delete this; - return NULL; - } - - if (Operand->isConstant()) - { - int result = ~static_cast(Operand)->GetValue().GetInt(); - FxExpression *e = new FxConstant(result, ScriptPosition); - delete this; - return e; - } - ValueType = TypeSInt32; - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxUnaryNotBitwise::Emit(VMFunctionBuilder *build) -{ - assert(Operand->ValueType->GetRegType() == REGT_INT); - ExpEmit from = Operand->Emit(build); - assert(!from.Konst); - // Do it in-place. - build->Emit(OP_NOT, from.RegNum, from.RegNum, 0); - return from; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxUnaryNotBoolean::FxUnaryNotBoolean(FxExpression *operand) -: FxExpression(operand->ScriptPosition) -{ - Operand=operand; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxUnaryNotBoolean::~FxUnaryNotBoolean() -{ - SAFE_DELETE(Operand); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxUnaryNotBoolean::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Operand, ctx); - - if (Operand->ValueType != TypeBool) - { - Operand = new FxBoolCast(Operand); - SAFE_RESOLVE(Operand, ctx); - } - - if (Operand->isConstant()) - { - bool result = !static_cast(Operand)->GetValue().GetBool(); - FxExpression *e = new FxConstant(result, ScriptPosition); - delete this; - return e; - } - - ValueType = TypeBool; - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) -{ - assert(Operand->ValueType == ValueType); - assert(ValueType == TypeBool); - ExpEmit from = Operand->Emit(build); - assert(!from.Konst); - // ~x & 1 - build->Emit(OP_NOT, from.RegNum, from.RegNum, 0); - build->Emit(OP_AND_RK, from.RegNum, from.RegNum, build->GetConstantInt(1)); - return from; -} - -//========================================================================== -// -// FxPreIncrDecr -// -//========================================================================== - -FxPreIncrDecr::FxPreIncrDecr(FxExpression *base, int token) -: FxExpression(base->ScriptPosition), Token(token), Base(base) -{ - AddressRequested = false; - AddressWritable = false; -} - -FxPreIncrDecr::~FxPreIncrDecr() -{ - SAFE_DELETE(Base); -} - -bool FxPreIncrDecr::RequestAddress() -{ - AddressRequested = true; - return AddressWritable; -} - -FxExpression *FxPreIncrDecr::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Base, ctx); - - ValueType = Base->ValueType; - - if (!Base->IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return nullptr; - } - else if (Base->ValueType == TypeBool) - { - ScriptPosition.Message(MSG_ERROR, "%s is not allowed on type bool", FScanner::TokenName(Token).GetChars()); - delete this; - return nullptr; - } - if (!(AddressWritable = Base->RequestAddress())) - { - ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); - delete this; - return nullptr; - } - - return this; -} - -ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) -{ - assert(Token == TK_Incr || Token == TK_Decr); - assert(ValueType == Base->ValueType && IsNumeric()); - - int zero = build->GetConstantInt(0); - int regtype = ValueType->GetRegType(); - ExpEmit pointer = Base->Emit(build); - - ExpEmit value(build, regtype); - build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero); - - if (regtype == REGT_INT) - { - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, value.RegNum, value.RegNum, build->GetConstantInt(1)); - } - else - { - build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, value.RegNum, value.RegNum, build->GetConstantFloat(1.)); - } - - build->Emit(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero); - - if (AddressRequested) - { - value.Free(build); - return pointer; - } - - pointer.Free(build); - return value; -} - -//========================================================================== -// -// FxPostIncrDecr -// -//========================================================================== - -FxPostIncrDecr::FxPostIncrDecr(FxExpression *base, int token) -: FxExpression(base->ScriptPosition), Token(token), Base(base) -{ -} - -FxPostIncrDecr::~FxPostIncrDecr() -{ - SAFE_DELETE(Base); -} - -FxExpression *FxPostIncrDecr::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Base, ctx); - - ValueType = Base->ValueType; - - if (!Base->IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return nullptr; - } - else if (Base->ValueType == TypeBool) - { - ScriptPosition.Message(MSG_ERROR, "%s is not allowed on type bool", FScanner::TokenName(Token).GetChars()); - delete this; - return nullptr; - } - if (!Base->RequestAddress()) - { - ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); - delete this; - return nullptr; - } - - return this; -} - -ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) -{ - assert(Token == TK_Incr || Token == TK_Decr); - assert(ValueType == Base->ValueType && IsNumeric()); - - int zero = build->GetConstantInt(0); - int regtype = ValueType->GetRegType(); - ExpEmit pointer = Base->Emit(build); - - ExpEmit out(build, regtype); - build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero); - - ExpEmit assign(build, regtype); - if (regtype == REGT_INT) - { - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, assign.RegNum, out.RegNum, build->GetConstantInt(1)); - } - else - { - build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, assign.RegNum, out.RegNum, build->GetConstantFloat(1.)); - } - - build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero); - - pointer.Free(build); - assign.Free(build); - return out; -} - -//========================================================================== -// -// FxAssign -// -//========================================================================== - -FxAssign::FxAssign(FxExpression *base, FxExpression *right) -: FxExpression(base->ScriptPosition), Base(base), Right(right) -{ - AddressRequested = false; - AddressWritable = false; -} - -FxAssign::~FxAssign() -{ - SAFE_DELETE(Base); - SAFE_DELETE(Right); -} - -bool FxAssign::RequestAddress() -{ - AddressRequested = true; - return AddressWritable; -} - -FxExpression *FxAssign::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Base, ctx); - - ValueType = Base->ValueType; - - SAFE_RESOLVE(Right, ctx); - - if (!Base->IsNumeric() || !Right->IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return nullptr; - } - if (!(AddressWritable = Base->RequestAddress())) - { - ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); - delete this; - return nullptr; - } - - if (Right->ValueType != ValueType) - { - if (ValueType == TypeBool) - { - Right = new FxBoolCast(Right); - } - else if (ValueType->GetRegType() == REGT_INT) - { - Right = new FxIntCast(Right); - } - else - { - Right = new FxFloatCast(Right); - } - SAFE_RESOLVE(Right, ctx); - } - - return this; -} - -ExpEmit FxAssign::Emit(VMFunctionBuilder *build) -{ - assert(ValueType == Base->ValueType && IsNumeric()); - assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); - - ExpEmit pointer = Base->Emit(build); - Address = pointer; - - ExpEmit result = Right->Emit(build); - - if (result.Konst) - { - ExpEmit temp(build, result.RegType); - build->Emit(result.RegType == REGT_FLOAT ? OP_LKF : OP_LK, temp.RegNum, result.RegNum); - result.Free(build); - result = temp; - } - - build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); - - if (AddressRequested) - { - result.Free(build); - return pointer; - } - - pointer.Free(build); - return result; -} - -//========================================================================== -// -// FxAssignSelf -// -//========================================================================== - -FxAssignSelf::FxAssignSelf(const FScriptPosition &pos) -: FxExpression(pos) -{ - Assignment = nullptr; -} - -FxExpression *FxAssignSelf::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - - // This should never happen if FxAssignSelf is used correctly - assert(Assignment != nullptr); - - ValueType = Assignment->ValueType; - - return this; -} - -ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) -{ - assert(ValueType = Assignment->ValueType); - ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it - ExpEmit out(build, ValueType->GetRegType()); - build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0)); - return out; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxBinary::FxBinary(int o, FxExpression *l, FxExpression *r) -: FxExpression(l->ScriptPosition) -{ - Operator=o; - left=l; - right=r; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxBinary::~FxBinary() -{ - SAFE_DELETE(left); - SAFE_DELETE(right); -} - -//========================================================================== -// -// -// -//========================================================================== - -bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) -{ - RESOLVE(left, ctx); - RESOLVE(right, ctx); - if (!left || !right) - { - delete this; - return false; - } - - if (left->ValueType == TypeBool && right->ValueType == TypeBool) - { - ValueType = TypeBool; - } - if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) - { - ValueType = TypeSInt32; - } - else if (left->IsNumeric() && right->IsNumeric()) - { - ValueType = TypeFloat64; - } - else if (left->ValueType->GetRegType() == REGT_POINTER && left->ValueType == right->ValueType) - { - ValueType = left->ValueType; - } - else - { - ValueType = TypeVoid; - } - - if (castnumeric) - { - // later! - } - return true; -} - -void FxBinary::Promote(FCompileContext &ctx) -{ - if (left->ValueType->GetRegType() == REGT_FLOAT && right->ValueType->GetRegType() == REGT_INT) - { - right = (new FxFloatCast(right))->Resolve(ctx); - } - else if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_FLOAT) - { - left = (new FxFloatCast(left))->Resolve(ctx); - } -} - -//========================================================================== -// -// -// -//========================================================================== - -FxAddSub::FxAddSub(int o, FxExpression *l, FxExpression *r) -: FxBinary(o, l, r) -{ -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxAddSub::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return NULL; - - if (!IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } - else if (left->isConstant() && right->isConstant()) - { - if (ValueType->GetRegType() == REGT_FLOAT) - { - double v; - double v1 = static_cast(left)->GetValue().GetFloat(); - double v2 = static_cast(right)->GetValue().GetFloat(); - - v = Operator == '+'? v1 + v2 : - Operator == '-'? v1 - v2 : 0; - - FxExpression *e = new FxConstant(v, ScriptPosition); - delete this; - return e; - } - else - { - int v; - int v1 = static_cast(left)->GetValue().GetInt(); - int v2 = static_cast(right)->GetValue().GetInt(); - - v = Operator == '+'? v1 + v2 : - Operator == '-'? v1 - v2 : 0; - - FxExpression *e = new FxConstant(v, ScriptPosition); - delete this; - return e; - - } - } - Promote(ctx); - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) -{ - assert(Operator == '+' || Operator == '-'); - ExpEmit op1 = left->Emit(build); - ExpEmit op2 = right->Emit(build); - if (Operator == '+') - { - // Since addition is commutative, only the second operand may be a constant. - if (op1.Konst) - { - swapvalues(op1, op2); - } - assert(!op1.Konst); - op1.Free(build); - op2.Free(build); - if (ValueType->GetRegType() == REGT_FLOAT) - { - assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); - ExpEmit to(build, REGT_FLOAT); - build->Emit(op2.Konst ? OP_ADDF_RK : OP_ADDF_RR, to.RegNum, op1.RegNum, op2.RegNum); - return to; - } - else - { - assert(ValueType->GetRegType() == REGT_INT); - assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT); - ExpEmit to(build, REGT_INT); - build->Emit(op2.Konst ? OP_ADD_RK : OP_ADD_RR, to.RegNum, op1.RegNum, op2.RegNum); - return to; - } - } - else - { - // Subtraction is not commutative, so either side may be constant (but not both). - assert(!op1.Konst || !op2.Konst); - op1.Free(build); - op2.Free(build); - if (ValueType->GetRegType() == REGT_FLOAT) - { - assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); - ExpEmit to(build, REGT_FLOAT); - build->Emit(op1.Konst ? OP_SUBF_KR : op2.Konst ? OP_SUBF_RK : OP_SUBF_RR, - to.RegNum, op1.RegNum, op2.RegNum); - return to; - } - else - { - assert(ValueType->GetRegType() == REGT_INT); - assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT); - ExpEmit to(build, REGT_INT); - build->Emit(op1.Konst ? OP_SUB_KR : op2.Konst ? OP_SUB_RK : OP_SUB_RR, - to.RegNum, op1.RegNum, op2.RegNum); - return to; - } - } -} - -//========================================================================== -// -// -// -//========================================================================== - -FxMulDiv::FxMulDiv(int o, FxExpression *l, FxExpression *r) -: FxBinary(o, l, r) -{ -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - - if (!ResolveLR(ctx, true)) return NULL; - - if (!IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } - else if (left->isConstant() && right->isConstant()) - { - if (ValueType->GetRegType() == REGT_FLOAT) - { - double v; - double v1 = static_cast(left)->GetValue().GetFloat(); - double v2 = static_cast(right)->GetValue().GetFloat(); - - if (Operator != '*' && v2 == 0) - { - ScriptPosition.Message(MSG_ERROR, "Division by 0"); - delete this; - return NULL; - } - - v = Operator == '*'? v1 * v2 : - Operator == '/'? v1 / v2 : - Operator == '%'? fmod(v1, v2) : 0; - - FxExpression *e = new FxConstant(v, ScriptPosition); - delete this; - return e; - } - else - { - int v; - int v1 = static_cast(left)->GetValue().GetInt(); - int v2 = static_cast(right)->GetValue().GetInt(); - - if (Operator != '*' && v2 == 0) - { - ScriptPosition.Message(MSG_ERROR, "Division by 0"); - delete this; - return NULL; - } - - v = Operator == '*'? v1 * v2 : - Operator == '/'? v1 / v2 : - Operator == '%'? v1 % v2 : 0; - - FxExpression *e = new FxConstant(v, ScriptPosition); - delete this; - return e; - - } - } - Promote(ctx); - return this; -} - - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) -{ - ExpEmit op1 = left->Emit(build); - ExpEmit op2 = right->Emit(build); - - if (Operator == '*') - { - // Multiplication is commutative, so only the second operand may be constant. - if (op1.Konst) - { - swapvalues(op1, op2); - } - assert(!op1.Konst); - op1.Free(build); - op2.Free(build); - if (ValueType->GetRegType() == REGT_FLOAT) - { - assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); - ExpEmit to(build, REGT_FLOAT); - build->Emit(op2.Konst ? OP_MULF_RK : OP_MULF_RR, to.RegNum, op1.RegNum, op2.RegNum); - return to; - } - else - { - assert(ValueType->GetRegType() == REGT_INT); - assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT); - ExpEmit to(build, REGT_INT); - build->Emit(op2.Konst ? OP_MUL_RK : OP_MUL_RR, to.RegNum, op1.RegNum, op2.RegNum); - return to; - } - } - else - { - // Division is not commutative, so either side may be constant (but not both). - assert(!op1.Konst || !op2.Konst); - assert(Operator == '%' || Operator == '/'); - op1.Free(build); - op2.Free(build); - if (ValueType->GetRegType() == REGT_FLOAT) - { - assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); - ExpEmit to(build, REGT_FLOAT); - build->Emit(Operator == '/' ? (op1.Konst ? OP_DIVF_KR : op2.Konst ? OP_DIVF_RK : OP_DIVF_RR) - : (op1.Konst ? OP_MODF_KR : op2.Konst ? OP_MODF_RK : OP_MODF_RR), - to.RegNum, op1.RegNum, op2.RegNum); - return to; - } - else - { - assert(ValueType->GetRegType() == REGT_INT); - assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT); - ExpEmit to(build, REGT_INT); - build->Emit(Operator == '/' ? (op1.Konst ? OP_DIV_KR : op2.Konst ? OP_DIV_RK : OP_DIV_RR) - : (op1.Konst ? OP_MOD_KR : op2.Konst ? OP_MOD_RK : OP_MOD_RR), - to.RegNum, op1.RegNum, op2.RegNum); - return to; - } - } -} - -//========================================================================== -// -// -// -//========================================================================== - -FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r) -: FxBinary(o, l, r) -{ -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return NULL; - - if (!IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } - else if (left->isConstant() && right->isConstant()) - { - int v; - - if (ValueType->GetRegType() == REGT_FLOAT) - { - double v1 = static_cast(left)->GetValue().GetFloat(); - double v2 = static_cast(right)->GetValue().GetFloat(); - v = Operator == '<'? v1 < v2 : - Operator == '>'? v1 > v2 : - Operator == TK_Geq? v1 >= v2 : - Operator == TK_Leq? v1 <= v2 : 0; - } - else - { - int v1 = static_cast(left)->GetValue().GetInt(); - int v2 = static_cast(right)->GetValue().GetInt(); - v = Operator == '<'? v1 < v2 : - Operator == '>'? v1 > v2 : - Operator == TK_Geq? v1 >= v2 : - Operator == TK_Leq? v1 <= v2 : 0; - } - FxExpression *e = new FxConstant(v, ScriptPosition); - delete this; - return e; - } - Promote(ctx); - ValueType = TypeBool; - return this; -} - - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build) -{ - ExpEmit op1 = left->Emit(build); - ExpEmit op2 = right->Emit(build); - assert(op1.RegType == op2.RegType); - assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT); - assert(!op1.Konst || !op2.Konst); - assert(Operator == '<' || Operator == '>' || Operator == TK_Geq || Operator == TK_Leq); - static const VM_UBYTE InstrMap[][4] = - { - { OP_LT_RR, OP_LTF_RR, 0 }, // < - { OP_LE_RR, OP_LEF_RR, 1 }, // > - { OP_LT_RR, OP_LTF_RR, 1 }, // >= - { OP_LE_RR, OP_LEF_RR, 0 } // <= - }; - int instr, check, index; - ExpEmit to(build, REGT_INT); - - index = Operator == '<' ? 0 : - Operator == '>' ? 1 : - Operator == TK_Geq ? 2 : 3; - instr = InstrMap[index][op1.RegType == REGT_INT ? 0 : 1]; - check = InstrMap[index][2]; - if (op2.Konst) - { - instr += 1; - } - else - { - op2.Free(build); - } - if (op1.Konst) - { - instr += 2; - } - else - { - op1.Free(build); - } - - // See FxBoolCast for comments, since it's the same thing. - build->Emit(OP_LI, to.RegNum, 0, 0); - build->Emit(instr, check, op1.RegNum, op2.RegNum); - build->Emit(OP_JMP, 1); - build->Emit(OP_LI, to.RegNum, 1); - return to; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxCompareEq::FxCompareEq(int o, FxExpression *l, FxExpression *r) -: FxBinary(o, l, r) -{ -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - - if (!ResolveLR(ctx, true)) return NULL; - - if (!left || !right) - { - delete this; - return NULL; - } - - if (!IsNumeric() && !IsPointer()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } - - if (left->isConstant() && right->isConstant()) - { - int v; - - if (ValueType->GetRegType() == REGT_FLOAT) - { - double v1 = static_cast(left)->GetValue().GetFloat(); - double v2 = static_cast(right)->GetValue().GetFloat(); - v = Operator == TK_Eq? v1 == v2 : v1 != v2; - } - else - { - int v1 = static_cast(left)->GetValue().GetInt(); - int v2 = static_cast(right)->GetValue().GetInt(); - v = Operator == TK_Eq? v1 == v2 : v1 != v2; - } - FxExpression *e = new FxConstant(v, ScriptPosition); - delete this; - return e; - } - Promote(ctx); - ValueType = TypeBool; - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) -{ - ExpEmit op1 = left->Emit(build); - ExpEmit op2 = right->Emit(build); - assert(op1.RegType == op2.RegType); - assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT || op1.RegType == REGT_POINTER); - int instr; - - // Only the second operand may be constant. - if (op1.Konst) - { - swapvalues(op1, op2); - } - assert(!op1.Konst); - - ExpEmit to(build, REGT_INT); - - instr = op1.RegType == REGT_INT ? OP_EQ_R : - op1.RegType == REGT_FLOAT ? OP_EQF_R : - OP_EQA_R; - op1.Free(build); - if (!op2.Konst) - { - op2.Free(build); - } - else - { - instr += 1; - } - - // See FxUnaryNotBoolean for comments, since it's the same thing. - build->Emit(OP_LI, to.RegNum, 0, 0); - build->Emit(instr, Operator != TK_Eq, op1.RegNum, op2.RegNum); - build->Emit(OP_JMP, 1); - build->Emit(OP_LI, to.RegNum, 1); - return to; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxBinaryInt::FxBinaryInt(int o, FxExpression *l, FxExpression *r) -: FxBinary(o, l, r) -{ - ValueType = TypeSInt32; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - if (!ResolveLR(ctx, false)) return NULL; - - if (ValueType->GetRegType() == REGT_FLOAT /* lax */) - { - // For DECORATE which allows floats here. - if (left->ValueType->GetRegType() != REGT_INT) - { - left = new FxIntCast(left); - left = left->Resolve(ctx); - } - if (right->ValueType->GetRegType() != REGT_INT) - { - right = new FxIntCast(right); - right = right->Resolve(ctx); - } - if (left == NULL || right == NULL) - { - delete this; - return NULL; - } - ValueType = TypeSInt32; - } - - if (ValueType->GetRegType() != REGT_INT) - { - ScriptPosition.Message(MSG_ERROR, "Integer type expected"); - delete this; - return NULL; - } - else if (left->isConstant() && right->isConstant()) - { - int v1 = static_cast(left)->GetValue().GetInt(); - int v2 = static_cast(right)->GetValue().GetInt(); - - FxExpression *e = new FxConstant( - Operator == TK_LShift? v1 << v2 : - Operator == TK_RShift? v1 >> v2 : - Operator == TK_URShift? int((unsigned int)(v1) >> v2) : - Operator == '&'? v1 & v2 : - Operator == '|'? v1 | v2 : - Operator == '^'? v1 ^ v2 : 0, ScriptPosition); - - delete this; - return e; - } - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build) -{ - assert(left->ValueType->GetRegType() == REGT_INT); - assert(right->ValueType->GetRegType() == REGT_INT); - static const VM_UBYTE InstrMap[][4] = - { - { OP_SLL_RR, OP_SLL_KR, OP_SLL_RI }, // TK_LShift - { OP_SRA_RR, OP_SRA_KR, OP_SRA_RI }, // TK_RShift - { OP_SRL_RR, OP_SRL_KR, OP_SRL_RI }, // TK_URShift - { OP_AND_RR, 0, OP_AND_RK }, // '&' - { OP_OR_RR, 0, OP_OR_RK }, // '|' - { OP_XOR_RR, 0, OP_XOR_RK }, // '^' - }; - int index, instr, rop; - ExpEmit op1, op2; - - index = Operator == TK_LShift ? 0 : - Operator == TK_RShift ? 1 : - Operator == TK_URShift ? 2 : - Operator == '&' ? 3 : - Operator == '|' ? 4 : - Operator == '^' ? 5 : -1; - assert(index >= 0); - op1 = left->Emit(build); - if (index < 3) - { // Shift instructions use right-hand immediates instead of constant registers. - if (right->isConstant()) - { - rop = static_cast(right)->GetValue().GetInt(); - op2.Konst = true; - } - else - { - op2 = right->Emit(build); - assert(!op2.Konst); - op2.Free(build); - rop = op2.RegNum; - } - } - else - { // The other operators only take a constant on the right-hand side. - op2 = right->Emit(build); - if (op1.Konst) - { - swapvalues(op1, op2); - } - assert(!op1.Konst); - rop = op2.RegNum; - op2.Free(build); - } - if (!op1.Konst) - { - op1.Free(build); - if (!op2.Konst) - { - instr = InstrMap[index][0]; - } - else - { - instr = InstrMap[index][2]; - } - } - else - { - assert(!op2.Konst); - instr = InstrMap[index][1]; - } - assert(instr != 0); - ExpEmit to(build, REGT_INT); - build->Emit(instr, to.RegNum, op1.RegNum, rop); - return to; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxBinaryLogical::FxBinaryLogical(int o, FxExpression *l, FxExpression *r) -: FxExpression(l->ScriptPosition) -{ - Operator=o; - left=l; - right=r; - ValueType = TypeBool; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxBinaryLogical::~FxBinaryLogical() -{ - SAFE_DELETE(left); - SAFE_DELETE(right); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - RESOLVE(left, ctx); - RESOLVE(right, ctx); - ABORT(right && left); - - if (left->ValueType != TypeBool) - { - left = new FxBoolCast(left); - SAFE_RESOLVE(left, ctx); - } - if (right->ValueType != TypeBool) - { - right = new FxBoolCast(right); - SAFE_RESOLVE(right, ctx); - } - - int b_left=-1, b_right=-1; - if (left->isConstant()) b_left = static_cast(left)->GetValue().GetBool(); - if (right->isConstant()) b_right = static_cast(right)->GetValue().GetBool(); - - // Do some optimizations. This will throw out all sub-expressions that are not - // needed to retrieve the final result. - if (Operator == TK_AndAnd) - { - if (b_left==0 || b_right==0) - { - FxExpression *x = new FxConstant(true, ScriptPosition); - delete this; - return x; - } - else if (b_left==1 && b_right==1) - { - FxExpression *x = new FxConstant(false, ScriptPosition); - delete this; - return x; - } - else if (b_left==1) - { - FxExpression *x = right; - right=NULL; - delete this; - return x; - } - else if (b_right==1) - { - FxExpression *x = left; - left=NULL; - delete this; - return x; - } - } - else if (Operator == TK_OrOr) - { - if (b_left==1 || b_right==1) - { - FxExpression *x = new FxConstant(true, ScriptPosition); - delete this; - return x; - } - if (b_left==0 && b_right==0) - { - FxExpression *x = new FxConstant(false, ScriptPosition); - delete this; - return x; - } - else if (b_left==0) - { - FxExpression *x = right; - right=NULL; - delete this; - return x; - } - else if (b_right==0) - { - FxExpression *x = left; - left=NULL; - delete this; - return x; - } - } - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) -{ - // This is not the "right" way to do these, but it works for now. - // (Problem: No information sharing is done between nodes to reduce the - // code size if you have something like a1 && a2 && a3 && ... && an.) - assert(left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT); - ExpEmit op1 = left->Emit(build); - assert(!op1.Konst); - int zero = build->GetConstantInt(0); - op1.Free(build); - - if (Operator == TK_AndAnd) - { - build->Emit(OP_EQ_K, 1, op1.RegNum, zero); - // If op1 is 0, skip evaluation of op2. - size_t patchspot = build->Emit(OP_JMP, 0, 0, 0); - - // Evaluate op2. - ExpEmit op2 = right->Emit(build); - assert(!op2.Konst); - op2.Free(build); - - ExpEmit to(build, REGT_INT); - build->Emit(OP_EQ_K, 1, op2.RegNum, zero); - build->Emit(OP_JMP, 2); - build->Emit(OP_LI, to.RegNum, 1); - build->Emit(OP_JMP, 1); - size_t target = build->Emit(OP_LI, to.RegNum, 0); - build->Backpatch(patchspot, target); - return to; - } - else - { - assert(Operator == TK_OrOr); - build->Emit(OP_EQ_K, 0, op1.RegNum, zero); - // If op1 is not 0, skip evaluation of op2. - size_t patchspot = build->Emit(OP_JMP, 0, 0, 0); - - // Evaluate op2. - ExpEmit op2 = right->Emit(build); - assert(!op2.Konst); - op2.Free(build); - - ExpEmit to(build, REGT_INT); - build->Emit(OP_EQ_K, 0, op2.RegNum, zero); - build->Emit(OP_JMP, 2); - build->Emit(OP_LI, to.RegNum, 0); - build->Emit(OP_JMP, 1); - size_t target = build->Emit(OP_LI, to.RegNum, 1); - build->Backpatch(patchspot, target); - return to; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f) -: FxExpression(c->ScriptPosition) -{ - condition = c; - truex=t; - falsex=f; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxConditional::~FxConditional() -{ - SAFE_DELETE(condition); - SAFE_DELETE(truex); - SAFE_DELETE(falsex); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxConditional::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - RESOLVE(condition, ctx); - RESOLVE(truex, ctx); - RESOLVE(falsex, ctx); - ABORT(condition && truex && falsex); - - if (truex->ValueType == TypeBool && falsex->ValueType == TypeBool) - ValueType = TypeBool; - else if (truex->ValueType->GetRegType() == REGT_INT && falsex->ValueType->GetRegType() == REGT_INT) - ValueType = TypeSInt32; - else if (truex->IsNumeric() && falsex->IsNumeric()) - ValueType = TypeFloat64; - //else if (truex->ValueType != falsex->ValueType) - - if (condition->ValueType != TypeBool) - { - condition = new FxBoolCast(condition); - SAFE_RESOLVE(condition, ctx); - } - - if (condition->isConstant()) - { - ExpVal condval = static_cast(condition)->GetValue(); - bool result = condval.GetBool(); - - FxExpression *e = result? truex:falsex; - delete (result? falsex:truex); - falsex = truex = NULL; - delete this; - return e; - } - - if (ValueType->GetRegType() == REGT_FLOAT) - { - if (truex->ValueType->GetRegType() != REGT_FLOAT) - { - truex = new FxFloatCast(truex); - RESOLVE(truex, ctx); - } - if (falsex->ValueType->GetRegType() != REGT_FLOAT) - { - falsex = new FxFloatCast(falsex); - RESOLVE(falsex, ctx); - } - } - - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxConditional::Emit(VMFunctionBuilder *build) -{ - size_t truejump, falsejump; - ExpEmit out; - - // The true and false expressions ought to be assigned to the - // same temporary instead of being copied to it. Oh well; good enough - // for now. - ExpEmit cond = condition->Emit(build); - assert(cond.RegType == REGT_INT && !cond.Konst); - - // Test condition. - build->Emit(OP_EQ_K, 1, cond.RegNum, build->GetConstantInt(0)); - falsejump = build->Emit(OP_JMP, 0); - - // Evaluate true expression. - if (truex->isConstant() && truex->ValueType->GetRegType() == REGT_INT) - { - out = ExpEmit(build, REGT_INT); - build->EmitLoadInt(out.RegNum, static_cast(truex)->GetValue().GetInt()); - } - else - { - ExpEmit trueop = truex->Emit(build); - if (trueop.Konst) - { - assert(trueop.RegType == REGT_FLOAT); - out = ExpEmit(build, REGT_FLOAT); - build->Emit(OP_LKF, out.RegNum, trueop.RegNum); - } - else - { - // Use the register returned by the true condition as the - // target for the false condition. - out = trueop; - } - } - // Make sure to skip the false path. - truejump = build->Emit(OP_JMP, 0); - - // Evaluate false expression. - build->BackpatchToHere(falsejump); - if (falsex->isConstant() && falsex->ValueType->GetRegType() == REGT_INT) - { - build->EmitLoadInt(out.RegNum, static_cast(falsex)->GetValue().GetInt()); - } - else - { - ExpEmit falseop = falsex->Emit(build); - if (falseop.Konst) - { - assert(falseop.RegType == REGT_FLOAT); - build->Emit(OP_LKF, out.RegNum, falseop.RegNum); - } - else - { - // Move result from the register returned by "false" to the one - // returned by "true" so that only one register is returned by - // this tree. - falseop.Free(build); - if (falseop.RegType == REGT_INT) - { - build->Emit(OP_MOVE, out.RegNum, falseop.RegNum, 0); - } - else - { - assert(falseop.RegType == REGT_FLOAT); - build->Emit(OP_MOVEF, out.RegNum, falseop.RegNum, 0); - } - } - } - build->BackpatchToHere(truejump); - - return out; -} - -//========================================================================== -// -// -// -//========================================================================== -FxAbs::FxAbs(FxExpression *v) -: FxExpression(v->ScriptPosition) -{ - val = v; - ValueType = v->ValueType; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxAbs::~FxAbs() -{ - SAFE_DELETE(val); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxAbs::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(val, ctx); - - - if (!val->IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } - else if (val->isConstant()) - { - ExpVal value = static_cast(val)->GetValue(); - switch (value.Type->GetRegType()) - { - case REGT_INT: - value.Int = abs(value.Int); - break; - - case REGT_FLOAT: - value.Float = fabs(value.Float); - break; - - default: - // shouldn't happen - delete this; - return NULL; - } - FxExpression *x = new FxConstant(value, ScriptPosition); - delete this; - return x; - } - ValueType = val->ValueType; - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxAbs::Emit(VMFunctionBuilder *build) -{ - ExpEmit absofsteal = val->Emit(build); - assert(!absofsteal.Konst); - ExpEmit out(build, absofsteal.RegType); - if (absofsteal.RegType == REGT_INT) - { - build->Emit(OP_ABS, out.RegNum, absofsteal.RegNum, 0); - } - else - { - assert(absofsteal.RegType == REGT_FLOAT); - build->Emit(OP_FLOP, out.RegNum, absofsteal.RegNum, FLOP_ABS); - } - return out; -} - -//========================================================================== -// -// -// -//========================================================================== -FxATan2::FxATan2(FxExpression *y, FxExpression *x, const FScriptPosition &pos) -: FxExpression(pos) -{ - yval = y; - xval = x; -} - -//========================================================================== -// -// -// -//========================================================================== -FxATan2::~FxATan2() -{ - SAFE_DELETE(yval); - SAFE_DELETE(xval); -} - -//========================================================================== -// -// -// -//========================================================================== -FxExpression *FxATan2::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(yval, ctx); - SAFE_RESOLVE(xval, ctx); - - if (!yval->IsNumeric() || !xval->IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); - delete this; - return NULL; - } - if (yval->isConstant() && xval->isConstant()) - { - double y = static_cast(yval)->GetValue().GetFloat(); - double x = static_cast(xval)->GetValue().GetFloat(); - FxExpression *z = new FxConstant(g_atan2(y, x) * (180 / M_PI), ScriptPosition); - delete this; - return z; - } - if (yval->ValueType->GetRegType() != REGT_FLOAT && !yval->isConstant()) - { - yval = new FxFloatCast(yval); - } - if (xval->ValueType->GetRegType() != REGT_FLOAT && !xval->isConstant()) - { - xval = new FxFloatCast(xval); - } - ValueType = TypeFloat64; - return this; -} - -//========================================================================== -// -// -// -//========================================================================== -ExpEmit FxATan2::Emit(VMFunctionBuilder *build) -{ - ExpEmit yreg = ToReg(build, yval); - ExpEmit xreg = ToReg(build, xval); - yreg.Free(build); - xreg.Free(build); - ExpEmit out(build, REGT_FLOAT); - build->Emit(OP_ATAN2, out.RegNum, yreg.RegNum, xreg.RegNum); - return out; -} - -//========================================================================== -// -// The atan2 opcode only takes registers as parameters, so any constants -// must be loaded into registers first. -// -//========================================================================== -ExpEmit FxATan2::ToReg(VMFunctionBuilder *build, FxExpression *val) -{ - if (val->isConstant()) - { - ExpEmit reg(build, REGT_FLOAT); - build->Emit(OP_LKF, reg.RegNum, build->GetConstantFloat(static_cast(val)->GetValue().GetFloat())); - return reg; - } - return val->Emit(build); -} - -//========================================================================== -// -// -// -//========================================================================== -FxMinMax::FxMinMax(TArray &expr, FName type, const FScriptPosition &pos) -: FxExpression(pos), Type(type) -{ - assert(expr.Size() > 0); - assert(type == NAME_Min || type == NAME_Max); - - choices.Resize(expr.Size()); - for (unsigned i = 0; i < expr.Size(); ++i) - { - choices[i] = expr[i]; - } -} - -//========================================================================== -// -// -// -//========================================================================== -FxExpression *FxMinMax::Resolve(FCompileContext &ctx) -{ - unsigned int i; - int intcount, floatcount; - - CHECKRESOLVED(); - - // Determine if float or int - intcount = floatcount = 0; - for (i = 0; i < choices.Size(); ++i) - { - RESOLVE(choices[i], ctx); - ABORT(choices[i]); - - if (choices[i]->ValueType->GetRegType() == REGT_FLOAT) - { - floatcount++; - } - else if (choices[i]->ValueType->GetRegType() == REGT_INT) - { - intcount++; - } - else - { - ScriptPosition.Message(MSG_ERROR, "Arguments must be of type int or float"); - delete this; - return NULL; - } - } - if (floatcount != 0) - { - ValueType = TypeFloat64; - if (intcount != 0) - { // There are some ints that need to be cast to floats - for (i = 0; i < choices.Size(); ++i) - { - if (choices[i]->ValueType->GetRegType() == REGT_INT) - { - choices[i] = new FxFloatCast(choices[i]); - RESOLVE(choices[i], ctx); - ABORT(choices[i]); - } - } - } - } - else - { - ValueType = TypeSInt32; - } - - // If at least two arguments are constants, they can be solved now. - - // Look for first constant - for (i = 0; i < choices.Size(); ++i) - { - if (choices[i]->isConstant()) - { - ExpVal best = static_cast(choices[i])->GetValue(); - // Compare against remaining constants, which are removed. - // The best value gets stored in this one. - for (unsigned j = i + 1; j < choices.Size(); ) - { - if (!choices[j]->isConstant()) - { - j++; - } - else - { - ExpVal value = static_cast(choices[j])->GetValue(); - assert(value.Type == ValueType); - if (Type == NAME_Min) - { - if (value.Type->GetRegType() == REGT_FLOAT) - { - if (value.Float < best.Float) - { - best.Float = value.Float; - } - } - else - { - if (value.Int < best.Int) - { - best.Int = value.Int; - } - } - } - else - { - if (value.Type->GetRegType() == REGT_FLOAT) - { - if (value.Float > best.Float) - { - best.Float = value.Float; - } - } - else - { - if (value.Int > best.Int) - { - best.Int = value.Int; - } - } - } - delete choices[j]; - choices[j] = NULL; - choices.Delete(j); - } - } - FxExpression *x = new FxConstant(best, ScriptPosition); - if (i == 0 && choices.Size() == 1) - { // Every choice was constant - delete this; - return x; - } - delete choices[i]; - choices[i] = x; - break; - } - } - return this; -} - -//========================================================================== -// -// -// -//========================================================================== -static void EmitLoad(VMFunctionBuilder *build, const ExpEmit resultreg, const ExpVal &value) -{ - if (resultreg.RegType == REGT_FLOAT) - { - build->Emit(OP_LKF, resultreg.RegNum, build->GetConstantFloat(value.GetFloat())); - } - else - { - build->EmitLoadInt(resultreg.RegNum, value.GetInt()); - } -} - -ExpEmit FxMinMax::Emit(VMFunctionBuilder *build) -{ - unsigned i; - int opcode, opA; - - assert(choices.Size() > 0); - assert(OP_LTF_RK == OP_LTF_RR+1); - assert(OP_LT_RK == OP_LT_RR+1); - assert(OP_LEF_RK == OP_LEF_RR+1); - assert(OP_LE_RK == OP_LE_RR+1); - - if (Type == NAME_Min) - { - opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_LEF_RR : OP_LE_RR; - opA = 1; - } - else - { - opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_LTF_RR : OP_LT_RR; - opA = 0; - } - - ExpEmit bestreg; - - // Get first value into a register. This will also be the result register. - if (choices[0]->isConstant()) - { - bestreg = ExpEmit(build, ValueType->GetRegType()); - EmitLoad(build, bestreg, static_cast(choices[0])->GetValue()); - } - else - { - bestreg = choices[0]->Emit(build); - } - - // Compare every choice. Better matches get copied to the bestreg. - for (i = 1; i < choices.Size(); ++i) - { - ExpEmit checkreg = choices[i]->Emit(build); - assert(checkreg.RegType == bestreg.RegType); - build->Emit(opcode + checkreg.Konst, opA, bestreg.RegNum, checkreg.RegNum); - build->Emit(OP_JMP, 1); - if (checkreg.Konst) - { - build->Emit(bestreg.RegType == REGT_FLOAT ? OP_LKF : OP_LK, bestreg.RegNum, checkreg.RegNum); - } - else - { - build->Emit(bestreg.RegType == REGT_FLOAT ? OP_MOVEF : OP_MOVE, bestreg.RegNum, checkreg.RegNum, 0); - checkreg.Free(build); - } - } - return bestreg; -} - -//========================================================================== -// -// -// -//========================================================================== -FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) -: FxExpression(pos) -{ - EmitTail = false; - if (mi != NULL && ma != NULL) - { - min = new FxIntCast(mi); - max = new FxIntCast(ma); - } - else min = max = NULL; - rng = r; - ValueType = TypeSInt32; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxRandom::~FxRandom() -{ - SAFE_DELETE(min); - SAFE_DELETE(max); -} - -//========================================================================== -// -// -// -//========================================================================== - -PPrototype *FxRandom::ReturnProto() -{ - EmitTail = true; - return FxExpression::ReturnProto(); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxRandom::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - if (min && max) - { - RESOLVE(min, ctx); - RESOLVE(max, ctx); - ABORT(min && max); - assert(min->ValueType == ValueType); - assert(max->ValueType == ValueType); - } - return this; -}; - - -//========================================================================== -// -// -// -//========================================================================== - -int DecoRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) -{ - assert(numparam >= 1 && numparam <= 3); - FRandom *rng = reinterpret_cast(param[0].a); - if (numparam == 1) - { - ACTION_RETURN_INT((*rng)()); - } - else if (numparam == 2) - { - int maskval = param[1].i; - ACTION_RETURN_INT(rng->Random2(maskval)); - } - else if (numparam == 3) - { - int min = param[1].i, max = param[2].i; - if (max < min) - { - swapvalues(max, min); - } - ACTION_RETURN_INT((*rng)(max - min + 1) + min); - } - - // Shouldn't happen - return 0; -} - -ExpEmit FxRandom::Emit(VMFunctionBuilder *build) -{ - // Call DecoRandom to generate a random number. - VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom); - - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); - callfunc = ((PSymbolVMFunction *)sym)->Function; - - int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); - - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); - if (min != NULL && max != NULL) - { - EmitParameter(build, min, ScriptPosition); - EmitParameter(build, max, ScriptPosition); - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); - } - else - { - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1); - } - - if (EmitTail) - { - ExpEmit call; - call.Final = true; - return call; - } - - ExpEmit out(build, REGT_INT); - build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); - return out; -} - -//========================================================================== -// -// -// -//========================================================================== -FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, const FScriptPosition &pos) -: FxExpression(pos) -{ - assert(expr.Size() > 0); - choices.Resize(expr.Size()); - for (unsigned int index = 0; index < expr.Size(); index++) - { - if (floaty) - { - choices[index] = new FxFloatCast(expr[index]); - } - else - { - choices[index] = new FxIntCast(expr[index]); - } - - } - rng = r; - if (floaty) - { - ValueType = TypeFloat64; - } - else - { - ValueType = TypeSInt32; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -FxRandomPick::~FxRandomPick() -{ -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxRandomPick::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - for (unsigned int index = 0; index < choices.Size(); index++) - { - RESOLVE(choices[index], ctx); - ABORT(choices[index]); - assert(choices[index]->ValueType == ValueType); - } - return this; -}; - - -//========================================================================== -// -// FxPick :: Emit -// -// The expression: -// a = pick[rng](i_0, i_1, i_2, ..., i_n) -// [where i_x is a complete expression and not just a value] -// is syntactic sugar for: -// -// switch(random[rng](0, n)) { -// case 0: a = i_0; -// case 1: a = i_1; -// case 2: a = i_2; -// ... -// case n: a = i_n; -// } -// -//========================================================================== - -ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) -{ - unsigned i; - - assert(choices.Size() > 0); - - // Call DecoRandom to generate a random number. - VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom); - - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); - callfunc = ((PSymbolVMFunction *)sym)->Function; - - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); - build->EmitParamInt(0); - build->EmitParamInt(choices.Size() - 1); - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); - - ExpEmit resultreg(build, REGT_INT); - build->Emit(OP_RESULT, 0, REGT_INT, resultreg.RegNum); - build->Emit(OP_IJMP, resultreg.RegNum, 0); - - // Free the result register now. The simple code generation algorithm should - // automatically pick it as the destination register for each case. - resultreg.Free(build); - - // For floating point results, we need to get a new register, since we can't - // reuse the integer one used to store the random result. - if (ValueType->GetRegType() == REGT_FLOAT) - { - resultreg = ExpEmit(build, REGT_FLOAT); - resultreg.Free(build); - } - - // Allocate space for the jump table. - size_t jumptable = build->Emit(OP_JMP, 0); - for (i = 1; i < choices.Size(); ++i) - { - build->Emit(OP_JMP, 0); - } - - // Emit each case - TArray finishes(choices.Size() - 1); - for (unsigned i = 0; i < choices.Size(); ++i) - { - build->BackpatchToHere(jumptable + i); - if (choices[i]->isConstant()) - { - EmitLoad(build, resultreg, static_cast(choices[i])->GetValue()); - } - else - { - ExpEmit casereg = choices[i]->Emit(build); - if (casereg.RegNum != resultreg.RegNum) - { // The result of the case is in a different register from what - // was expected. Copy it to the one we wanted. - - resultreg.Reuse(build); // This is really just for the assert in Reuse() - build->Emit(ValueType->GetRegType() == REGT_INT ? OP_MOVE : OP_MOVEF, resultreg.RegNum, casereg.RegNum, 0); - resultreg.Free(build); - } - // Free this register so the remaining cases can use it. - casereg.Free(build); - } - // All but the final case needs a jump to the end of the expression's code. - if (i + 1 < choices.Size()) - { - size_t loc = build->Emit(OP_JMP, 0); - finishes.Push(loc); - } - } - // Backpatch each case (except the last, since it ends here) to jump to here. - for (i = 0; i < choices.Size() - 1; ++i) - { - build->BackpatchToHere(finishes[i]); - } - // The result register needs to be in-use when we return. - // It should have been freed earlier, so restore its in-use flag. - resultreg.Reuse(build); - return resultreg; -} - -//========================================================================== -// -// -// -//========================================================================== -FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) -: FxRandom(r, NULL, NULL, pos) -{ - if (mi != NULL && ma != NULL) - { - min = new FxFloatCast(mi); - max = new FxFloatCast(ma); - } - ValueType = TypeFloat64; -} - -//========================================================================== -// -// -// -//========================================================================== - -int DecoFRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) -{ - assert(numparam == 1 || numparam == 3); - FRandom *rng = reinterpret_cast(param[0].a); - - int random = (*rng)(0x40000000); - double frandom = random / double(0x40000000); - - if (numparam == 3) - { - double min = param[1].f, max = param[2].f; - if (max < min) - { - swapvalues(max, min); - } - ACTION_RETURN_FLOAT(frandom * (max - min) + min); - } - else - { - ACTION_RETURN_FLOAT(frandom); - } -} - -ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) -{ - // Call the DecoFRandom function to generate a floating point random number.. - VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoFRandom, DecoFRandom); - - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); - callfunc = ((PSymbolVMFunction *)sym)->Function; - - int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); - - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); - if (min != NULL && max != NULL) - { - EmitParameter(build, min, ScriptPosition); - EmitParameter(build, max, ScriptPosition); - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); - } - else - { - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1); - } - - if (EmitTail) - { - ExpEmit call; - call.Final = true; - return call; - } - - ExpEmit out(build, REGT_FLOAT); - build->Emit(OP_RESULT, 0, REGT_FLOAT, out.RegNum); - return out; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos) -: FxExpression(pos) -{ - EmitTail = false; - rng = r; - if (m) mask = new FxIntCast(m); - else mask = new FxConstant(-1, pos); - ValueType = TypeSInt32; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxRandom2::~FxRandom2() -{ - SAFE_DELETE(mask); -} - -//========================================================================== -// -// -// -//========================================================================== - -PPrototype *FxRandom2::ReturnProto() -{ - EmitTail = true; - return FxExpression::ReturnProto(); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxRandom2::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(mask, ctx); - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) -{ - // Call the DecoRandom function to generate the random number. - VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom); - - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); - callfunc = ((PSymbolVMFunction *)sym)->Function; - - int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); - - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); - EmitParameter(build, mask, ScriptPosition); - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); - - if (EmitTail) - { - ExpEmit call; - call.Final = true; - return call; - } - - ExpEmit out(build, REGT_INT); - build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); - return out; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxIdentifier::FxIdentifier(FName name, const FScriptPosition &pos) -: FxExpression(pos) -{ - Identifier = name; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) -{ - PSymbol * sym; - FxExpression *newex = NULL; - //FBaseCVar * cv = NULL; - //FString s; - int num; - //const PClass *Class; - - CHECKRESOLVED(); - // see if the current class (if valid) defines something with this name. - if ((sym = ctx.FindInClass(Identifier)) != NULL) - { - if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) - { - ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars()); - newex = FxConstant::MakeConstant(sym, ScriptPosition); - } - else if (sym->IsKindOf(RUNTIME_CLASS(PField))) - { - PField *vsym = static_cast(sym); - ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as member variable, index %d\n", Identifier.GetChars(), vsym->Offset); - newex = new FxClassMember((new FxSelf(ScriptPosition))->Resolve(ctx), vsym, ScriptPosition); - } - else - { - ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); - } - } - // now check the global identifiers. - else if ((sym = ctx.FindGlobal(Identifier)) != NULL) - { - if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) - { - ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global constant\n", Identifier.GetChars()); - newex = FxConstant::MakeConstant(sym, ScriptPosition); - } - else - { - ScriptPosition.Message(MSG_ERROR, "Invalid global identifier '%s'\n", Identifier.GetChars()); - } - } - /* - else if ((Class = PClass::FindClass(Identifier))) - { - pos.Message(MSG_DEBUGLOG, "Resolving name '%s' as class name\n", Identifier.GetChars()); - newex = new FxClassType(Class, ScriptPosition); - } - } - */ - - // also check for CVars - /* - else if ((cv = FindCVar(Identifier, NULL)) != NULL) - { - CLOG(CL_RESOLVE, LPrintf("Resolving name '%s' as cvar\n", Identifier.GetChars())); - newex = new FxCVar(cv, ScriptPosition); - } - */ - // and line specials - else if ((num = P_FindLineSpecial(Identifier, NULL, NULL))) - { - ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num); - newex = new FxConstant(num, ScriptPosition); - } - else - { - ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); - newex = new FxConstant(0, ScriptPosition); - } - delete this; - return newex? newex->Resolve(ctx) : NULL; -} - - -//========================================================================== -// -// -// -//========================================================================== - -FxSelf::FxSelf(const FScriptPosition &pos) -: FxExpression(pos) -{ -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxSelf::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - if (!ctx.Class) - { - // can't really happen with DECORATE's expression evaluator. - ScriptPosition.Message(MSG_ERROR, "self used outside of a member function"); - delete this; - return NULL; - } - ValueType = ctx.Class; - ValueType = NewPointer(RUNTIME_CLASS(DObject)); - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxSelf::Emit(VMFunctionBuilder *build) -{ - // self is always the first pointer passed to the function - ExpEmit me(0, REGT_POINTER); - me.Fixed = true; - return me; -} - - -//========================================================================== -// -// -// -//========================================================================== - -FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition &pos) -: FxExpression(pos) -{ - classx = x; - membervar = mem; - AddressRequested = false; - //if (classx->IsDefaultObject()) Readonly=true; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxClassMember::~FxClassMember() -{ - SAFE_DELETE(classx); -} - -//========================================================================== -// -// -// -//========================================================================== - -bool FxClassMember::RequestAddress() -{ - AddressRequested = true; - return !!(~membervar->Flags & VARF_ReadOnly); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxClassMember::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(classx, ctx); - - PPointer *ptrtype = dyn_cast(classx->ValueType); - if (ptrtype == NULL || !ptrtype->IsKindOf(RUNTIME_CLASS(DObject))) - { - ScriptPosition.Message(MSG_ERROR, "Member variable requires a class or object"); - delete this; - return NULL; - } - ValueType = membervar->Type; - return this; -} - -ExpEmit FxClassMember::Emit(VMFunctionBuilder *build) -{ - if (build->IsActionFunc && ~membervar->Flags & VARF_Native) - { // Check if this is a user-defined variable. - // As of right now, FxClassMember is only ever used with FxSelf. - // This very user variable was defined in stateowner so if - // self (a0) != stateowner (a1) then the offset is most likely - // going to end up being totally wrong even if the variable was - // redefined in self which means we have to abort to avoid reading - // or writing to a random address and possibly crash. - build->Emit(OP_EQA_R, 1, 0, 1); - build->Emit(OP_JMP, 1); - build->Emit(OP_THROW, 2, X_BAD_SELF); - } - - ExpEmit obj = classx->Emit(build); - assert(obj.RegType == REGT_POINTER); - - if (obj.Konst) - { - // If the situation where we are dereferencing a constant - // pointer is common, then it would probably be worthwhile - // to add new opcodes for those. But as of right now, I - // don't expect it to be a particularly common case. - ExpEmit newobj(build, REGT_POINTER); - build->Emit(OP_LKP, newobj.RegNum, obj.RegNum); - obj = newobj; - } - - if (AddressRequested) - { - if (membervar->Offset == 0) - { - return obj; - } - obj.Free(build); - ExpEmit out(build, REGT_POINTER); - build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->Offset)); - return out; - } - - int offsetreg = build->GetConstantInt((int)membervar->Offset); - ExpEmit loc(build, membervar->Type->GetRegType()); - - build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg); - obj.Free(build); - return loc; -} - - -//========================================================================== -// -// -// -//========================================================================== - -FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index) -:FxExpression(base->ScriptPosition) -{ - Array=base; - index = _index; - AddressRequested = false; - AddressWritable = false; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxArrayElement::~FxArrayElement() -{ - SAFE_DELETE(Array); - SAFE_DELETE(index); -} - -//========================================================================== -// -// -// -//========================================================================== - -bool FxArrayElement::RequestAddress() -{ - AddressRequested = true; - return AddressWritable; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Array,ctx); - SAFE_RESOLVE(index,ctx); - - if (index->ValueType->GetRegType() == REGT_FLOAT /* lax */) - { - // DECORATE allows floats here so cast them to int. - index = new FxIntCast(index); - index = index->Resolve(ctx); - if (index == NULL) - { - delete this; - return NULL; - } - } - if (index->ValueType->GetRegType() != REGT_INT) - { - ScriptPosition.Message(MSG_ERROR, "Array index must be integer"); - delete this; - return NULL; - } - - PArray *arraytype = dyn_cast(Array->ValueType); - if (arraytype == NULL) - { - ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); - delete this; - return NULL; - } - if (index->isConstant()) - { - unsigned indexval = static_cast(index)->GetValue().GetInt(); - if (indexval >= arraytype->ElementCount) - { - ScriptPosition.Message(MSG_ERROR, "Array index out of bounds"); - delete this; - return NULL; - } - } - - ValueType = arraytype->ElementType; - if (ValueType->GetRegType() != REGT_INT && ValueType->GetRegType() != REGT_FLOAT) - { - // int arrays only for now - ScriptPosition.Message(MSG_ERROR, "Only numeric arrays are supported."); - delete this; - return NULL; - } - AddressWritable = Array->RequestAddress(); - return this; -} - -//========================================================================== -// -// in its current state this won't be able to do more than handle the args array. -// -//========================================================================== - -ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) -{ - ExpEmit start = Array->Emit(build); - PArray *const arraytype = static_cast(Array->ValueType); - ExpEmit dest(build, arraytype->ElementType->GetRegType()); - - if (start.Konst) - { - ExpEmit tmpstart(build, REGT_POINTER); - build->Emit(OP_LKP, tmpstart.RegNum, start.RegNum); - start.Free(build); - start = tmpstart; - } - if (index->isConstant()) - { - unsigned indexval = static_cast(index)->GetValue().GetInt(); - assert(indexval < arraytype->ElementCount && "Array index out of bounds"); - indexval *= arraytype->ElementSize; - - if (AddressRequested) - { - if (indexval != 0) - { - build->Emit(OP_ADDA_RK, start.RegNum, start.RegNum, build->GetConstantInt(indexval)); - } - } - else - { - build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum, - start.RegNum, build->GetConstantInt(indexval)); - } - } - else - { - ExpEmit indexv(index->Emit(build)); - int shiftbits = 0; - while (1u << shiftbits < arraytype->ElementSize) - { - shiftbits++; - } - assert(1u << shiftbits == arraytype->ElementSize && "Element sizes other than power of 2 are not implemented"); - build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); - if (shiftbits > 0) - { - build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, shiftbits); - } - - if (AddressRequested) - { - build->Emit(OP_ADDA_RR, start.RegNum, start.RegNum, indexv.RegNum); - } - else - { - build->Emit(arraytype->ElementType->GetLoadOp() + 1, // added 1 to use the *_R version that - dest.RegNum, start.RegNum, indexv.RegNum); // takes the offset from a register - } - indexv.Free(build); - } - if (AddressRequested) - { - dest.Free(build); - return start; - } - - start.Free(build); - return dest; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxFunctionCall::FxFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos) -: FxExpression(pos) -{ - Self = self; - MethodName = methodname; - ArgList = args; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxFunctionCall::~FxFunctionCall() -{ - SAFE_DELETE(Self); - SAFE_DELETE(ArgList); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) -{ - for (size_t i = 0; i < countof(FxFlops); ++i) - { - if (MethodName == FxFlops[i].Name) - { - if (Self != NULL) - { - ScriptPosition.Message(MSG_ERROR, "Global functions cannot have a self pointer"); - delete this; - return NULL; - } - FxExpression *x = new FxFlopFunctionCall(i, ArgList, ScriptPosition); - ArgList = NULL; - delete this; - return x->Resolve(ctx); - } - } - - int min, max, special; - if (MethodName == NAME_ACS_NamedExecuteWithResult || MethodName == NAME_CallACS) - { - special = -ACS_ExecuteWithResult; - min = 1; - max = 5; - } - else - { - special = P_FindLineSpecial(MethodName.GetChars(), &min, &max); - } - if (special != 0 && min >= 0) - { - int paramcount = ArgList? ArgList->Size() : 0; - if (paramcount < min) - { - ScriptPosition.Message(MSG_ERROR, "Not enough parameters for '%s' (expected %d, got %d)", - MethodName.GetChars(), min, paramcount); - delete this; - return NULL; - } - else if (paramcount > max) - { - ScriptPosition.Message(MSG_ERROR, "too many parameters for '%s' (expected %d, got %d)", - MethodName.GetChars(), max, paramcount); - delete this; - return NULL; - } - FxExpression *x = new FxActionSpecialCall(Self, special, ArgList, ScriptPosition); - ArgList = NULL; - delete this; - return x->Resolve(ctx); - } - - ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); - delete this; - return NULL; -} - - -//========================================================================== -// -// FxActionSpecialCall -// -// If special is negative, then the first argument will be treated as a -// name for ACS_NamedExecuteWithResult. -// -//========================================================================== - -FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgumentList *args, const FScriptPosition &pos) -: FxExpression(pos) -{ - Self = self; - Special = special; - ArgList = args; - EmitTail = false; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxActionSpecialCall::~FxActionSpecialCall() -{ - SAFE_DELETE(Self); - SAFE_DELETE(ArgList); -} - -//========================================================================== -// -// -// -//========================================================================== - -PPrototype *FxActionSpecialCall::ReturnProto() -{ - EmitTail = true; - return FxExpression::ReturnProto(); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - bool failed = false; - - if (ArgList != NULL) - { - for (unsigned i = 0; i < ArgList->Size(); i++) - { - (*ArgList)[i] = (*ArgList)[i]->Resolve(ctx); - if ((*ArgList)[i] == NULL) failed = true; - if (Special < 0 && i == 0) - { - if ((*ArgList)[i]->ValueType != TypeName) - { - ScriptPosition.Message(MSG_ERROR, "Name expected for parameter %d", i); - failed = true; - } - } - else if ((*ArgList)[i]->ValueType->GetRegType() != REGT_INT) - { - if ((*ArgList)[i]->ValueType->GetRegType() == REGT_FLOAT /* lax */) - { - (*ArgList)[i] = new FxIntCast((*ArgList)[i]); - } - else - { - ScriptPosition.Message(MSG_ERROR, "Integer expected for parameter %d", i); - failed = true; - } - } - } - if (failed) - { - delete this; - return NULL; - } - } - ValueType = TypeSInt32; - return this; -} - - -//========================================================================== -// -// -// -//========================================================================== - -int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) -{ - assert(numparam > 2 && numparam < 8); - assert(param[0].Type == REGT_INT); - assert(param[1].Type == REGT_POINTER); - int v[5] = { 0 }; - - for (int i = 2; i < numparam; ++i) - { - v[i - 2] = param[i].i; - } - ACTION_RETURN_INT(P_ExecuteSpecial(param[0].i, NULL, reinterpret_cast(param[1].a), false, v[0], v[1], v[2], v[3], v[4])); -} - -ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) -{ - assert(Self == NULL); - unsigned i = 0; - - build->Emit(OP_PARAMI, abs(Special)); // pass special number - build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self - if (ArgList != NULL) - { - for (; i < ArgList->Size(); ++i) - { - FxExpression *argex = (*ArgList)[i]; - if (Special < 0 && i == 0) - { - assert(argex->ValueType == TypeName); - assert(argex->isConstant()); - build->EmitParamInt(-static_cast(argex)->GetValue().GetName()); - } - else - { - assert(argex->ValueType->GetRegType() == REGT_INT); - if (argex->isConstant()) - { - build->EmitParamInt(static_cast(argex)->GetValue().GetInt()); - } - else - { - ExpEmit arg(argex->Emit(build)); - build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum); - arg.Free(build); - } - } - } - } - // Call the DecoCallLineSpecial function to perform the desired special. - VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoCallLineSpecial, DecoCallLineSpecial); - - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); - callfunc = ((PSymbolVMFunction *)sym)->Function; - - if (EmitTail) - { - build->Emit(OP_TAIL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2 + i, 0); - ExpEmit call; - call.Final = true; - return call; - } - - ExpEmit dest(build, REGT_INT); - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2 + i, 1); - build->Emit(OP_RESULT, 0, REGT_INT, dest.RegNum); - return dest; -} - -//========================================================================== -// -// FxVMFunctionCall -// -//========================================================================== - -FxVMFunctionCall::FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos) -: FxExpression(pos) -{ - Function = func; - ArgList = args; - EmitTail = false; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxVMFunctionCall::~FxVMFunctionCall() -{ - SAFE_DELETE(ArgList); -} - -//========================================================================== -// -// -// -//========================================================================== - -PPrototype *FxVMFunctionCall::ReturnProto() -{ - EmitTail = true; - return Function->Variants[0].Implementation->Proto; -} - -//========================================================================== -// -// -// -//========================================================================== - -VMFunction *FxVMFunctionCall::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 (EmitTail && (ArgList ? ArgList->Size() : 0) == 0 && (Function->Flags & VARF_Action)) - { - return Function->Variants[0].Implementation; - } - - return nullptr; -} - -//========================================================================== -// -// FxVMFunctionCall :: Resolve -// -//========================================================================== - -FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - bool failed = false; - - if (ArgList != NULL) - { - for (unsigned i = 0; i < ArgList->Size(); i++) - { - (*ArgList)[i] = (*ArgList)[i]->Resolve(ctx); - if ((*ArgList)[i] == NULL) failed = true; - } - } - if (failed) - { - delete this; - return NULL; - } - TArray &rets = Function->Variants[0].Implementation->Proto->ReturnTypes; - if (rets.Size() > 0) - { - ValueType = rets[0]; - } - else - { - ValueType = TypeVoid; - } - - return this; -} - -//========================================================================== -// -// Assumption: This call is being generated inside a function whose a0 -// register is a self pointer. For action functions, a1 maps to stateowner -// and a2 maps to callingstate. (self, stateowner, callingstate) -// -//========================================================================== - -ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) -{ - assert((build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= NAP) || - (!build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 1)); - int count = (ArgList ? ArgList->Size() : 0); - - if (count == 1) - { - ExpEmit reg; - if (CheckEmitCast(build, EmitTail, reg)) - { - return reg; - } - } - // Emit code to pass implied parameters - if (Function->Flags & VARF_Method) - { - build->Emit(OP_PARAM, 0, REGT_POINTER, 0); - count += 1; - } - if (Function->Flags & VARF_Action) - { - static_assert(NAP == 3, "This code needs to be updated if NAP changes"); - if (build->IsActionFunc) - { - build->Emit(OP_PARAM, 0, REGT_POINTER, 1); - build->Emit(OP_PARAM, 0, REGT_POINTER, 2); - } - else - { - int null = build->GetConstantAddress(nullptr, ATAG_GENERIC); - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, null); - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, null); - } - count += 2; - } - // Emit code to pass explicit parameters - if (ArgList != NULL) - { - for (unsigned i = 0; i < ArgList->Size(); ++i) - { - EmitParameter(build, (*ArgList)[i], ScriptPosition); - } - } - // Get a constant register for this function - VMFunction *vmfunc = Function->Variants[0].Implementation; - int funcaddr = build->GetConstantAddress(vmfunc, ATAG_OBJECT); - // Emit the call - if (EmitTail) - { // Tail call - build->Emit(OP_TAIL_K, funcaddr, count, 0); - ExpEmit call; - call.Final = true; - return call; - } - else if (vmfunc->Proto->ReturnTypes.Size() > 0) - { // Call, expecting one result - 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; - } - else - { // Call, expecting no results - build->Emit(OP_CALL_K, funcaddr, count, 0); - return ExpEmit(); - } -} - -//========================================================================== -// -// If calling one of the casting kludge functions, don't bother calling the -// function; just use the parameter directly. Returns true if this was a -// kludge function, false otherwise. -// -//========================================================================== - -bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, ExpEmit ®) -{ - FName funcname = Function->SymbolName; - if (funcname == NAME___decorate_internal_int__ || - funcname == NAME___decorate_internal_bool__ || - funcname == NAME___decorate_internal_state__ || - funcname == NAME___decorate_internal_float__) - { - FxExpression *arg = (*ArgList)[0]; - if (returnit) - { - if (arg->isConstant() && - (funcname == NAME___decorate_internal_int__ || - funcname == NAME___decorate_internal_bool__)) - { // Use immediate version for integers in range - build->EmitRetInt(0, true, static_cast(arg)->GetValue().Int); - } - else - { - ExpEmit where = arg->Emit(build); - build->Emit(OP_RET, RET_FINAL, where.RegType | (where.Konst ? REGT_KONST : 0), where.RegNum); - where.Free(build); - } - reg = ExpEmit(); - reg.Final = true; - } - else - { - reg = arg->Emit(build); - } - return true; - } - return false; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxFlopFunctionCall::FxFlopFunctionCall(size_t index, FArgumentList *args, const FScriptPosition &pos) -: FxExpression(pos) -{ - assert(index < countof(FxFlops) && "FLOP index out of range"); - Index = (int)index; - ArgList = args; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxFlopFunctionCall::~FxFlopFunctionCall() -{ - SAFE_DELETE(ArgList); -} - -FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - - if (ArgList == NULL || ArgList->Size() != 1) - { - ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", FName(FxFlops[Index].Name).GetChars()); - delete this; - return NULL; - } - - (*ArgList)[0] = (*ArgList)[0]->Resolve(ctx); - if ((*ArgList)[0] == NULL) - { - delete this; - return NULL; - } - - if (!(*ArgList)[0]->IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); - delete this; - return NULL; - } - if ((*ArgList)[0]->isConstant()) - { - double v = static_cast((*ArgList)[0])->GetValue().GetFloat(); - v = FxFlops[Index].Evaluate(v); - FxExpression *x = new FxConstant(v, ScriptPosition); - delete this; - return x; - } - if ((*ArgList)[0]->ValueType->GetRegType() == REGT_INT) - { - (*ArgList)[0] = new FxFloatCast((*ArgList)[0]); - } - ValueType = TypeFloat64; - return this; -} - -//========================================================================== -// -// -//========================================================================== - -ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) -{ - ExpEmit v = (*ArgList)[0]->Emit(build); - assert(!v.Konst && v.RegType == REGT_FLOAT); - - build->Emit(OP_FLOP, v.RegNum, v.RegNum, FxFlops[Index].Flop); - return v; -} - -//========================================================================== -// -// FxSequence :: Resolve -// -//========================================================================== - -FxExpression *FxSequence::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - for (unsigned i = 0; i < Expressions.Size(); ++i) - { - if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx))) - { - delete this; - return NULL; - } - } - return this; -} - -//========================================================================== -// -// FxSequence :: Emit -// -//========================================================================== - -ExpEmit FxSequence::Emit(VMFunctionBuilder *build) -{ - for (unsigned i = 0; i < Expressions.Size(); ++i) - { - ExpEmit v = Expressions[i]->Emit(build); - // Throw away any result. We don't care about it. - v.Free(build); - } - return ExpEmit(); -} - -//========================================================================== -// -// FxSequence :: GetDirectFunction -// -//========================================================================== - -VMFunction *FxSequence::GetDirectFunction() -{ - if (Expressions.Size() == 1) - { - return Expressions[0]->GetDirectFunction(); - } - return NULL; -} - -//========================================================================== -// -// FxIfStatement -// -//========================================================================== - -FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part, - FxExpression *false_part, const FScriptPosition &pos) -: FxExpression(pos) -{ - Condition = cond; - WhenTrue = true_part; - WhenFalse = false_part; - assert(cond != NULL); -} - -FxIfStatement::~FxIfStatement() -{ - SAFE_DELETE(Condition); - SAFE_DELETE(WhenTrue); - SAFE_DELETE(WhenFalse); -} - -FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - - if (WhenTrue == nullptr && WhenFalse == nullptr) - { // We don't do anything either way, so disappear - delete this; - return nullptr; - } - - SAFE_RESOLVE(Condition, ctx); - - if (Condition->ValueType != TypeBool) - { - Condition = new FxBoolCast(Condition); - SAFE_RESOLVE(Condition, ctx); - } - - if (WhenTrue != nullptr) - { - WhenTrue = WhenTrue->Resolve(ctx); - ABORT(WhenTrue); - } - if (WhenFalse != nullptr) - { - WhenFalse = WhenFalse->Resolve(ctx); - ABORT(WhenFalse); - } - - ValueType = TypeVoid; - - if (Condition->isConstant()) - { - ExpVal condval = static_cast(Condition)->GetValue(); - bool result = condval.GetBool(); - - FxExpression *e = result ? WhenTrue : WhenFalse; - delete (result ? WhenFalse : WhenTrue); - WhenTrue = WhenFalse = NULL; - if (e == NULL) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts. - delete this; - return e; - } - - return this; -} - -ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) -{ - ExpEmit v; - size_t jumpspot; - FxExpression *path1, *path2; - int condcheck; - - // This is pretty much copied from FxConditional, except we don't - // keep any results. - ExpEmit cond = Condition->Emit(build); - assert(cond.RegType == REGT_INT && !cond.Konst); - - if (WhenTrue != NULL) - { - path1 = WhenTrue; - path2 = WhenFalse; - condcheck = 1; - } - else - { - // When there is only a false path, reverse the condition so we can - // treat it as a true path. - assert(WhenFalse != NULL); - path1 = WhenFalse; - path2 = NULL; - condcheck = 0; - } - - // Test condition. - build->Emit(OP_EQ_K, condcheck, cond.RegNum, build->GetConstantInt(0)); - jumpspot = build->Emit(OP_JMP, 0); - cond.Free(build); - - // Evaluate first path - 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); - v.Free(build); - jumpspot = path1jump; - } - build->BackpatchToHere(jumpspot); - return ExpEmit(); -} - -//========================================================================== -// -// FxWhileLoop -// -//========================================================================== - -FxWhileLoop::FxWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) -: FxExpression(pos), Condition(condition), Code(code) -{ - ValueType = TypeVoid; -} - -FxWhileLoop::~FxWhileLoop() -{ - SAFE_DELETE(Condition); - SAFE_DELETE(Code); -} - -FxExpression *FxWhileLoop::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Condition, ctx); - SAFE_RESOLVE_OPT(Code, ctx); - - ctx.HandleJumps(TK_Break, this); - ctx.HandleJumps(TK_Continue, this); - - if (Condition->ValueType != TypeBool) - { - Condition = new FxBoolCast(Condition); - SAFE_RESOLVE(Condition, ctx); - } - - if (Condition->isConstant()) - { - if (static_cast(Condition)->GetValue().GetBool() == false) - { // Nothing happens - FxExpression *nop = new FxNop(ScriptPosition); - delete this; - return nop; - } - else if (Code == nullptr) - { // "while (true) { }" - // Someone could be using this for testing. - ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); - } - } - - return this; -} - -ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) -{ - assert(Condition->ValueType == TypeBool); - - size_t loopstart, loopend; - size_t jumpspot; - - // Evaluate the condition and execute/break out of the loop. - loopstart = build->GetAddress(); - if (!Condition->isConstant()) - { - ExpEmit cond = Condition->Emit(build); - build->Emit(OP_TEST, cond.RegNum, 0); - jumpspot = build->Emit(OP_JMP, 0); - cond.Free(build); - } - else assert(static_cast(Condition)->GetValue().GetBool() == true); - - // Execute the loop's content. - if (Code != nullptr) - { - ExpEmit code = Code->Emit(build); - code.Free(build); - } - - // Loop back. - build->Backpatch(build->Emit(OP_JMP, 0), loopstart); - loopend = build->GetAddress(); - - if (!Condition->isConstant()) - { - build->Backpatch(jumpspot, loopend); - } - - // Give a proper address to any break/continue statement within this loop. - for (unsigned int i = 0; i < JumpAddresses.Size(); i++) - { - if (JumpAddresses[i]->Token == TK_Break) - { - build->Backpatch(JumpAddresses[i]->Address, loopend); - } - else - { // Continue statement. - build->Backpatch(JumpAddresses[i]->Address, loopstart); - } - } - - return ExpEmit(); -} - -//========================================================================== -// -// FxDoWhileLoop -// -//========================================================================== - -FxDoWhileLoop::FxDoWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) -: FxExpression(pos), Condition(condition), Code(code) -{ - ValueType = TypeVoid; -} - -FxDoWhileLoop::~FxDoWhileLoop() -{ - SAFE_DELETE(Condition); - SAFE_DELETE(Code); -} - -FxExpression *FxDoWhileLoop::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Condition, ctx); - SAFE_RESOLVE_OPT(Code, ctx); - - ctx.HandleJumps(TK_Break, this); - ctx.HandleJumps(TK_Continue, this); - - if (Condition->ValueType != TypeBool) - { - Condition = new FxBoolCast(Condition); - SAFE_RESOLVE(Condition, ctx); - } - - if (Condition->isConstant()) - { - if (static_cast(Condition)->GetValue().GetBool() == false) - { // The code executes once, if any. - if (JumpAddresses.Size() == 0) - { // We would still have to handle the jumps however. - FxExpression *e = Code; - if (e == nullptr) e = new FxNop(ScriptPosition); - Code = nullptr; - delete this; - return e; - } - } - else if (Code == nullptr) - { // "do { } while (true);" - // Someone could be using this for testing. - ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); - } - } - - return this; -} - -ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) -{ - assert(Condition->ValueType == TypeBool); - - size_t loopstart, loopend; - size_t codestart; - - // Execute the loop's content. - codestart = build->GetAddress(); - if (Code != nullptr) - { - ExpEmit code = Code->Emit(build); - code.Free(build); - } - - // Evaluate the condition and execute/break out of the loop. - loopstart = build->GetAddress(); - if (!Condition->isConstant()) - { - ExpEmit cond = Condition->Emit(build); - build->Emit(OP_TEST, cond.RegNum, 1); - cond.Free(build); - build->Backpatch(build->Emit(OP_JMP, 0), codestart); - } - else if (static_cast(Condition)->GetValue().GetBool() == true) - { // Always looping - build->Backpatch(build->Emit(OP_JMP, 0), codestart); - } - loopend = build->GetAddress(); - - // Give a proper address to any break/continue statement within this loop. - for (unsigned int i = 0; i < JumpAddresses.Size(); i++) - { - if (JumpAddresses[i]->Token == TK_Break) - { - build->Backpatch(JumpAddresses[i]->Address, loopend); - } - else - { // Continue statement. - build->Backpatch(JumpAddresses[i]->Address, loopstart); - } - } - - return ExpEmit(); -} - -//========================================================================== -// -// FxForLoop -// -//========================================================================== - -FxForLoop::FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos) -: FxExpression(pos), Init(init), Condition(condition), Iteration(iteration), Code(code) -{ - ValueType = TypeVoid; -} - -FxForLoop::~FxForLoop() -{ - SAFE_DELETE(Init); - SAFE_DELETE(Condition); - SAFE_DELETE(Iteration); - SAFE_DELETE(Code); -} - -FxExpression *FxForLoop::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE_OPT(Init, ctx); - SAFE_RESOLVE_OPT(Condition, ctx); - SAFE_RESOLVE_OPT(Iteration, ctx); - SAFE_RESOLVE_OPT(Code, ctx); - - ctx.HandleJumps(TK_Break, this); - ctx.HandleJumps(TK_Continue, this); - - if (Condition != nullptr) - { - if (Condition->ValueType != TypeBool) - { - Condition = new FxBoolCast(Condition); - SAFE_RESOLVE(Condition, ctx); - } - - if (Condition->isConstant()) - { - if (static_cast(Condition)->GetValue().GetBool() == false) - { // Nothing happens - FxExpression *nop = new FxNop(ScriptPosition); - delete this; - return nop; - } - else - { // "for (..; true; ..)" - delete Condition; - Condition = nullptr; - } - } - } - if (Condition == nullptr && Code == nullptr) - { // "for (..; ; ..) { }" - // Someone could be using this for testing. - ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); - } - - return this; -} - -ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) -{ - assert((Condition && Condition->ValueType == TypeBool && !Condition->isConstant()) || Condition == nullptr); - - size_t loopstart, loopend; - size_t codestart; - size_t jumpspot; - - // Init statement. - if (Init != nullptr) - { - ExpEmit init = Init->Emit(build); - init.Free(build); - } - - // Evaluate the condition and execute/break out of the loop. - codestart = build->GetAddress(); - if (Condition != nullptr) - { - ExpEmit cond = Condition->Emit(build); - build->Emit(OP_TEST, cond.RegNum, 0); - cond.Free(build); - jumpspot = build->Emit(OP_JMP, 0); - } - - // Execute the loop's content. - if (Code != nullptr) - { - ExpEmit code = Code->Emit(build); - code.Free(build); - } - - // Iteration statement. - loopstart = build->GetAddress(); - if (Iteration != nullptr) - { - ExpEmit iter = Iteration->Emit(build); - iter.Free(build); - } - build->Backpatch(build->Emit(OP_JMP, 0), codestart); - - // End of loop. - loopend = build->GetAddress(); - if (Condition != nullptr) - { - build->Backpatch(jumpspot, loopend); - } - - // Give a proper address to any break/continue statement within this loop. - for (unsigned int i = 0; i < JumpAddresses.Size(); i++) - { - if (JumpAddresses[i]->Token == TK_Break) - { - build->Backpatch(JumpAddresses[i]->Address, loopend); - } - else - { // Continue statement. - build->Backpatch(JumpAddresses[i]->Address, loopstart); - } - } - - return ExpEmit(); -} - -//========================================================================== -// -// FxJumpStatement -// -//========================================================================== - -FxJumpStatement::FxJumpStatement(int token, const FScriptPosition &pos) -: FxExpression(pos), Token(token), AddressResolver(nullptr) -{ - ValueType = TypeVoid; -} - -FxExpression *FxJumpStatement::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - - ctx.Jumps.Push(this); - - return this; -} - -ExpEmit FxJumpStatement::Emit(VMFunctionBuilder *build) -{ - if (AddressResolver == nullptr) - { - ScriptPosition.Message(MSG_ERROR, "Jump statement %s has nowhere to go!", FScanner::TokenName(Token).GetChars()); - } - - Address = build->Emit(OP_JMP, 0); - - return ExpEmit(); -} - -//========================================================================== -// -//========================================================================== - -FxReturnStatement::FxReturnStatement(FxExpression *value, const FScriptPosition &pos) -: FxExpression(pos), Value(value) -{ - ValueType = TypeVoid; -} - -FxReturnStatement::~FxReturnStatement() -{ - SAFE_DELETE(Value); -} - -FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE_OPT(Value, ctx); - - PPrototype *retproto; - if (Value == nullptr) - { - TArray none(0); - retproto = NewPrototype(none, none); - } - else - { - retproto = Value->ReturnProto(); - } - - ctx.CheckReturn(retproto, ScriptPosition); - - return this; -} - -ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build) -{ - ExpEmit out(0, REGT_NIL); - - // If we return nothing, use a regular RET opcode. - // Otherwise just return the value we're given. - if (Value == nullptr) - { - build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0); - } - else - { - out = Value->Emit(build); - - // Check if it is a function call that simplified itself - // into a tail call in which case we don't emit anything. - if (!out.Final) - { - if (Value->ValueType == TypeVoid) - { // Nothing is returned. - build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0); - } - else - { - build->Emit(OP_RET, RET_FINAL, out.RegType | (out.Konst ? REGT_KONST : 0), out.RegNum); - } - } - } - - out.Final = true; - return out; -} - -VMFunction *FxReturnStatement::GetDirectFunction() -{ - if (Value != nullptr) - { - return Value->GetDirectFunction(); - } - return nullptr; -} - -//========================================================================== -// -//========================================================================== - -FxClassTypeCast::FxClassTypeCast(PClass *dtype, FxExpression *x) -: FxExpression(x->ScriptPosition) -{ - desttype = dtype; - basex=x; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxClassTypeCast::~FxClassTypeCast() -{ - SAFE_DELETE(basex); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(basex, ctx); - - if (basex->ValueType != TypeName) - { - ScriptPosition.Message(MSG_ERROR, "Cannot convert to class type"); - delete this; - return NULL; - } - - if (basex->isConstant()) - { - FName clsname = static_cast(basex)->GetValue().GetName(); - PClass *cls = NULL; - - if (clsname != NAME_None) - { - cls = PClass::FindClass(clsname); - if (cls == NULL) - { - /* lax */ - // Since this happens in released WADs it must pass without a terminal error... :( - ScriptPosition.Message(MSG_OPTERROR, - "Unknown class name '%s'", - clsname.GetChars(), desttype->TypeName.GetChars()); - } - else - { - if (!cls->IsDescendantOf(desttype)) - { - ScriptPosition.Message(MSG_ERROR, "class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); - delete this; - return NULL; - } - ScriptPosition.Message(MSG_DEBUG, "resolving '%s' as class name", clsname.GetChars()); - } - } - FxExpression *x = new FxConstant(cls, ScriptPosition); - delete this; - return x; - } - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -int DecoNameToClass(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) -{ - assert(numparam == 2); - assert(numret == 1); - assert(param[0].Type == REGT_INT); - assert(param[1].Type == REGT_POINTER); - assert(ret->RegType == REGT_POINTER); - - FName clsname = ENamedName(param[0].i); - const PClass *cls = PClass::FindClass(clsname); - const PClass *desttype = reinterpret_cast(param[0].a); - - if (!cls->IsDescendantOf(desttype)) - { - Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); - cls = NULL; - } - ret->SetPointer(const_cast(cls), ATAG_OBJECT); - return 1; -} - -ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) -{ - if (basex->ValueType != TypeName) - { - return ExpEmit(build->GetConstantAddress(NULL, ATAG_OBJECT), REGT_POINTER, true); - } - ExpEmit clsname = basex->Emit(build); - assert(!clsname.Konst); - ExpEmit dest(build, REGT_POINTER); - build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum); - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast(desttype), ATAG_OBJECT)); - - // Call the DecoNameToClass function to convert from 'name' to class. - VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoNameToClass, DecoNameToClass); - - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); - callfunc = ((PSymbolVMFunction *)sym)->Function; - - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); - build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); - clsname.Free(build); - return dest; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - ABORT(ctx.Class); - - if (ctx.Class->NumOwnedStates == 0) - { - // This can't really happen - assert(false); - } - if (ctx.Class->NumOwnedStates <= index) - { - ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d", - ctx.Class->TypeName.GetChars(), index); - delete this; - return NULL; - } - FxExpression *x = new FxConstant(ctx.Class->OwnedStates + index, ScriptPosition); - delete this; - return x; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxRuntimeStateIndex::FxRuntimeStateIndex(FxExpression *index) -: FxExpression(index->ScriptPosition), Index(index) -{ - EmitTail = false; - ValueType = TypeState; -} - -FxRuntimeStateIndex::~FxRuntimeStateIndex() -{ - SAFE_DELETE(Index); -} - -PPrototype *FxRuntimeStateIndex::ReturnProto() -{ - EmitTail = true; - return FxExpression::ReturnProto(); -} - -FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(Index, ctx); - - if (!Index->IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return nullptr; - } - else if (Index->ValueType->GetRegType() != REGT_INT) - { // Float. - Index = new FxIntCast(Index); - SAFE_RESOLVE(Index, ctx); - } - - return this; -} - -static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int index) -{ - PClassActor *cls = stateowner->GetClass(); - - while (cls != RUNTIME_CLASS(AActor)) - { - // both calling and target state need to belong to the same class. - if (cls->OwnsState(stateinfo->mCallingState)) - { - return cls->OwnsState(stateinfo->mCallingState + index); - } - - // We can safely assume the ParentClass is of type PClassActor - // since we stop when we see the Actor base class. - cls = static_cast(cls->ParentClass); - } - return false; -} - -static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) -{ - PARAM_PROLOGUE; - PARAM_OBJECT(stateowner, AActor); - PARAM_POINTER(stateinfo, FStateParamInfo); - PARAM_INT(index); - - if (index == 0 || !VerifyJumpTarget(stateowner, stateinfo, index)) - { - // Null is returned if the location was invalid which means that no jump will be performed - // if used as return value - // 0 always meant the same thing so we handle it here for compatibility - ACTION_RETURN_STATE(nullptr); - } - else - { - ACTION_RETURN_STATE(stateinfo->mCallingState + index); - } -} - -ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build) -{ - assert(build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 3 && - "FxRuntimeStateIndex is only valid inside action functions"); - - ExpEmit out(build, REGT_POINTER); - - build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // stateowner - build->Emit(OP_PARAM, 0, REGT_POINTER, 2); // stateinfo - ExpEmit id = Index->Emit(build); - build->Emit(OP_PARAM, 0, REGT_INT | (id.Konst ? REGT_KONST : 0), id.RegNum); // index - - VMFunction *callfunc; - PSymbol *sym; - - sym = FindDecorateBuiltinFunction(NAME_DecoHandleRuntimeState, DecoHandleRuntimeState); - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != nullptr); - callfunc = ((PSymbolVMFunction *)sym)->Function; - - if (EmitTail) - { - build->Emit(OP_TAIL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); - out.Final = true; - } - else - { - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); - build->Emit(OP_RESULT, 0, REGT_POINTER, out.RegNum); - } - - return out; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPosition &pos) - :FxExpression(pos) -{ - FName scopename; - FString statestring = _statestring; - int scopeindex = statestring.IndexOf("::"); - - if (scopeindex >= 0) - { - scopename = FName(statestring, scopeindex, false); - statestring = statestring.Right(statestring.Len() - scopeindex - 2); - } - else - { - scopename = NULL; - } - names = MakeStateNameList(statestring); - names.Insert(0, scopename); - scope = NULL; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - ABORT(ctx.Class); - - if (names[0] == NAME_None) - { - scope = NULL; - } - else if (names[0] == NAME_Super) - { - scope = dyn_cast(ctx.Class->ParentClass); - } - else - { - scope = PClass::FindActor(names[0]); - if (scope == NULL) - { - ScriptPosition.Message(MSG_ERROR, "Unknown class '%s' in state label", names[0].GetChars()); - delete this; - return NULL; - } - else if (!scope->IsDescendantOf(ctx.Class)) - { - ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(),ctx.Class->TypeName.GetChars()); - delete this; - return NULL; - } - } - if (scope != NULL) - { - FState *destination = NULL; - // If the label is class specific we can resolve it right here - if (names[1] != NAME_None) - { - destination = scope->FindState(names.Size()-1, &names[1], false); - if (destination == NULL) - { - ScriptPosition.Message(MSG_OPTERROR, "Unknown state jump destination"); - /* lax */ - return this; - } - } - FxExpression *x = new FxConstant(destination, ScriptPosition); - delete this; - return x; - } - names.Delete(0); - names.ShrinkToFit(); - ValueType = TypeState; - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - -static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, FName *names, int numnames) -{ - PARAM_OBJECT_AT(0, self, AActor); - FState *state = self->GetClass()->FindState(numparam - 1, names); - if (state == NULL) - { - const char *dot = ""; - Printf("Jump target '"); - for (int i = 0; i < numparam - 1; i++) - { - Printf("%s%s", dot, names[i].GetChars()); - dot = "."; - } - Printf("' not found in %s\n", self->GetClass()->TypeName.GetChars()); - } - ret->SetPointer(state, ATAG_STATE); - return 1; -} - -// Find a state with any number of dots in its name. -int DecoFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) -{ - assert(numparam > 1); - assert(numret == 1); - assert(ret->RegType == REGT_POINTER); - - FName *names = (FName *)alloca((numparam - 1) * sizeof(FName)); - for (int i = 1; i < numparam; ++i) - { - PARAM_NAME_AT(i, zaname); - names[i - 1] = zaname; - } - return DoFindState(stack, param, numparam, ret, names, numparam - 1); -} - -// Find a state without any dots in its name. -int DecoFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) -{ - assert(numparam == 2); - assert(numret == 1); - assert(ret->RegType == REGT_POINTER); - - PARAM_NAME_AT(1, zaname); - return DoFindState(stack, param, numparam, ret, &zaname, 1); -} - -ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) -{ - ExpEmit dest(build, REGT_POINTER); - if (build->IsActionFunc) - { - build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // pass stateowner - } - else - { - build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self - } - for (unsigned i = 0; i < names.Size(); ++i) - { - build->EmitParamInt(names[i]); - } - - // For one name, use the DecoFindSingleNameState function. For more than - // one name, use the DecoFindMultiNameState function. - VMFunction *callfunc; - PSymbol *sym; - - if (names.Size() == 1) - { - sym = FindDecorateBuiltinFunction(NAME_DecoFindSingleNameState, DecoFindSingleNameState); - } - else - { - sym = FindDecorateBuiltinFunction(NAME_DecoFindMultiNameState, DecoFindMultiNameState); - } - - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); - callfunc = ((PSymbolVMFunction *)sym)->Function; - - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), names.Size() + 1, 1); - build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); - return dest; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxDamageValue::FxDamageValue(FxExpression *v) -: FxExpression(v->ScriptPosition) -{ - val = v; - ValueType = TypeVoid; - MyFunction = NULL; -} - -FxDamageValue::~FxDamageValue() -{ - SAFE_DELETE(val); - -} - -FxExpression *FxDamageValue::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(val, ctx) - - if (!val->IsNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } - return this; -} - -// This is a highly-specialized "expression" type that emits a complete function. -ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build) -{ - if (val->isConstant()) - { - build->EmitRetInt(0, false, static_cast(val)->GetValue().Int); - } - else - { - ExpEmit emitval = val->Emit(build); - assert(emitval.RegType == REGT_INT); - build->Emit(OP_RET, 0, REGT_INT | (emitval.Konst ? REGT_KONST : 0), emitval.RegNum); - } - build->Emit(OP_RETI, 1 | RET_FINAL, true); - - return ExpEmit(); -} diff --git a/src/v_video.cpp b/src/v_video.cpp index 37cfdd480..b086e5e6b 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -69,8 +69,8 @@ int active_con_scale(); FRenderer *Renderer; -IMPLEMENT_ABSTRACT_CLASS (DCanvas) -IMPLEMENT_ABSTRACT_CLASS (DFrameBuffer) +IMPLEMENT_CLASS(DCanvas, true, false, false, false) +IMPLEMENT_CLASS(DFrameBuffer, true, false, false, false) #if defined(_DEBUG) && defined(_M_IX86) #define DBGBREAK { __asm int 3 } @@ -106,11 +106,11 @@ public: float Gamma; }; -IMPLEMENT_ABSTRACT_CLASS (DDummyFrameBuffer) +IMPLEMENT_CLASS(DDummyFrameBuffer, true, false, false, false) // SimpleCanvas is not really abstract, but this macro does not // try to generate a CreateNew() function. -IMPLEMENT_ABSTRACT_CLASS (DSimpleCanvas) +IMPLEMENT_CLASS(DSimpleCanvas, true, false, false, false) class FPaletteTester : public FTexture { diff --git a/src/virtual.h b/src/virtual.h new file mode 100644 index 000000000..d3a2bfa3a --- /dev/null +++ b/src/virtual.h @@ -0,0 +1,134 @@ + + + +// Templates really are powerful +#define VMEXPORTED_NATIVES_START \ + template class ExportedNatives : public ExportedNatives {}; \ + template<> class ExportedNatives { \ + protected: ExportedNatives() {} \ + public: \ + static ExportedNatives *Get() { static ExportedNatives *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives; return Instance; } \ + ExportedNatives(const ExportedNatives&) = delete; \ + ExportedNatives(ExportedNatives&&) = delete; + +#define VMEXPORTED_NATIVES_FUNC(func) \ + template ret func(void *ptr, args ... arglist) { return ret(); } + +#define VMEXPORTED_NATIVES_END }; + +#define VMEXPORT_NATIVES_START(cls, parent) \ + template<> class ExportedNatives : public ExportedNatives { \ + protected: ExportedNatives() {} \ + public: \ + static ExportedNatives *Get() { static ExportedNatives *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives; return Instance; } \ + ExportedNatives(const ExportedNatives&) = delete; \ + ExportedNatives(ExportedNatives&&) = delete; + +#define VMEXPORT_NATIVES_FUNC(func) \ + template ret func(void *ptr, args ... arglist) { return static_cast(ptr)->object::func(arglist...); } + +#define VMEXPORT_NATIVES_END(cls) }; + + +//Initial list +VMEXPORTED_NATIVES_START + VMEXPORTED_NATIVES_FUNC(Destroy) + VMEXPORTED_NATIVES_FUNC(Tick) + VMEXPORTED_NATIVES_FUNC(PostBeginPlay) +VMEXPORTED_NATIVES_END + +template +class DVMObject : public T +{ +public: + static char *FormatClassName() + { + static char *name = nullptr; + if (name == nullptr) + { + name = new char[64]; + mysnprintf(name, 64, "DVMObject<%s>", Super::RegistrationInfo.Name); + atterm([]{ delete[] DVMObject::RegistrationInfo.Name; }); + } + return name; + } + + virtual PClass *StaticType() const + { + return RegistrationInfo.MyClass; + } + static ClassReg RegistrationInfo; + static ClassReg * const RegistrationInfoPtr; + typedef T Super; + +private: + typedef DVMObject ThisClass; + static void InPlaceConstructor(void *mem) + { + new((EInPlace *)mem) DVMObject; + } + +public: + void Destroy() + { + if (this->ObjectFlags & OF_SuperCall) + { + this->ObjectFlags &= OF_SuperCall; + ExportedNatives::Get()->template Destroy(this); + } + else + { + static int VIndex = -1; + if (VIndex < 0) + { + // Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override. + auto sym = dyn_cast(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false)); + assert(sym != nullptr); + VIndex = sym->Variants[0].Implementation->VirtualIndex; + assert(VIndex >= 0); + } + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(this->GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); + } + } + void Tick() + { + ExportedNatives::Get()->template Tick(this); + } + + void PostBeginPlay() + { + ExportedNatives::Get()->template PostBeginPlay(this); + } +}; + +template +ClassReg DVMObject::RegistrationInfo = +{ + nullptr, + DVMObject::FormatClassName(), + &DVMObject::Super::RegistrationInfo, + nullptr, + nullptr, + DVMObject::InPlaceConstructor, + nullptr, + sizeof(DVMObject), + DVMObject::MetaClassNum +}; +template _DECLARE_TI(DVMObject) + +VMEXPORT_NATIVES_START(DObject, void) + VMEXPORT_NATIVES_FUNC(Destroy) +VMEXPORT_NATIVES_END(DObject) + +VMEXPORT_NATIVES_START(DThinker, DObject) + VMEXPORT_NATIVES_FUNC(Tick) + VMEXPORT_NATIVES_FUNC(PostBeginPlay) + VMEXPORT_NATIVES_END(DThinker) + +/* +VMEXPORT_NATIVES_START(AActor, DThinker) +VMEXPORT_NATIVES_END(AActor) +*/ \ No newline at end of file diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 108edff3b..12ca10e32 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -51,6 +51,7 @@ #include "r_data/r_translate.h" #include "templates.h" #include "gstrings.h" +#include "cmdlib.h" // States for the intermission typedef enum diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 10ab11c72..6d162bbec 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -91,7 +91,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_CLASS(D3DFB) +IMPLEMENT_CLASS(D3DFB, false, false, false, false) struct D3DFB::PackedTexture { diff --git a/src/win32/fb_ddraw.cpp b/src/win32/fb_ddraw.cpp index 7cc603786..bd5a4db23 100644 --- a/src/win32/fb_ddraw.cpp +++ b/src/win32/fb_ddraw.cpp @@ -61,7 +61,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_CLASS(DDrawFB) +IMPLEMENT_CLASS(DDrawFB, false, false, false, false) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/win32/win32video.cpp b/src/win32/win32video.cpp index 18c66f5d3..df96f7f41 100644 --- a/src/win32/win32video.cpp +++ b/src/win32/win32video.cpp @@ -80,7 +80,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS(BaseWinFB) +IMPLEMENT_CLASS(BaseWinFB, true, false, false, false) typedef IDirect3D9 *(WINAPI *DIRECT3DCREATE9FUNC)(UINT SDKVersion); typedef HRESULT (WINAPI *DIRECTDRAWCREATEFUNC)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter); diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp deleted file mode 100644 index b7bfe81ba..000000000 --- a/src/zscript/zcc_compile.cpp +++ /dev/null @@ -1,642 +0,0 @@ -#include "dobject.h" -#include "sc_man.h" -#include "c_console.h" -#include "c_dispatch.h" -#include "w_wad.h" -#include "cmdlib.h" -#include "m_alloc.h" -#include "zcc_parser.h" -#include "zcc_compile.h" -#include "v_text.h" -#include "gdtoa.h" - -#define DEFINING_CONST ((PSymbolConst *)(void *)1) - -//========================================================================== -// -// ZCCCompiler Constructor -// -//========================================================================== - -ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols) -: Outer(_outer), Symbols(&_symbols), AST(ast), ErrorCount(0), WarnCount(0) -{ - // Group top-level nodes by type - if (ast.TopNode != NULL) - { - ZCC_TreeNode *node = ast.TopNode; - do - { - switch (node->NodeType) - { - case AST_Class: - case AST_Struct: - case AST_ConstantDef: - if (AddNamedNode(static_cast(node))) - { - switch (node->NodeType) - { - case AST_Class: Classes.Push(static_cast(node)); break; - case AST_Struct: Structs.Push(static_cast(node)); break; - case AST_ConstantDef: Constants.Push(static_cast(node)); break; - default: assert(0 && "Default case is just here to make GCC happy. It should never be reached"); - } - } - break; - - case AST_Enum: break; - case AST_EnumTerminator:break; - - default: - assert(0 && "Unhandled AST node type"); - break; - } - node = node->SiblingNext; - } - while (node != ast.TopNode); - } -} - -//========================================================================== -// -// ZCCCompiler :: AddNamedNode -// -// Keeps track of definition nodes by their names. Ensures that all names -// in this scope are unique. -// -//========================================================================== - -bool ZCCCompiler::AddNamedNode(ZCC_NamedNode *node) -{ - FName name = node->NodeName; - PSymbol *check = Symbols->FindSymbol(name, false); - if (check != NULL) - { - assert(check->IsA(RUNTIME_CLASS(PSymbolTreeNode))); - Error(node, "Attempt to redefine '%s'", name.GetChars()); - Error(static_cast(check)->Node, " Original definition is here"); - return false; - } - else - { - Symbols->AddSymbol(new PSymbolTreeNode(name, node)); - return true; - } -} - -//========================================================================== -// -// ZCCCompiler :: Warn -// -// Prints a warning message, and increments WarnCount. -// -//========================================================================== - -void ZCCCompiler::Warn(ZCC_TreeNode *node, const char *msg, ...) -{ - va_list argptr; - va_start(argptr, msg); - MessageV(node, TEXTCOLOR_ORANGE, msg, argptr); - va_end(argptr); - - WarnCount++; -} - -//========================================================================== -// -// ZCCCompiler :: Error -// -// Prints an error message, and increments ErrorCount. -// -//========================================================================== - -void ZCCCompiler::Error(ZCC_TreeNode *node, const char *msg, ...) -{ - va_list argptr; - va_start(argptr, msg); - MessageV(node, TEXTCOLOR_RED, msg, argptr); - va_end(argptr); - - ErrorCount++; -} - -//========================================================================== -// -// ZCCCompiler :: MessageV -// -// Prints a message, annotated with the source location for the tree node. -// -//========================================================================== - -void ZCCCompiler::MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr) -{ - FString composed; - - composed.Format("%s%s, line %d: ", txtcolor, node->SourceName->GetChars(), node->SourceLoc); - composed.VAppendFormat(msg, argptr); - composed += '\n'; - PrintString(PRINT_HIGH, composed); -} - -//========================================================================== -// -// ZCCCompiler :: Compile -// -// Compile everything defined at this level. -// -//========================================================================== - -int ZCCCompiler::Compile() -{ - CompileConstants(Constants); - return ErrorCount; -} - -//========================================================================== -// -// ZCCCompiler :: CompileConstants -// -// Make symbols from every constant defined at this level. -// -//========================================================================== - -void ZCCCompiler::CompileConstants(const TArray &defs) -{ - for (unsigned i = 0; i < defs.Size(); ++i) - { - ZCC_ConstantDef *def = defs[i]; - if (def->Symbol == NULL) - { - PSymbolConst *sym = CompileConstant(def); - } - } -} - -//========================================================================== -// -// ZCCCompiler :: CompileConstant -// -// For every constant definition, evaluate its value (which should result -// in a constant), and create a symbol for it. Simplify() uses recursion -// to resolve constants used before their declarations. -// -//========================================================================== - -PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def) -{ - assert(def->Symbol == NULL); - - def->Symbol = DEFINING_CONST; // avoid recursion - ZCC_Expression *val = Simplify(def->Value); - def->Value = val; - PSymbolConst *sym = NULL; - if (val->NodeType == AST_ExprConstant) - { - ZCC_ExprConstant *cval = static_cast(val); - if (cval->Type == TypeString) - { - sym = new PSymbolConstString(def->NodeName, *(cval->StringVal)); - } - else if (cval->Type->IsA(RUNTIME_CLASS(PInt))) - { - sym = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal); - } - else if (cval->Type->IsA(RUNTIME_CLASS(PFloat))) - { - sym = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->DoubleVal); - } - else - { - Error(def->Value, "Bad type for constant definiton"); - } - } - else - { - Error(def->Value, "Constant definition requires a constant value"); - } - if (sym == NULL) - { - // Create a dummy constant so we don't make any undefined value warnings. - sym = new PSymbolConstNumeric(def->NodeName, TypeError, 0); - } - def->Symbol = sym; - Symbols->ReplaceSymbol(sym); - return sym; -} - - -//========================================================================== -// -// ZCCCompiler :: Simplify -// -// For an expression, -// Evaluate operators whose arguments are both constants, replacing it -// with a new constant. -// For a binary operator with one constant argument, put it on the right- -// hand operand, where permitted. -// Perform automatic type promotion. -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root) -{ - if (root->NodeType == AST_ExprUnary) - { - return SimplifyUnary(static_cast(root)); - } - else if (root->NodeType == AST_ExprBinary) - { - return SimplifyBinary(static_cast(root)); - } - else if (root->Operation == PEX_ID) - { - return IdentifyIdentifier(static_cast(root)); - } - else if (root->Operation == PEX_MemberAccess) - { - return SimplifyMemberAccess(static_cast(root)); - } - else if (root->Operation == PEX_FuncCall) - { - return SimplifyFunctionCall(static_cast(root)); - } - return root; -} - -//========================================================================== -// -// ZCCCompiler :: SimplifyUnary -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary) -{ - unary->Operand = Simplify(unary->Operand); - ZCC_OpProto *op = PromoteUnary(unary->Operation, unary->Operand); - if (op == NULL) - { // Oh, poo! - unary->Type = TypeError; - } - else if (unary->Operand->Operation == PEX_ConstValue) - { - return op->EvalConst1(static_cast(unary->Operand)); - } - return unary; -} - -//========================================================================== -// -// ZCCCompiler :: SimplifyBinary -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary) -{ - binary->Left = Simplify(binary->Left); - binary->Right = Simplify(binary->Right); - ZCC_OpProto *op = PromoteBinary(binary->Operation, binary->Left, binary->Right); - if (op == NULL) - { - binary->Type = TypeError; - } - else if (binary->Left->Operation == PEX_ConstValue && - binary->Right->Operation == PEX_ConstValue) - { - return op->EvalConst2(static_cast(binary->Left), - static_cast(binary->Right), AST.Strings); - } - return binary; -} - -//========================================================================== -// -// ZCCCompiler :: SimplifyMemberAccess -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop) -{ - dotop->Left = Simplify(dotop->Left); - - if (dotop->Left->Operation == PEX_TypeRef) - { // Type refs can be evaluated now. - PType *ref = static_cast(dotop->Left)->RefType; - PSymbolTable *symtable; - PSymbol *sym = ref->Symbols.FindSymbolInTable(dotop->Right, symtable); - if (sym == NULL) - { - Error(dotop, "'%s' is not a valid member", FName(dotop->Right).GetChars()); - } - else - { - ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable); - if (expr == NULL) - { - Error(dotop, "Unhandled symbol type encountered"); - } - else - { - return expr; - } - } - } - return dotop; -} - -//========================================================================== -// -// ZCCCompiler :: SimplifyFunctionCall -// -// This may replace a function call with cast(s), since they look like the -// same thing to the parser. -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop) -{ - ZCC_FuncParm *parm; - int parmcount = 0; - - callop->Function = Simplify(callop->Function); - parm = callop->Parameters; - if (parm != NULL) - { - do - { - parmcount++; - assert(parm->NodeType == AST_FuncParm); - parm->Value = Simplify(parm->Value); - parm = static_cast(parm->SiblingNext); - } - while (parm != callop->Parameters); - } - // If the left side is a type ref, then this is actually a cast - // and not a function call. - if (callop->Function->Operation == PEX_TypeRef) - { - if (parmcount != 1) - { - Error(callop, "Type cast requires one parameter"); - callop->ToErrorNode(); - } - else - { - PType *dest = static_cast(callop->Function)->RefType; - const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; - int routelen = parm->Value->Type->FindConversion(dest, route, countof(route)); - if (routelen < 0) - { - ///FIXME: Need real type names - Error(callop, "Cannot convert type 1 to type 2"); - callop->ToErrorNode(); - } - else - { - ZCC_Expression *val = ApplyConversion(parm->Value, route, routelen); - assert(val->Type == dest); - return val; - } - } - } - return callop; -} - -//========================================================================== -// -// ZCCCompiler :: PromoteUnary -// -// Converts the operand into a format preferred by the operator. -// -//========================================================================== - -ZCC_OpProto *ZCCCompiler::PromoteUnary(EZCCExprType op, ZCC_Expression *&expr) -{ - if (expr->Type == TypeError) - { - return NULL; - } - const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; - int routelen = countof(route); - ZCC_OpProto *proto = ZCC_OpInfo[op].FindBestProto(expr->Type, route, routelen); - - if (proto != NULL) - { - expr = ApplyConversion(expr, route, routelen); - } - return proto; -} - -//========================================================================== -// -// ZCCCompiler :: PromoteBinary -// -// Converts the operands into a format (hopefully) compatible with the -// operator. -// -//========================================================================== - -ZCC_OpProto *ZCCCompiler::PromoteBinary(EZCCExprType op, ZCC_Expression *&left, ZCC_Expression *&right) -{ - // If either operand is of type 'error', the result is also 'error' - if (left->Type == TypeError || right->Type == TypeError) - { - return NULL; - } - const PType::Conversion *route1[CONVERSION_ROUTE_SIZE], *route2[CONVERSION_ROUTE_SIZE]; - int route1len = countof(route1), route2len = countof(route2); - ZCC_OpProto *proto = ZCC_OpInfo[op].FindBestProto(left->Type, route1, route1len, right->Type, route2, route2len); - if (proto != NULL) - { - left = ApplyConversion(left, route1, route1len); - right = ApplyConversion(right, route2, route2len); - } - return proto; -} - -//========================================================================== -// -// ZCCCompiler :: ApplyConversion -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::ApplyConversion(ZCC_Expression *expr, const PType::Conversion **route, int routelen) -{ - for (int i = 0; i < routelen; ++i) - { - if (expr->Operation != PEX_ConstValue) - { - expr = AddCastNode(route[i]->TargetType, expr); - } - else - { - route[i]->ConvertConstant(static_cast(expr), AST.Strings); - } - } - return expr; -} - -//========================================================================== -// -// ZCCCompiler :: AddCastNode -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::AddCastNode(PType *type, ZCC_Expression *expr) -{ - assert(expr->Operation != PEX_ConstValue && "Expression must not be constant"); - // TODO: add a node here - return expr; -} - -//========================================================================== -// -// ZCCCompiler :: IdentifyIdentifier -// -// Returns a node that represents what the identifer stands for. -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode) -{ - // Check the symbol table for the identifier. - PSymbolTable *table; - PSymbol *sym = Symbols->FindSymbolInTable(idnode->Identifier, table); - if (sym != NULL) - { - ZCC_Expression *node = NodeFromSymbol(sym, idnode, table); - if (node != NULL) - { - return node; - } - } - else - { - Error(idnode, "Unknown identifier '%s'", FName(idnode->Identifier).GetChars()); - } - // Identifier didn't refer to anything good, so type error it. - idnode->ToErrorNode(); - return idnode; -} - -//========================================================================== -// -// ZCCCompiler :: CompileNode -// -//========================================================================== - -PSymbol *ZCCCompiler::CompileNode(ZCC_NamedNode *node) -{ - assert(node != NULL); - if (node->NodeType == AST_ConstantDef) - { - ZCC_ConstantDef *def = static_cast(node); - PSymbolConst *sym = def->Symbol; - - if (sym == DEFINING_CONST) - { - Error(node, "Definition of '%s' is infinitely recursive", FName(node->NodeName).GetChars()); - sym = NULL; - } - else - { - assert(sym == NULL); - sym = CompileConstant(def); - } - return sym; - } - else if (node->NodeType == AST_Struct) - { - - } - return NULL; -} - -//========================================================================== -// -// ZCCCompiler :: NodeFromSymbol -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table) -{ - assert(sym != NULL); - if (sym->IsA(RUNTIME_CLASS(PSymbolTreeNode))) - { - PSymbolTable *prevtable = Symbols; - Symbols = table; - sym = CompileNode(static_cast(sym)->Node); - Symbols = prevtable; - if (sym == NULL) - { - return NULL; - } - } - if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) - { - return NodeFromSymbolConst(static_cast(sym), source); - } - else if (sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) - { - return NodeFromSymbolType(static_cast(sym), source); - } - return NULL; -} - -//========================================================================== -// -// ZCCCompiler :: NodeFromSymbolConst -// -// Returns a new AST constant node with the symbol's content. -// -//========================================================================== - -ZCC_ExprConstant *ZCCCompiler::NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode) -{ - ZCC_ExprConstant *val = static_cast(AST.InitNode(sizeof(*val), AST_ExprConstant, idnode)); - val->Operation = PEX_ConstValue; - if (sym == NULL) - { - val->Type = TypeError; - val->IntVal = 0; - } - else if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConstString))) - { - val->StringVal = AST.Strings.Alloc(static_cast(sym)->Str); - val->Type = TypeString; - } - else - { - val->Type = sym->ValueType; - if (val->Type != TypeError) - { - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric))); - if (sym->ValueType->IsKindOf(RUNTIME_CLASS(PInt))) - { - val->IntVal = static_cast(sym)->Value; - } - else - { - assert(sym->ValueType->IsKindOf(RUNTIME_CLASS(PFloat))); - val->DoubleVal = static_cast(sym)->Float; - } - } - } - return val; -} - -//========================================================================== -// -// ZCCCompiler :: NodeFromSymbolType -// -// Returns a new AST type ref node with the symbol's content. -// -//========================================================================== - -ZCC_ExprTypeRef *ZCCCompiler::NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode) -{ - ZCC_ExprTypeRef *ref = static_cast(AST.InitNode(sizeof(*ref), AST_ExprTypeRef, idnode)); - ref->Operation = PEX_TypeRef; - ref->RefType = sym->Type; - ref->Type = NewClassPointer(RUNTIME_CLASS(PType)); - return ref; -} diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h deleted file mode 100644 index d034464b7..000000000 --- a/src/zscript/zcc_compile.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef ZCC_COMPILE_H -#define ZCC_COMPILE_H - -class ZCCCompiler -{ -public: - ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols); - int Compile(); - -private: - void CompileConstants(const TArray &defs); - PSymbolConst *CompileConstant(ZCC_ConstantDef *def); - - TArray Constants; - TArray Structs; - TArray Classes; - - bool AddNamedNode(ZCC_NamedNode *node); - - ZCC_Expression *Simplify(ZCC_Expression *root); - ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary); - ZCC_Expression *SimplifyBinary(ZCC_ExprBinary *binary); - ZCC_Expression *SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop); - ZCC_Expression *SimplifyFunctionCall(ZCC_ExprFuncCall *callop); - ZCC_OpProto *PromoteUnary(EZCCExprType op, ZCC_Expression *&expr); - ZCC_OpProto *PromoteBinary(EZCCExprType op, ZCC_Expression *&left, ZCC_Expression *&right); - - void PromoteToInt(ZCC_Expression *&expr); - void PromoteToUInt(ZCC_Expression *&expr); - void PromoteToDouble(ZCC_Expression *&expr); - void PromoteToString(ZCC_Expression *&expr); - - ZCC_Expression *ApplyConversion(ZCC_Expression *expr, const PType::Conversion **route, int routelen); - ZCC_Expression *AddCastNode(PType *type, ZCC_Expression *expr); - - ZCC_Expression *IdentifyIdentifier(ZCC_ExprID *idnode); - ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table); - ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode); - ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode); - PSymbol *CompileNode(ZCC_NamedNode *node); - - - void Warn(ZCC_TreeNode *node, const char *msg, ...); - void Error(ZCC_TreeNode *node, const char *msg, ...); - void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr); - - DObject *Outer; - PSymbolTable *Symbols; - ZCC_AST &AST; - int ErrorCount; - int WarnCount; -}; - -void ZCC_InitConversions(); - -#endif diff --git a/src/zscript/zcc_exprlist.h b/src/zscript/zcc_exprlist.h deleted file mode 100644 index e36aedea6..000000000 --- a/src/zscript/zcc_exprlist.h +++ /dev/null @@ -1,57 +0,0 @@ -// Name n-ary -xx(Nil, ) - -xx(ID, ) -xx(Super, ) -xx(Self, ) -xx(ConstValue, ) -xx(FuncCall, ) -xx(ArrayAccess, ) -xx(MemberAccess, ) -xx(TypeRef, ) - -xx(PostInc, ) -xx(PostDec, ) - -xx(PreInc, ) -xx(PreDec, ) -xx(Negate, ) -xx(AntiNegate, ) -xx(BitNot, ) -xx(BoolNot, ) -xx(SizeOf, ) -xx(AlignOf, ) - -xx(Add, ) -xx(Sub, ) -xx(Mul, ) -xx(Div, ) -xx(Mod, ) -xx(Pow, ) -xx(CrossProduct, ) -xx(DotProduct, ) -xx(LeftShift, ) -xx(RightShift, ) -xx(Concat, ) - -xx(LT, ) -xx(LTEQ, ) -xx(LTGTEQ, ) -xx(Is, ) - -xx(EQEQ, ) -xx(APREQ, ) - -xx(BitAnd, ) -xx(BitOr, ) -xx(BitXor, ) -xx(BoolAnd, ) -xx(BoolOr, ) - -xx(Scope, ) - -xx(Trinary, ) - -xx(Cast, ) - -#undef xx diff --git a/src/zstring.cpp b/src/zstring.cpp index e8e867323..ac047f05c 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -1262,3 +1262,11 @@ FStringData *FStringData::MakeCopy () FString::StrCopy (copy->Chars(), Chars(), Len); return copy; } + +FStringf::FStringf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + VFormat(fmt, ap); + va_end(ap); +} diff --git a/src/zstring.h b/src/zstring.h index ba9208719..fba61884f 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -309,6 +309,13 @@ private: bool operator >= (const FString &illegal) const; }; +class FStringf : public FString +{ +public: + FStringf(const char *fmt, ...); +}; + + namespace StringFormat { enum diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt deleted file mode 100644 index 71e82f613..000000000 --- a/wadsrc/static/actors/actor.txt +++ /dev/null @@ -1,393 +0,0 @@ -ACTOR Actor native //: Thinker -{ - Scale 1 - Health 1000 - Reactiontime 8 - Radius 20 - Height 16 - Mass 100 - RenderStyle Normal - Alpha 1 - MinMissileChance 200 - MeleeRange 44 - MaxDropoffHeight 24 - MaxStepHeight 24 - BounceFactor 0.7 - WallBounceFactor 0.75 - BounceCount -1 - FloatSpeed 4 - FloatBobPhase -1 // randomly initialize by default - Gravity 1 - Friction 1 - DamageFactor 1.0 - PushFactor 0.25 - WeaveIndexXY 0 - WeaveIndexZ 16 - DesignatedTeam 255 - PainType Normal - DeathType Normal - TeleFogSourceType "TeleportFog" - TeleFogDestType "TeleportFog" - RipperLevel 0 - RipLevelMin 0 - RipLevelMax 0 - DefThreshold 100 - BloodType "Blood", "BloodSplatter", "AxeBlood" - ExplosionDamage 128 - MissileHeight 32 - SpriteAngle 0 - SpriteRotation 0 - StencilColor "00 00 00" - VisibleAngles 0, 0 - VisiblePitch 0, 0 - - // Functions - native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); - native bool IsPointerEqual(int ptr_select1, int ptr_select2); - native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); - native float GetDistance(bool checkz, int ptr = AAPTR_DEFAULT); - native float GetAngle(int flags, int ptr = AAPTR_DEFAULT); - native float GetZAt(float px = 0, float py = 0, float angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); - native int GetSpawnHealth(); - native int GetGibHealth(); - native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); - native float GetCVar(string cvar); - native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); - native int CountProximity(class classname, float distance, int flags = 0, int ptr = AAPTR_DEFAULT); - native float GetSpriteAngle(int ptr = AAPTR_DEFAULT); - native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); - native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT); - action native int OverlayID(); - action native float OverlayX(int layer = 0); - action native float OverlayY(int layer = 0); - - // Action functions - // Meh, MBF redundant functions. Only for DeHackEd support. - action native A_Turn(float angle = 0); - action native bool A_LineEffect(int boomspecial = 0, int tag = 0); - // End of MBF redundant functions. - - action native A_MonsterRail(); - action native A_BFGSpray(class spraytype = "BFGExtra", int numrays = 40, int damagecount = 15, float/*angle*/ angle = 90, float distance = 16*64, float/*angle*/ vrange = 32, int damage = 0, int flags = 0); - action native A_Pain(); - action native A_NoBlocking(); - action native A_XScream(); - action native A_Look(); - action native A_Chase(state melee = "*", state missile = "none", int flags = 0); - action native 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); - action native 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); - action native 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); - action native A_PosAttack(); - action native A_Scream(); - action native A_SPosAttack(); - action native A_SPosAttackUseAtkSound(); - action native A_VileChase(); - action native A_VileStart(); - action native A_VileTarget(class fire = "ArchvileFire"); - action native A_VileAttack(sound snd = "vile/stop", int initialdmg = 20, int blastdmg = 70, int blastradius = 70, float thrustfac = 1.0, name damagetype = "Fire", int flags = 0); - action native A_StartFire(); - action native A_Fire(float spawnheight = 0); - action native A_FireCrackle(); - action native A_Tracer(); - action native A_SkelWhoosh(); - action native A_SkelFist(); - action native A_SkelMissile(); - action native A_FatRaise(); - action native A_FatAttack1(class spawntype = "FatShot"); - action native A_FatAttack2(class spawntype = "FatShot"); - action native A_FatAttack3(class spawntype = "FatShot"); - action native A_BossDeath(); - action native A_CPosAttack(); - action native A_CPosRefire(); - action native A_TroopAttack(); - action native A_SargAttack(); - action native A_HeadAttack(); - action native A_BruisAttack(); - action native A_SkullAttack(float speed = 20); - action native A_BetaSkullAttack(); - action native A_Metal(); - action native A_SpidRefire(); - action native A_BabyMetal(); - action native A_BspiAttack(); - action native A_Hoof(); - action native A_CyberAttack(); - action native A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); - action native A_DualPainAttack(class spawntype = "LostSoul"); - action native A_PainDie(class spawntype = "LostSoul"); - action native A_KeenDie(int doortag = 666); - action native A_BrainPain(); - action native A_BrainScream(); - action native A_BrainDie(); - action native A_BrainAwake(); - action native A_BrainSpit(class spawntype = "none"); // needs special treatment for default - action native A_SpawnSound(); - action native A_SpawnFly(class spawntype = "none"); // needs special treatment for default - action native A_BrainExplode(); - action native A_Die(name damagetype = "none"); - action native A_Detonate(); - action native A_Mushroom(class spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5); - native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0); - - action native A_SetFloorClip(); - action native A_UnSetFloorClip(); - action native A_HideThing(); - action native A_UnHideThing(); - action native A_SetInvulnerable(); - action native A_UnSetInvulnerable(); - action native A_SetReflective(); - action native A_UnSetReflective(); - action native A_SetReflectiveInvulnerable(); - action native A_UnSetReflectiveInvulnerable(); - action native A_SetShootable(); - action native A_UnSetShootable(); - action native A_NoGravity(); - action native A_Gravity(); - action native A_LowGravity(); - native void A_SetGravity(float gravity); - action native A_Fall(); - action native A_SetSolid(); - action native A_UnsetSolid(); - action native A_SetFloat(); - action native A_UnsetFloat(); - - action native A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); - - action native A_ScreamAndUnblock(); - action native A_ActiveAndUnblock(); - action native A_ActiveSound(); - - action native A_FastChase(); - action native A_FreezeDeath(); - action native A_FreezeDeathChunks(); - action native A_GenericFreezeDeath(); - action native A_IceGuyDie(); - action native A_CentaurDefend(); - action native A_BishopMissileWeave(); - action native A_CStaffMissileSlither(); - action native A_PlayerScream(); - action native A_SkullPop(class skulltype = "BloodySkull"); - action native A_CheckPlayerDone(); - - action native A_Wander(int flags = 0); - action native A_Look2(); - action native A_TossGib(); - action native A_SentinelBob(); - action native A_SentinelRefire(); - action native A_Tracer2(); - action native A_SetShadow(); - action native A_ClearShadow(); - action native A_GetHurt(); - action native A_TurretLook(); - action native A_KlaxonBlare(); - action native A_Countdown(); - action native A_AlertMonsters(float maxdist = 0, int flags = 0); - action native A_ClearSoundTarget(); - action native A_FireAssaultGun(); - action native A_CheckTerrain(); - action native A_FaceConsolePlayer(float MaxTurnAngle = 0); // [TP] no-op - - action native A_MissileAttack(); - action native A_MeleeAttack(); - action native A_ComboAttack(); - action native A_BulletAttack(); - action native A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", float snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, float runspeed = 160.0, class pufftype = "BulletPuff"); - action native A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM, bool local = false); - native void A_PlayWeaponSound(sound whattoplay); - action native A_FLoopActiveSound(); - action native A_LoopActiveSound(); - action native A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was... - native void A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0); - native void A_StopSoundEx(coerce name slot); - 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/*angle*/ spread_xy, float/*angle*/ 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/*angle*/ spread_xy = 0, float/*angle*/ 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); - native state A_JumpIfMasterCloser(float distance, state label, bool noz = false); - native state A_JumpIfTargetOutsideMeleeRange(state label); - native state A_JumpIfTargetInsideMeleeRange(state label); - native state A_JumpIfInventory(class itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT); - native state A_JumpIfArmorType(name Type, state label, int amount = 1); - action native bool A_SetInventory(class itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false); - native bool A_GiveInventory(class itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); - 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_Log(string whattoprint); - native void A_LogInt(int whattoprint); - native void A_LogFloat(float whattoprint); - native void A_SetTranslucent(float alpha, int style = 0); - native void A_SetRenderStyle(float alpha, int style); - action native A_FadeIn(float reduce = 0.1, int flags = 0); - action native A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true - native void A_FadeTo(float target, float amount = 0.1, int flags = 0); - native void A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false); - native void A_SetMass(int mass); - native void A_SpawnDebris(class spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1); - native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, float 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, float sizestep = 0); - 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_ChangeFlag(string flagname, bool value); - native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); - 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); - native state A_CheckFloor(state label); - native state A_CheckCeiling(state label); - native state A_PlayerSkinCheck(state label); - native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); - action 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); - 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 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); - - native void A_Recoil(float xyvel); - native state A_JumpIfInTargetInventory(class itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT); - 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 = ""); - action native 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); - action native A_Blast(int flags = 0, float strength = 255, float radius = 255, float speed = 20, class blasteffect = "BlastEffect", sound blastsound = "BlastRadius"); - action native A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0); - action native A_RadiusDamageSelf(int damage = 128, float distance = 128, int flags = 0, class flashtype = "None"); - action native int A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class pufftype = "BulletPuff", name damagetype = "none"); - action native A_Stop(); - action native A_Respawn(int flags = 1); - action native A_BarrelDestroy(); - action native A_QueueCorpse(); - action native A_DeQueueCorpse(); - 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(); - 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); - native state A_JumpIfTargetInLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); - native state A_JumpIfInTargetLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); - native bool A_SelectWeapon(class whichweapon, int flags = 0); - action native A_Punch(); - action native A_Feathers(); - action native A_ClassBossHealth(); - action native A_ShootGun(); - action native A_RocketInFlight(); - action native A_Bang4Cloud(); - action native A_DropFire(); - native void A_GiveQuestItem(int itemno); - action native A_RemoveForcefield(); - native void A_DropWeaponPieces(class p1, class p2, class p3); - action native A_PigPain (); - native state A_MonsterRefire(int chance, state label); - action native A_SetAngle(float angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); - native void A_SetPitch(float pitch, int flags = 0, int ptr = AAPTR_DEFAULT); - native void A_SetRoll(float/*angle*/ roll, int flags = 0, int ptr = AAPTR_DEFAULT); - native void A_ScaleVelocity(float scale, int ptr = AAPTR_DEFAULT); - action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0, int ptr = AAPTR_DEFAULT); - native void A_SetArg(int pos, int value); - native void A_SetUserVar(name varname, int value); - native void A_SetUserArray(name varname, int index, int value); - native void A_SetUserVarFloat(name varname, float value); - native void A_SetUserArrayFloat(name varname, int index, float value); - native void A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0); - native void A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); - native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, float mulWaveX = 1, float mulWaveY = 1, float mulWaveZ = 1, int falloff = 0, int highpoint = 0, float rollIntensity = 0, float rollWave = 0); - action native A_SetTics(int tics); - native void A_SetDamageType(name damagetype); - native void A_DropItem(class item, int dropamount = -1, int chance = 256); - native void A_SetSpeed(float speed, int ptr = AAPTR_DEFAULT); - native void A_SetFloatSpeed(float speed, int ptr = AAPTR_DEFAULT); - native void A_SetPainThreshold(int threshold, int ptr = AAPTR_DEFAULT); - native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_DamageTracer(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_DamageSiblings(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native A_RemoveTarget(int flags = 0, class filter = "None", name species = "None"); - action native A_RemoveMaster(int flags = 0, class filter = "None", name species = "None"); - action native A_RemoveTracer(int flags = 0, class filter = "None", name species = "None"); - action native A_RemoveChildren(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); - action native A_RemoveSiblings(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); - native void A_Remove(int removee, int flags = 0, class filter = "None", name species = "None"); - native int A_GiveToChildren(class itemtype, int amount = 0); - native int A_GiveToSiblings(class itemtype, int amount = 0); - native int A_TakeFromChildren(class itemtype, int amount = 0); - native int A_TakeFromSiblings(class itemtype, int amount = 0); - native void A_SetTeleFog(class oldpos, class newpos); - action native A_SwapTeleFog(); - native void A_SetFloatBobPhase(int bob); - native void A_SetHealth(int health, int ptr = AAPTR_DEFAULT); - action native A_ResetHealth(int ptr = AAPTR_DEFAULT); - native state A_JumpIfHigherOrLower(state high, state low, float offsethigh = 0, float offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET); - native void A_SetSpecies(name species, int ptr = AAPTR_DEFAULT); - native void A_SetRipperLevel(int level); - native void A_SetRipMin(int mininum); - native void A_SetRipMax(int maximum); - native void A_SetChaseThreshold(int threshold, bool def = false, int ptr = AAPTR_DEFAULT); - native state A_CheckProximity(state jump, class classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT); - native state A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0); - native state A_CheckSightOrRange(float distance, state label, bool two_dimension = false); - 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 int A_ClearOverlays(int sstart = 0, int sstop = 0, bool safety = true); - action native bool A_CopySpriteFrame(int from, int to, int flags = 0); - action native bool A_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT); - action native bool A_SetSpriteRotation(float angle = 0, int ptr = AAPTR_DEFAULT); - action native bool A_SetVisibleRotation(float anglestart = 0, float angleend = 0, float pitchstart = 0, float pitchend = 0, int flags = 0, int ptr = AAPTR_DEFAULT); - native void A_SetTranslation(string transname); - - native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0); - native void 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 bool A_Overlay(int layer, state start = "", bool nooverride = false); - action native A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0); - action native A_OverlayOffset(int layer = PSP_WEAPON, float wx = 0, float wy = 32, int flags = 0); - action native A_OverlayFlags(int layer, int flags, bool set); - - native int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0); - native int ACS_NamedSuspend(name script, int mapnum=0); - native int ACS_NamedTerminate(name script, int mapnum=0); - native int ACS_NamedLockedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0); - native int ACS_NamedLockedExecuteDoor(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0); - native int ACS_NamedExecuteWithResult(name script, int arg1=0, int arg2=0, int arg3=0, int arg4=0); - native void ACS_NamedExecuteAlways(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0); - - States - { - Spawn: - TNT1 A -1 - Stop - Null: - TNT1 A 1 - Stop - GenericFreezeDeath: - // Generic freeze death frames. Woo! - "####" "#" 5 A_GenericFreezeDeath - "----" A 1 A_FreezeDeathChunks - Wait - GenericCrush: - POL5 A -1 - Stop - } - - // Internal functions - native state __decorate_internal_state__(state); - native int __decorate_internal_int__(int); - native bool __decorate_internal_bool__(bool); - native float __decorate_internal_float__(float); -} diff --git a/wadsrc/static/actors/chex/chexammo.txt b/wadsrc/static/actors/chex/chexammo.txt deleted file mode 100644 index 27c5d419b..000000000 --- a/wadsrc/static/actors/chex/chexammo.txt +++ /dev/null @@ -1,77 +0,0 @@ -// Renaming and changing messages - -// Mini Zorch ----------------------------------------------------------------- - -actor MiniZorchRecharge : Clip -{ - inventory.pickupmessage "$GOTZORCHRECHARGE" -} - -actor MiniZorchPack : Clip -{ - Inventory.PickupMessage "$GOTMINIZORCHPACK" - Inventory.Amount 50 - States - { - Spawn: - AMMO A -1 - Stop - } -} - -// Large Zorch ---------------------------------------------------------------- - -actor LargeZorchRecharge : Shell -{ - inventory.pickupmessage "$GOTLARGEZORCHERRECHARGE" -} - -actor LargeZorchPack : Shell -{ - Inventory.PickupMessage "$GOTLARGEZORCHERPACK" - Inventory.Amount 20 - States - { - Spawn: - SBOX A -1 - Stop - } -} - -// Zorch Propulsor ------------------------------------------------------------ - -actor PropulsorZorch : RocketAmmo -{ - inventory.pickupmessage "$GOTPROPULSORRECHARGE" -} - -actor PropulsorZorchPack : RocketAmmo -{ - Inventory.PickupMessage "$GOTPROPULSORPACK" - Inventory.Amount 5 - States - { - Spawn: - BROK A -1 - Stop - } -} - -// Phasing Zorch -------------------------------------------------------------- - -actor PhasingZorch : Cell -{ - inventory.pickupmessage "$GOTPHASINGZORCHERRECHARGE" -} - -actor PhasingZorchPack : Cell -{ - Inventory.PickupMessage "$GOTPHASINGZORCHERPACK" - Inventory.Amount 100 - States - { - Spawn: - CELP A -1 - Stop - } -} diff --git a/wadsrc/static/actors/chex/chexdecorations.txt b/wadsrc/static/actors/chex/chexdecorations.txt deleted file mode 100644 index 6515061c5..000000000 --- a/wadsrc/static/actors/chex/chexdecorations.txt +++ /dev/null @@ -1,120 +0,0 @@ -// Doom items renamed with height changes - -// Civilians ------------------------------------------------------------------ - -actor ChexCivilian1 : GreenTorch -{ - height 54 -} - -actor ChexCivilian2 : ShortGreenTorch -{ - height 54 -} - -actor ChexCivilian3 : ShortRedTorch -{ - height 48 -} - -// Landing Zone --------------------------------------------------------------- - -actor ChexLandingLight : Column -{ - height 35 -} - -actor ChexSpaceship : TechPillar -{ - height 52 -} - -// Trees and Plants ----------------------------------------------------------- - -actor ChexAppleTree : Stalagtite -{ - height 92 -} - -actor ChexBananaTree : BigTree -{ - height 108 -} - -actor ChexOrangeTree : TorchTree -{ - height 92 -} - -actor ChexSubmergedPlant : ShortGreenColumn -{ - height 42 -} - -actor ChexTallFlower : HeadsOnAStick -{ - height 25 -} - -actor ChexTallFlower2 : DeadStick -{ - height 25 -} - -// Slime Fountain ------------------------------------------------------------- - -actor ChexSlimeFountain : BlueTorch -{ - height 48 - States - { - Spawn: - TBLU ABCD 4 - Loop - } -} - -// Cavern Decorations --------------------------------------------------------- - -actor ChexCavernColumn : TallRedColumn -{ - height 128 -} - -actor ChexCavernStalagmite : TallGreenColumn -{ - height 60 -} - -// Misc. Props ---------------------------------------------------------------- - -actor ChexChemicalBurner : EvilEye -{ - height 25 -} - -actor ChexChemicalFlask : Candlestick -{ - renderstyle translucent - alpha 0.75 -} - -actor ChexFlagOnPole : SkullColumn -{ - height 128 -} - -actor ChexGasTank : Candelabra -{ - height 36 -} - -actor ChexLightColumn : ShortBlueTorch -{ - height 86 -} - -actor ChexMineCart : ShortRedColumn -{ - height 30 -} diff --git a/wadsrc/static/actors/chex/chexitems.txt b/wadsrc/static/actors/chex/chexitems.txt deleted file mode 100644 index 431728e07..000000000 --- a/wadsrc/static/actors/chex/chexitems.txt +++ /dev/null @@ -1,59 +0,0 @@ - -// General Pickups ============================================================ - -// Health --------------------------------------------------------------------- - -actor GlassOfWater : HealthBonus -{ - inventory.pickupmessage "$GOTWATER" -} - -actor BowlOfFruit : Stimpack -{ - inventory.pickupmessage "$GOTFRUIT" -} - -actor BowlOfVegetables : Medikit -{ - inventory.pickupmessage "$GOTVEGETABLES" - health.lowmessage 25, "$GOTVEGETABLESNEED" -} - -actor SuperchargeBreakfast : Soulsphere -{ - inventory.pickupmessage "$GOTBREAKFAST" -} - -// Armor ---------------------------------------------------------------------- - -actor SlimeRepellent : ArmorBonus -{ - inventory.pickupmessage "$GOTREPELLENT" -} - -actor ChexArmor : GreenArmor -{ - inventory.pickupmessage "$GOTCHEXARMOR" -} - -actor SuperChexArmor : BlueArmor -{ - inventory.pickupmessage "$GOTSUPERCHEXARMOR" -} - -// Powerups =================================================================== - -actor ComputerAreaMap : Allmap -{ - inventory.pickupmessage "$GOTCHEXMAP" -} - -actor SlimeProofSuit : RadSuit -{ - inventory.pickupmessage "$GOTSLIMESUIT" -} - -actor Zorchpack : Backpack -{ - inventory.pickupmessage "$GOTZORCHPACK" -} diff --git a/wadsrc/static/actors/chex/chexkeys.txt b/wadsrc/static/actors/chex/chexkeys.txt deleted file mode 100644 index 0d5156392..000000000 --- a/wadsrc/static/actors/chex/chexkeys.txt +++ /dev/null @@ -1,16 +0,0 @@ -// These are merely renames of the Doom cards - -actor ChexBlueCard : BlueCard -{ - inventory.pickupmessage "$GOTCBLUEKEY" -} - -actor ChexYellowCard : YellowCard -{ - inventory.pickupmessage "$GOTCYELLOWKEY" -} - -actor ChexRedCard : RedCard -{ - inventory.pickupmessage "$GOTCREDKEY" -} diff --git a/wadsrc/static/actors/chex/chexplayer.txt b/wadsrc/static/actors/chex/chexplayer.txt deleted file mode 100644 index 210a68470..000000000 --- a/wadsrc/static/actors/chex/chexplayer.txt +++ /dev/null @@ -1,29 +0,0 @@ -// Chex Warrior - -actor ChexPlayer : DoomPlayer -{ - player.displayname "Chex Warrior" - player.crouchsprite "" - player.colorrange 192, 207 //Not perfect, but its better than everyone being blue. - player.startitem "MiniZorcher" - player.startitem "Bootspoon" - player.startitem "MiniZorchRecharge", 50 - player.damagescreencolor "60 b0 58" - player.WeaponSlot 1, Bootspoon, SuperBootspork - player.WeaponSlot 2, MiniZorcher - player.WeaponSlot 3, LargeZorcher, SuperLargeZorcher - player.WeaponSlot 4, RapidZorcher - player.WeaponSlot 5, ZorchPropulsor - player.WeaponSlot 6, PhasingZorcher - player.WeaponSlot 7, LAZDevice - - Player.Colorset 0, "Light Blue", 0xC0, 0xCF, 0xC2 - Player.Colorset 1, "Green", 0x70, 0x7F, 0x72 - Player.Colorset 2, "Gray", 0x60, 0x6F, 0x62 - Player.Colorset 3, "Brown", 0x40, 0x4F, 0x42 - Player.Colorset 4, "Red", 0x20, 0x2F, 0x22 - Player.Colorset 5, "Light Gray", 0x58, 0x67, 0x5A - Player.Colorset 6, "Light Brown", 0x38, 0x47, 0x3A - Player.Colorset 7, "Light Red", 0xB0, 0xBF, 0xB2 - -} diff --git a/wadsrc/static/actors/chex/chexweapons.txt b/wadsrc/static/actors/chex/chexweapons.txt deleted file mode 100644 index 0cdb96849..000000000 --- a/wadsrc/static/actors/chex/chexweapons.txt +++ /dev/null @@ -1,124 +0,0 @@ -// Same as Doom weapons, but the obituaries are removed. - -actor Bootspoon : Fist -{ - obituary "$OB_MPSPOON" - Tag "$TAG_SPOON" -} - -actor SuperBootspork : Chainsaw -{ - obituary "$OB_MPBOOTSPORK" - Inventory.PickupMessage "$GOTSUPERBOOTSPORK" - Tag "$TAG_SPORK" -} - -actor MiniZorcher : Pistol -{ - obituary "$OB_MPZORCH" - inventory.pickupmessage "$GOTMINIZORCHER" - Tag "$TAG_MINIZORCHER" - states - { - Spawn: - MINZ A -1 - stop - } -} - -actor LargeZorcher : Shotgun -{ - obituary "$OB_MPZORCH" - inventory.pickupmessage "$GOTLARGEZORCHER" - Tag "$TAG_LARGEZORCHER" -} - -actor SuperLargeZorcher : SuperShotgun -{ - obituary "$OB_MPMEGAZORCH" - inventory.pickupmessage "$GOTSUPERLARGEZORCHER" - Tag "$TAG_SUPERLARGEZORCHER" -} - -actor RapidZorcher : Chaingun -{ - obituary "$OB_MPRAPIDZORCH" - inventory.pickupmessage "$GOTRAPIDZORCHER" - Tag "$TAG_RAPIDZORCHER" -} - -actor ZorchPropulsor : RocketLauncher -{ - obituary "" - inventory.pickupmessage "$GOTZORCHPROPULSOR" - Tag "$TAG_ZORCHPROPULSOR" - States - { - Fire: - MISG B 8 A_GunFlash - MISG B 12 A_FireCustomMissile("PropulsorMissile") - MISG B 0 A_ReFire - Goto Ready - } -} - -actor PropulsorMissile : Rocket -{ - -ROCKETTRAIL - -DEHEXPLOSION - RenderStyle Translucent - Obituary "$OB_MPPROPULSOR" - Alpha 0.75 -} - -actor PhasingZorcher : PlasmaRifle -{ - obituary "" - inventory.pickupmessage "$GOTPHASINGZORCHER" - Tag "$TAG_PHASINGZORCHER" - states - { - Fire: - PLSG A 0 A_GunFlash - PLSG A 3 A_FireCustomMissile("PhaseZorchMissile") - PLSG B 20 A_ReFire - Goto Ready - Flash: - PLSF A 0 A_Jump(128, "Flash2") - PLSF A 3 Bright A_Light1 - Goto LightDone - Flash2: - PLSF B 3 Bright A_Light1 - Goto LightDone - } -} - -actor PhaseZorchMissile : PlasmaBall -{ - RenderStyle Translucent - Obituary "$OB_MPPHASEZORCH" - Alpha 0.75 -} - -actor LAZDevice : BFG9000 -{ - obituary "" - inventory.pickupmessage "$GOTLAZDEVICE" - Tag "$TAG_LAZDEVICE" - states - { - Fire: - BFGG A 20 A_BFGsound - BFGG B 10 A_GunFlash - BFGG B 10 A_FireCustomMissile("LAZBall") - BFGG B 20 A_ReFire - Goto Ready - } -} - -actor LAZBall : BFGBall -{ - RenderStyle Translucent - Obituary "$OB_MPLAZ_BOOM" - Alpha 0.75 -} diff --git a/wadsrc/static/actors/doom/arachnotron.txt b/wadsrc/static/actors/doom/arachnotron.txt deleted file mode 100644 index 1a70a11d1..000000000 --- a/wadsrc/static/actors/doom/arachnotron.txt +++ /dev/null @@ -1,85 +0,0 @@ -//=========================================================================== -// -// Arachnotron -// -//=========================================================================== -ACTOR Arachnotron -{ - Health 500 - Radius 64 - Height 64 - Mass 600 - Speed 12 - PainChance 128 - Monster - +FLOORCLIP - +BOSSDEATH - SeeSound "baby/sight" - PainSound "baby/pain" - DeathSound "baby/death" - ActiveSound "baby/active" - Obituary "$OB_BABY" - States - { - Spawn: - BSPI AB 10 A_Look - Loop - See: - BSPI A 20 - BSPI A 3 A_BabyMetal - BSPI ABBCC 3 A_Chase - BSPI D 3 A_BabyMetal - BSPI DEEFF 3 A_Chase - Goto See+1 - Missile: - BSPI A 20 BRIGHT A_FaceTarget - BSPI G 4 BRIGHT A_BspiAttack - BSPI H 4 BRIGHT - BSPI H 1 BRIGHT A_SpidRefire - Goto Missile+1 - Pain: - BSPI I 3 - BSPI I 3 A_Pain - Goto See+1 - Death: - BSPI J 20 A_Scream - BSPI K 7 A_NoBlocking - BSPI LMNO 7 - BSPI P -1 A_BossDeath - Stop - Raise: - BSPI P 5 - BSPI ONMLKJ 5 - Goto See+1 - } -} - -//=========================================================================== -// -// Arachnotron plasma -// -//=========================================================================== -ACTOR ArachnotronPlasma -{ - Radius 13 - Height 8 - Speed 25 - Damage 5 - Projectile - +RANDOMIZE - RenderStyle Add - Alpha 0.75 - SeeSound "baby/attack" - DeathSound "baby/shotx" - States - { - Spawn: - APLS AB 5 BRIGHT - Loop - Death: - APBX ABCDE 5 BRIGHT - Stop - } -} - - diff --git a/wadsrc/static/actors/doom/archvile.txt b/wadsrc/static/actors/doom/archvile.txt deleted file mode 100644 index f2c5d6ab4..000000000 --- a/wadsrc/static/actors/doom/archvile.txt +++ /dev/null @@ -1,83 +0,0 @@ -//=========================================================================== -// -// Arch Vile -// -//=========================================================================== - -ACTOR Archvile -{ - Health 700 - Radius 20 - Height 56 - Mass 500 - Speed 15 - PainChance 10 - Monster - MaxTargetRange 896 - +QUICKTORETALIATE - +FLOORCLIP - +NOTARGET - SeeSound "vile/sight" - PainSound "vile/pain" - DeathSound "vile/death" - ActiveSound "vile/active" - MeleeSound "vile/stop" - Obituary "$OB_VILE" - States - { - Spawn: - VILE AB 10 A_Look - Loop - See: - VILE AABBCCDDEEFF 2 A_VileChase - Loop - Missile: - VILE G 0 BRIGHT A_VileStart - VILE G 10 BRIGHT A_FaceTarget - VILE H 8 BRIGHT A_VileTarget - VILE IJKLMN 8 BRIGHT A_FaceTarget - VILE O 8 BRIGHT A_VileAttack - VILE P 20 BRIGHT - Goto See - Heal: - VILE "[\]" 10 BRIGHT - Goto See - Pain: - VILE Q 5 - VILE Q 5 A_Pain - Goto See - Death: - VILE Q 7 - VILE R 7 A_Scream - VILE S 7 A_NoBlocking - VILE TUVWXY 7 - VILE Z -1 - Stop - } -} - - -//=========================================================================== -// -// Arch Vile Fire -// -//=========================================================================== - -ACTOR ArchvileFire -{ - +NOBLOCKMAP +NOGRAVITY - RenderStyle Add - Alpha 1 - States - { - Spawn: - FIRE A 2 BRIGHT A_StartFire - FIRE BAB 2 BRIGHT A_Fire - FIRE C 2 BRIGHT A_FireCrackle - FIRE BCBCDCDCDEDED 2 BRIGHT A_Fire - FIRE E 2 BRIGHT A_FireCrackle - FIRE FEFEFGHGHGH 2 BRIGHT A_Fire - Stop - } -} - diff --git a/wadsrc/static/actors/doom/bossbrain.txt b/wadsrc/static/actors/doom/bossbrain.txt deleted file mode 100644 index 67b6da7d6..000000000 --- a/wadsrc/static/actors/doom/bossbrain.txt +++ /dev/null @@ -1,120 +0,0 @@ - -//=========================================================================== -// -// Boss Brain -// -//=========================================================================== - -ACTOR BossBrain -{ - Health 250 - Mass 10000000 - PainChance 255 - +SOLID +SHOOTABLE - +NOICEDEATH - +OLDRADIUSDMG - PainSound "brain/pain" - DeathSound "brain/death" - States - { - BrainExplode: - MISL BC 10 Bright - MISL D 10 A_BrainExplode - Stop - Spawn: - BBRN A -1 - Stop - Pain: - BBRN B 36 A_BrainPain - Goto Spawn - Death: - BBRN A 100 A_BrainScream - BBRN AA 10 - BBRN A -1 A_BrainDie - Stop - } -} - - -//=========================================================================== -// -// Boss Eye -// -//=========================================================================== - -ACTOR BossEye -{ - Height 32 - +NOBLOCKMAP - +NOSECTOR - States - { - Spawn: - SSWV A 10 A_Look - Loop - See: - SSWV A 181 A_BrainAwake - SSWV A 150 A_BrainSpit - Wait - } -} - -//=========================================================================== -// -// Boss Target -// -//=========================================================================== - -ACTOR BossTarget : SpecialSpot -{ - Height 32 - +NOBLOCKMAP - +NOSECTOR -} - -//=========================================================================== -// -// Spawn shot -// -//=========================================================================== - -ACTOR SpawnShot -{ - Radius 6 - Height 32 - Speed 10 - Damage 3 - Projectile - +NOCLIP - -ACTIVATEPCROSS - +RANDOMIZE - SeeSound "brain/spit" - DeathSound "brain/cubeboom" - States - { - Spawn: - BOSF A 3 BRIGHT A_SpawnSound - BOSF BCD 3 BRIGHT A_SpawnFly - Loop - } -} - -//=========================================================================== -// -// Spawn fire -// -//=========================================================================== - -ACTOR SpawnFire -{ - Height 78 - +NOBLOCKMAP - +NOGRAVITY - RenderStyle Add - States - { - Spawn: - FIRE ABCDEFGH 4 Bright A_Fire - Stop - } -} diff --git a/wadsrc/static/actors/doom/bruiser.txt b/wadsrc/static/actors/doom/bruiser.txt deleted file mode 100644 index 0a2bdcff6..000000000 --- a/wadsrc/static/actors/doom/bruiser.txt +++ /dev/null @@ -1,131 +0,0 @@ -//=========================================================================== -// -// Baron of Hell -// -//=========================================================================== -ACTOR BaronOfHell -{ - Health 1000 - Radius 24 - Height 64 - Mass 1000 - Speed 8 - PainChance 50 - Monster - +FLOORCLIP - +BOSSDEATH - SeeSound "baron/sight" - PainSound "baron/pain" - DeathSound "baron/death" - ActiveSound "baron/active" - Obituary "$OB_BARON" - HitObituary "$OB_BARONHIT" - States - { - Spawn: - BOSS AB 10 A_Look - Loop - See: - BOSS AABBCCDD 3 A_Chase - Loop - Melee: - Missile: - BOSS EF 8 A_FaceTarget - BOSS G 8 A_BruisAttack - Goto See - Pain: - BOSS H 2 - BOSS H 2 A_Pain - Goto See - Death: - BOSS I 8 - BOSS J 8 A_Scream - BOSS K 8 - BOSS L 8 A_NoBlocking - BOSS MN 8 - BOSS O -1 A_BossDeath - Stop - Raise: - BOSS O 8 - BOSS NMLKJI 8 - Goto See - } -} - -//=========================================================================== -// -// Hell Knight -// -//=========================================================================== -ACTOR HellKnight : BaronOfHell -{ - Health 500 - -BOSSDEATH - SeeSound "knight/sight" - ActiveSound "knight/active" - PainSound "knight/pain" - DeathSound "knight/death" - HitObituary "$OB_KNIGHTHIT" - Obituary "$OB_KNIGHT" - States - { - Spawn: - BOS2 AB 10 A_Look - Loop - See: - BOS2 AABBCCDD 3 A_Chase - Loop - Melee: - Missile: - BOS2 EF 8 A_FaceTarget - BOS2 G 8 A_BruisAttack - Goto See - Pain: - BOS2 H 2 - BOS2 H 2 A_Pain - Goto See - Death: - BOS2 I 8 - BOS2 J 8 A_Scream - BOS2 K 8 - BOS2 L 8 A_NoBlocking - BOS2 MN 8 - BOS2 O -1 - Stop - Raise: - BOS2 O 8 - BOS2 NMLKJI 8 - Goto See - } -} - -//=========================================================================== -// -// Baron slime ball -// -//=========================================================================== -ACTOR BaronBall -{ - Radius 6 - Height 16 - Speed 15 - FastSpeed 20 - Damage 8 - Projectile - +RANDOMIZE - RenderStyle Add - Alpha 1 - SeeSound "baron/attack" - DeathSound "baron/shotx" - Decal "BaronScorch" - States - { - Spawn: - BAL7 AB 4 BRIGHT - Loop - Death: - BAL7 CDE 6 BRIGHT - Stop - } -} - diff --git a/wadsrc/static/actors/doom/cacodemon.txt b/wadsrc/static/actors/doom/cacodemon.txt deleted file mode 100644 index db2ee7657..000000000 --- a/wadsrc/static/actors/doom/cacodemon.txt +++ /dev/null @@ -1,82 +0,0 @@ -//=========================================================================== -// -// Cacodemon -// -//=========================================================================== -ACTOR Cacodemon -{ - Health 400 - Radius 31 - Height 56 - Mass 400 - Speed 8 - PainChance 128 - Monster - +FLOAT +NOGRAVITY - SeeSound "caco/sight" - PainSound "caco/pain" - DeathSound "caco/death" - ActiveSound "caco/active" - Obituary "$OB_CACO" - HitObituary "$OB_CACOHIT" - States - { - Spawn: - HEAD A 10 A_Look - Loop - See: - HEAD A 3 A_Chase - Loop - Missile: - HEAD B 5 A_FaceTarget - HEAD C 5 A_FaceTarget - HEAD D 5 BRIGHT A_HeadAttack - Goto See - Pain: - HEAD E 3 - HEAD E 3 A_Pain - HEAD F 6 - Goto See - Death: - HEAD G 8 - HEAD H 8 A_Scream - HEAD I 8 - HEAD J 8 - HEAD K 8 A_NoBlocking - HEAD L -1 A_SetFloorClip - Stop - Raise: - HEAD L 8 A_UnSetFloorClip - HEAD KJIHG 8 - Goto See - } -} - -//=========================================================================== -// -// Cacodemon plasma ball -// -//=========================================================================== -ACTOR CacodemonBall -{ - Radius 6 - Height 8 - Speed 10 - FastSpeed 20 - Damage 5 - Projectile - +RANDOMIZE - RenderStyle Add - Alpha 1 - SeeSound "caco/attack" - DeathSound "caco/shotx" - States - { - Spawn: - BAL2 AB 4 BRIGHT - Loop - Death: - BAL2 CDE 6 BRIGHT - Stop - } -} diff --git a/wadsrc/static/actors/doom/cyberdemon.txt b/wadsrc/static/actors/doom/cyberdemon.txt deleted file mode 100644 index 9f9c986f4..000000000 --- a/wadsrc/static/actors/doom/cyberdemon.txt +++ /dev/null @@ -1,61 +0,0 @@ - -//=========================================================================== -// -// Cyberdemon -// -//=========================================================================== -ACTOR Cyberdemon -{ - Health 4000 - Radius 40 - Height 110 - Mass 1000 - Speed 16 - PainChance 20 - Monster - MinMissileChance 160 - +BOSS - +MISSILEMORE - +FLOORCLIP - +NORADIUSDMG - +DONTMORPH - +BOSSDEATH - SeeSound "cyber/sight" - PainSound "cyber/pain" - DeathSound "cyber/death" - ActiveSound "cyber/active" - Obituary "$OB_CYBORG" - States - { - Spawn: - CYBR AB 10 A_Look - Loop - See: - CYBR A 3 A_Hoof - CYBR ABBCC 3 A_Chase - CYBR D 3 A_Metal - CYBR D 3 A_Chase - Loop - Missile: - CYBR E 6 A_FaceTarget - CYBR F 12 A_CyberAttack - CYBR E 12 A_FaceTarget - CYBR F 12 A_CyberAttack - CYBR E 12 A_FaceTarget - CYBR F 12 A_CyberAttack - Goto See - Pain: - CYBR G 10 A_Pain - Goto See - Death: - CYBR H 10 - CYBR I 10 A_Scream - CYBR JKL 10 - CYBR M 10 A_NoBlocking - CYBR NO 10 - CYBR P 30 - CYBR P -1 A_BossDeath - Stop - } -} - diff --git a/wadsrc/static/actors/doom/demon.txt b/wadsrc/static/actors/doom/demon.txt deleted file mode 100644 index 3680b24e9..000000000 --- a/wadsrc/static/actors/doom/demon.txt +++ /dev/null @@ -1,71 +0,0 @@ -//=========================================================================== -// -// Pink Demon -// -//=========================================================================== -ACTOR Demon -{ - Health 150 - PainChance 180 - Speed 10 - Radius 30 - Height 56 - Mass 400 - Monster - +FLOORCLIP - SeeSound "demon/sight" - AttackSound "demon/melee" - PainSound "demon/pain" - DeathSound "demon/death" - ActiveSound "demon/active" - Obituary "$OB_DEMONHIT" - States - { - Spawn: - SARG AB 10 A_Look - Loop - See: - SARG AABBCCDD 2 Fast A_Chase - Loop - Melee: - SARG EF 8 Fast A_FaceTarget - SARG G 8 Fast A_SargAttack - Goto See - Pain: - SARG H 2 Fast - SARG H 2 Fast A_Pain - Goto See - Death: - SARG I 8 - SARG J 8 A_Scream - SARG K 4 - SARG L 4 A_NoBlocking - SARG M 4 - SARG N -1 - Stop - Raise: - SARG N 5 - SARG MLKJI 5 - Goto See - } -} - -//=========================================================================== -// -// Spectre -// -//=========================================================================== -ACTOR Spectre : Demon -{ - +SHADOW - RenderStyle OptFuzzy - Alpha 0.5 - SeeSound "spectre/sight" - AttackSound "spectre/melee" - PainSound "spectre/pain" - DeathSound "spectre/death" - ActiveSound "spectre/active" - HitObituary "$OB_SPECTREHIT" -} - - diff --git a/wadsrc/static/actors/doom/doomammo.txt b/wadsrc/static/actors/doom/doomammo.txt deleted file mode 100644 index bc931c08f..000000000 --- a/wadsrc/static/actors/doom/doomammo.txt +++ /dev/null @@ -1,142 +0,0 @@ -// Clip -------------------------------------------------------------------- - -ACTOR Clip : Ammo -{ - Inventory.PickupMessage "$GOTCLIP" - Inventory.Amount 10 - Inventory.MaxAmount 200 - Ammo.BackpackAmount 10 - Ammo.BackpackMaxAmount 400 - Inventory.Icon "CLIPA0" - States - { - Spawn: - CLIP A -1 - Stop - } -} - -// Clip box ---------------------------------------------------------------- - -ACTOR ClipBox : Clip -{ - Inventory.PickupMessage "$GOTCLIPBOX" - Inventory.Amount 50 - States - { - Spawn: - AMMO A -1 - Stop - } -} - -// Rocket ------------------------------------------------------------------ - -ACTOR RocketAmmo : Ammo -{ - Inventory.PickupMessage "$GOTROCKET" - Inventory.Amount 1 - Inventory.MaxAmount 50 - Ammo.BackpackAmount 1 - Ammo.BackpackMaxAmount 100 - Inventory.Icon "ROCKA0" - States - { - Spawn: - ROCK A -1 - Stop - } -} - -// Rocket box -------------------------------------------------------------- - -ACTOR RocketBox : RocketAmmo -{ - Inventory.PickupMessage "$GOTROCKBOX" - Inventory.Amount 5 - States - { - Spawn: - BROK A -1 - Stop - } -} - -// Cell -------------------------------------------------------------------- - -ACTOR Cell : Ammo -{ - Inventory.PickupMessage "$GOTCELL" - Inventory.Amount 20 - Inventory.MaxAmount 300 - Ammo.BackpackAmount 20 - Ammo.BackpackMaxAmount 600 - Inventory.Icon "CELLA0" - States - { - Spawn: - CELL A -1 - Stop - } -} - -// Cell pack --------------------------------------------------------------- - -ACTOR CellPack : Cell -{ - Inventory.PickupMessage "$GOTCELLBOX" - Inventory.Amount 100 - States - { - Spawn: - CELP A -1 - Stop - } -} - -// Shells ------------------------------------------------------------------ - -ACTOR Shell : Ammo -{ - Inventory.PickupMessage "$GOTSHELLS" - Inventory.Amount 4 - Inventory.MaxAmount 50 - Ammo.BackpackAmount 4 - Ammo.BackpackMaxAmount 100 - Inventory.Icon "SHELA0" - States - { - Spawn: - SHEL A -1 - Stop - } -} - -// Shell box --------------------------------------------------------------- - -ACTOR ShellBox : Shell -{ - Inventory.PickupMessage "$GOTSHELLBOX" - Inventory.Amount 20 - States - { - Spawn: - SBOX A -1 - Stop - } -} - -// Backpack --------------------------------------------------------------- - -ACTOR Backpack : BackpackItem -{ - Height 26 - Inventory.PickupMessage "$GOTBACKPACK" - States - { - Spawn: - BPAK A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/doom/doomarmor.txt b/wadsrc/static/actors/doom/doomarmor.txt deleted file mode 100644 index 578c4f0fe..000000000 --- a/wadsrc/static/actors/doom/doomarmor.txt +++ /dev/null @@ -1,60 +0,0 @@ - -// Armor bonus -------------------------------------------------------------- - -Actor ArmorBonus : BasicArmorBonus -{ - Radius 20 - Height 16 - Inventory.Pickupmessage "$GOTARMBONUS" - Inventory.Icon "BON2A0" - Armor.Savepercent 33.335 - Armor.Saveamount 1 - Armor.Maxsaveamount 200 - +COUNTITEM - +INVENTORY.ALWAYSPICKUP - States - { - Spawn: - BON2 ABCDCB 6 - loop - } -} - -// Green armor -------------------------------------------------------------- - -Actor GreenArmor : BasicArmorPickup -{ - Radius 20 - Height 16 - Inventory.Pickupmessage "$GOTARMOR" - Inventory.Icon "ARM1A0" - Armor.SavePercent 33.335 - Armor.SaveAmount 100 - States - { - Spawn: - ARM1 A 6 - ARM1 B 7 bright - loop - } -} - -// Blue armor --------------------------------------------------------------- - -Actor BlueArmor : BasicArmorPickup -{ - Radius 20 - Height 16 - Inventory.Pickupmessage "$GOTMEGA" - Inventory.Icon "ARM2A0" - Armor.Savepercent 50 - Armor.Saveamount 200 - States - { - Spawn: - ARM2 A 6 - ARM2 B 6 bright - loop - } -} - diff --git a/wadsrc/static/actors/doom/doomartifacts.txt b/wadsrc/static/actors/doom/doomartifacts.txt deleted file mode 100644 index e9caa5f11..000000000 --- a/wadsrc/static/actors/doom/doomartifacts.txt +++ /dev/null @@ -1,171 +0,0 @@ -// Invulnerability Sphere --------------------------------------------------- - -ACTOR InvulnerabilitySphere : PowerupGiver -{ - +COUNTITEM - +INVENTORY.AUTOACTIVATE - +INVENTORY.ALWAYSPICKUP - +INVENTORY.BIGPOWERUP - Inventory.MaxAmount 0 - Powerup.Type Invulnerable - Powerup.Color InverseMap - Inventory.PickupMessage "$GOTINVUL" - States - { - Spawn: - PINV ABCD 6 Bright - Loop - } -} - -// Soulsphere -------------------------------------------------------------- - -ACTOR Soulsphere : Health -{ - +COUNTITEM - +INVENTORY.AUTOACTIVATE - +INVENTORY.ALWAYSPICKUP - +INVENTORY.FANCYPICKUPSOUND - Inventory.Amount 100 - Inventory.MaxAmount 200 - Inventory.PickupMessage "$GOTSUPER" - Inventory.PickupSound "misc/p_pkup" - States - { - Spawn: - SOUL ABCDCB 6 Bright - Loop - } -} - -// Mega sphere -------------------------------------------------------------- - -ACTOR MegasphereHealth : Health // for manipulation by Dehacked -{ - Inventory.Amount 200 - Inventory.MaxAmount 200 - +INVENTORY.ALWAYSPICKUP -} - -// DeHackEd can only modify the blue armor's type, not the megasphere's. -actor BlueArmorForMegasphere : BlueArmor -{ - Armor.SavePercent 50 - Armor.SaveAmount 200 -} - -ACTOR Megasphere : CustomInventory -{ - +COUNTITEM - +INVENTORY.ALWAYSPICKUP - Inventory.PickupMessage "$GOTMSPHERE" - Inventory.PickupSound "misc/p_pkup" - States - { - Spawn: - MEGA ABCD 6 BRIGHT - Loop - Pickup: - TNT1 A 0 A_GiveInventory("BlueArmorForMegasphere", 1) - TNT1 A 0 A_GiveInventory("MegasphereHealth", 1) - Stop - } -} - -// Invisibility ------------------------------------------------------------- - -ACTOR BlurSphere : PowerupGiver -{ - +COUNTITEM - +VISIBILITYPULSE - +INVENTORY.AUTOACTIVATE - +INVENTORY.ALWAYSPICKUP - +INVENTORY.BIGPOWERUP - Inventory.MaxAmount 0 - Powerup.Type Invisibility - RenderStyle Translucent - Inventory.PickupMessage "$GOTINVIS" - States - { - Spawn: - PINS ABCD 6 Bright - Loop - } -} - -// Radiation suit (aka iron feet) ------------------------------------------- - -ACTOR RadSuit : PowerupGiver -{ - Height 46 - +INVENTORY.AUTOACTIVATE - +INVENTORY.ALWAYSPICKUP - Inventory.MaxAmount 0 - Inventory.PickupMessage "$GOTSUIT" - Powerup.Type IronFeet - States - { - Spawn: - SUIT A -1 Bright - Stop - } -} - -// infrared ----------------------------------------------------------------- - -ACTOR Infrared : PowerupGiver -{ - +COUNTITEM - +INVENTORY.AUTOACTIVATE - +INVENTORY.ALWAYSPICKUP - Inventory.MaxAmount 0 - Powerup.Type LightAmp - Inventory.PickupMessage "$GOTVISOR" - States - { - Spawn: - PVIS A 6 Bright - PVIS B 6 - Loop - } -} - -// Allmap ------------------------------------------------------------------- - -ACTOR Allmap : MapRevealer -{ - +COUNTITEM - +INVENTORY.FANCYPICKUPSOUND - +INVENTORY.ALWAYSPICKUP - Inventory.MaxAmount 0 - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$GOTMAP" - States - { - Spawn: - PMAP ABCDCB 6 Bright - Loop - } -} - -// Berserk ------------------------------------------------------------------ - -ACTOR Berserk : CustomInventory -{ - +COUNTITEM - +INVENTORY.ALWAYSPICKUP - Inventory.PickupMessage "$GOTBERSERK" - Inventory.PickupSound "misc/p_pkup" - States - { - Spawn: - PSTR A -1 - Stop - Pickup: - TNT1 A 0 A_GiveInventory("PowerStrength") - TNT1 A 0 HealThing(100, 0) - TNT1 A 0 A_SelectWeapon("Fist") - Stop - } -} - diff --git a/wadsrc/static/actors/doom/doomdecorations.txt b/wadsrc/static/actors/doom/doomdecorations.txt deleted file mode 100644 index 4206c09ed..000000000 --- a/wadsrc/static/actors/doom/doomdecorations.txt +++ /dev/null @@ -1,753 +0,0 @@ - -// Tech lamp --------------------------------------------------------------- - -ACTOR TechLamp -{ - Radius 16 - Height 80 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - TLMP ABCD 4 BRIGHT - Loop - } -} - -// Tech lamp 2 ------------------------------------------------------------- - -ACTOR TechLamp2 -{ - Radius 16 - Height 60 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - TLP2 ABCD 4 BRIGHT - Loop - } -} - -// Column ------------------------------------------------------------------ - -ACTOR Column -{ - Radius 16 - Height 48 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - COLU A -1 BRIGHT - Stop - } -} - -// Tall green column ------------------------------------------------------- - -ACTOR TallGreenColumn -{ - Radius 16 - Height 52 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - COL1 A -1 - Stop - } -} - -// Short green column ------------------------------------------------------ - -ACTOR ShortGreenColumn -{ - Radius 16 - Height 40 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - COL2 A -1 - Stop - } -} - -// Tall red column --------------------------------------------------------- - -ACTOR TallRedColumn -{ - Radius 16 - Height 52 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - COL3 A -1 - Stop - } -} - -// Short red column -------------------------------------------------------- - -ACTOR ShortRedColumn -{ - Radius 16 - Height 40 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - COL4 A -1 - Stop - } -} - -// Skull column ------------------------------------------------------------ - -ACTOR SkullColumn -{ - Radius 16 - Height 40 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - COL6 A -1 - Stop - } -} - -// Heart column ------------------------------------------------------------ - -ACTOR HeartColumn -{ - Radius 16 - Height 40 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - COL5 AB 14 - Loop - } -} - -// Evil eye ---------------------------------------------------------------- - -ACTOR EvilEye -{ - Radius 16 - Height 54 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - CEYE ABCB 6 BRIGHT - Loop - } -} - -// Floating skull ---------------------------------------------------------- - -ACTOR FloatingSkull -{ - Radius 16 - Height 26 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - FSKU ABC 6 BRIGHT - Loop - } -} - -// Torch tree -------------------------------------------------------------- - -ACTOR TorchTree -{ - Radius 16 - Height 56 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - TRE1 A -1 - Stop - } -} - -// Blue torch -------------------------------------------------------------- - -ACTOR BlueTorch -{ - Radius 16 - Height 68 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - TBLU ABCD 4 BRIGHT - Loop - } -} - -// Green torch ------------------------------------------------------------- - -ACTOR GreenTorch -{ - Radius 16 - Height 68 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - TGRN ABCD 4 BRIGHT - Loop - } -} - -// Red torch --------------------------------------------------------------- - -ACTOR RedTorch -{ - Radius 16 - Height 68 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - TRED ABCD 4 BRIGHT - Loop - } -} - -// Short blue torch -------------------------------------------------------- - -ACTOR ShortBlueTorch -{ - Radius 16 - Height 37 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - SMBT ABCD 4 BRIGHT - Loop - } -} - -// Short green torch ------------------------------------------------------- - -ACTOR ShortGreenTorch -{ - Radius 16 - Height 37 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - SMGT ABCD 4 BRIGHT - Loop - } -} - -// Short red torch --------------------------------------------------------- - -ACTOR ShortRedTorch -{ - Radius 16 - Height 37 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - SMRT ABCD 4 BRIGHT - Loop - } -} - -// Stalagtite -------------------------------------------------------------- - -ACTOR Stalagtite -{ - Radius 16 - Height 40 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - SMIT A -1 - Stop - } -} - -// Tech pillar ------------------------------------------------------------- - -ACTOR TechPillar -{ - Radius 16 - Height 128 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - ELEC A -1 - Stop - } -} - -// Candle stick ------------------------------------------------------------ - -ACTOR Candlestick -{ - Radius 20 - Height 14 - ProjectilePassHeight -16 - States - { - Spawn: - CAND A -1 BRIGHT - Stop - } -} - -// Candelabra -------------------------------------------------------------- - -ACTOR Candelabra -{ - Radius 16 - Height 60 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - CBRA A -1 BRIGHT - Stop - } -} - -// Bloody twitch ----------------------------------------------------------- - -ACTOR BloodyTwitch -{ - Radius 16 - Height 68 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - GOR1 A 10 - GOR1 B 15 - GOR1 C 8 - GOR1 B 6 - Loop - } -} - -// Meat 2 ------------------------------------------------------------------ - -ACTOR Meat2 -{ - Radius 16 - Height 84 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - GOR2 A -1 - Stop - } -} - -// Meat 3 ------------------------------------------------------------------ - -ACTOR Meat3 -{ - Radius 16 - Height 84 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - GOR3 A -1 - Stop - } -} - -// Meat 4 ------------------------------------------------------------------ - -ACTOR Meat4 -{ - Radius 16 - Height 68 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - GOR4 A -1 - Stop - } -} - -// Meat 5 ------------------------------------------------------------------ - -ACTOR Meat5 -{ - Radius 16 - Height 52 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - GOR5 A -1 - Stop - } -} - -// Nonsolid meat ----------------------------------------------------------- - -ACTOR NonsolidMeat2 : Meat2 -{ - -SOLID - Radius 20 -} - -ACTOR NonsolidMeat3 : Meat3 -{ - -SOLID - Radius 20 -} - -ACTOR NonsolidMeat4 : Meat4 -{ - -SOLID - Radius 20 -} - -ACTOR NonsolidMeat5 : Meat5 -{ - -SOLID - Radius 20 -} - -// Nonsolid bloody twitch -------------------------------------------------- - -ACTOR NonsolidTwitch : BloodyTwitch -{ - -SOLID - Radius 20 -} - -// Head on a stick --------------------------------------------------------- - -ACTOR HeadOnAStick -{ - Radius 16 - Height 56 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - POL4 A -1 - Stop - } -} - -// Heads (plural!) on a stick ---------------------------------------------- - -ACTOR HeadsOnAStick -{ - Radius 16 - Height 64 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - POL2 A -1 - Stop - } -} - -// Head candles ------------------------------------------------------------ - -ACTOR HeadCandles -{ - Radius 16 - Height 42 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - POL3 AB 6 BRIGHT - Loop - } -} - -// Dead on a stick --------------------------------------------------------- - -ACTOR DeadStick -{ - Radius 16 - Height 64 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - POL1 A -1 - Stop - } -} - -// Still alive on a stick -------------------------------------------------- - -ACTOR LiveStick -{ - Radius 16 - Height 64 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - POL6 A 6 - POL6 B 8 - Loop - } -} - -// Big tree ---------------------------------------------------------------- - -ACTOR BigTree -{ - Radius 32 - Height 108 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - TRE2 A -1 - Stop - } -} - -// Burning barrel ---------------------------------------------------------- - -ACTOR BurningBarrel -{ - Radius 16 - Height 32 - ProjectilePassHeight -16 - +SOLID - States - { - Spawn: - FCAN ABC 4 BRIGHT - Loop - } -} - -// Hanging with no guts ---------------------------------------------------- - -ACTOR HangNoGuts -{ - Radius 16 - Height 88 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - HDB1 A -1 - Stop - } -} - -// Hanging from bottom with no brain --------------------------------------- - -ACTOR HangBNoBrain -{ - Radius 16 - Height 88 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - HDB2 A -1 - Stop - } -} - -// Hanging from top, looking down ------------------------------------------ - -ACTOR HangTLookingDown -{ - Radius 16 - Height 64 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - HDB3 A -1 - Stop - } -} - -// Hanging from top, looking up -------------------------------------------- - -ACTOR HangTLookingUp -{ - Radius 16 - Height 64 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - HDB5 A -1 - Stop - } -} - -// Hanging from top, skully ------------------------------------------------ - -ACTOR HangTSkull -{ - Radius 16 - Height 64 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - HDB4 A -1 - Stop - } -} - -// Hanging from top without a brain ---------------------------------------- - -ACTOR HangTNoBrain -{ - Radius 16 - Height 64 - +SOLID - +NOGRAVITY - +SPAWNCEILING - States - { - Spawn: - HDB6 A -1 - Stop - } -} - -// Colon gibs -------------------------------------------------------------- - -ACTOR ColonGibs -{ - Radius 20 - Height 4 - +NOBLOCKMAP - +MOVEWITHSECTOR - States - { - Spawn: - POB1 A -1 - Stop - } -} - -// Small pool o' blood ----------------------------------------------------- - -ACTOR SmallBloodPool -{ - Radius 20 - Height 1 - +NOBLOCKMAP - +MOVEWITHSECTOR - States - { - Spawn: - POB2 A -1 - Stop - } -} - -// brain stem lying on the ground ------------------------------------------ - -ACTOR BrainStem -{ - Radius 20 - Height 4 - +NOBLOCKMAP - +MOVEWITHSECTOR - States - { - Spawn: - BRS1 A -1 - Stop - } -} - - -// Grey stalagmite (unused Doom sprite, definition taken from Skulltag ----- - -ACTOR Stalagmite -{ - Radius 16 - Height 48 - +SOLID - States - { - Spawn: - SMT2 A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/doom/doomhealth.txt b/wadsrc/static/actors/doom/doomhealth.txt deleted file mode 100644 index c1a8d96ff..000000000 --- a/wadsrc/static/actors/doom/doomhealth.txt +++ /dev/null @@ -1,45 +0,0 @@ -// Health bonus ------------------------------------------------------------- - -ACTOR HealthBonus : Health -{ - +COUNTITEM - +INVENTORY.ALWAYSPICKUP - Inventory.Amount 1 - Inventory.MaxAmount 200 - Inventory.PickupMessage "$GOTHTHBONUS" - States - { - Spawn: - BON1 ABCDCB 6 - Loop - } -} - -// Stimpack ----------------------------------------------------------------- - -ACTOR Stimpack : Health -{ - Inventory.Amount 10 - Inventory.PickupMessage "$GOTSTIM" - States - { - Spawn: - STIM A -1 - Stop - } -} - -// Medikit ----------------------------------------------------------------- - -ACTOR Medikit : Health -{ - Inventory.Amount 25 - Inventory.PickupMessage "$GOTMEDIKIT" - Health.LowMessage 25, "$GOTMEDINEED" - States - { - Spawn: - MEDI A -1 - Stop - } -} diff --git a/wadsrc/static/actors/doom/doomimp.txt b/wadsrc/static/actors/doom/doomimp.txt deleted file mode 100644 index 008cc5229..000000000 --- a/wadsrc/static/actors/doom/doomimp.txt +++ /dev/null @@ -1,88 +0,0 @@ -//=========================================================================== -// -// Imp -// -//=========================================================================== -ACTOR DoomImp -{ - Health 60 - Radius 20 - Height 56 - Mass 100 - Speed 8 - PainChance 200 - Monster - +FLOORCLIP - SeeSound "imp/sight" - PainSound "imp/pain" - DeathSound "imp/death" - ActiveSound "imp/active" - HitObituary "$OB_IMPHIT" - Obituary "$OB_IMP" - States - { - Spawn: - TROO AB 10 A_Look - Loop - See: - TROO AABBCCDD 3 A_Chase - Loop - Melee: - Missile: - TROO EF 8 A_FaceTarget - TROO G 6 A_TroopAttack - Goto See - Pain: - TROO H 2 - TROO H 2 A_Pain - Goto See - Death: - TROO I 8 - TROO J 8 A_Scream - TROO K 6 - TROO L 6 A_NoBlocking - TROO M -1 - Stop - XDeath: - TROO N 5 - TROO O 5 A_XScream - TROO P 5 - TROO Q 5 A_NoBlocking - TROO RST 5 - TROO U -1 - Stop - Raise: - TROO ML 8 - TROO KJI 6 - Goto See - } -} - -//=========================================================================== -// -// Imp fireball -// -//=========================================================================== -ACTOR DoomImpBall -{ - Radius 6 - Height 8 - Speed 10 - FastSpeed 20 - Damage 3 - Projectile - +RANDOMIZE - RenderStyle Add - Alpha 1 - SeeSound "imp/attack" - DeathSound "imp/shotx" - States - { - Spawn: - BAL1 AB 4 BRIGHT - Loop - Death: - BAL1 CDE 6 BRIGHT - Stop - } -} diff --git a/wadsrc/static/actors/doom/doomkeys.txt b/wadsrc/static/actors/doom/doomkeys.txt deleted file mode 100644 index d24392559..000000000 --- a/wadsrc/static/actors/doom/doomkeys.txt +++ /dev/null @@ -1,98 +0,0 @@ - -Actor DoomKey : Key -{ - Radius 20 - Height 16 - +NOTDMATCH -} - -// Blue key card ------------------------------------------------------------ - -Actor BlueCard : DoomKey -{ - Inventory.Pickupmessage "$GOTBLUECARD" - Inventory.Icon "STKEYS0" - States - { - Spawn: - BKEY A 10 - BKEY B 10 bright - loop - } -} - -// Yellow key card ---------------------------------------------------------- - -Actor YellowCard : DoomKey -{ - Inventory.Pickupmessage "$GOTYELWCARD" - Inventory.Icon "STKEYS1" - States - { - Spawn: - YKEY A 10 - YKEY B 10 bright - loop - } -} - -// Red key card ------------------------------------------------------------- - -Actor RedCard : DoomKey -{ - Inventory.Pickupmessage "$GOTREDCARD" - Inventory.Icon "STKEYS2" - States - { - Spawn: - RKEY A 10 - RKEY B 10 bright - loop - } -} - -// Blue skull key ----------------------------------------------------------- - -Actor BlueSkull : DoomKey -{ - Inventory.Pickupmessage "$GOTBLUESKUL" - Inventory.Icon "STKEYS3" - States - { - Spawn: - BSKU A 10 - BSKU B 10 bright - loop - } -} - -// Yellow skull key --------------------------------------------------------- - -Actor YellowSkull : DoomKey -{ - Inventory.Pickupmessage "$GOTYELWSKUL" - Inventory.Icon "STKEYS4" - States - { - Spawn: - YSKU A 10 - YSKU B 10 bright - loop - } -} - -// Red skull key ------------------------------------------------------------ - -Actor RedSkull : DoomKey -{ - Inventory.Pickupmessage "$GOTREDSKUL" - Inventory.Icon "STKEYS5" - States - { - Spawn: - RSKU A 10 - RSKU B 10 bright - loop - } -} - diff --git a/wadsrc/static/actors/doom/doommisc.txt b/wadsrc/static/actors/doom/doommisc.txt deleted file mode 100644 index cb22474b9..000000000 --- a/wadsrc/static/actors/doom/doommisc.txt +++ /dev/null @@ -1,104 +0,0 @@ -// The barrel of green goop ------------------------------------------------ - -ACTOR ExplosiveBarrel -{ - Health 20 - Radius 10 - Height 42 - +SOLID - +SHOOTABLE - +NOBLOOD - +ACTIVATEMCROSS - +DONTGIB - +NOICEDEATH - +OLDRADIUSDMG - DeathSound "world/barrelx" - Obituary "$OB_BARREL" - States - { - Spawn: - BAR1 AB 6 - Loop - Death: - BEXP A 5 BRIGHT - BEXP B 5 BRIGHT A_Scream - BEXP C 5 BRIGHT - BEXP D 5 BRIGHT A_Explode - BEXP E 10 BRIGHT - TNT1 A 1050 BRIGHT A_BarrelDestroy - TNT1 A 5 A_Respawn - Wait - } -} - -// Bullet puff ------------------------------------------------------------- - -ACTOR BulletPuff -{ - +NOBLOCKMAP - +NOGRAVITY - +ALLOWPARTICLES - +RANDOMIZE - RenderStyle Translucent - Alpha 0.5 - VSpeed 1 - Mass 5 - States - { - Spawn: - PUFF A 4 Bright - PUFF B 4 - Melee: - PUFF CD 4 - Stop - } -} - -// Container for an unused state ------------------------------------------- - -/* Doom defined the states S_STALAG, S_DEADTORSO, and S_DEADBOTTOM but never - * actually used them. For compatibility with DeHackEd patches, they still - * need to be kept around. This actor serves that purpose. - */ - -ACTOR DoomUnusedStates -{ - States - { - Label1: - SMT2 A -1 - stop - Label2: - PLAY N -1 - stop - PLAY S -1 - stop - TNT: // MBF compatibility - TNT1 A -1 - Loop - } -} - -// MBF Beta emulation items - -Actor EvilSceptre : ScoreItem -{ - Inventory.PickupMessage "$BETA_BONUS3" - States - { - Spawn: - BON3 A 6 - Loop - } -} - -Actor UnholyBible : ScoreItem -{ - Inventory.PickupMessage "$BETA_BONUS4" - States - { - Spawn: - BON4 A 6 - Loop - } -} diff --git a/wadsrc/static/actors/doom/doomplayer.txt b/wadsrc/static/actors/doom/doomplayer.txt deleted file mode 100644 index e31c10ea7..000000000 --- a/wadsrc/static/actors/doom/doomplayer.txt +++ /dev/null @@ -1,90 +0,0 @@ -//=========================================================================== -// -// Player -// -//=========================================================================== -ACTOR DoomPlayer : PlayerPawn -{ - Speed 1 - Health 100 - Radius 16 - Height 56 - Mass 100 - PainChance 255 - Player.DisplayName "Marine" - Player.CrouchSprite "PLYC" - Player.StartItem "Pistol" - Player.StartItem "Fist" - Player.StartItem "Clip", 50 - Player.WeaponSlot 1, Fist, Chainsaw - Player.WeaponSlot 2, Pistol - Player.WeaponSlot 3, Shotgun, SuperShotgun - Player.WeaponSlot 4, Chaingun - Player.WeaponSlot 5, RocketLauncher - Player.WeaponSlot 6, PlasmaRifle - Player.WeaponSlot 7, BFG9000 - - Player.ColorRange 112, 127 - Player.Colorset 0, "Green", 0x70, 0x7F, 0x72 - Player.Colorset 1, "Gray", 0x60, 0x6F, 0x62 - Player.Colorset 2, "Brown", 0x40, 0x4F, 0x42 - Player.Colorset 3, "Red", 0x20, 0x2F, 0x22 - // Doom Legacy additions - Player.Colorset 4, "Light Gray", 0x58, 0x67, 0x5A - Player.Colorset 5, "Light Brown", 0x38, 0x47, 0x3A - Player.Colorset 6, "Light Red", 0xB0, 0xBF, 0xB2 - Player.Colorset 7, "Light Blue", 0xC0, 0xCF, 0xC2 - - States - { - Spawn: - PLAY A -1 - Loop - See: - PLAY ABCD 4 - Loop - Missile: - PLAY E 12 - Goto Spawn - Melee: - PLAY F 6 BRIGHT - Goto Missile - Pain: - PLAY G 4 - PLAY G 4 A_Pain - Goto Spawn - Death: - PLAY H 0 A_PlayerSkinCheck("AltSkinDeath") - Death1: - PLAY H 10 - PLAY I 10 A_PlayerScream - PLAY J 10 A_NoBlocking - PLAY KLM 10 - PLAY N -1 - Stop - XDeath: - PLAY O 0 A_PlayerSkinCheck("AltSkinXDeath") - XDeath1: - PLAY O 5 - PLAY P 5 A_XScream - PLAY Q 5 A_NoBlocking - PLAY RSTUV 5 - PLAY W -1 - Stop - AltSkinDeath: - PLAY H 6 - PLAY I 6 A_PlayerScream - PLAY JK 6 - PLAY L 6 A_NoBlocking - PLAY MNO 6 - PLAY P -1 - Stop - AltSkinXDeath: - PLAY Q 5 A_PlayerScream - PLAY R 0 A_NoBlocking - PLAY R 5 A_SkullPop - PLAY STUVWX 5 - PLAY Y -1 - Stop - } -} diff --git a/wadsrc/static/actors/doom/doomweapons.txt b/wadsrc/static/actors/doom/doomweapons.txt deleted file mode 100644 index 16369572b..000000000 --- a/wadsrc/static/actors/doom/doomweapons.txt +++ /dev/null @@ -1,574 +0,0 @@ -// -------------------------------------------------------------------------- -// -// Doom weapon base class -// -// -------------------------------------------------------------------------- - -ACTOR DoomWeapon : Weapon -{ - Weapon.Kickback 100 -} - -// -------------------------------------------------------------------------- -// -// Fist -// -// -------------------------------------------------------------------------- - -ACTOR Fist : Weapon -{ - Weapon.SelectionOrder 3700 - Weapon.Kickback 100 - Obituary "$OB_MPFIST" - Tag "$TAG_FIST" - +WEAPON.WIMPY_WEAPON - +WEAPON.MELEEWEAPON - States - { - Ready: - PUNG A 1 A_WeaponReady - Loop - Deselect: - PUNG A 1 A_Lower - Loop - Select: - PUNG A 1 A_Raise - Loop - Fire: - PUNG B 4 - PUNG C 4 A_Punch - PUNG D 5 - PUNG C 4 - PUNG B 5 A_ReFire - Goto Ready - } -} - - -// -------------------------------------------------------------------------- -// -// Pistol -// -// -------------------------------------------------------------------------- - -ACTOR Pistol : DoomWeapon -{ - Weapon.SelectionOrder 1900 - Weapon.AmmoUse 1 - Weapon.AmmoGive 20 - Weapon.AmmoType "Clip" - Obituary "$OB_MPPISTOL" - +WEAPON.WIMPY_WEAPON - Inventory.Pickupmessage "$PICKUP_PISTOL_DROPPED" - Tag "$TAG_PISTOL" - States - { - Ready: - PISG A 1 A_WeaponReady - Loop - Deselect: - PISG A 1 A_Lower - Loop - Select: - PISG A 1 A_Raise - Loop - Fire: - PISG A 4 - PISG B 6 A_FirePistol - PISG C 4 - PISG B 5 A_ReFire - Goto Ready - Flash: - PISF A 7 Bright A_Light1 - Goto LightDone - PISF A 7 Bright A_Light1 - Goto LightDone - Spawn: - PIST A -1 - Stop - } -} - -// -------------------------------------------------------------------------- -// -// Chainsaw -// -// -------------------------------------------------------------------------- - -ACTOR Chainsaw : Weapon -{ - Weapon.Kickback 0 - Weapon.SelectionOrder 2200 - Weapon.UpSound "weapons/sawup" - Weapon.ReadySound "weapons/sawidle" - Inventory.PickupMessage "$GOTCHAINSAW" - Obituary "$OB_MPCHAINSAW" - Tag "$TAG_CHAINSAW" - +WEAPON.MELEEWEAPON - States - { - Ready: - SAWG CD 4 A_WeaponReady - Loop - Deselect: - SAWG C 1 A_Lower - Loop - Select: - SAWG C 1 A_Raise - Loop - Fire: - SAWG AB 4 A_Saw - SAWG B 0 A_ReFire - Goto Ready - Spawn: - CSAW A -1 - Stop - } -} - - -// -------------------------------------------------------------------------- -// -// Shotgun -// -// -------------------------------------------------------------------------- - -ACTOR Shotgun : DoomWeapon -{ - Weapon.SelectionOrder 1300 - Weapon.AmmoUse 1 - Weapon.AmmoGive 8 - Weapon.AmmoType "Shell" - Inventory.PickupMessage "$GOTSHOTGUN" - Obituary "$OB_MPSHOTGUN" - Tag "$TAG_SHOTGUN" - States - { - Ready: - SHTG A 1 A_WeaponReady - Loop - Deselect: - SHTG A 1 A_Lower - Loop - Select: - SHTG A 1 A_Raise - Loop - Fire: - SHTG A 3 - SHTG A 7 A_FireShotgun - SHTG BC 5 - SHTG D 4 - SHTG CB 5 - SHTG A 3 - SHTG A 7 A_ReFire - Goto Ready - Flash: - SHTF A 4 Bright A_Light1 - SHTF B 3 Bright A_Light2 - Goto LightDone - Spawn: - SHOT A -1 - Stop - } -} - -// -------------------------------------------------------------------------- -// -// Shotgun -// -// -------------------------------------------------------------------------- - -ACTOR SuperShotgun : DoomWeapon -{ - Weapon.SelectionOrder 400 - Weapon.AmmoUse 2 - Weapon.AmmoGive 8 - Weapon.AmmoType "Shell" - Inventory.PickupMessage "$GOTSHOTGUN2" - Obituary "$OB_MPSSHOTGUN" - Tag "$TAG_SUPERSHOTGUN" - States - { - Ready: - SHT2 A 1 A_WeaponReady - Loop - Deselect: - SHT2 A 1 A_Lower - Loop - Select: - SHT2 A 1 A_Raise - Loop - Fire: - SHT2 A 3 - SHT2 A 7 A_FireShotgun2 - SHT2 B 7 - SHT2 C 7 A_CheckReload - SHT2 D 7 A_OpenShotgun2 - SHT2 E 7 - SHT2 F 7 A_LoadShotgun2 - SHT2 G 6 - SHT2 H 6 A_CloseShotgun2 - SHT2 A 5 A_ReFire - Goto Ready - // unused states - SHT2 B 7 - SHT2 A 3 - Goto Deselect - Flash: - SHT2 I 4 Bright A_Light1 - SHT2 J 3 Bright A_Light2 - Goto LightDone - Spawn: - SGN2 A -1 - Stop - } -} - -// -------------------------------------------------------------------------- -// -// Chaingun -// -// -------------------------------------------------------------------------- - -ACTOR Chaingun : DoomWeapon -{ - Weapon.SelectionOrder 700 - Weapon.AmmoUse 1 - Weapon.AmmoGive 20 - Weapon.AmmoType "Clip" - Inventory.PickupMessage "$GOTCHAINGUN" - Obituary "$OB_MPCHAINGUN" - Tag "$TAG_CHAINGUN" - States - { - Ready: - CHGG A 1 A_WeaponReady - Loop - Deselect: - CHGG A 1 A_Lower - Loop - Select: - CHGG A 1 A_Raise - Loop - Fire: - CHGG AB 4 A_FireCGun - CHGG B 0 A_ReFire - Goto Ready - Flash: - CHGF A 5 Bright A_Light1 - Goto LightDone - CHGF B 5 Bright A_Light2 - Goto LightDone - Spawn: - MGUN A -1 - Stop - } -} - -// -------------------------------------------------------------------------- -// -// Rocket launcher -// -// -------------------------------------------------------------------------- - -ACTOR RocketLauncher : DoomWeapon -{ - Weapon.SelectionOrder 2500 - Weapon.AmmoUse 1 - Weapon.AmmoGive 2 - Weapon.AmmoType "RocketAmmo" - +WEAPON.NOAUTOFIRE - Inventory.PickupMessage "$GOTLAUNCHER" - Tag "$TAG_ROCKETLAUNCHER" - States - { - Ready: - MISG A 1 A_WeaponReady - Loop - Deselect: - MISG A 1 A_Lower - Loop - Select: - MISG A 1 A_Raise - Loop - Fire: - MISG B 8 A_GunFlash - MISG B 12 A_FireMissile - MISG B 0 A_ReFire - Goto Ready - Flash: - MISF A 3 Bright A_Light1 - MISF B 4 Bright - MISF CD 4 Bright A_Light2 - Goto LightDone - Spawn: - LAUN A -1 - Stop - } -} - -ACTOR Rocket -{ - Radius 11 - Height 8 - Speed 20 - Damage 20 - Projectile - +RANDOMIZE - +DEHEXPLOSION - +ROCKETTRAIL - SeeSound "weapons/rocklf" - DeathSound "weapons/rocklx" - Obituary "$OB_MPROCKET" - States - { - Spawn: - MISL A 1 Bright - Loop - Death: - MISL B 8 Bright A_Explode - MISL C 6 Bright - MISL D 4 Bright - Stop - } -} - -// -------------------------------------------------------------------------- -// -// Grenade -- Taken and adapted from Skulltag, with MBF stuff added to it -// -// -------------------------------------------------------------------------- - -ACTOR Grenade -{ - Radius 8 - Height 8 - Speed 25 - Damage 20 - Projectile - -NOGRAVITY - +RANDOMIZE - +DEHEXPLOSION - +GRENADETRAIL - BounceType "Doom" - Gravity 0.25 - SeeSound "weapons/grenlf" - DeathSound "weapons/grenlx" - BounceSound "weapons/grbnce" - Obituary "$OB_GRENADE" - DamageType Grenade - - States - { - Spawn: - SGRN A 1 Bright - Loop - Death: - MISL B 8 Bright A_Explode - MISL C 6 Bright - MISL D 4 Bright - Stop - Grenade: - MISL A 1000 A_Die - Wait - Detonate: - MISL B 4 A_Scream - MISL C 6 A_Detonate - MISL D 10 - Stop - Mushroom: - MISL B 8 A_Mushroom - Goto Death+1 - } -} - -// -------------------------------------------------------------------------- -// -// Plasma rifle -// -// -------------------------------------------------------------------------- - -ACTOR PlasmaRifle : DoomWeapon -{ - Weapon.SelectionOrder 100 - Weapon.AmmoUse 1 - Weapon.AmmoGive 40 - Weapon.AmmoType "Cell" - Inventory.PickupMessage "$GOTPLASMA" - Tag "$TAG_PLASMARIFLE" - States - { - Ready: - PLSG A 1 A_WeaponReady - Loop - Deselect: - PLSG A 1 A_Lower - Loop - Select: - PLSG A 1 A_Raise - Loop - Fire: - PLSG A 3 A_FirePlasma - PLSG B 20 A_ReFire - Goto Ready - Flash: - PLSF A 4 Bright A_Light1 - Goto LightDone - PLSF B 4 Bright A_Light1 - Goto LightDone - Spawn: - PLAS A -1 - Stop - } -} - -ACTOR PlasmaBall -{ - Radius 13 - Height 8 - Speed 25 - Damage 5 - Projectile - +RANDOMIZE - RenderStyle Add - Alpha 0.75 - SeeSound "weapons/plasmaf" - DeathSound "weapons/plasmax" - Obituary "$OB_MPPLASMARIFLE" - States - { - Spawn: - PLSS AB 6 Bright - Loop - Death: - PLSE ABCDE 4 Bright - Stop - } -} - -// -------------------------------------------------------------------------- -// -// BFG 2704 -// -// -------------------------------------------------------------------------- - -ACTOR PlasmaBall1 : PlasmaBall -{ - Damage 4 - BounceType "Classic" - BounceFactor 1.0 - Obituary "$OB_MPBFG_MBF" - States - { - Spawn: - PLS1 AB 6 Bright - Loop - Death: - PLS1 CDEFG 4 Bright - Stop - } -} - -ACTOR PlasmaBall2 : PlasmaBall1 -{ - States - { - Spawn: - PLS2 AB 6 Bright - Loop - Death: - PLS2 CDE 4 Bright - Stop - } -} - -// -------------------------------------------------------------------------- -// -// BFG 9000 -// -// -------------------------------------------------------------------------- - -ACTOR BFG9000 : DoomWeapon -{ - Height 20 - Weapon.SelectionOrder 2800 - Weapon.AmmoUse 40 - Weapon.AmmoGive 40 - Weapon.AmmoType "Cell" - +WEAPON.NOAUTOFIRE - Inventory.PickupMessage "$GOTBFG9000" - Tag "$TAG_BFG9000" - States - { - Ready: - BFGG A 1 A_WeaponReady - Loop - Deselect: - BFGG A 1 A_Lower - Loop - Select: - BFGG A 1 A_Raise - Loop - Fire: - BFGG A 20 A_BFGsound - BFGG B 10 A_GunFlash - BFGG B 10 A_FireBFG - BFGG B 20 A_ReFire - Goto Ready - Flash: - BFGF A 11 Bright A_Light1 - BFGF B 6 Bright A_Light2 - Goto LightDone - Spawn: - BFUG A -1 - Stop - OldFire: - BFGG A 10 A_BFGsound - BFGG BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 1 A_FireOldBFG - BFGG B 0 A_Light0 - BFGG B 20 A_ReFire - Goto Ready - } -} - - -ACTOR BFGBall -{ - Radius 13 - Height 8 - Speed 25 - Damage 100 - Projectile - +RANDOMIZE - RenderStyle Add - Alpha 0.75 - DeathSound "weapons/bfgx" - Obituary "$OB_MPBFG_BOOM" - States - { - Spawn: - BFS1 AB 4 Bright - Loop - Death: - BFE1 AB 8 Bright - BFE1 C 8 Bright A_BFGSpray - BFE1 DEF 8 Bright - Stop - } -} - -ACTOR BFGExtra -{ - +NOBLOCKMAP - +NOGRAVITY - RenderStyle Add - Alpha 0.75 - DamageType "BFGSplash" - States - { - Spawn: - BFE2 ABCD 8 Bright - Stop - } -} - diff --git a/wadsrc/static/actors/doom/fatso.txt b/wadsrc/static/actors/doom/fatso.txt deleted file mode 100644 index 9b3a7d26a..000000000 --- a/wadsrc/static/actors/doom/fatso.txt +++ /dev/null @@ -1,89 +0,0 @@ -//=========================================================================== -// -// Mancubus -// -//=========================================================================== -ACTOR Fatso -{ - Health 600 - Radius 48 - Height 64 - Mass 1000 - Speed 8 - PainChance 80 - Monster - +FLOORCLIP - +BOSSDEATH - SeeSound "fatso/sight" - PainSound "fatso/pain" - DeathSound "fatso/death" - ActiveSound "fatso/active" - Obituary "$OB_FATSO" - States - { - Spawn: - FATT AB 15 A_Look - Loop - See: - FATT AABBCCDDEEFF 4 A_Chase - Loop - Missile: - FATT G 20 A_FatRaise - FATT H 10 BRIGHT A_FatAttack1 - FATT IG 5 A_FaceTarget - FATT H 10 BRIGHT A_FatAttack2 - FATT IG 5 A_FaceTarget - FATT H 10 BRIGHT A_FatAttack3 - FATT IG 5 A_FaceTarget - Goto See - Pain: - FATT J 3 - FATT J 3 A_Pain - Goto See - Death: - FATT K 6 - FATT L 6 A_Scream - FATT M 6 A_NoBlocking - FATT NOPQRS 6 - FATT T -1 A_BossDeath - Stop - Raise: - FATT R 5 - FATT QPONMLK 5 - Goto See - } -} - - - -//=========================================================================== -// -// Mancubus fireball -// -//=========================================================================== -ACTOR FatShot -{ - Radius 6 - Height 8 - Speed 20 - Damage 8 - Projectile - +RANDOMIZE - RenderStyle Add - Alpha 1 - SeeSound "fatso/attack" - DeathSound "fatso/shotx" - States - { - Spawn: - MANF AB 4 BRIGHT - Loop - Death: - MISL B 8 BRIGHT - MISL C 6 BRIGHT - MISL D 4 BRIGHT - Stop - } -} - - diff --git a/wadsrc/static/actors/doom/keen.txt b/wadsrc/static/actors/doom/keen.txt deleted file mode 100644 index 7ad41d2ce..000000000 --- a/wadsrc/static/actors/doom/keen.txt +++ /dev/null @@ -1,41 +0,0 @@ -//=========================================================================== -// -// Commander Keen -// -//=========================================================================== -ACTOR CommanderKeen -{ - Health 100 - Radius 16 - Height 72 - Mass 10000000 - PainChance 256 - +SOLID - +SPAWNCEILING - +NOGRAVITY - +SHOOTABLE - +COUNTKILL - +NOICEDEATH - +ISMONSTER - PainSound "keen/pain" - DeathSound "keen/death" - States - { - Spawn: - KEEN A -1 - Loop - Death: - KEEN AB 6 - KEEN C 6 A_Scream - KEEN DEFGH 6 - KEEN I 6 - KEEN J 6 - KEEN K 6 A_KeenDie - KEEN L -1 - Stop - Pain: - KEEN M 4 - KEEN M 8 A_Pain - Goto Spawn - } -} diff --git a/wadsrc/static/actors/doom/lostsoul.txt b/wadsrc/static/actors/doom/lostsoul.txt deleted file mode 100644 index bd6212cf2..000000000 --- a/wadsrc/static/actors/doom/lostsoul.txt +++ /dev/null @@ -1,80 +0,0 @@ -//=========================================================================== -// -// Lost Soul -// -//=========================================================================== -ACTOR LostSoul -{ - Health 100 - Radius 16 - Height 56 - Mass 50 - Speed 8 - Damage 3 - PainChance 256 - Monster - +FLOAT +NOGRAVITY +MISSILEMORE +DONTFALL +NOICEDEATH - AttackSound "skull/melee" - PainSound "skull/pain" - DeathSound "skull/death" - ActiveSound "skull/active" - RenderStyle SoulTrans - Obituary "$OB_SKULL" - States - { - Spawn: - SKUL AB 10 BRIGHT A_Look - Loop - See: - SKUL AB 6 BRIGHT A_Chase - Loop - Missile: - SKUL C 10 BRIGHT A_FaceTarget - SKUL D 4 BRIGHT A_SkullAttack - SKUL CD 4 BRIGHT - Goto Missile+2 - Pain: - SKUL E 3 BRIGHT - SKUL E 3 BRIGHT A_Pain - Goto See - Death: - SKUL F 6 BRIGHT - SKUL G 6 BRIGHT A_Scream - SKUL H 6 BRIGHT - SKUL I 6 BRIGHT A_NoBlocking - SKUL J 6 - SKUL K 6 - Stop - } -} - -Actor BetaSkull : LostSoul -{ - States - { - Spawn: - SKUL A 10 A_Look - Loop - See: - SKUL BCDA 5 A_Chase - Loop - Missile: - SKUL E 4 A_FaceTarget - SKUL F 5 A_BetaSkullAttack - SKUL F 4 - Goto See - Pain: - SKUL G 4 - SKUL H 2 A_Pain - Goto See - SKUL I 4 - Goto See - Death: - SKUL JKLM 5 - SKUL N 5 A_Scream - SKUL O 5 - SKUL P 5 A_Fall - SKUL Q 5 A_Stop - Wait - } -} diff --git a/wadsrc/static/actors/doom/painelemental.txt b/wadsrc/static/actors/doom/painelemental.txt deleted file mode 100644 index bba475650..000000000 --- a/wadsrc/static/actors/doom/painelemental.txt +++ /dev/null @@ -1,50 +0,0 @@ -//=========================================================================== -// -// Pain Elemental -// -//=========================================================================== -ACTOR PainElemental -{ - Health 400 - Radius 31 - Height 56 - Mass 400 - Speed 8 - PainChance 128 - Monster - +FLOAT - +NOGRAVITY - SeeSound "pain/sight" - PainSound "pain/pain" - DeathSound "pain/death" - ActiveSound "pain/active" - States - { - Spawn: - PAIN A 10 A_Look - Loop - See: - PAIN AABBCC 3 A_Chase - Loop - Missile: - PAIN D 5 A_FaceTarget - PAIN E 5 A_FaceTarget - PAIN F 5 BRIGHT A_FaceTarget - PAIN F 0 BRIGHT A_PainAttack - Goto See - Pain: - PAIN G 6 - PAIN G 6 A_Pain - Goto See - Death: - PAIN H 8 BRIGHT - PAIN I 8 BRIGHT A_Scream - PAIN JK 8 BRIGHT - PAIN L 8 BRIGHT A_PainDie - PAIN M 8 BRIGHT - Stop - Raise: - PAIN MLKJIH 8 - Goto See - } -} diff --git a/wadsrc/static/actors/doom/possessed.txt b/wadsrc/static/actors/doom/possessed.txt deleted file mode 100644 index 6961cc8a5..000000000 --- a/wadsrc/static/actors/doom/possessed.txt +++ /dev/null @@ -1,241 +0,0 @@ - -//=========================================================================== -// -// Zombie man -// -//=========================================================================== -ACTOR ZombieMan -{ - Health 20 - Radius 20 - Height 56 - Speed 8 - PainChance 200 - Monster - +FLOORCLIP - SeeSound "grunt/sight" - AttackSound "grunt/attack" - PainSound "grunt/pain" - DeathSound "grunt/death" - ActiveSound "grunt/active" - Obituary "$OB_ZOMBIE" - DropItem "Clip" - States - { - Spawn: - POSS AB 10 A_Look - Loop - See: - POSS AABBCCDD 4 A_Chase - Loop - Missile: - POSS E 10 A_FaceTarget - POSS F 8 A_PosAttack - POSS E 8 - Goto See - Pain: - POSS G 3 - POSS G 3 A_Pain - Goto See - Death: - POSS H 5 - POSS I 5 A_Scream - POSS J 5 A_NoBlocking - POSS K 5 - POSS L -1 - Stop - XDeath: - POSS M 5 - POSS N 5 A_XScream - POSS O 5 A_NoBlocking - POSS PQRST 5 - POSS U -1 - Stop - Raise: - POSS K 5 - POSS JIH 5 - Goto See - } -} - -//=========================================================================== -// -// Sergeant / Shotgun guy -// -//=========================================================================== -ACTOR ShotgunGuy -{ - Health 30 - Radius 20 - Height 56 - Mass 100 - Speed 8 - PainChance 170 - Monster - +FLOORCLIP - SeeSound "shotguy/sight" - AttackSound "shotguy/attack" - PainSound "shotguy/pain" - DeathSound "shotguy/death" - ActiveSound "shotguy/active" - Obituary "$OB_SHOTGUY" - DropItem "Shotgun" - States - { - Spawn: - SPOS AB 10 A_Look - Loop - See: - SPOS AABBCCDD 3 A_Chase - Loop - Missile: - SPOS E 10 A_FaceTarget - SPOS F 10 BRIGHT A_SposAttackUseAtkSound - SPOS E 10 - Goto See - Pain: - SPOS G 3 - SPOS G 3 A_Pain - Goto See - Death: - SPOS H 5 - SPOS I 5 A_Scream - SPOS J 5 A_NoBlocking - SPOS K 5 - SPOS L -1 - Stop - XDeath: - SPOS M 5 - SPOS N 5 A_XScream - SPOS O 5 A_NoBlocking - SPOS PQRST 5 - SPOS U -1 - Stop - Raise: - SPOS L 5 - SPOS KJIH 5 - Goto See - } -} - -//=========================================================================== -// -// Chaingunner -// -//=========================================================================== -ACTOR ChaingunGuy -{ - Health 70 - Radius 20 - Height 56 - Mass 100 - Speed 8 - PainChance 170 - Monster - +FLOORCLIP - SeeSound "chainguy/sight" - PainSound "chainguy/pain" - DeathSound "chainguy/death" - ActiveSound "chainguy/active" - AttackSound "chainguy/attack" - Obituary "$OB_CHAINGUY" - Dropitem "Chaingun" - States - { - Spawn: - CPOS AB 10 A_Look - Loop - See: - CPOS AABBCCDD 3 A_Chase - Loop - Missile: - CPOS E 10 A_FaceTarget - CPOS FE 4 BRIGHT A_CPosAttack - CPOS F 1 A_CPosRefire - Goto Missile+1 - Pain: - CPOS G 3 - CPOS G 3 A_Pain - Goto See - Death: - CPOS H 5 - CPOS I 5 A_Scream - CPOS J 5 A_NoBlocking - CPOS KLM 5 - CPOS N -1 - Stop - XDeath: - CPOS O 5 - CPOS P 5 A_XScream - CPOS Q 5 A_NoBlocking - CPOS RS 5 - CPOS T -1 - Stop - Raise: - CPOS N 5 - CPOS MLKJIH 5 - Goto See - } -} - -//=========================================================================== -// -// SS Nazi -// -//=========================================================================== -ACTOR WolfensteinSS -{ - Health 50 - Radius 20 - Height 56 - Speed 8 - PainChance 170 - Monster - +FLOORCLIP - SeeSound "wolfss/sight" - PainSound "wolfss/pain" - DeathSound "wolfss/death" - ActiveSound "wolfss/active" - AttackSound "wolfss/attack" - Obituary "$OB_WOLFSS" - Dropitem "Clip" - States - { - Spawn: - SSWV AB 10 A_Look - Loop - See: - SSWV AABBCCDD 3 A_Chase - Loop - Missile: - SSWV E 10 A_FaceTarget - SSWV F 10 A_FaceTarget - SSWV G 4 BRIGHT A_CPosAttack - SSWV F 6 A_FaceTarget - SSWV G 4 BRIGHT A_CPosAttack - SSWV F 1 A_CPosRefire - Goto Missile+1 - Pain: - SSWV H 3 - SSWV H 3 A_Pain - Goto See - Death: - SSWV I 5 - SSWV J 5 A_Scream - SSWV K 5 A_NoBlocking - SSWV L 5 - SSWV M -1 - Stop - XDeath: - SSWV N 5 - SSWV O 5 A_XScream - SSWV P 5 A_NoBlocking - SSWV QRSTU 5 - SSWV V -1 - Stop - Raise: - SSWV M 5 - SSWV LKJI 5 - Goto See - } -} diff --git a/wadsrc/static/actors/doom/revenant.txt b/wadsrc/static/actors/doom/revenant.txt deleted file mode 100644 index 4062647f4..000000000 --- a/wadsrc/static/actors/doom/revenant.txt +++ /dev/null @@ -1,113 +0,0 @@ -//=========================================================================== -// -// Revenant -// -//=========================================================================== -ACTOR Revenant -{ - Health 300 - Radius 20 - Height 56 - Mass 500 - Speed 10 - PainChance 100 - Monster - MeleeThreshold 196 - +MISSILEMORE - +FLOORCLIP - SeeSound "skeleton/sight" - PainSound "skeleton/pain" - DeathSound "skeleton/death" - ActiveSound "skeleton/active" - MeleeSound "skeleton/melee" - HitObituary "$OB_UNDEADHIT" - Obituary "$OB_UNDEAD" - States - { - Spawn: - SKEL AB 10 A_Look - Loop - See: - SKEL AABBCCDDEEFF 2 A_Chase - Loop - Melee: - SKEL G 0 A_FaceTarget - SKEL G 6 A_SkelWhoosh - SKEL H 6 A_FaceTarget - SKEL I 6 A_SkelFist - Goto See - Missile: - SKEL J 0 BRIGHT A_FaceTarget - SKEL J 10 BRIGHT A_FaceTarget - SKEL K 10 A_SkelMissile - SKEL K 10 A_FaceTarget - Goto See - Pain: - SKEL L 5 - SKEL L 5 A_Pain - Goto See - Death: - SKEL LM 7 - SKEL N 7 A_Scream - SKEL O 7 A_NoBlocking - SKEL P 7 - SKEL Q -1 - Stop - Raise: - SKEL Q 5 - SKEL PONML 5 - Goto See - } -} - - -//=========================================================================== -// -// Revenant Tracer -// -//=========================================================================== -ACTOR RevenantTracer -{ - Radius 11 - Height 8 - Speed 10 - Damage 10 - Projectile - +SEEKERMISSILE - +RANDOMIZE - SeeSound "skeleton/attack" - DeathSound "skeleton/tracex" - RenderStyle Add - States - { - Spawn: - FATB AB 2 BRIGHT A_Tracer - Loop - Death: - FBXP A 8 BRIGHT - FBXP B 6 BRIGHT - FBXP C 4 BRIGHT - Stop - } -} - - -//=========================================================================== -// -// Revenant Tracer Smoke -// -//=========================================================================== -ACTOR RevenantTracerSmoke -{ - +NOBLOCKMAP - +NOGRAVITY - +NOTELEPORT - RenderStyle Translucent - Alpha 0.5 - States - { - Spawn: - PUFF ABABC 4 - Stop - } -} diff --git a/wadsrc/static/actors/doom/scriptedmarine.txt b/wadsrc/static/actors/doom/scriptedmarine.txt deleted file mode 100644 index 73de9a49d..000000000 --- a/wadsrc/static/actors/doom/scriptedmarine.txt +++ /dev/null @@ -1,306 +0,0 @@ - -// Scriptable marine ------------------------------------------------------- - -ACTOR ScriptedMarine native -{ - Health 100 - Radius 16 - Height 56 - Mass 100 - Speed 8 - Painchance 160 - MONSTER - -COUNTKILL - Translation 0 - Damage 100 - DeathSound "*death" - PainSound "*pain50" - - action native A_M_Refire (bool ignoremissile=false); - action native A_M_CheckAttack (); - action native A_MarineChase (); - action native A_MarineLook (); - action native A_MarineNoise (); - action native A_M_Punch (int force); - action native A_M_SawRefire (); - action native A_M_FirePistol (bool accurate); - action native A_M_FireShotgun (); - action native A_M_FireShotgun2 (); - action native A_M_FireCGun(bool accurate); - action native A_M_FireMissile (); - action native A_M_FirePlasma (); - action native A_M_FireRailgun (); - action native A_M_BFGsound (); - action native A_M_FireBFG (); - - States - { - Spawn: - PLAY A 4 A_MarineLook - PLAY A 4 A_MarineNoise - Loop - Idle: - PLAY A 4 A_MarineLook - PLAY A 4 A_MarineNoise - PLAY A 4 A_MarineLook - PLAY B 4 A_MarineNoise - PLAY B 4 A_MarineLook - PLAY B 4 A_MarineNoise - Loop - See: - PLAY ABCD 4 A_MarineChase - Loop - - Melee.Fist: - PLAY E 4 A_FaceTarget - PLAY E 4 A_M_Punch(1) - PLAY A 9 - PLAY A 0 A_M_Refire(1) - Loop - PLAY A 5 A_FaceTarget - Goto See - Melee.Berserk: - PLAY E 4 A_FaceTarget - PLAY E 4 A_M_Punch(10) - PLAY A 9 - PLAY A 0 A_M_Refire(1) - Loop - PLAY A 5 A_FaceTarget - Goto See - Melee.Chainsaw: - PLAY E 4 A_MarineNoise - PLAY E 4 A_M_Saw - PLAY E 0 A_M_SawRefire - goto Melee.Chainsaw+1 - PLAY A 0 - Goto See - - Missile: - Missile.None: - PLAY E 12 A_FaceTarget - Goto Idle - PLAY F 6 BRIGHT - Loop - Missile.Pistol: - PLAY E 4 A_FaceTarget - PLAY F 6 BRIGHT A_M_FirePistol(1) - PLAY A 4 A_FaceTarget - PLAY A 0 A_M_Refire - PLAY A 5 - Goto See - Fireloop.Pistol: - PLAY F 6 BRIGHT A_M_FirePistol(0) - PLAY A 4 A_FaceTarget - PLAY A 0 A_M_Refire - Goto Fireloop.Pistol - PLAY A 5 - Goto See - Missile.Shotgun: - PLAY E 3 A_M_CheckAttack - PLAY F 7 BRIGHT A_M_FireShotgun - Goto See - Missile.SSG: - PLAY E 3 A_M_CheckAttack - PLAY F 7 BRIGHT A_M_FireShotgun2 - Goto See - Missile.Chaingun: - PLAY E 4 A_FaceTarget - PLAY FF 4 BRIGHT A_M_FireCGun(1) - PLAY FF 4 BRIGHT A_M_FireCGun(0) - PLAY A 0 A_M_Refire - Goto Missile.Chaingun+3 - PLAY A 0 - Goto See - Missile.Rocket: - PLAY E 8 - PLAY F 6 BRIGHT A_M_FireMissile - PLAY E 6 - PLAY A 0 A_M_Refire - Loop - PLAY A 0 - Goto See - Missile.Plasma: - PLAY E 2 A_FaceTarget - PLAY E 0 A_FaceTarget - PLAY F 3 BRIGHT A_M_FirePlasma - PLAY A 0 A_M_Refire - Goto Missile.Plasma+1 - PLAY A 0 - Goto See - Missile.Railgun: - PLAY E 4 A_M_CheckAttack - PLAY F 6 BRIGHT A_M_FireRailgun - Goto See - Missile.BFG: - PLAY E 5 A_M_BFGSound - PLAY EEEEE 5 A_FaceTarget - PLAY F 6 BRIGHT A_M_FireBFG - PLAY A 4 A_FaceTarget - PLAY A 0 A_M_Refire - Loop - PLAY A 0 - Goto See - - SkipAttack: - PLAY A 1 - Goto See - Pain: - PLAY G 4 - PLAY G 4 A_Pain - Goto Idle - Death: - PLAY H 10 - PLAY I 10 A_Scream - PLAY J 10 A_NoBlocking - PLAY KLM 10 - PLAY N -1 - Stop - XDeath: - PLAY O 5 - PLAY P 5 A_XScream - PLAY Q 5 A_NoBlocking - PLAY RSTUV 5 - PLAY W -1 - Stop - Raise: - PLAY MLKJIH 5 - Goto See - } -} - -//--------------------------------------------------------------------------- - -ACTOR MarineFist : ScriptedMarine -{ - States - { - Melee: - Goto Super::Melee.Fist - Missile: - Stop - } -} - - -//--------------------------------------------------------------------------- - -ACTOR MarineBerserk : MarineFist -{ - States - { - Melee: - Goto Super::Melee.Berserk - Missile: - Stop - } -} -//--------------------------------------------------------------------------- - -ACTOR MarineChainsaw : ScriptedMarine -{ - States - { - Melee: - Goto Super::Melee.Chainsaw - Missile: - Stop - } -} - - - -//--------------------------------------------------------------------------- - -ACTOR MarinePistol : ScriptedMarine -{ - States - { - Missile: - Goto Super::Missile.Pistol - } - -} - -//--------------------------------------------------------------------------- - -ACTOR MarineShotgun : ScriptedMarine -{ - States - { - Missile: - Goto Super::Missile.Shotgun - } - -} - - - -//--------------------------------------------------------------------------- - -ACTOR MarineSSG : ScriptedMarine -{ - States - { - Missile: - Goto Super::Missile.SSG - } -} - -//--------------------------------------------------------------------------- - -ACTOR MarineChaingun : ScriptedMarine -{ - States - { - Missile: - Goto Super::Missile.Chaingun - } -} - - -//--------------------------------------------------------------------------- - -ACTOR MarineRocket : MarineFist -{ - States - { - Missile: - Goto Super::Missile.Rocket - } - -} - -//--------------------------------------------------------------------------- - -ACTOR MarinePlasma : ScriptedMarine -{ - States - { - Missile: - Goto Super::Missile.Plasma - } - -} - -//--------------------------------------------------------------------------- - -ACTOR MarineRailgun : ScriptedMarine -{ - States - { - Missile: - Goto Super::Missile.Railgun - } - -} - -//--------------------------------------------------------------------------- - -ACTOR MarineBFG : ScriptedMarine -{ - States - { - Missile: - Goto Super::Missile.BFG - } -} diff --git a/wadsrc/static/actors/doom/spidermaster.txt b/wadsrc/static/actors/doom/spidermaster.txt deleted file mode 100644 index e087b3fb3..000000000 --- a/wadsrc/static/actors/doom/spidermaster.txt +++ /dev/null @@ -1,59 +0,0 @@ -//=========================================================================== -// -// Spider boss -// -//=========================================================================== -ACTOR SpiderMastermind -{ - Health 3000 - Radius 128 - Height 100 - Mass 1000 - Speed 12 - PainChance 40 - Monster - MinMissileChance 160 - +BOSS - +MISSILEMORE - +FLOORCLIP - +NORADIUSDMG - +DONTMORPH - +BOSSDEATH - SeeSound "spider/sight" - AttackSound "spider/attack" - PainSound "spider/pain" - DeathSound "spider/death" - ActiveSound "spider/active" - Obituary "$OB_SPIDER" - States - { - Spawn: - SPID AB 10 A_Look - Loop - See: - SPID A 3 A_Metal - SPID ABB 3 A_Chase - SPID C 3 A_Metal - SPID CDD 3 A_Chase - SPID E 3 A_Metal - SPID EFF 3 A_Chase - Loop - Missile: - SPID A 20 BRIGHT A_FaceTarget - SPID G 4 BRIGHT A_SPosAttackUseAtkSound - SPID H 4 BRIGHT A_SposAttackUseAtkSound - SPID H 1 BRIGHT A_SpidRefire - Goto Missile+1 - Pain: - SPID I 3 - SPID I 3 A_Pain - Goto See - Death: - SPID J 20 A_Scream - SPID K 10 A_NoBlocking - SPID LMNOPQR 10 - SPID S 30 - SPID S -1 A_BossDeath - Stop - } -} diff --git a/wadsrc/static/actors/doom/stealthmonsters.txt b/wadsrc/static/actors/doom/stealthmonsters.txt deleted file mode 100644 index 275537485..000000000 --- a/wadsrc/static/actors/doom/stealthmonsters.txt +++ /dev/null @@ -1,103 +0,0 @@ - -ACTOR StealthArachnotron : Arachnotron -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHBABY" -} - -ACTOR StealthArchvile : Archvile -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHVILE" -} - -ACTOR StealthBaron : BaronOfHell -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHBARON" - HitObituary "$OB_STEALTHBARON" -} - -ACTOR StealthCacodemon : Cacodemon -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHCACO" - HitObituary "$OB_STEALTHCACO" -} - -ACTOR StealthChaingunGuy : ChaingunGuy -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHCHAINGUY" -} - -ACTOR StealthDemon : Demon -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHDEMON" - HitObituary "$OB_STEALTHDEMON" -} - -ACTOR StealthHellKnight : HellKnight -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHKNIGHT" - HitObituary "$OB_STEALTHKNIGHT" -} - -ACTOR StealthDoomImp : DoomImp -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHIMP" - HitObituary "$OB_STEALTHIMP" -} - -ACTOR StealthFatso : Fatso -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHFATSO" -} - -ACTOR StealthRevenant : Revenant -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHUNDEAD" - HitObituary "$OB_STEALTHUNDEAD" -} - -ACTOR StealthShotgunGuy : ShotgunGuy -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHSHOTGUNGUY" -} - -ACTOR StealthZombieMan : ZombieMan -{ - +STEALTH - RenderStyle Translucent - Alpha 0 - Obituary "$OB_STEALTHZOMBIE" -} - diff --git a/wadsrc/static/actors/heretic/beast.txt b/wadsrc/static/actors/heretic/beast.txt deleted file mode 100644 index 73eb630ec..000000000 --- a/wadsrc/static/actors/heretic/beast.txt +++ /dev/null @@ -1,109 +0,0 @@ - -// Beast -------------------------------------------------------------------- - -ACTOR Beast -{ - Health 220 - Radius 32 - Height 74 - Mass 200 - Speed 14 - Painchance 100 - Monster - +FLOORCLIP - SeeSound "beast/sight" - AttackSound "beast/attack" - PainSound "beast/pain" - DeathSound "beast/death" - ActiveSound "beast/active" - Obituary "$OB_BEAST" - DropItem "CrossbowAmmo", 84, 10 - States - { - Spawn: - BEAS AB 10 A_Look - Loop - See: - BEAS ABCDEF 3 A_Chase - Loop - Missile: - BEAS H 10 A_FaceTarget - BEAS I 10 A_CustomComboAttack("BeastBall", 32, random[BeastAttack](1,8)*3, "beast/attack") - Goto See - Pain: - BEAS G 3 - BEAS G 3 A_Pain - Goto See - Death: - BEAS R 6 - BEAS S 6 A_Scream - BEAS TUV 6 - BEAS W 6 A_NoBlocking - BEAS XY 6 - BEAS Z -1 - Stop - XDeath: - BEAS J 5 - BEAS K 6 A_Scream - BEAS L 5 - BEAS M 6 - BEAS N 5 - BEAS O 6 A_NoBlocking - BEAS P 5 - BEAS Q -1 - Stop - } -} - -// Beast ball --------------------------------------------------------------- - -ACTOR BeastBall -{ - Radius 9 - Height 8 - Speed 12 - FastSpeed 20 - Damage 4 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - -NOBLOCKMAP - +WINDTHRUST - +SPAWNSOUNDSOURCE - RenderStyle Add - SeeSound "beast/attack" - States - { - Spawn: - FRB1 AABBCC 2 A_SpawnItemEx("Puffy", random2[BeastPuff]()*0.015625, random2[BeastPuff]()*0.015625, random2[BeastPuff]()*0.015625, - 0,0,0,0,SXF_ABSOLUTEPOSITION, 64) - Loop - Death: - FRB1 DEFGH 4 - Stop - } -} - -// Puffy -------------------------------------------------------------------- - -ACTOR Puffy -{ - Radius 6 - Height 8 - Speed 10 - +NOBLOCKMAP - +NOGRAVITY - +MISSILE - +NOTELEPORT - +DONTSPLASH - RenderStyle Add - States - { - Spawn: - FRB1 DEFGH 4 - Stop - } -} - - - diff --git a/wadsrc/static/actors/heretic/chicken.txt b/wadsrc/static/actors/heretic/chicken.txt deleted file mode 100644 index 8d3b1e71d..000000000 --- a/wadsrc/static/actors/heretic/chicken.txt +++ /dev/null @@ -1,181 +0,0 @@ - -// Beak puff ---------------------------------------------------------------- - -ACTOR BeakPuff : StaffPuff -{ - Mass 5 - Renderstyle Translucent - Alpha 0.4 - AttackSound "chicken/attack" - VSpeed 1 -} - -// Beak --------------------------------------------------------------------- - -ACTOR Beak : Weapon -{ - Weapon.SelectionOrder 10000 - +WEAPON.DONTBOB - +WEAPON.MELEEWEAPON - Weapon.YAdjust 15 - Weapon.SisterWeapon "BeakPowered" - - action native A_BeakRaise (); - action native A_BeakAttackPL1(); - - States - { - Ready: - BEAK A 1 A_WeaponReady - Loop - Deselect: - BEAK A 1 A_Lower - Loop - Select: - BEAK A 1 A_BeakRaise - Loop - Fire: - BEAK A 18 A_BeakAttackPL1 - Goto Ready - } -} - - -ACTOR BeakPowered : Beak -{ - +WEAPON.POWERED_UP - Weapon.SisterWeapon "Beak" - - action native A_BeakAttackPL2(); - - States - { - Fire: - BEAK A 12 A_BeakAttackPL2 - Goto Ready - } -} - -// Chicken player ----------------------------------------------------------- - -ACTOR ChickenPlayer : PlayerPawn native -{ - Health 30 - ReactionTime 0 - PainChance 255 - Radius 16 - Height 24 - Speed 1 - Gravity 0.125 - +NOSKIN - +CANSUPERMORPH - PainSound "chicken/pain" - DeathSound "chicken/death" - Player.JumpZ 1 - Player.Viewheight 21 - Player.ForwardMove 1.22, 1.22 - Player.SideMove 1.22, 1.22 - Player.SpawnClass "Chicken" - Player.SoundClass "Chicken" - Player.DisplayName "Chicken" - Player.MorphWeapon "Beak" - -PICKUP - States - { - Spawn: - CHKN A -1 - Stop - See: - CHKN ABAB 3 - Loop - Melee: - Missile: - CHKN C 12 - Goto Spawn - Pain: - CHKN D 4 A_Feathers - CHKN C 4 A_Pain - Goto Spawn - Death: - CHKN E 6 A_Scream - CHKN F 6 A_Feathers - CHKN G 6 - CHKN H 6 A_NoBlocking - CHKN IJK 6 - CHKN L -1 - Stop - } -} - - - -// Chicken (non-player) ----------------------------------------------------- - -ACTOR Chicken : MorphedMonster -{ - Health 10 - Radius 9 - Height 22 - Mass 40 - Speed 4 - Painchance 200 - Monster - -COUNTKILL - +WINDTHRUST - +DONTMORPH - +FLOORCLIP - SeeSound "chicken/pain" - AttackSound "chicken/attack" - PainSound "chicken/pain" - DeathSound "chicken/death" - ActiveSound "chicken/active" - Obituary "$OB_CHICKEN" - States - { - Spawn: - CHKN AB 10 A_Look - Loop - See: - CHKN AB 3 A_Chase - Loop - Pain: - CHKN D 5 A_Feathers - CHKN C 5 A_Pain - Goto See - Melee: - CHKN A 8 A_FaceTarget - CHKN C 10 A_CustomMeleeAttack(random[ChicAttack](1,2)) - Goto See - Death: - CHKN E 6 A_Scream - CHKN F 6 A_Feathers - CHKN G 6 - CHKN H 6 A_NoBlocking - CHKN IJK 6 - CHKN L -1 - Stop - } -} - - -// Feather ------------------------------------------------------------------ - -ACTOR Feather -{ - Radius 2 - Height 4 - +MISSILE +DROPOFF - +NOTELEPORT +CANNOTPUSH - +WINDTHRUST +DONTSPLASH - Gravity 0.125 - States - { - Spawn: - CHKN MNOPQPON 3 - Loop - Death: - CHKN N 6 - Stop - } -} - diff --git a/wadsrc/static/actors/heretic/clink.txt b/wadsrc/static/actors/heretic/clink.txt deleted file mode 100644 index 7f3e4370d..000000000 --- a/wadsrc/static/actors/heretic/clink.txt +++ /dev/null @@ -1,46 +0,0 @@ - -ACTOR Clink -{ - Health 150 - Radius 20 - Height 64 - Mass 75 - Speed 14 - Painchance 32 - Monster - +NOBLOOD - +FLOORCLIP - SeeSound "clink/sight" - AttackSound "clink/attack" - PainSound "clink/pain" - DeathSound "clink/death" - ActiveSound "clink/active" - Obituary "$OB_CLINK" - DropItem "SkullRodAmmo", 84, 20 - States - { - Spawn: - CLNK AB 10 A_Look - Loop - See: - CLNK ABCD 3 A_Chase - Loop - Melee: - CLNK E 5 A_FaceTarget - CLNK F 4 A_FaceTarget - CLNK G 7 A_CustomMeleeAttack(random[ClinkAttack](3,9), "clink/attack", "clink/attack") - Goto See - Pain: - CLNK H 3 - CLNK H 3 A_Pain - Goto See - Death: - CLNK IJ 6 - CLNK K 5 A_Scream - CLNK L 5 A_NoBlocking - CLNK MN 5 - CLNK O -1 - Stop - } -} - diff --git a/wadsrc/static/actors/heretic/dsparil.txt b/wadsrc/static/actors/heretic/dsparil.txt deleted file mode 100644 index 8b2f4dc5c..000000000 --- a/wadsrc/static/actors/heretic/dsparil.txt +++ /dev/null @@ -1,270 +0,0 @@ - -// Boss spot ---------------------------------------------------------------- - -ACTOR BossSpot : SpecialSpot -{ - +INVISIBLE -} - -// Sorcerer (D'Sparil on his serpent) --------------------------------------- - -ACTOR Sorcerer1 -{ - Health 2000 - Radius 28 - Height 100 - Mass 800 - Speed 16 - PainChance 56 - Monster - +BOSS - +DONTMORPH - +NORADIUSDMG - +NOTARGET - +NOICEDEATH - +FLOORCLIP - +DONTGIB - SeeSound "dsparilserpent/sight" - AttackSound "dsparilserpent/attack" - PainSound "dsparilserpent/pain" - DeathSound "dsparilserpent/death" - ActiveSound "dsparilserpent/active" - Obituary "$OB_DSPARIL1" - HitObituary "$OB_DSPARIL1HIT" - - action native A_Sor1Pain (); - action native A_Sor1Chase (); - action native A_Srcr1Attack (); - action native A_SorcererRise (); - - States - { - Spawn: - SRCR AB 10 A_Look - Loop - See: - SRCR ABCD 5 A_Sor1Chase - Loop - Pain: - SRCR Q 6 A_Sor1Pain - Goto See - Missile: - SRCR Q 7 A_FaceTarget - SRCR R 6 A_FaceTarget - SRCR S 10 A_Srcr1Attack - Goto See - Missile2: - SRCR S 10 A_FaceTarget - SRCR Q 7 A_FaceTarget - SRCR R 6 A_FaceTarget - SRCR S 10 A_Srcr1Attack - Goto See - Death: - SRCR E 7 - SRCR F 7 A_Scream - SRCR G 7 - SRCR HIJK 6 - SRCR L 25 A_PlaySound("dsparil/zap", CHAN_BODY, 1, false, ATTN_NONE) - SRCR MN 5 - SRCR O 4 - SRCR L 20 A_PlaySound("dsparil/zap", CHAN_BODY, 1, false, ATTN_NONE) - SRCR MN 5 - SRCR O 4 - SRCR L 12 - SRCR P -1 A_SorcererRise - } -} - - -// Sorcerer FX 1 ------------------------------------------------------------ - -ACTOR SorcererFX1 -{ - Radius 10 - Height 10 - Speed 20 - FastSpeed 28 - Damage 10 - DamageType Fire - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - RenderStyle Add - States - { - Spawn: - FX14 ABC 6 BRIGHT - Loop - Death: - FX14 DEFGH 5 BRIGHT - Stop - } -} - - -// Sorcerer 2 (D'Sparil without his serpent) -------------------------------- - -ACTOR Sorcerer2 -{ - Health 3500 - Radius 16 - Height 70 - Mass 300 - Speed 14 - Painchance 32 - Monster - +DROPOFF - +BOSS - +DONTMORPH - +FULLVOLACTIVE - +NORADIUSDMG - +NOTARGET - +NOICEDEATH - +FLOORCLIP - +BOSSDEATH - SeeSound "dsparil/sight" - AttackSound "dsparil/attack" - PainSound "dsparil/pain" - ActiveSound "dsparil/active" - Obituary "$OB_DSPARIL2" - HitObituary "$OB_DSPARIL2HIT" - - action native A_Srcr2Decide (); - action native A_Srcr2Attack (); - action native A_Sor2DthInit (); - action native A_Sor2DthLoop (); - - States - { - Spawn: - SOR2 MN 10 A_Look - Loop - See: - SOR2 MNOP 4 A_Chase - Loop - Rise: - SOR2 AB 4 - SOR2 C 4 A_PlaySound("dsparil/rise", CHAN_BODY, 1, false, ATTN_NONE) - SOR2 DEF 4 - SOR2 G 12 A_PlaySound("dsparil/sight", CHAN_BODY, 1, false, ATTN_NONE) - Goto See - Pain: - SOR2 Q 3 - SOR2 Q 6 A_Pain - Goto See - Missile: - SOR2 R 9 A_Srcr2Decide - SOR2 S 9 A_FaceTarget - SOR2 T 20 A_Srcr2Attack - Goto See - Teleport: - SOR2 LKJIHG 6 - Goto See - Death: - SDTH A 8 A_Sor2DthInit - SDTH B 8 - SDTH C 8 A_PlaySound("dsparil/scream", CHAN_BODY, 1, false, ATTN_NONE) - DeathLoop: - SDTH DE 7 - SDTH F 7 A_Sor2DthLoop - SDTH G 6 A_PlaySound("dsparil/explode", CHAN_BODY, 1, false, ATTN_NONE) - SDTH H 6 - SDTH I 18 - SDTH J 6 A_NoBlocking - SDTH K 6 A_PlaySound("dsparil/bones", CHAN_BODY, 1, false, ATTN_NONE) - SDTH LMN 6 - SDTH O -1 A_BossDeath - Stop - } -} - - - -// Sorcerer 2 FX 1 ---------------------------------------------------------- - -ACTOR Sorcerer2FX1 -{ - Radius 10 - Height 6 - Speed 20 - FastSpeed 28 - Damage 1 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - RenderStyle Add - - action native A_BlueSpark (); - - States - { - Spawn: - FX16 ABC 3 BRIGHT A_BlueSpark - Loop - Death: - FX16 G 5 BRIGHT A_Explode(random[S2FX1](80,111)) - FX16 HIJKL 5 BRIGHT - Stop - } -} - -// Sorcerer 2 FX Spark ------------------------------------------------------ - -ACTOR Sorcerer2FXSpark -{ - Radius 20 - Height 16 - +NOBLOCKMAP - +NOGRAVITY - +NOTELEPORT - +CANNOTPUSH - RenderStyle Add - States - { - Spawn: - FX16 DEF 12 BRIGHT - Stop - } -} - -// Sorcerer 2 FX 2 ---------------------------------------------------------- - -ACTOR Sorcerer2FX2 -{ - Radius 10 - Height 6 - Speed 6 - Damage 10 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - RenderStyle Add - - action native A_GenWizard (); - - States - { - Spawn: - FX11 A 35 BRIGHT - FX11 A 5 BRIGHT A_GenWizard - FX11 B 5 BRIGHT - Goto Spawn+1 - Death: - FX11 CDEFG 5 BRIGHT - Stop - - } -} -// Sorcerer 2 Telefade ------------------------------------------------------ - -ACTOR Sorcerer2Telefade -{ - +NOBLOCKMAP - States - { - Spawn: - SOR2 GHIJKL 6 - Stop - } -} - diff --git a/wadsrc/static/actors/heretic/hereticammo.txt b/wadsrc/static/actors/heretic/hereticammo.txt deleted file mode 100644 index 35f404274..000000000 --- a/wadsrc/static/actors/heretic/hereticammo.txt +++ /dev/null @@ -1,204 +0,0 @@ - -// Wimpy ammo --------------------------------------------------------------- - -ACTOR GoldWandAmmo : Ammo -{ - Inventory.PickupMessage "$TXT_AMMOGOLDWAND1" - Inventory.Amount 10 - Inventory.MaxAmount 100 - Ammo.BackpackAmount 10 - Ammo.BackpackMaxAmount 200 - Inventory.Icon "INAMGLD" - States - { - Spawn: - AMG1 A -1 - Stop - } -} - -// Hefty ammo --------------------------------------------------------------- - -ACTOR GoldWandHefty : GoldWandAmmo -{ - Inventory.PickupMessage "$TXT_AMMOGOLDWAND2" - Inventory.Amount 50 - States - { - Spawn: - AMG2 ABC 4 - Loop - } -} -// Wimpy ammo --------------------------------------------------------------- - -ACTOR CrossbowAmmo : Ammo -{ - Inventory.PickupMessage "$TXT_AMMOCROSSBOW1" - Inventory.Amount 5 - Inventory.MaxAmount 50 - Ammo.BackpackAmount 5 - Ammo.BackpackMaxAmount 100 - Inventory.Icon "INAMBOW" - States - { - Spawn: - AMC1 A -1 - Stop - } -} - -// Hefty ammo --------------------------------------------------------------- - -ACTOR CrossbowHefty : CrossbowAmmo -{ - Inventory.PickupMessage "$TXT_AMMOCROSSBOW2" - Inventory.Amount 20 - States - { - Spawn: - AMC2 ABC 5 - Loop - } -} -// Wimpy ammo --------------------------------------------------------------- - -ACTOR MaceAmmo : Ammo -{ - Inventory.PickupMessage "$TXT_AMMOMACE1" - Inventory.Amount 20 - Inventory.MaxAmount 150 - Ammo.BackpackAmount 20 - Ammo.BackpackMaxAmount 300 - Inventory.Icon "INAMLOB" - States - { - Spawn: - AMM1 A -1 - Stop - } -} - -// Hefty ammo --------------------------------------------------------------- - -ACTOR MaceHefty : MaceAmmo -{ - Inventory.PickupMessage "$TXT_AMMOMACE2" - Inventory.Amount 100 - States - { - Spawn: - AMM2 A -1 - Stop - } -} - -// Wimpy ammo --------------------------------------------------------------- - -ACTOR BlasterAmmo : Ammo -{ - Inventory.PickupMessage "$TXT_AMMOBLASTER1" - Inventory.Amount 10 - Inventory.MaxAmount 200 - Ammo.BackpackAmount 10 - Ammo.BackpackMaxAmount 400 - Inventory.Icon "INAMBST" - States - { - Spawn: - AMB1 ABC 4 - Loop - } -} - -// Hefty ammo --------------------------------------------------------------- - -ACTOR BlasterHefty : BlasterAmmo -{ - Inventory.PickupMessage "$TXT_AMMOBLASTER2" - Inventory.Amount 25 - States - { - Spawn: - AMB2 ABC 4 - Loop - } -} - -// Wimpy ammo --------------------------------------------------------------- - -ACTOR SkullRodAmmo : Ammo -{ - Inventory.PickupMessage "$TXT_AMMOSKULLROD1" - Inventory.Amount 20 - Inventory.MaxAmount 200 - Ammo.BackpackAmount 20 - Ammo.BackpackMaxAmount 400 - Inventory.Icon "INAMRAM" - States - { - Spawn: - AMS1 AB 5 - Loop - } -} - -// Hefty ammo --------------------------------------------------------------- - -ACTOR SkullRodHefty : SkullRodAmmo -{ - Inventory.PickupMessage "$TXT_AMMOSKULLROD2" - Inventory.Amount 100 - States - { - Spawn: - AMS2 AB 5 - Loop - } -} - -// Wimpy ammo --------------------------------------------------------------- - -ACTOR PhoenixRodAmmo : Ammo -{ - Inventory.PickupMessage "$TXT_AMMOPHOENIXROD1" - Inventory.Amount 1 - Inventory.MaxAmount 20 - Ammo.BackpackAmount 1 - Ammo.BackpackMaxAmount 40 - Inventory.Icon "INAMPNX" - States - { - Spawn: - AMP1 ABC 4 - Loop - } -} -// Hefty ammo --------------------------------------------------------------- - -ACTOR PhoenixRodHefty : PhoenixRodAmmo -{ - Inventory.PickupMessage "$TXT_AMMOPHOENIXROD2" - Inventory.Amount 10 - States - { - Spawn: - AMP2 ABC 4 - Loop - } -} - -// --- Bag of holding ------------------------------------------------------- - -ACTOR BagOfHolding : BackpackItem -{ - Inventory.PickupMessage "$TXT_ITEMBAGOFHOLDING" - +COUNTITEM - +FLOATBOB - States - { - Spawn: - BAGH A -1 - Stop - } -} diff --git a/wadsrc/static/actors/heretic/hereticarmor.txt b/wadsrc/static/actors/heretic/hereticarmor.txt deleted file mode 100644 index 91684cc0e..000000000 --- a/wadsrc/static/actors/heretic/hereticarmor.txt +++ /dev/null @@ -1,35 +0,0 @@ - -// Silver Shield (Shield1) -------------------------------------------------- - -Actor SilverShield : BasicArmorPickup -{ - +FLOATBOB - Inventory.Pickupmessage "$TXT_ITEMSHIELD1" - Inventory.Icon "SHLDA0" - Armor.Savepercent 50 - Armor.Saveamount 100 - States - { - Spawn: - SHLD A -1 - stop - } -} - -// Enchanted shield (Shield2) ----------------------------------------------- - -Actor EnchantedShield : BasicArmorPickup -{ - +FLOATBOB - Inventory.Pickupmessage "$TXT_ITEMSHIELD2" - Inventory.Icon "SHD2A0" - Armor.Savepercent 75 - Armor.Saveamount 200 - States - { - Spawn: - SHD2 A -1 - stop - } -} - diff --git a/wadsrc/static/actors/heretic/hereticartifacts.txt b/wadsrc/static/actors/heretic/hereticartifacts.txt deleted file mode 100644 index 9555415fd..000000000 --- a/wadsrc/static/actors/heretic/hereticartifacts.txt +++ /dev/null @@ -1,103 +0,0 @@ -// Super map ---------------------------------------------------------------- - -ACTOR SuperMap : MapRevealer -{ - +COUNTITEM - +INVENTORY.ALWAYSPICKUP - +FLOATBOB - Inventory.MaxAmount 0 - Inventory.PickupMessage "$TXT_ITEMSUPERMAP" - States - { - Spawn: - SPMP A -1 - Stop - } -} - - -// Invisibility ------------------------------------------------------------- - -ACTOR ArtiInvisibility : PowerupGiver -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - RenderStyle Translucent - Alpha 0.4 - Inventory.RespawnTics 4230 - Inventory.Icon ARTIINVS - Powerup.Type Ghost - Inventory.PickupMessage "$TXT_ARTIINVISIBILITY" - Tag "$TAG_ARTIINVISIBILITY" - States - { - Spawn: - INVS A 350 Bright - Loop - } -} - - -// Tome of power ------------------------------------------------------------ - -ACTOR ArtiTomeOfPower : PowerupGiver native -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - Inventory.Icon "ARTIPWBK" - Powerup.Type Weaponlevel2 - Inventory.PickupMessage "$TXT_ARTITOMEOFPOWER" - Tag "$TAG_ARTITOMEOFPOWER" - States - { - Spawn: - PWBK A 350 - Loop - } -} - - -// Time bomb ---------------------------------------------------------------- - -ACTOR ActivatedTimeBomb -{ - +NOGRAVITY - RenderStyle Translucent - Alpha 0.4 - DeathSound "misc/timebomb" - - action native A_Timebomb(); - - States - { - Spawn: - FBMB ABCD 10 - FBMB E 6 A_Scream - XPL1 A 4 BRIGHT A_Timebomb - XPL1 BCDEF 4 BRIGHT - Stop - } -} - - -ACTOR ArtiTimeBomb : Inventory native -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - +INVENTORY.INVBAR - +INVENTORY.FANCYPICKUPSOUND - Inventory.Icon "ARTIFBMB" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIFIREBOMB" - Tag "$TAG_ARTIFIREBOMB" - Inventory.DefMaxAmount - States - { - Spawn: - FBMB E 350 - Loop - } -} diff --git a/wadsrc/static/actors/heretic/hereticdecorations.txt b/wadsrc/static/actors/heretic/hereticdecorations.txt deleted file mode 100644 index 032ee33a1..000000000 --- a/wadsrc/static/actors/heretic/hereticdecorations.txt +++ /dev/null @@ -1,248 +0,0 @@ -ACTOR SkullHang70 -{ - Radius 20 - Height 70 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - SKH1 A -1 - Stop - } -} - -ACTOR SkullHang60 -{ - Radius 20 - Height 60 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - SKH2 A -1 - Stop - } -} - -ACTOR SkullHang45 -{ - Radius 20 - Height 45 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - SKH3 A -1 - Stop - } -} - -ACTOR SkullHang35 -{ - Radius 20 - Height 35 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - SKH4 A -1 - Stop - } -} - -ACTOR Chandelier -{ - Radius 20 - Height 60 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - CHDL ABC 4 - Loop - } -} - -ACTOR SerpentTorch -{ - Radius 12 - Height 54 - +SOLID - States - { - Spawn: - SRTC ABC 4 - Loop - } -} - -ACTOR SmallPillar -{ - Radius 16 - Height 34 - +SOLID - States - { - Spawn: - SMPL A -1 - Stop - } -} - -ACTOR StalagmiteSmall -{ - Radius 8 - Height 32 - +SOLID - States - { - Spawn: - STGS A -1 - Stop - } -} - -ACTOR StalagmiteLarge -{ - Radius 12 - Height 64 - +SOLID - States - { - Spawn: - STGL A -1 - Stop - } -} - -ACTOR StalactiteSmall -{ - Radius 8 - Height 36 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - STCS A -1 - Stop - } -} - -ACTOR StalactiteLarge -{ - Radius 12 - Height 68 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - STCL A -1 - Stop - } -} - -ACTOR FireBrazier -{ - Radius 16 - Height 44 - +SOLID - States - { - Spawn: - KFR1 ABCDEFGH 3 Bright - Loop - } -} - -ACTOR Barrel -{ - Radius 12 - Height 32 - +SOLID - States - { - Spawn: - BARL A -1 - Stop - } -} - -ACTOR BrownPillar -{ - Radius 14 - Height 128 - +SOLID - States - { - Spawn: - BRPL A -1 - Stop - } -} - -ACTOR Moss1 -{ - Radius 20 - Height 23 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - MOS1 A -1 - Stop - } -} - -ACTOR Moss2 -{ - Radius 20 - Height 27 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - MOS2 A -1 - Stop - } -} - -ACTOR WallTorch -{ - Radius 6 - Height 16 - +NOGRAVITY - +FIXMAPTHINGPOS - States - { - Spawn: - WTRH ABC 6 Bright - Loop - } -} - -ACTOR HangingCorpse -{ - Radius 8 - Height 104 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - HCOR A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/heretic/hereticimp.txt b/wadsrc/static/actors/heretic/hereticimp.txt deleted file mode 100644 index fdbdeb9b7..000000000 --- a/wadsrc/static/actors/heretic/hereticimp.txt +++ /dev/null @@ -1,156 +0,0 @@ - -// Heretic imp (as opposed to the Doom variety) ----------------------------- - -ACTOR HereticImp -{ - Health 40 - Radius 16 - Height 36 - Mass 50 - Speed 10 - Painchance 200 - Monster - +FLOAT - +NOGRAVITY - +SPAWNFLOAT - +DONTOVERLAP - +MISSILEMORE - SeeSound "himp/sight" - AttackSound "himp/attack" - PainSound "himp/pain" - DeathSound "himp/death" - ActiveSound "himp/active" - Obituary "$OB_HERETICIMP" - HitObituary "$OB_HERETICIMPHIT" - - action native A_ImpMsAttack(); - action native A_ImpDeath(); - action native A_ImpXDeath1(); - action native A_ImpExplode(); - - - States - { - Spawn: - IMPX ABCB 10 A_Look - Loop - See: - IMPX AABBCCBB 3 A_Chase - Loop - Melee: - IMPX DE 6 A_FaceTarget - IMPX F 6 A_CustomMeleeAttack(random[ImpMeAttack](5,12), "himp/attack", "himp/attack") - Goto See - Missile: - IMPX A 10 A_FaceTarget - IMPX B 6 A_ImpMsAttack - IMPX CBAB 6 - Goto Missile+2 - Pain: - IMPX G 3 - IMPX G 3 A_Pain - Goto See - Death: - IMPX G 4 A_ImpDeath - IMPX H 5 - Wait - XDeath: - IMPX S 5 A_ImpXDeath1 - IMPX TU 5 - IMPX V 5 A_Gravity - IMPX W 5 - Wait - Crash: - IMPX I 7 A_ImpExplode - IMPX J 7 A_Scream - IMPX K 7 - IMPX L -1 - Stop - XCrash: - IMPX X 7 - IMPX Y 7 - IMPX Z -1 - Stop - } -} - -// Heretic imp leader ------------------------------------------------------- - -ACTOR HereticImpLeader : HereticImp -{ - Species "HereticImpLeader" - Health 80 - -MISSILEMORE - AttackSound "himp/leaderattack" - States - { - Melee: - Stop - Missile: - IMPX DE 6 A_FaceTarget - IMPX F 6 A_CustomComboAttack("HereticImpBall", 32, random[ImpMsAttack2](5,12), "himp/leaderattack") - Goto See - } -} - -// Heretic imp chunk 1 ------------------------------------------------------ - -ACTOR HereticImpChunk1 -{ - Mass 5 - Radius 4 - +NOBLOCKMAP - +MOVEWITHSECTOR - States - { - Spawn: - IMPX M 5 - IMPX NO 700 - Stop - } -} - -// Heretic imp chunk 2 ------------------------------------------------------ - -ACTOR HereticImpChunk2 -{ - Mass 5 - Radius 4 - +NOBLOCKMAP - +MOVEWITHSECTOR - States - { - Spawn: - IMPX P 5 - IMPX QR 700 - Stop - } -} - -// Heretic imp ball --------------------------------------------------------- - -ACTOR HereticImpBall -{ - Radius 8 - Height 8 - Speed 10 - FastSpeed 20 - Damage 1 - Projectile - SeeSound "himp/leaderattack" - +SPAWNSOUNDSOURCE - -ACTIVATEPCROSS - -ACTIVATEIMPACT - RenderStyle Add - States - { - Spawn: - FX10 ABC 6 Bright - Loop - Death: - FX10 DEFG 5 Bright - Stop - } -} - - diff --git a/wadsrc/static/actors/heretic/heretickeys.txt b/wadsrc/static/actors/heretic/heretickeys.txt deleted file mode 100644 index 1bda24dcc..000000000 --- a/wadsrc/static/actors/heretic/heretickeys.txt +++ /dev/null @@ -1,144 +0,0 @@ - -ACTOR HereticKey : Key -{ - +NOTDMATCH - Radius 20 - Height 16 -} - -// Green key ------------------------------------------------------------ - -ACTOR KeyGreen : HereticKey -{ - Inventory.PickupMessage "$TXT_GOTGREENKEY" - Inventory.Icon "GKEYICON" - States - { - Spawn: - AKYY ABCDEFGHIJ 3 Bright - Loop - } -} - -// Blue key ----------------------------------------------------------------- - -ACTOR KeyBlue : HereticKey -{ - Inventory.PickupMessage "$TXT_GOTBLUEKEY" - Inventory.Icon "BKEYICON" - States - { - Spawn: - BKYY ABCDEFGHIJ 3 Bright - Loop - } -} - -// Yellow key --------------------------------------------------------------- - -ACTOR KeyYellow : HereticKey -{ - Inventory.PickupMessage "$TXT_GOTYELLOWKEY" - Inventory.Icon "YKEYICON" - States - { - Spawn: - CKYY ABCDEFGHI 3 Bright - Loop - } -} - - -// --- Blue Key gizmo ----------------------------------------------------------- - -ACTOR KeyGizmoBlue -{ - Radius 16 - Height 50 - +SOLID - States - { - Spawn: - KGZ1 A 1 - KGZ1 A 1 A_SpawnItemEx("KeyGizmoFloatBlue", 0, 0, 60) - KGZ1 A -1 - Stop - } -} - -ACTOR KeyGizmoFloatBlue -{ - Radius 16 - Height 16 - +SOLID - +NOGRAVITY - States - { - Spawn: - KGZB A -1 Bright - Stop - } -} - -// --- Green Key gizmo ----------------------------------------------------------- - -ACTOR KeyGizmoGreen -{ - Radius 16 - Height 50 - +SOLID - States - { - Spawn: - KGZ1 A 1 - KGZ1 A 1 A_SpawnItemEx("KeyGizmoFloatGreen", 0, 0, 60) - KGZ1 A -1 - Stop - } -} - -ACTOR KeyGizmoFloatGreen -{ - Radius 16 - Height 16 - +SOLID - +NOGRAVITY - States - { - Spawn: - KGZG A -1 Bright - Stop - } -} - -// --- Yellow Key gizmo ----------------------------------------------------------- - -ACTOR KeyGizmoYellow -{ - Radius 16 - Height 50 - +SOLID - States - { - Spawn: - KGZ1 A 1 - KGZ1 A 1 A_SpawnItemEx("KeyGizmoFloatYellow", 0, 0, 60) - KGZ1 A -1 - Stop - } -} - -ACTOR KeyGizmoFloatYellow -{ - Radius 16 - Height 16 - +SOLID - +NOGRAVITY - States - { - Spawn: - KGZY A -1 Bright - Stop - } -} - diff --git a/wadsrc/static/actors/heretic/hereticmisc.txt b/wadsrc/static/actors/heretic/hereticmisc.txt deleted file mode 100644 index 9b000ede3..000000000 --- a/wadsrc/static/actors/heretic/hereticmisc.txt +++ /dev/null @@ -1,229 +0,0 @@ - -// Pod ---------------------------------------------------------------------- - -ACTOR Pod -{ - Health 45 - Radius 16 - Height 54 - Painchance 255 - +SOLID +NOBLOOD +SHOOTABLE +DROPOFF - +WINDTHRUST +PUSHABLE +SLIDESONWALLS - +CANPASS +TELESTOMP +DONTMORPH - +NOBLOCKMONST +DONTGIB +OLDRADIUSDMG - DeathSound "world/podexplode" - PushFactor 0.5 - - action native A_PodPain (class podtype = "PodGoo"); - action native A_RemovePod (); - - States - { - Spawn: - PPOD A 10 - Loop - Pain: - PPOD B 14 A_PodPain - Goto Spawn - Death: - PPOD C 5 BRIGHT A_RemovePod - PPOD D 5 BRIGHT A_Scream - PPOD E 5 BRIGHT A_Explode - PPOD F 10 BRIGHT - Stop - Grow: - PPOD IJKLMNOP 3 - Goto Spawn - } -} - - -// Pod goo (falls from pod when damaged) ------------------------------------ - -ACTOR PodGoo -{ - Radius 2 - Height 4 - Gravity 0.125 - +NOBLOCKMAP +MISSILE +DROPOFF - +NOTELEPORT +CANNOTPUSH - States - { - Spawn: - PPOD GH 8 - Loop - Death: - PPOD G 10 - Stop - } -} - -// Pod generator ------------------------------------------------------------ - -ACTOR PodGenerator -{ - +NOBLOCKMAP - +NOSECTOR - +DONTSPLASH - AttackSound "world/podgrow" - - action native A_MakePod (class podtype = "Pod"); - - States - { - Spawn: - TNT1 A 35 A_MakePod - Loop - } -} - - -// Teleglitter generator 1 -------------------------------------------------- - -ACTOR TeleGlitterGenerator1 -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - +MOVEWITHSECTOR - States - { - Spawn: - TNT1 A 8 A_SpawnItemEx("TeleGlitter1", random[TeleGlitter](0,31)-16, random[TeleGlitter](0,31)-16, 0, 0,0,0.25) - Loop - } -} - -// Teleglitter generator 2 -------------------------------------------------- - -ACTOR TeleGlitterGenerator2 -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - +MOVEWITHSECTOR - States - { - Spawn: - TNT1 A 8 A_SpawnItemEx("TeleGlitter2", random[TeleGlitter2](0,31)-16, random[TeleGlitter2](0,31)-16, 0, 0,0,0.25) - Loop - } -} - - -// Teleglitter 1 ------------------------------------------------------------ - -ACTOR TeleGlitter1 -{ - +NOBLOCKMAP +NOGRAVITY +MISSILE - RenderStyle Add - Damage 0 - - action native A_AccTeleGlitter (); - - States - { - Spawn: - TGLT A 2 BRIGHT - TGLT B 2 BRIGHT A_AccTeleGlitter - TGLT C 2 BRIGHT - TGLT D 2 BRIGHT A_AccTeleGlitter - TGLT E 2 BRIGHT - Loop - } -} - -// Teleglitter 2 ------------------------------------------------------------ - -ACTOR TeleGlitter2 : TeleGlitter1 -{ - States - { - Spawn: - TGLT F 2 BRIGHT - TGLT G 2 BRIGHT A_AccTeleGlitter - TGLT H 2 BRIGHT - TGLT I 2 BRIGHT A_AccTeleGlitter - TGLT J 2 BRIGHT - Loop - } -} - - -// --- Volcano -------------------------------------------------------------- - -ACTOR Volcano -{ - Radius 12 - Height 20 - +SOLID - - action native A_VolcanoSet (); - action native A_VolcanoBlast (); - - States - { - Spawn: - VLCO A 350 - VLCO A 35 A_VolcanoSet - VLCO BCDBCD 3 - VLCO E 10 A_VolcanoBlast - Goto Spawn+1 - } - -} - -// Volcano blast ------------------------------------------------------------ - -ACTOR VolcanoBlast -{ - Radius 8 - Height 8 - Speed 2 - Damage 2 - DamageType Fire - Gravity 0.125 - +NOBLOCKMAP +MISSILE +DROPOFF - +NOTELEPORT - DeathSound "world/volcano/blast" - - action native A_VolcBallImpact (); - - States - { - Spawn: - VFBL AB 4 BRIGHT A_SpawnItemEx("Puffy", random2[BeastPuff]()*0.015625, random2[BeastPuff]()*0.015625, random2[BeastPuff]()*0.015625, - 0,0,0,0,SXF_ABSOLUTEPOSITION, 64) - Loop - - Death: - XPL1 A 4 BRIGHT A_VolcBallImpact - XPL1 BCDEF 4 BRIGHT - Stop - } -} - -// Volcano T Blast ---------------------------------------------------------- - -ACTOR VolcanoTBlast -{ - Radius 8 - Height 6 - Speed 2 - Damage 1 - DamageType Fire - Gravity 0.125 - +NOBLOCKMAP +MISSILE +DROPOFF - +NOTELEPORT - States - { - Spawn: - VTFB AB 4 BRIGHT - Loop - Death: - SFFI CBABCDE 4 BRIGHT - Stop - } -} - - diff --git a/wadsrc/static/actors/heretic/hereticplayer.txt b/wadsrc/static/actors/heretic/hereticplayer.txt deleted file mode 100644 index 5a3e43772..000000000 --- a/wadsrc/static/actors/heretic/hereticplayer.txt +++ /dev/null @@ -1,129 +0,0 @@ -ACTOR HereticPlayer : PlayerPawn -{ - Health 100 - Radius 16 - Height 56 - Mass 100 - Painchance 255 - Speed 1 - Player.DisplayName "Corvus" - Player.StartItem "GoldWand" - Player.StartItem "Staff" - Player.StartItem "GoldWandAmmo", 50 - Player.WeaponSlot 1, Staff, Gauntlets - Player.WeaponSlot 2, GoldWand - Player.WeaponSlot 3, Crossbow - Player.WeaponSlot 4, Blaster - Player.WeaponSlot 5, SkullRod - Player.WeaponSlot 6, PhoenixRod - Player.WeaponSlot 7, Mace - - Player.ColorRange 225, 240 - Player.Colorset 0, "Green", 225, 240, 238 - Player.Colorset 1, "Yellow", 114, 129, 127 - Player.Colorset 2, "Red", 145, 160, 158 - Player.Colorset 3, "Blue", 190, 205, 203 - // Doom Legacy additions - Player.Colorset 4, "Brown", 67, 82, 80 - Player.Colorset 5, "Light Gray", 9, 24, 22 - Player.Colorset 6, "Light Brown", 74, 89, 87 - Player.Colorset 7, "Light Red", 150, 165, 163 - Player.Colorset 8, "Light Blue", 192, 207, 205 - Player.Colorset 9, "Beige", 95, 110, 108 - - States - { - Spawn: - PLAY A -1 - Stop - See: - PLAY ABCD 4 - Loop - Melee: - Missile: - PLAY F 6 BRIGHT - PLAY E 12 - Goto Spawn - Pain: - PLAY G 4 - PLAY G 4 A_Pain - Goto Spawn - Death: - PLAY H 6 A_PlayerSkinCheck("AltSkinDeath") - PLAY I 6 A_PlayerScream - PLAY JK 6 - PLAY L 6 A_NoBlocking - PLAY MNO 6 - PLAY P -1 - Stop - XDeath: - PLAY Q 0 A_PlayerSkinCheck("AltSkinXDeath") - PLAY Q 5 A_PlayerScream - PLAY R 0 A_NoBlocking - PLAY R 5 A_SkullPop - PLAY STUVWX 5 - PLAY Y -1 - Stop - Burn: - FDTH A 5 BRIGHT A_PlaySound("*burndeath") - FDTH B 4 BRIGHT - FDTH C 5 BRIGHT - FDTH D 4 BRIGHT A_PlayerScream - FDTH E 5 BRIGHT - FDTH F 4 BRIGHT - FDTH G 5 BRIGHT A_PlaySound("*burndeath") - FDTH H 4 BRIGHT - FDTH I 5 BRIGHT - FDTH J 4 BRIGHT - FDTH K 5 BRIGHT - FDTH L 4 BRIGHT - FDTH M 5 BRIGHT - FDTH N 4 BRIGHT - FDTH O 5 BRIGHT A_NoBlocking - FDTH P 4 BRIGHT - FDTH Q 5 BRIGHT - FDTH R 4 BRIGHT - ACLO E 35 A_CheckPlayerDone - Wait - AltSkinDeath: - PLAY H 10 - PLAY I 10 A_PlayerScream - PLAY J 10 A_NoBlocking - PLAY KLM 10 - PLAY N -1 - Stop - AltSkinXDeath: - PLAY O 5 - PLAY P 5 A_XScream - PLAY Q 5 A_NoBlocking - PLAY RSTUV 5 - PLAY W -1 - Stop - } -} - -// The player's skull ------------------------------------------------------- - -ACTOR BloodySkull : PlayerChunk -{ - Radius 4 - Height 4 - +NOBLOCKMAP - +DROPOFF - +LOWGRAVITY - +CANNOTPUSH - +SKYEXPLODE - +NOBLOCKMONST - +NOSKIN - States - { - Spawn: - BSKL A 0 - BSKL ABCDE 5 A_CheckFloor("Hit") - Goto Spawn+1 - Hit: - BSKL F 16 A_CheckPlayerDone - Wait - } -} - diff --git a/wadsrc/static/actors/heretic/hereticweaps.txt b/wadsrc/static/actors/heretic/hereticweaps.txt deleted file mode 100644 index 41461379a..000000000 --- a/wadsrc/static/actors/heretic/hereticweaps.txt +++ /dev/null @@ -1,1133 +0,0 @@ - -ACTOR HereticWeapon : Weapon -{ - Weapon.Kickback 150 -} - - -// Staff -------------------------------------------------------------------- - -ACTOR Staff : HereticWeapon -{ - Weapon.SelectionOrder 3800 - +THRUGHOST - +WIMPY_WEAPON - +MELEEWEAPON - Weapon.sisterweapon "StaffPowered" - Obituary "$OB_MPSTAFF" - Tag "$TAG_STAFF" - - action native A_StaffAttack (int damage, class puff); - - States - { - Ready: - STFF A 1 A_WeaponReady - Loop - Deselect: - STFF A 1 A_Lower - Loop - Select: - STFF A 1 A_Raise - Loop - Fire: - STFF B 6 - STFF C 8 A_StaffAttack(random[StaffAttack](5, 20), "StaffPuff") - STFF B 8 A_ReFire - Goto Ready - } -} - -ACTOR StaffPowered : Staff -{ - Weapon.sisterweapon "Staff" - Weapon.ReadySound "weapons/staffcrackle" - +WEAPON.POWERED_UP - +WEAPON.READYSNDHALF - +WEAPON.STAFF2_KICKBACK - Obituary "$OB_MPPSTAFF" - Tag "$TAG_STAFFP" - States - { - Ready: - STFF DEF 4 A_WeaponReady - Loop - Deselect: - STFF D 1 A_Lower - Loop - Select: - STFF D 1 A_Raise - Loop - Fire: - STFF G 6 - STFF H 8 A_StaffAttack(random[StaffAttack](18, 81), "StaffPuff2") - STFF G 8 A_ReFire - Goto Ready - } -} - - -// Staff puff --------------------------------------------------------------- - -ACTOR StaffPuff -{ - RenderStyle Translucent - Alpha 0.4 - VSpeed 1 - +NOBLOCKMAP - +NOGRAVITY - +PUFFONACTORS - AttackSound "weapons/staffhit" - States - { - Spawn: - PUF3 A 4 BRIGHT - PUF3 BCD 4 - Stop - } -} - -// Staff puff 2 ------------------------------------------------------------- - -ACTOR StaffPuff2 -{ - RenderStyle Add - +NOBLOCKMAP - +NOGRAVITY - +PUFFONACTORS - AttackSound "weapons/staffpowerhit" - States - { - Spawn: - PUF4 ABCDEF 4 BRIGHT - Stop - } -} - - - -// Gold wand ---------------------------------------------------------------- - -ACTOR GoldWand : HereticWeapon -{ - +BLOODSPLATTER - Weapon.SelectionOrder 2000 - Weapon.AmmoGive 25 - Weapon.AmmoUse 1 - Weapon.AmmoType "GoldWandAmmo" - Weapon.SisterWeapon "GoldWandPowered" - Weapon.YAdjust 5 - Inventory.PickupMessage "$TXT_WPNGOLDWAND" - Obituary "$OB_MPGOLDWAND" - Tag "$TAG_GOLDWAND" - - action native A_FireGoldWandPL1 (); - - States - { - Spawn: - GWAN A -1 - Stop - Ready: - GWND A 1 A_WeaponReady - Loop - Deselect: - GWND A 1 A_Lower - Loop - Select: - GWND A 1 A_Raise - Loop - Fire: - GWND B 3 - GWND C 5 A_FireGoldWandPL1 - GWND D 3 - GWND D 0 A_ReFire - Goto Ready - } -} - -ACTOR GoldWandPowered : GoldWand -{ - +WEAPON.POWERED_UP - Weapon.AmmoGive 0 - Weapon.SisterWeapon "GoldWand" - Obituary "$OB_MPPGOLDWAND" - Tag "$TAG_GOLDWANDP" - - action native A_FireGoldWandPL2 (); - - States - { - Fire: - GWND B 3 - GWND C 4 A_FireGoldWandPL2 - GWND D 3 - GWND D 0 A_ReFire - Goto Ready - } -} - - -// Gold wand FX1 ------------------------------------------------------------ - -ACTOR GoldWandFX1 -{ - Radius 10 - Height 6 - Speed 22 - Damage 2 - Projectile - RenderStyle Add - DeathSound "weapons/wandhit" - Obituary "$OB_MPPGOLDWAND" - States - { - Spawn: - FX01 AB 6 BRIGHT - Loop - Death: - FX01 EFGH 3 BRIGHT - Stop - } -} - -// Gold wand FX2 ------------------------------------------------------------ - -ACTOR GoldWandFX2 : GoldWandFX1 -{ - Speed 18 - Damage 1 - DeathSound "" - States - { - Spawn: - FX01 CD 6 BRIGHT - Loop - } -} - -// Gold wand puff 1 --------------------------------------------------------- - -ACTOR GoldWandPuff1 -{ - +NOBLOCKMAP - +NOGRAVITY - +PUFFONACTORS - RenderStyle Add - States - { - Spawn: - PUF2 ABCDE 3 BRIGHT - Stop - } -} - -// Gold wand puff 2 --------------------------------------------------------- - -ACTOR GoldWandPuff2 : GoldWandFX1 -{ - Skip_Super - +NOBLOCKMAP - +NOGRAVITY - +PUFFONACTORS - States - { - Spawn: - Goto Super::Death - } -} - - -// Crossbow ----------------------------------------------------------------- - -ACTOR Crossbow : HereticWeapon -{ - Weapon.SelectionOrder 800 - Weapon.AmmoUse 1 - Weapon.AmmoGive 10 - Weapon.AmmoType "CrossbowAmmo" - Weapon.SisterWeapon "CrossbowPowered" - Weapon.YAdjust 15 - Inventory.PickupMessage "$TXT_WPNCROSSBOW" - Tag "$TAG_CROSSBOW" - - action native A_FireCrossbowPL1 (); - - States - { - Spawn: - WBOW A -1 - Stop - Ready: - CRBW AAAAAABBBBBBCCCCCC 1 A_WeaponReady - Loop - Deselect: - CRBW A 1 A_Lower - Loop - Select: - CRBW A 1 A_Raise - Loop - Fire: - CRBW D 6 A_FireCrossbowPL1 - CRBW EFGH 3 - CRBW AB 4 - CRBW C 5 A_ReFire - Goto Ready - } -} - - -ACTOR CrossbowPowered : Crossbow -{ - +WEAPON.POWERED_UP - Weapon.AmmoGive 0 - Weapon.SisterWeapon "Crossbow" - Tag "$TAG_CROSSBOWP" - - action native A_FireCrossbowPL2(); - - States - { - Fire: - CRBW D 5 A_FireCrossbowPL2 - CRBW E 3 - CRBW F 2 - CRBW G 3 - CRBW H 2 - CRBW A 3 - CRBW B 3 - CRBW C 4 A_ReFire - Goto Ready - } -} - - -// Crossbow FX1 ------------------------------------------------------------- - -ACTOR CrossbowFX1 -{ - Radius 11 - Height 8 - Speed 30 - Damage 10 - Projectile - RenderStyle Add - SeeSound "weapons/bowshoot" - DeathSound "weapons/bowhit" - Obituary "$OB_MPCROSSBOW" - States - { - Spawn: - FX03 B 1 BRIGHT - Loop - Death: - FX03 HIJ 8 BRIGHT - Stop - } -} - - -// Crossbow FX2 ------------------------------------------------------------- - -ACTOR CrossbowFX2 : CrossbowFX1 -{ - Speed 32 - Damage 6 - Obituary "$OB_MPPCROSSBOW" - States - { - Spawn: - FX03 B 1 BRIGHT A_SpawnItemEx("CrossbowFX4", random2[BoltSpark]()*0.015625, random2[BoltSpark]()*0.015625, 0, 0,0,0,0,SXF_ABSOLUTEPOSITION, 50) - Loop - } -} - -// Crossbow FX3 ------------------------------------------------------------- - -ACTOR CrossbowFX3 : CrossbowFX1 -{ - Speed 20 - Damage 2 - SeeSound "" - -NOBLOCKMAP - +WINDTHRUST - +THRUGHOST - States - { - Spawn: - FX03 A 1 BRIGHT - Loop - Death: - FX03 CDE 8 BRIGHT - Stop - } -} - -// Crossbow FX4 ------------------------------------------------------------- - -ACTOR CrossbowFX4 -{ - +NOBLOCKMAP - Gravity 0.125 - RenderStyle Add - States - { - Spawn: - FX03 FG 8 BRIGHT - Stop - } -} - - - - -// Gauntlets ---------------------------------------------------------------- - -ACTOR Gauntlets : Weapon -{ - +BLOODSPLATTER - Weapon.SelectionOrder 2300 - +WEAPON.WIMPY_WEAPON - +WEAPON.MELEEWEAPON - Weapon.Kickback 0 - Weapon.YAdjust 15 - Weapon.UpSound "weapons/gauntletsactivate" - Weapon.SisterWeapon "GauntletsPowered" - Inventory.PickupMessage "$TXT_WPNGAUNTLETS" - Tag "$TAG_GAUNTLETS" - Obituary "$OB_MPGAUNTLETS" - - action native A_GauntletAttack (int power); - - States - { - Spawn: - WGNT A -1 - Stop - Ready: - GAUN A 1 A_WeaponReady - Loop - Deselect: - GAUN A 1 A_Lower - Loop - Select: - GAUN A 1 A_Raise - Loop - Fire: - GAUN B 4 A_PlayWeaponSound("weapons/gauntletsuse") - GAUN C 4 - Hold: - GAUN DEF 4 BRIGHT A_GauntletAttack(0) - GAUN C 4 A_ReFire - GAUN B 4 A_Light0 - Goto Ready - } -} - - -ACTOR GauntletsPowered : Gauntlets -{ - +POWERED_UP - Tag "$TAG_GAUNTLETSP" - Obituary "$OB_MPPGAUNTLETS" - Weapon.SisterWeapon "Gauntlets" - States - { - Ready: - GAUN GHI 4 A_WeaponReady - Loop - Deselect: - GAUN G 1 A_Lower - Loop - Select: - GAUN G 1 A_Raise - Loop - Fire: - GAUN J 4 A_PlayWeaponSound("weapons/gauntletsuse") - GAUN K 4 - Hold: - GAUN LMN 4 BRIGHT A_GauntletAttack(1) - GAUN K 4 A_ReFire - GAUN J 4 A_Light0 - Goto Ready - } -} - - -// Gauntlet puff 1 ---------------------------------------------------------- - -ACTOR GauntletPuff1 -{ - +NOBLOCKMAP - +NOGRAVITY - +PUFFONACTORS - RenderStyle Translucent - Alpha 0.4 - VSpeed 0.8 - States - { - Spawn: - PUF1 ABCD 4 BRIGHT - Stop - } -} - -// Gauntlet puff 2 --------------------------------------------------------- - -ACTOR GauntletPuff2 : GauntletPuff1 -{ - States - { - Spawn: - PUF1 EFGH 4 BRIGHT - Stop - } -} - - -// The mace itself ---------------------------------------------------------- - -ACTOR Mace : HereticWeapon -{ - Weapon.SelectionOrder 1400 - Weapon.AmmoUse 1 - Weapon.AmmoGive1 50 - Weapon.YAdjust 15 - Weapon.AmmoType "MaceAmmo" - Weapon.SisterWeapon "MacePowered" - Inventory.PickupMessage "$TXT_WPNMACE" - Tag "$TAG_MACE" - - action native A_FireMacePL1(); - - States - { - Spawn: - WMCE A -1 - Stop - Ready: - MACE A 1 A_WeaponReady - Loop - Deselect: - MACE A 1 A_Lower - Loop - Select: - MACE A 1 A_Raise - Loop - Fire: - MACE B 4 - Hold: - MACE CDEF 3 A_FireMacePL1 - MACE C 4 A_ReFire - MACE DEFB 4 - Goto Ready - } -} - -ACTOR MacePowered : Mace -{ - +WEAPON.POWERED_UP - Weapon.AmmoUse 5 - Weapon.AmmoGive 0 - Weapon.SisterWeapon "Mace" - Tag "$TAG_MACEP" - - action native A_FireMacePL2(); - - States - { - Fire: - Hold: - MACE B 4 - MACE D 4 A_FireMacePL2 - MACE B 4 - MACE A 8 A_ReFire - Goto Ready - } -} - -// Mace FX1 ----------------------------------------------------------------- - -ACTOR MaceFX1 -{ - Radius 8 - Height 6 - Speed 20 - Damage 2 - Projectile - +THRUGHOST - BounceType "HereticCompat" - SeeSound "weapons/maceshoot" - Obituary "$OB_MPMACE" - - action native A_MacePL1Check(); - action native A_MaceBallImpact(); - - States - { - Spawn: - FX02 AB 4 A_MacePL1Check - Loop - Death: - FX02 F 4 BRIGHT A_MaceBallImpact - FX02 GHIJ 4 BRIGHT - Stop - } -} - -// Mace FX2 ----------------------------------------------------------------- - -ACTOR MaceFX2 : MaceFX1 -{ - Speed 10 - Damage 6 - Gravity 0.125 - -NOGRAVITY - SeeSound "" - - action native A_MaceBallImpact2(); - - States - { - Spawn: - FX02 CD 4 - Loop - Death: - FX02 F 4 A_MaceBallImpact2 - goto Super::Death+1 - } -} - -// Mace FX3 ----------------------------------------------------------------- - -ACTOR MaceFX3 : MaceFX1 -{ - Speed 7 - Damage 4 - -NOGRAVITY - Gravity 0.125 - States - { - Spawn: - FX02 AB 4 - Loop - } -} - - -// Mace FX4 ----------------------------------------------------------------- - -ACTOR MaceFX4 native -{ - Radius 8 - Height 6 - Speed 7 - Damage 18 - Gravity 0.125 - Projectile - -NOGRAVITY - +TELESTOMP - +THRUGHOST - -NOTELEPORT - BounceType "HereticCompat" - SeeSound "" - Obituary "$OB_MPPMACE" - - action native A_DeathBallImpact(); - - States - { - Spawn: - FX02 E 99 - Loop - Death: - FX02 C 4 A_DeathBallImpact - FX02 GHIJ 4 BRIGHT - Stop - } -} - - -// Mace spawn spot ---------------------------------------------------------- - -ACTOR MaceSpawner : SpecialSpot -{ - +NOSECTOR - +NOBLOCKMAP - States - { - Spawn: - TNT1 A 1 - TNT1 A -1 A_SpawnSingleItem("Mace", 64, 64, 0) - Stop - } -} - - -// Blaster ------------------------------------------------------------------ - -ACTOR Blaster : HereticWeapon -{ - +BLOODSPLATTER - Weapon.SelectionOrder 500 - Weapon.AmmoUse 1 - Weapon.AmmoGive 30 - Weapon.YAdjust 15 - Weapon.AmmoType "BlasterAmmo" - Weapon.SisterWeapon "BlasterPowered" - Inventory.PickupMessage "$TXT_WPNBLASTER" - Tag "$TAG_BLASTER" - Obituary "$OB_MPBLASTER" - - action native A_FireBlasterPL1(); - - States - { - Spawn: - WBLS A -1 - Stop - Ready: - BLSR A 1 A_WeaponReady - Loop - Deselect: - BLSR A 1 A_Lower - Loop - Select: - BLSR A 1 A_Raise - Loop - Fire: - BLSR BC 3 - Hold: - BLSR D 2 A_FireBlasterPL1 - BLSR CB 2 - BLSR A 0 A_ReFire - Goto Ready - } -} - -ACTOR BlasterPowered : Blaster -{ - +WEAPON.POWERED_UP - Weapon.AmmoUse 5 - Weapon.AmmoGive 0 - Weapon.SisterWeapon "Blaster" - Tag "$TAG_BLASTERP" - States - { - Fire: - BLSR BC 0 - Hold: - BLSR D 3 A_FireCustomMissile("BlasterFX1") - BLSR CB 4 - BLSR A 0 A_ReFire - Goto Ready - } -} - -// Blaster FX 1 ------------------------------------------------------------- - -ACTOR BlasterFX1 : FastProjectile native -{ - Radius 12 - Height 8 - Speed 184 - Damage 2 - SeeSound "weapons/blastershoot" - DeathSound "weapons/blasterhit" - +SPAWNSOUNDSOURCE - Obituary "$OB_MPPBLASTER" - - action native A_SpawnRippers(); - - States - { - Spawn: - ACLO E 200 - Loop - Death: - FX18 A 3 BRIGHT A_SpawnRippers - FX18 B 3 BRIGHT - FX18 CDEFG 4 BRIGHT - Stop - } -} - -// Blaster smoke ------------------------------------------------------------ - -ACTOR BlasterSmoke -{ - +NOBLOCKMAP - +NOGRAVITY - +NOTELEPORT - +CANNOTPUSH - RenderStyle Translucent - Alpha 0.4 - States - { - Spawn: - FX18 HIJKL 4 - Stop - } -} - -// Ripper ------------------------------------------------------------------- - -ACTOR Ripper native -{ - Radius 8 - Height 6 - Speed 14 - Damage 1 - Projectile - +RIPPER - DeathSound "weapons/blasterpowhit" - Obituary "$OB_MPPBLASTER" - States - { - Spawn: - FX18 M 4 - FX18 N 5 - Loop - Death: - FX18 OPQRS 4 BRIGHT - Stop - } -} - -// Blaster Puff ------------------------------------------------------------- - -ACTOR BlasterPuff -{ - +NOBLOCKMAP - +NOGRAVITY - +PUFFONACTORS - RenderStyle Add - SeeSound "weapons/blasterhit" - States - { - Crash: - FX17 ABCDE 4 BRIGHT - Stop - Spawn: - FX17 FG 3 BRIGHT - FX17 HIJKL 4 BRIGHT - Stop - } -} - - -// Skull (Horn) Rod --------------------------------------------------------- - -ACTOR SkullRod : HereticWeapon -{ - Weapon.SelectionOrder 200 - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 50 - Weapon.YAdjust 15 - Weapon.AmmoType1 "SkullRodAmmo" - Weapon.SisterWeapon "SkullRodPowered" - Inventory.PickupMessage "$TXT_WPNSKULLROD" - Tag "$TAG_SKULLROD" - - action native A_FireSkullRodPL1(); - - States - { - Spawn: - WSKL A -1 - Stop - Ready: - HROD A 1 A_WeaponReady - Loop - Deselect: - HROD A 1 A_Lower - Loop - Select: - HROD A 1 A_Raise - Loop - Fire: - HROD AB 4 A_FireSkullRodPL1 - HROD B 0 A_ReFire - Goto Ready - } -} - -ACTOR SkullRodPowered : SkullRod -{ - +WEAPON.POWERED_UP - Weapon.AmmoUse1 5 - Weapon.AmmoGive1 0 - Weapon.SisterWeapon "SkullRod" - Tag "$TAG_SKULLRODP" - - action native A_FireSkullRodPL2(); - - States - { - Fire: - HROD C 2 - HROD D 3 - HROD E 2 - HROD F 3 - HROD G 4 A_FireSkullRodPL2 - HROD F 2 - HROD E 3 - HROD D 2 - HROD C 2 A_ReFire - Goto Ready - } -} - -// Horn Rod FX 1 ------------------------------------------------------------ - -ACTOR HornRodFX1 -{ - Radius 12 - Height 8 - Speed 22 - Damage 3 - Projectile - +WINDTHRUST - -NOBLOCKMAP - RenderStyle Add - SeeSound "weapons/hornrodshoot" - DeathSound "weapons/hornrodhit" - Obituary "$OB_MPSKULLROD" - States - { - Spawn: - FX00 AB 6 BRIGHT - Loop - Death: - FX00 HI 5 BRIGHT - FX00 JK 4 BRIGHT - FX00 LM 3 BRIGHT - Stop - } -} - - -// Horn Rod FX 2 ------------------------------------------------------------ - -ACTOR HornRodFX2 native -{ - Radius 12 - Height 8 - Speed 22 - Damage 10 - Health 140 - Projectile - RenderStyle Add - SeeSound "weapons/hornrodpowshoot" - DeathSound "weapons/hornrodpowhit" - Obituary "$OB_MPPSKULLROD" - - action native A_AddPlayerRain(); - action native A_HideInCeiling(); - action native A_SkullRodStorm(); - - States - { - Spawn: - FX00 C 3 BRIGHT - FX00 D 3 BRIGHT A_SeekerMissile(10, 30) - FX00 E 3 BRIGHT - FX00 F 3 BRIGHT A_SeekerMissile(10, 30) - Loop - Death: - FX00 H 5 BRIGHT A_AddPlayerRain - FX00 I 5 BRIGHT - FX00 J 4 BRIGHT - FX00 KLM 3 BRIGHT - FX00 G 1 A_HideInCeiling - FX00 G 1 A_SkullRodStorm - Wait - } -} - -// Rain pillar 1 ------------------------------------------------------------ - -ACTOR RainPillar native -{ - Radius 5 - Height 12 - Speed 12 - Damage 5 - Mass 5 - Projectile - -ACTIVATEPCROSS - -ACTIVATEIMPACT - RenderStyle Add - Obituary "$OB_MPPSKULLROD" - - action native A_RainImpact(); - - States - { - Spawn: - FX22 A -1 BRIGHT - Stop - Death: - FX22 B 4 BRIGHT A_RainImpact - FX22 CDEF 4 BRIGHT - Stop - NotFloor: - FX22 GHI 4 BRIGHT - Stop - } -} - -// Rain tracker "inventory" item -------------------------------------------- - -ACTOR RainTracker : Inventory native -{ - +INVENTORY.UNDROPPABLE -} - - -// Phoenix Rod -------------------------------------------------------------- - -ACTOR PhoenixRod : Weapon native -{ - +WEAPON.NOAUTOFIRE - Weapon.SelectionOrder 2600 - Weapon.Kickback 150 - Weapon.YAdjust 15 - Weapon.AmmoUse 1 - Weapon.AmmoGive 2 - Weapon.AmmoType "PhoenixRodAmmo" - Weapon.Sisterweapon "PhoenixRodPowered" - Inventory.PickupMessage "$TXT_WPNPHOENIxROD" - Tag "$TAG_PHOENIxROD" - - action native A_FirePhoenixPL1(); - - States - { - Spawn: - WPHX A -1 - Stop - Ready: - PHNX A 1 A_WeaponReady - Loop - Deselect: - PHNX A 1 A_Lower - Loop - Select: - PHNX A 1 A_Raise - Loop - Fire: - PHNX B 5 - PHNX C 7 A_FirePhoenixPL1 - PHNX DB 4 - PHNX B 0 A_ReFire - Goto Ready - } -} - -ACTOR PhoenixRodPowered : PhoenixRod native -{ - +WEAPON.POWERED_UP - +WEAPON.MELEEWEAPON - Weapon.SisterWeapon "PhoenixRod" - Weapon.AmmoGive 0 - Tag "$TAG_PHOENIxRODP" - - action native A_InitPhoenixPL2(); - action native A_FirePhoenixPL2(); - action native A_ShutdownPhoenixPL2(); - - States - { - Fire: - PHNX B 3 A_InitPhoenixPL2 - Hold: - PHNX C 1 A_FirePhoenixPL2 - PHNX B 4 A_ReFire - Powerdown: - PHNX B 4 A_ShutdownPhoenixPL2 - Goto Ready - } -} - -// Phoenix FX 1 ------------------------------------------------------------- - -ACTOR PhoenixFX1 native -{ - Radius 11 - Height 8 - Speed 20 - Damage 20 - DamageType Fire - Projectile - +THRUGHOST - +SPECIALFIREDAMAGE - SeeSound "weapons/phoenixshoot" - DeathSound "weapons/phoenixhit" - Obituary "$OB_MPPHOENIXROD" - - action native A_PhoenixPuff(); - - States - { - Spawn: - FX04 A 4 BRIGHT A_PhoenixPuff - Loop - Death: - FX08 A 6 BRIGHT A_Explode - FX08 BC 5 BRIGHT - FX08 DEFGH 4 BRIGHT - Stop - } -} - -// Phoenix puff ------------------------------------------------------------- - -ACTOR PhoenixPuff -{ - +NOBLOCKMAP - +NOGRAVITY - +NOTELEPORT - +CANNOTPUSH - RenderStyle Translucent - Alpha 0.4 - States - { - Spawn: - FX04 BCDEF 4 - Stop - } -} - -// Phoenix FX 2 ------------------------------------------------------------- - -ACTOR PhoenixFX2 native -{ - Radius 6 - Height 8 - Speed 10 - Damage 2 - DamageType Fire - Projectile - RenderStyle Add - Obituary "$OB_MPPPHOENIXROD" - - action native A_FlameEnd(); - action native A_FloatPuff(); - - States - { - Spawn: - FX09 ABABA 2 BRIGHT - FX09 B 2 BRIGHT A_FlameEnd - FX09 CDEF 2 BRIGHT - Stop - Death: - FX09 G 3 BRIGHT - FX09 H 3 BRIGHT A_FloatPuff - FX09 I 4 BRIGHT - FX09 JK 5 BRIGHT - Stop - } -} - diff --git a/wadsrc/static/actors/heretic/ironlich.txt b/wadsrc/static/actors/heretic/ironlich.txt deleted file mode 100644 index 43d7c16c5..000000000 --- a/wadsrc/static/actors/heretic/ironlich.txt +++ /dev/null @@ -1,175 +0,0 @@ - -// Ironlich ----------------------------------------------------------------- - -ACTOR Ironlich -{ - Health 700 - Radius 40 - Height 72 - Mass 325 - Speed 6 - Painchance 32 - Monster - +NOBLOOD - +DONTMORPH - +DONTSQUASH - +BOSSDEATH - SeeSound "ironlich/sight" - AttackSound "ironlich/attack" - PainSound "ironlich/pain" - DeathSound "ironlich/death" - ActiveSound "ironlich/active" - Obituary "$OB_IRONLICH" - HitObituary "$OB_IRONLICHHIT" - DropItem "BlasterAmmo", 84, 10 - DropItem "ArtiEgg", 51, 0 - - action native A_LichAttack (); - - States - { - Spawn: - LICH A 10 A_Look - Loop - See: - LICH A 4 A_Chase - Loop - Missile: - LICH A 5 A_FaceTarget - LICH B 20 A_LichAttack - Goto See - Pain: - LICH A 4 - LICH A 4 A_Pain - Goto See - Death: - LICH C 7 - LICH D 7 A_Scream - LICH EF 7 - LICH G 7 A_NoBlocking - LICH H 7 - LICH I -1 A_BossDeath - Stop - } -} - -// Head FX 1 ---------------------------------------------------------------- - -ACTOR HeadFX1 -{ - Radius 12 - Height 6 - Speed 13 - FastSpeed 20 - Damage 1 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - +THRUGHOST - RenderStyle Add - - action native A_LichIceImpact(); - - States - { - Spawn: - FX05 ABC 6 BRIGHT - Loop - Death: - FX05 D 5 BRIGHT A_LichIceImpact - FX05 EFG 5 BRIGHT - Stop - } -} - -// Head FX 2 ---------------------------------------------------------------- - -ACTOR HeadFX2 -{ - Radius 12 - Height 6 - Speed 8 - Damage 3 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - RenderStyle Add - States - { - Spawn: - FX05 HIJ 6 BRIGHT - Loop - Death: - FX05 DEFG 5 BRIGHT - Stop - } -} - - -// Head FX 3 ---------------------------------------------------------------- - -ACTOR HeadFX3 -{ - Radius 14 - Height 12 - Speed 10 - FastSpeed 18 - Damage 5 - Projectile - +WINDTHRUST - -ACTIVATEIMPACT - -ACTIVATEPCROSS - -NOBLOCKMAP - RenderStyle Add - - action native A_LichFireGrow (); - - States - { - Spawn: - FX06 ABC 4 BRIGHT A_LichFireGrow - Loop - NoGrow: - FX06 ABC 5 BRIGHT - Loop - Death: - FX06 DEFG 5 BRIGHT - Stop - } -} - - -// Whirlwind ---------------------------------------------------------------- - -ACTOR Whirlwind native -{ - Radius 16 - Height 74 - Speed 10 - Damage 1 - Projectile - -ACTIVATEIMPACT - -ACTIVATEMCROSS - +SEEKERMISSILE - +EXPLOCOUNT - +StepMissile - RenderStyle Translucent - DefThreshold 60 - Threshold 50 - Alpha 0.4 - - action native A_WhirlwindSeek(); - - States - { - Spawn: - FX07 DEFG 3 - FX07 ABC 3 A_WhirlwindSeek - Goto Spawn+4 - Death: - FX07 GFED 4 - Stop - } -} - - diff --git a/wadsrc/static/actors/heretic/knight.txt b/wadsrc/static/actors/heretic/knight.txt deleted file mode 100644 index 863c67b75..000000000 --- a/wadsrc/static/actors/heretic/knight.txt +++ /dev/null @@ -1,118 +0,0 @@ - -// Knight ------------------------------------------------------------------- - -ACTOR Knight -{ - Health 200 - Radius 24 - Height 78 - Mass 150 - Speed 12 - Painchance 100 - Monster - +FLOORCLIP - SeeSound "hknight/sight" - AttackSound "hknight/attack" - PainSound "hknight/pain" - DeathSound "hknight/death" - ActiveSound "hknight/active" - Obituary "$OB_BONEKNIGHT" - HitObituary "$OB_BONEKNIGHTHIT" - DropItem "CrossbowAmmo", 84, 5 - - action native A_KnightAttack (); - - States - { - Spawn: - KNIG AB 10 A_Look - Loop - See: - KNIG ABCD 4 A_Chase - Loop - Melee: - Missile: - KNIG E 10 A_FaceTarget - KNIG F 8 A_FaceTarget - KNIG G 8 A_KnightAttack - KNIG E 10 A_FaceTarget - KNIG F 8 A_FaceTarget - KNIG G 8 A_KnightAttack - Goto See - Pain: - KNIG H 3 - KNIG H 3 A_Pain - Goto See - Death: - KNIG I 6 - KNIG J 6 A_Scream - KNIG K 6 - KNIG L 6 A_NoBlocking - KNIG MN 6 - KNIG O -1 - Stop - } - -} - - -// Knight ghost ------------------------------------------------------------- - -ACTOR KnightGhost : Knight -{ - +SHADOW - +GHOST - RenderStyle Translucent - Alpha 0.4 -} - -// Knight axe --------------------------------------------------------------- - -ACTOR KnightAxe -{ - Radius 10 - Height 8 - Speed 9 - FastSpeed 18 - Damage 2 - Projectile - -NOBLOCKMAP - -ACTIVATEIMPACT - -ACTIVATEPCROSS - +WINDTHRUST - +THRUGHOST - DeathSound "hknight/hit" - States - { - Spawn: - SPAX A 3 BRIGHT A_PlaySound("hknight/axewhoosh") - SPAX BC 3 BRIGHT - Loop - Death: - SPAX DEF 6 BRIGHT - Stop - } -} - - -// Red axe ------------------------------------------------------------------ - -ACTOR RedAxe : KnightAxe -{ - +NOBLOCKMAP - -WINDTHRUST - Damage 7 - - action native A_DripBlood (); - - States - { - Spawn: - RAXE AB 5 BRIGHT A_DripBlood - Loop - Death: - RAXE CDE 6 BRIGHT - Stop - } -} - diff --git a/wadsrc/static/actors/heretic/mummy.txt b/wadsrc/static/actors/heretic/mummy.txt deleted file mode 100644 index 331f315cd..000000000 --- a/wadsrc/static/actors/heretic/mummy.txt +++ /dev/null @@ -1,133 +0,0 @@ - -// Mummy -------------------------------------------------------------------- - -ACTOR Mummy -{ - Health 80 - Radius 22 - Height 62 - Mass 75 - Speed 12 - Painchance 128 - Monster - +FLOORCLIP - SeeSound "mummy/sight" - AttackSound "mummy/attack1" - PainSound "mummy/pain" - DeathSound "mummy/death" - ActiveSound "mummy/active" - HitObituary "$OB_MUMMY" - DropItem "GoldWandAmmo", 84, 3 - States - { - Spawn: - MUMM AB 10 A_Look - Loop - See: - MUMM ABCD 4 A_Chase - Loop - Melee: - MUMM E 6 A_FaceTarget - MUMM F 6 A_CustomMeleeAttack(random[MummyAttack](1,8)*2, "mummy/attack2", "mummy/attack") - MUMM G 6 - Goto See - Pain: - MUMM H 4 - MUMM H 4 A_Pain - Goto See - Death: - MUMM I 5 - MUMM J 5 A_Scream - MUMM K 5 A_SpawnItemEx("MummySoul", 0,0,10, 0,0,1) - MUMM L 5 - MUMM M 5 A_NoBlocking - MUMM NO 5 - MUMM P -1 - Stop - } -} - -// Mummy leader ------------------------------------------------------------- - -ACTOR MummyLeader : Mummy -{ - Species "MummyLeader" - Health 100 - Painchance 64 - Obituary "$OB_MUMMYLEADER" - States - { - Missile: - MUMM X 5 A_FaceTarget - MUMM Y 5 Bright A_FaceTarget - MUMM X 5 A_FaceTarget - MUMM Y 5 Bright A_FaceTarget - MUMM X 5 A_FaceTarget - MUMM Y 5 Bright A_CustomComboAttack("MummyFX1", 32, random[MummyAttack2](1,8)*2, "mummy/attack2") - Goto See - } -} - -// Mummy ghost -------------------------------------------------------------- - -ACTOR MummyGhost : Mummy -{ - +SHADOW - +GHOST - RenderStyle Translucent - Alpha 0.4 -} - -// Mummy leader ghost ------------------------------------------------------- - -ACTOR MummyLeaderGhost : MummyLeader -{ - Species "MummyLeaderGhost" - +SHADOW - +GHOST - RenderStyle Translucent - Alpha 0.4 -} - -// Mummy soul --------------------------------------------------------------- - -ACTOR MummySoul -{ - +NOBLOCKMAP - +NOGRAVITY - States - { - Spawn: - MUMM QRS 5 - MUMM TUVW 9 - Stop - } -} - -// Mummy FX 1 (flying head) ------------------------------------------------- - -ACTOR MummyFX1 -{ - Radius 8 - Height 14 - Speed 9 - FastSpeed 18 - Damage 4 - RenderStyle Add - Projectile - -ACTIVATEPCROSS - -ACTIVATEIMPACT - +SEEKERMISSILE - States - { - Spawn: - FX15 A 5 Bright A_PlaySound("mummy/head") - FX15 B 5 Bright A_SeekerMissile(10,20) - FX15 C 5 Bright - FX15 B 5 Bright A_SeekerMissile(10,20) - Loop - Death: - FX15 DEFG 5 Bright - Stop - } -} diff --git a/wadsrc/static/actors/heretic/snake.txt b/wadsrc/static/actors/heretic/snake.txt deleted file mode 100644 index bb9beb3dd..000000000 --- a/wadsrc/static/actors/heretic/snake.txt +++ /dev/null @@ -1,95 +0,0 @@ - -ACTOR Snake -{ - Health 280 - Radius 22 - Height 70 - Speed 10 - Painchance 48 - Monster - +FLOORCLIP - AttackSound "snake/attack" - SeeSound "snake/sight" - PainSound "snake/pain" - DeathSound "snake/death" - ActiveSound "snake/active" - Obituary "$OB_SNAKE" - DropItem "PhoenixRodAmmo", 84, 5 - States - { - Spawn: - SNKE AB 10 A_Look - Loop - See: - SNKE ABCD 4 A_Chase - Loop - Missile: - SNKE FF 5 A_FaceTarget - SNKE FFF 4 A_CustomMissile("SnakeProjA", 32, 0, 0, CMF_CHECKTARGETDEAD) - SNKE FFF 5 A_FaceTarget - SNKE F 4 A_CustomMissile("SnakeProjB", 32, 0, 0, CMF_CHECKTARGETDEAD) - Goto See - Pain: - SNKE E 3 - SNKE E 3 A_Pain - Goto See - Death: - SNKE G 5 - SNKE H 5 A_Scream - SNKE IJKL 5 - SNKE M 5 A_NoBlocking - SNKE NO 5 - SNKE P -1 - Stop - } -} - -// Snake projectile A ------------------------------------------------------- - -ACTOR SnakeProjA -{ - Radius 12 - Height 8 - Speed 14 - FastSpeed 20 - Damage 1 - Projectile - -NOBLOCKMAP - -ACTIVATEIMPACT - -ACTIVATEPCROSS - +WINDTHRUST - +SPAWNSOUNDSOURCE - RenderStyle Add - SeeSound "snake/attack" - States - { - Spawn: - SNFX ABCD 5 Bright - Loop - Death: - SNFX EF 5 Bright - SNFX G 4 Bright - SNFX HI 3 Bright - Stop - } -} - -// Snake projectile B ------------------------------------------------------- - -ACTOR SnakeProjB : SnakeProjA -{ - Damage 3 - +NOBLOCKMAP - -WINDTHRUST - States - { - Spawn: - SNFX JK 6 Bright - Loop - Death: - SNFX LM 5 Bright - SNFX N 4 Bright - SNFX O 3 Bright - Stop - } -} diff --git a/wadsrc/static/actors/heretic/wizard.txt b/wadsrc/static/actors/heretic/wizard.txt deleted file mode 100644 index 11ef0ad67..000000000 --- a/wadsrc/static/actors/heretic/wizard.txt +++ /dev/null @@ -1,96 +0,0 @@ - -// Wizard -------------------------------------------------------- - -ACTOR Wizard -{ - Health 180 - Radius 16 - Height 68 - Mass 100 - Speed 12 - Painchance 64 - Monster - +FLOAT - +NOGRAVITY - +DONTOVERLAP - SeeSound "wizard/sight" - AttackSound "wizard/attack" - PainSound "wizard/pain" - DeathSound "wizard/death" - ActiveSound "wizard/active" - Obituary "$OB_WIZARD" - HitObituary "$OB_WIZARDHIT" - DropItem "BlasterAmmo", 84, 10 - DropItem "ArtiTomeOfPower", 4, 0 - - action native A_GhostOff (); - action native A_WizAtk1 (); - action native A_WizAtk2 (); - action native A_WizAtk3 (); - - States - { - Spawn: - WZRD AB 10 A_Look - Loop - See: - WZRD A 3 A_Chase - WZRD A 4 A_Chase - WZRD A 3 A_Chase - WZRD A 4 A_Chase - WZRD B 3 A_Chase - WZRD B 4 A_Chase - WZRD B 3 A_Chase - WZRD B 4 A_Chase - Loop - Missile: - WZRD C 4 A_WizAtk1 - WZRD C 4 A_WizAtk2 - WZRD C 4 A_WizAtk1 - WZRD C 4 A_WizAtk2 - WZRD C 4 A_WizAtk1 - WZRD C 4 A_WizAtk2 - WZRD C 4 A_WizAtk1 - WZRD C 4 A_WizAtk2 - WZRD D 12 A_WizAtk3 - Goto See - Pain: - WZRD E 3 A_GhostOff - WZRD E 3 A_Pain - Goto See - Death: - WZRD F 6 A_GhostOff - WZRD G 6 A_Scream - WZRD HI 6 - WZRD J 6 A_NoBlocking - WZRD KL 6 - WZRD M -1 A_SetFloorClip - Stop - } -} - -// Projectile -------------------------------------------------------- - -ACTOR WizardFX1 -{ - Radius 10 - Height 6 - Speed 18 - FastSpeed 24 - Damage 3 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - RenderStyle Add - States - { - Spawn: - FX11 AB 6 BRIGHT - Loop - Death: - FX11 CDEFG 5 BRIGHT - Stop - } -} - - diff --git a/wadsrc/static/actors/hexen/baseweapons.txt b/wadsrc/static/actors/hexen/baseweapons.txt deleted file mode 100644 index d40536316..000000000 --- a/wadsrc/static/actors/hexen/baseweapons.txt +++ /dev/null @@ -1,20 +0,0 @@ -// The Doom and Heretic players are not excluded from pickup in case -// somebody wants to use these weapons with either of those games. - -ACTOR FighterWeapon : Weapon native -{ - Weapon.Kickback 150 - Inventory.ForbiddenTo ClericPlayer, MagePlayer -} - -ACTOR ClericWeapon : Weapon native -{ - Weapon.Kickback 150 - Inventory.ForbiddenTo FighterPlayer, MagePlayer -} - -ACTOR MageWeapon : Weapon native -{ - Weapon.Kickback 150 - Inventory.ForbiddenTo FighterPlayer, ClericPlayer -} diff --git a/wadsrc/static/actors/hexen/bats.txt b/wadsrc/static/actors/hexen/bats.txt deleted file mode 100644 index 521d46e6e..000000000 --- a/wadsrc/static/actors/hexen/bats.txt +++ /dev/null @@ -1,47 +0,0 @@ - -// Bat Spawner -------------------------------------------------------------- - -ACTOR BatSpawner : SwitchableDecoration -{ - +NOBLOCKMAP +NOSECTOR +NOGRAVITY - RenderStyle None - - action native A_BatSpawnInit(); - action native A_BatSpawn(); - - States - { - Spawn: - Active: - TNT1 A 2 - TNT1 A 2 A_BatSpawnInit - TNT1 A 2 A_BatSpawn - Wait - Inactive: - TNT1 A -1 - Stop - } -} - -// Bat ---------------------------------------------------------------------- - -ACTOR Bat -{ - Speed 5 - Radius 3 - Height 3 - +NOBLOCKMAP +NOGRAVITY +MISSILE - +NOTELEPORT +CANPASS - - action native A_BatMove(); - - States - { - Spawn: - ABAT ABC 2 A_BatMove - Loop - Death: - ABAT A 2 - Stop - } -} diff --git a/wadsrc/static/actors/hexen/bishop.txt b/wadsrc/static/actors/hexen/bishop.txt deleted file mode 100644 index 435420ddd..000000000 --- a/wadsrc/static/actors/hexen/bishop.txt +++ /dev/null @@ -1,151 +0,0 @@ - -// Bishop ------------------------------------------------------------------- - -ACTOR Bishop -{ - Health 130 - Radius 22 - Height 65 - Speed 10 - PainChance 110 - Monster - +FLOAT +NOGRAVITY +NOBLOOD - +TELESTOMP - +DONTOVERLAP - +NOTARGETSWITCH - SeeSound "BishopSight" - AttackSound "BishopAttack" - PainSound "BishopPain" - DeathSound "BishopDeath" - ActiveSound "BishopActiveSounds" - Obituary"$OB_BISHOP" - - action native A_BishopChase(); - action native A_BishopDecide(); - action native A_BishopDoBlur(); - action native A_BishopSpawnBlur(); - action native A_BishopPainBlur(); - action native A_BishopAttack(); - action native A_BishopAttack2(); - - States - { - Spawn: - BISH A 10 A_Look - Loop - See: - BISH A 2 A_Chase - BISH A 2 A_BishopChase - BISH A 2 - BISH B 2 A_BishopChase - BISH B 2 A_Chase - BISH B 2 A_BishopChase - BISH A 1 A_BishopDecide - Loop - Blur: - BISH A 2 A_BishopDoBlur - BISH A 4 A_BishopSpawnBlur - Wait - Pain: - BISH C 6 A_Pain - BISH CCC 6 A_BishopPainBlur - BISH C 0 - Goto See - Missile: - BISH A 3 A_FaceTarget - BISH DE 3 A_FaceTarget - BISH F 3 A_BishopAttack - BISH F 5 A_BishopAttack2 - Wait - Death: - BISH G 6 - BISH H 6 Bright A_Scream - BISH I 5 Bright A_NoBlocking - BISH J 5 BRIGHT A_Explode(random[BishopBoom](25,40)) - BISH K 5 Bright - BISH LM 4 Bright - BISH N 4 A_SpawnItemEx("BishopPuff", 0,0,40, 0,0,0.5) - BISH O 4 A_QueueCorpse - BISH P -1 - Stop - Ice: - BISH X 5 A_FreezeDeath - BISH X 1 A_FreezeDeathChunks - Wait - } -} - -// Bishop puff -------------------------------------------------------------- - -ACTOR BishopPuff -{ - +NOBLOCKMAP +NOGRAVITY - RenderStyle Translucent - Alpha 0.6 - States - { - Spawn: - BISH QRST 5 - BISH UV 6 - BISH W 5 - Stop - } -} - -// Bishop pain blur --------------------------------------------------------- - -ACTOR BishopPainBlur -{ - +NOBLOCKMAP +NOGRAVITY - RenderStyle Translucent - Alpha 0.6 - States - { - Spawn: - BISH C 8 - Stop - } -} - -// Bishop FX ---------------------------------------------------------------- - -ACTOR BishopFX -{ - Radius 10 - Height 6 - Speed 10 - Damage 1 - Projectile - +SEEKERMISSILE - -ACTIVATEIMPACT -ACTIVATEPCROSS - +STRIFEDAMAGE - RenderStyle Add - DeathSound "BishopMissileExplode" - States - { - Spawn: - BPFX ABAB 1 Bright A_BishopMissileWeave - BPFX B 0 Bright A_SeekerMissile(2,3) - Loop - Death: - BPFX CDEF 4 Bright - BPFX GH 3 Bright - Stop - } -} - -// Bishop blur -------------------------------------------------------------- - -ACTOR BishopBlur -{ - +NOBLOCKMAP +NOGRAVITY - RenderStyle Translucent - Alpha 0.6 - States - { - Spawn: - BISH A 16 - BISH A 8 A_SetTranslucent(0.4) - Stop - } -} diff --git a/wadsrc/static/actors/hexen/blastradius.txt b/wadsrc/static/actors/hexen/blastradius.txt deleted file mode 100644 index 561240438..000000000 --- a/wadsrc/static/actors/hexen/blastradius.txt +++ /dev/null @@ -1,36 +0,0 @@ - -ACTOR ArtiBlastRadius : CustomInventory -{ - +FLOATBOB - Inventory.DefMaxAmount - Inventory.PickupFlash "PickupFlash" - +INVBAR +FANCYPICKUPSOUND - Inventory.Icon "ARTIBLST" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIBLASTRADIUS" - Tag "$TAG_ARTIBLASTRADIUS" - States - { - Spawn: - BLST ABCDEFGH 4 Bright - Loop - Use: - TNT1 A 0 A_Blast - } -} - -// Blast Effect ------------------------------------------------------------- - -ACTOR BlastEffect -{ - +NOBLOCKMAP +NOGRAVITY +NOCLIP - +NOTELEPORT - RenderStyle Translucent - Alpha 0.666 - States - { - Spawn: - RADE ABCDEFGHI 4 - Stop - } -} diff --git a/wadsrc/static/actors/hexen/boostarmor.txt b/wadsrc/static/actors/hexen/boostarmor.txt deleted file mode 100644 index b55c29f88..000000000 --- a/wadsrc/static/actors/hexen/boostarmor.txt +++ /dev/null @@ -1,21 +0,0 @@ - -// Boost Armor Artifact (Dragonskin Bracers) -------------------------------- - -ACTOR ArtiBoostArmor : Inventory native -{ - +COUNTITEM - +FLOATBOB - Inventory.DefMaxAmount - Inventory.PickupFlash "PickupFlash" - +INVBAR +FANCYPICKUPSOUND - Inventory.Icon "ARTIBRAC" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIBOOSTARMOR" - Tag "$TAG_ARTIBOOSTARMOR" - States - { - Spawn: - BRAC ABCDEFGH 4 Bright - Loop - } -} diff --git a/wadsrc/static/actors/hexen/centaur.txt b/wadsrc/static/actors/hexen/centaur.txt deleted file mode 100644 index d036566bd..000000000 --- a/wadsrc/static/actors/hexen/centaur.txt +++ /dev/null @@ -1,186 +0,0 @@ -// Centaur ------------------------------------------------------------------ - -ACTOR Centaur -{ - Health 200 - Painchance 135 - Speed 13 - Height 64 - Mass 120 - Monster - +FLOORCLIP - +TELESTOMP - +SHIELDREFLECT - SeeSound "CentaurSight" - AttackSound "CentaurAttack" - PainSound "CentaurPain" - DeathSound "CentaurDeath" - ActiveSound "CentaurActive" - HowlSound "PuppyBeat" - Obituary "$OB_CENTAUR" - DamageFactor "Electric", 3 - States - { - Spawn: - CENT AB 10 A_Look - Loop - See: - CENT ABCD 4 A_Chase - Loop - Pain: - CENT G 6 A_Pain - CENT G 6 A_SetReflectiveInvulnerable - CENT EEE 15 A_CentaurDefend - CENT E 1 A_UnsetReflectiveInvulnerable - Goto See - Melee: - CENT H 5 A_FaceTarget - CENT I 4 A_FaceTarget - CENT J 7 A_CustomMeleeAttack(random[CentaurAttack](3,9)) - Goto See - Death: - CENT K 4 - CENT L 4 A_Scream - CENT MN 4 - CENT O 4 A_NoBlocking - CENT PQ 4 - CENT R 4 A_QueueCorpse - CENT S 4 - CENT T -1 - Stop - XDeath: - CTXD A 4 - CTXD B 4 A_NoBlocking - CTXD C 0 A_SpawnItemEx("CentaurSword", 0, 0, 45, - 1 + random[CentaurDrop](-128,127)*0.03125, - 1 + random[CentaurDrop](-128,127)*0.03125, - 8 + random[CentaurDrop](0,255)*0.015625, 270) - CTXD C 4 A_SpawnItemEx("CentaurShield", 0, 0, 45, - 1 + random[CentaurDrop](-128,127)*0.03125, - 1 + random[CentaurDrop](-128,127)*0.03125, - 8 + random[CentaurDrop](0,255)*0.015625, 90) - CTXD D 3 A_Scream - CTXD E 4 A_QueueCorpse - CTXD F 3 - CTXD G 4 - CTXD H 3 - CTXD I 4 - CTXD J 3 - CTXD K -1 - Ice: - CENT U 5 A_FreezeDeath - CENT U 1 A_FreezeDeathChunks - Wait - } -} - -// Centaur Leader ----------------------------------------------------------- - -ACTOR CentaurLeader : Centaur -{ - Health 250 - PainChance 96 - Speed 10 - Obituary "$OB_SLAUGHTAUR" - HitObituary "$OB_SLAUGHTAURHIT" - States - { - Missile: - CENT E 10 A_FaceTarget - CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET) - CENT E 10 A_FaceTarget - CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET) - Goto See - } -} - -// Mashed centaur ----------------------------------------------------------- -// -// The mashed centaur is only placed through ACS. Nowhere in the game source -// is it ever referenced. - -ACTOR CentaurMash : Centaur -{ - +NOBLOOD - +BLASTED - -TELESTOMP - +NOICEDEATH - RenderStyle Translucent - Alpha 0.4 - States - { - Death: - XDeath: - Ice: - Stop - } -} - -// Centaur projectile ------------------------------------------------------- - -ACTOR CentaurFX -{ - Speed 20 - Damage 4 - Projectile - +SPAWNSOUNDSOURCE - RenderStyle Add - SeeSound "CentaurLeaderAttack" - DeathSound "CentaurMissileExplode" - States - { - Spawn: - CTFX A -1 Bright - Stop - Death: - CTFX B 4 Bright - CTFX C 3 Bright - CTFX D 4 Bright - CTFX E 3 Bright - CTFX F 2 Bright - Stop - } -} - -// Centaur shield (debris) -------------------------------------------------- - -ACTOR CentaurShield -{ - +DROPOFF - +CORPSE - +NOTELEPORT - States - { - Spawn: - CTDP ABCDEF 3 - Goto Spawn+2 - Crash: - CTDP G 4 - CTDP H 4 A_QueueCorpse - CTDP I 4 - CTDP J -1 - Stop - } -} - -// Centaur sword (debris) --------------------------------------------------- - -ACTOR CentaurSword -{ - +DROPOFF - +CORPSE - +NOTELEPORT - States - { - Spawn: - CTDP KLMNOPQ 3 - Goto Spawn+2 - Crash: - CTDP R 4 - CTDP S 4 A_QueueCorpse - CTDP T -1 - Stop - } -} - - diff --git a/wadsrc/static/actors/hexen/clericboss.txt b/wadsrc/static/actors/hexen/clericboss.txt deleted file mode 100644 index dac0f741c..000000000 --- a/wadsrc/static/actors/hexen/clericboss.txt +++ /dev/null @@ -1,79 +0,0 @@ - -// Cleric Boss (Traductus) -------------------------------------------------- - -ACTOR ClericBoss -{ - Health 800 - PainChance 50 - Speed 25 - Radius 16 - Height 64 - Monster - +FLOORCLIP +TELESTOMP - +DONTMORPH - PainSound "PlayerClericPain" - DeathSound "PlayerClericCrazyDeath" - Obituary "$OBCBOSS" - - action native A_ClericAttack(); - - States - { - Spawn: - CLER A 2 - CLER A 3 A_ClassBossHealth - CLER A 5 A_Look - Wait - See: - CLER ABCD 4 A_FastChase - Loop - Pain: - CLER H 4 - CLER H 4 A_Pain - Goto See - Melee: - Missile: - CLER EF 8 A_FaceTarget - CLER G 10 A_ClericAttack - Goto See - Death: - CLER I 6 - CLER K 6 A_Scream - CLER LL 6 - CLER M 6 A_NoBlocking - CLER NOP 6 - CLER Q -1 - Stop - XDeath: - CLER R 5 A_Scream - CLER S 5 - CLER T 5 A_NoBlocking - CLER UVWXYZ 5 - CLER "[" -1 - Stop - Ice: - CLER "\" 5 A_FreezeDeath - CLER "\" 1 A_FreezeDeathChunks - Wait - Burn: - CLER C 5 Bright A_PlaySound("PlayerClericBurnDeath") - FDTH D 4 Bright - FDTH G 5 Bright - FDTH H 4 Bright A_Scream - FDTH I 5 Bright - FDTH J 4 Bright - FDTH K 5 Bright - FDTH L 4 Bright - FDTH M 5 Bright - FDTH N 4 Bright - FDTH O 5 Bright - FDTH P 4 Bright - FDTH Q 5 Bright - FDTH R 4 Bright - FDTH S 5 Bright A_NoBlocking - FDTH T 4 Bright - FDTH U 5 Bright - FDTH V 4 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/clericflame.txt b/wadsrc/static/actors/hexen/clericflame.txt deleted file mode 100644 index b6688a6ed..000000000 --- a/wadsrc/static/actors/hexen/clericflame.txt +++ /dev/null @@ -1,196 +0,0 @@ - -// The Cleric's Flame Strike ------------------------------------------------ - -ACTOR CWeapFlame : ClericWeapon -{ - +NOGRAVITY - Weapon.SelectionOrder 1000 - Weapon.AmmoUse 4 - Weapon.AmmoGive 25 - Weapon.KickBack 150 - Weapon.YAdjust 10 - Weapon.AmmoType1 "Mana2" - Inventory.PickupMessage "$TXT_WEAPON_C3" - Tag "$TAG_CWEAPFLAME" - - action native A_CFlameAttack(); - - States - { - Spawn: - WCFM ABCDEFGH 4 Bright - Loop - Select: - CFLM A 1 A_Raise - Loop - Deselect: - CFLM A 1 A_Lower - Loop - Ready: - CFLM AAAABBBBCCCC 1 A_WeaponReady - Loop - Fire: - CFLM A 2 Offset (0, 40) - CFLM D 2 Offset (0, 50) - CFLM D 2 Offset (0, 36) - CFLM E 4 Bright - CFLM F 4 Bright A_CFlameAttack - CFLM E 4 Bright - CFLM G 2 Offset (0, 40) - CFLM G 2 - Goto Ready - } -} - -// Floor Flame -------------------------------------------------------------- - -ACTOR CFlameFloor -{ - +NOBLOCKMAP +NOGRAVITY - RenderStyle Add - States - { - Spawn: - CFFX N 5 Bright - CFFX O 4 Bright - CFFX P 3 Bright - Stop - } -} - -// Flame Puff --------------------------------------------------------------- - -ACTOR FlamePuff -{ - Radius 1 - Height 1 - +NOBLOCKMAP +NOGRAVITY - RenderStyle Add - SeeSound "ClericFlameExplode" - AttackSound "ClericFlameExplode" - States - { - Spawn: - CFFX ABC 3 Bright - CFFX D 4 Bright - CFFX E 3 Bright - CFFX F 4 Bright - CFFX G 3 Bright - CFFX H 4 Bright - CFFX I 3 Bright - CFFX J 4 Bright - CFFX K 3 Bright - CFFX L 4 Bright - CFFX M 3 Bright - Stop - } -} - -// Flame Puff 2 ------------------------------------------------------------- - -ACTOR FlamePuff2 : FlamePuff -{ - States - { - Spawn: - CFFX ABC 3 Bright - CFFX D 4 Bright - CFFX E 3 Bright - CFFX F 4 Bright - CFFX G 3 Bright - CFFX H 4 Bright - CFFX IC 3 Bright - CFFX D 4 Bright - CFFX E 3 Bright - CFFX F 4 Bright - CFFX G 3 Bright - CFFX H 4 Bright - CFFX I 3 Bright - CFFX J 4 Bright - CFFX K 3 Bright - CFFX L 4 Bright - CFFX M 3 Bright - Stop - } -} - -// Circle Flame ------------------------------------------------------------- - -ACTOR CircleFlame -{ - Radius 6 - Damage 2 - DamageType "Fire" - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - RenderStyle Add - DeathSound "ClericFlameCircle" - Obituary "$OB_MPCWEAPFLAME" - - action native A_CFlameRotate(); - - States - { - Spawn: - CFCF A 4 Bright - CFCF B 2 Bright A_CFlameRotate - CFCF C 2 Bright - CFCF D 1 Bright - CFCF E 2 Bright - CFCF F 2 Bright A_CFlameRotate - CFCF G 1 Bright - CFCF HI 2 Bright - CFCF J 1 Bright A_CFlameRotate - CFCF K 2 Bright - CFCF LM 3 Bright - CFCF N 2 Bright A_CFlameRotate - CFCF O 3 Bright - CFCF P 2 Bright - Stop - Death: - CFCF QR 3 Bright - CFCF S 3 Bright A_Explode(20, 20, 0) - CFCF TUVWXYZ 3 Bright - Stop - } -} - -// Flame Missile ------------------------------------------------------------ - -ACTOR CFlameMissile : FastProjectile native -{ - Speed 200 - Radius 14 - Height 8 - Damage 8 - DamageType "Fire" - +INVISIBLE - RenderStyle Add - Obituary "$OB_MPCWEAPFLAME" - - action native A_CFlamePuff(); - action native A_CFlameMissile(); - - States - { - Spawn: - CFFX A 4 Bright - CFFX A 1 A_CFlamePuff - Goto Death + 1 - Death: - CFFX A 1 Bright A_CFlameMissile - CFFX ABC 3 Bright - CFFX D 4 Bright - CFFX E 3 Bright - CFFX F 4 Bright - CFFX G 3 Bright - CFFX H 4 Bright - CFFX I 3 Bright - CFFX J 4 Bright - CFFX K 3 Bright - CFFX L 4 Bright - CFFX M 3 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/clericholy.txt b/wadsrc/static/actors/hexen/clericholy.txt deleted file mode 100644 index f24a846b3..000000000 --- a/wadsrc/static/actors/hexen/clericholy.txt +++ /dev/null @@ -1,237 +0,0 @@ - -// Cleric Weapon Piece ------------------------------------------------------ - -ACTOR ClericWeaponPiece : WeaponPiece -{ - Inventory.PickupSound "misc/w_pkup" - Inventory.PickupMessage "$TXT_WRAITHVERGE_PIECE" - Inventory.ForbiddenTo FighterPlayer, MagePlayer - WeaponPiece.Weapon CWeapWraithverge - +FLOATBOB -} - -// Cleric Weapon Piece 1 ---------------------------------------------------- - -ACTOR CWeaponPiece1 : ClericWeaponPiece -{ - WeaponPiece.Number 1 - States - { - Spawn: - WCH1 A -1 - Stop - } -} - -// Cleric Weapon Piece 2 ---------------------------------------------------- - -ACTOR CWeaponPiece2 : ClericWeaponPiece -{ - WeaponPiece.Number 2 - States - { - Spawn: - WCH2 A -1 - Stop - } -} - -// Cleric Weapon Piece 3 ---------------------------------------------------- - -ACTOR CWeaponPiece3 : ClericWeaponPiece -{ - WeaponPiece.Number 3 - States - { - Spawn: - WCH3 A -1 - Stop - } -} - -// Wraithverge Drop --------------------------------------------------------- - -ACTOR WraithvergeDrop -{ - States - { - Spawn: - TNT1 A 1 - TNT1 A 1 A_DropWeaponPieces("CWeaponPiece1", "CWeaponPiece2", "CWeaponPiece3") - Stop - } -} - -// Cleric's Wraithverge (Holy Symbol?) -------------------------------------- - -ACTOR CWeapWraithverge : ClericWeapon native -{ - Health 3 - Weapon.SelectionOrder 3000 - +WEAPON.PRIMARY_USES_BOTH - +Inventory.NoAttenPickupSound - Weapon.AmmoUse1 18 - Weapon.AmmoUse2 18 - Weapon.AmmoGive1 20 - Weapon.AmmoGive2 20 - Weapon.KickBack 150 - Weapon.AmmoType1 "Mana1" - Weapon.AmmoType2 "Mana2" - Inventory.PickupMessage "$TXT_WEAPON_C4" - Tag "$TAG_CWEAPWRAITHVERGE" - Inventory.PickupSound "WeaponBuild" - - action native A_CHolyAttack(); - action native A_CHolyPalette(); - - States - { - Spawn: - TNT1 A -1 - Stop - Ready: - CHLY A 1 A_WeaponReady - Loop - Select: - CHLY A 1 A_Raise - Loop - Deselect: - CHLY A 1 A_Lower - Loop - Fire: - CHLY AB 1 Bright Offset (0, 40) - CHLY CD 2 Bright Offset (0, 43) - CHLY E 2 Bright Offset (0, 45) - CHLY F 6 Bright Offset (0, 48) A_CHolyAttack - CHLY GG 2 Bright Offset (0, 40) A_CHolyPalette - CHLY G 2 Offset (0, 36) A_CHolyPalette - Goto Ready - } -} - -// Holy Missile ------------------------------------------------------------- - -ACTOR HolyMissile -{ - Speed 30 - Radius 15 - Height 8 - Damage 4 - Projectile - -ACTIVATEIMPACT -ACTIVATEPCROSS - +EXTREMEDEATH - - action native A_CHolyAttack2(); - - States - { - Spawn: - SPIR PPPP 3 Bright A_SpawnItemEx("HolyMissilePuff") - Death: - SPIR P 1 Bright A_CHolyAttack2 - Stop - } -} - -// Holy Missile Puff -------------------------------------------------------- - -ACTOR HolyMissilePuff -{ - Radius 4 - Height 8 - +NOBLOCKMAP +NOGRAVITY +DROPOFF - +NOTELEPORT - RenderStyle "Translucent" - Alpha 0.4 - States - { - Spawn: - SPIR QRSTU 3 - Stop - } -} - -// Holy Puff ---------------------------------------------------------------- - -ACTOR HolyPuff -{ - +NOBLOCKMAP +NOGRAVITY - RenderStyle Translucent - Alpha 0.6 - States - { - Spawn: - SPIR KLMNO 3 - Stop - } -} - -// Holy Spirit -------------------------------------------------------------- - -ACTOR HolySpirit native -{ - Health 105 - Speed 12 - Radius 10 - Height 6 - Damage 3 - Projectile - +RIPPER +SEEKERMISSILE - +FOILINVUL +SKYEXPLODE +NOEXPLODEFLOOR +CANBLAST - +EXTREMEDEATH - RenderStyle Translucent - Alpha 0.4 - DeathSound "SpiritDie" - Obituary "$OB_MPCWEAPWRAITHVERGE" - - action native A_CHolySeek(); - action native A_CHolyCheckScream(); - - States - { - Spawn: - SPIR AAB 2 A_CHolySeek - SPIR B 2 A_CHolyCheckScream - Loop - Death: - SPIR D 4 - SPIR E 4 A_Scream - SPIR FGHI 4 - Stop - } -} - -// Holy Tail ---------------------------------------------------------------- - -ACTOR HolyTail -{ - Radius 1 - Height 1 - +NOBLOCKMAP +NOGRAVITY +DROPOFF +NOCLIP - +NOTELEPORT - RenderStyle Translucent - Alpha 0.6 - - action native A_CHolyTail(); - - States - { - Spawn: - SPIR C 1 A_CHolyTail - Loop - TailTrail: - SPIR D -1 - Stop - } -} - -// Holy Tail Trail --------------------------------------------------------- - -ACTOR HolyTailTrail : HolyTail -{ - States - { - Spawn: - Goto TailTrail - } -} diff --git a/wadsrc/static/actors/hexen/clericmace.txt b/wadsrc/static/actors/hexen/clericmace.txt deleted file mode 100644 index dfb06d958..000000000 --- a/wadsrc/static/actors/hexen/clericmace.txt +++ /dev/null @@ -1,46 +0,0 @@ - -// The Cleric's Mace -------------------------------------------------------- - -ACTOR CWeapMace : ClericWeapon -{ - Weapon.SelectionOrder 3500 - Weapon.KickBack 150 - Weapon.YAdjust -8 - +BLOODSPLATTER - Obituary "$OB_MPCWEAPMACE" - Tag "$TAG_CWEAPMACE" - - action native A_CMaceAttack(); - - States - { - Select: - CMCE A 1 A_Raise - Loop - Deselect: - CMCE A 1 A_Lower - Loop - Ready: - CMCE A 1 A_WeaponReady - Loop - Fire: - CMCE B 2 Offset (60, 20) - CMCE B 1 Offset (30, 33) - CMCE B 2 Offset (8, 45) - CMCE C 1 Offset (8, 45) - CMCE D 1 Offset (8, 45) - CMCE E 1 Offset (8, 45) - CMCE E 1 Offset (-11, 58) A_CMaceAttack - CMCE F 1 Offset (8, 45) - CMCE F 2 Offset (-8, 74) - CMCE F 1 Offset (-20, 96) - CMCE F 8 Offset (-33, 160) - CMCE A 2 Offset (8, 75) A_ReFire - CMCE A 1 Offset (8, 65) - CMCE A 2 Offset (8, 60) - CMCE A 1 Offset (8, 55) - CMCE A 2 Offset (8, 50) - CMCE A 1 Offset (8, 45) - Goto Ready - } -} diff --git a/wadsrc/static/actors/hexen/clericplayer.txt b/wadsrc/static/actors/hexen/clericplayer.txt deleted file mode 100644 index 4b762af5d..000000000 --- a/wadsrc/static/actors/hexen/clericplayer.txt +++ /dev/null @@ -1,103 +0,0 @@ -// The cleric --------------------------------------------------------------- - -ACTOR ClericPlayer : PlayerPawn -{ - Health 100 - ReactionTime 0 - PainChance 255 - Radius 16 - Height 64 - Speed 1 - +NOSKIN - +NODAMAGETHRUST - +NOTHRUSTWHENINVUL - PainSound "PlayerClericPain" - RadiusDamageFactor 0.25 - Player.JumpZ 9 - Player.Viewheight 48 - Player.SpawnClass "Cleric" - Player.DisplayName "Cleric" - Player.SoundClass "cleric" - Player.ScoreIcon "CLERFACE" - Player.InvulnerabilityMode "Ghost" - Player.HealRadiusType "Health" - Player.Hexenarmor 10, 10, 25, 5, 20 - Player.StartItem "CWeapMace" - Player.Portrait "P_CWALK1" - Player.WeaponSlot 1, CWeapMace - Player.WeaponSlot 2, CWeapStaff - Player.WeaponSlot 3, CWeapFlame - Player.WeaponSlot 4, CWeapWraithverge - Player.FlechetteType "ArtiPoisonBag1" - - Player.ColorRange 146, 163 - Player.Colorset 0, "Blue", 146, 163, 161 - Player.ColorsetFile 1, "Red", "TRANTBL7", 0xB3 - Player.ColorsetFile 2, "Gold", "TRANTBL8", 0x8C - Player.ColorsetFile 3, "Dull Green", "TRANTBL9", 0x41 - Player.ColorsetFile 4, "Green", "TRANTBLA", 0xC9 - Player.ColorsetFile 5, "Gray", "TRANTBLB", 0x30 - Player.ColorsetFile 6, "Brown", "TRANTBLC", 0x72 - Player.ColorsetFile 7, "Purple", "TRANTBLD", 0xEE - - States - { - Spawn: - CLER A -1 - Stop - See: - CLER ABCD 4 - Loop - Pain: - CLER H 4 - CLER H 4 A_Pain - Goto Spawn - Missile: - Melee: - CLER EFG 6 - Goto Spawn - Death: - CLER I 6 - CLER J 6 A_PlayerScream - CLER KL 6 - CLER M 6 A_NoBlocking - CLER NOP 6 - CLER Q -1 - Stop - XDeath: - CLER R 5 A_PlayerScream - CLER S 5 - CLER T 5 A_NoBlocking - CLER UVWXYZ 5 - CLER [ -1 - Stop - Ice: - CLER "\" 5 A_FreezeDeath - CLER "\" 1 A_FreezeDeathChunks - Wait - Burn: - FDTH C 5 BRIGHT A_PlaySound("*burndeath") - FDTH D 4 BRIGHT - FDTH G 5 BRIGHT - FDTH H 4 BRIGHT A_PlayerScream - FDTH I 5 BRIGHT - FDTH J 4 BRIGHT - FDTH K 5 BRIGHT - FDTH L 4 BRIGHT - FDTH M 5 BRIGHT - FDTH N 4 BRIGHT - FDTH O 5 BRIGHT - FDTH P 4 BRIGHT - FDTH Q 5 BRIGHT - FDTH R 4 BRIGHT - FDTH S 5 BRIGHT A_NoBlocking - FDTH T 4 BRIGHT - FDTH U 5 BRIGHT - FDTH V 4 BRIGHT - ACLO E 35 A_CheckPlayerDone - Wait - ACLO E 8 - Stop - } -} - diff --git a/wadsrc/static/actors/hexen/clericstaff.txt b/wadsrc/static/actors/hexen/clericstaff.txt deleted file mode 100644 index bd848b5c6..000000000 --- a/wadsrc/static/actors/hexen/clericstaff.txt +++ /dev/null @@ -1,96 +0,0 @@ - -// The Cleric's Serpent Staff ----------------------------------------------- - -ACTOR CWeapStaff : ClericWeapon -{ - Weapon.SelectionOrder 1600 - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 25 - Weapon.KickBack 150 - Weapon.YAdjust 10 - Weapon.AmmoType1 "Mana1" - Inventory.PickupMessage "$TXT_WEAPON_C2" - Obituary "$OB_MPCWEAPSTAFFM" - Tag "$TAG_CWEAPSTAFF" - - action native A_CStaffInitBlink(); - action native A_CStaffCheckBlink(); - action native A_CStaffCheck(); - action native A_CStaffAttack(); - - States - { - Spawn: - WCSS A -1 - Stop - Select: - CSSF C 1 A_Raise - Loop - Deselect: - CSSF B 3 - CSSF C 4 - CSSF C 1 A_Lower - Wait - Ready: - CSSF C 4 - CSSF B 3 A_CStaffInitBlink - CSSF AAAAAAA 1 A_WeaponReady - CSSF A 1 A_CStaffCheckBlink - Goto Ready + 2 - Fire: - CSSF A 1 Offset (0, 45) A_CStaffCheck - CSSF J 1 Offset (0, 50) A_CStaffAttack - CSSF J 2 Offset (0, 50) - CSSF J 2 Offset (0, 45) - CSSF A 2 Offset (0, 40) - CSSF A 2 Offset (0, 36) - Goto Ready + 2 - Blink: - CSSF BBBCCCCCBBB 1 A_WeaponReady - Goto Ready + 2 - Drain: - CSSF K 10 Offset (0, 36) - Goto Ready + 2 - } -} - -// Serpent Staff Missile ---------------------------------------------------- - -ACTOR CStaffMissile native -{ - Speed 22 - Radius 12 - Height 10 - Damage 5 - RenderStyle Add - Projectile - DeathSound "ClericCStaffExplode" - Obituary "$OB_MPCWEAPSTAFFR" - States - { - Spawn: - CSSF DDEE 1 Bright A_CStaffMissileSlither - Loop - Death: - CSSF FG 4 Bright - CSSF HI 3 Bright - Stop - } -} - -// Serpent Staff Puff ------------------------------------------------------- - -ACTOR CStaffPuff -{ - +NOBLOCKMAP +NOGRAVITY - +PUFFONACTORS - RenderStyle Translucent - Alpha 0.6 - SeeSound "ClericCStaffHitThing" - States - { - Spawn: - FHFX STUVW 4 - Stop - } -} diff --git a/wadsrc/static/actors/hexen/demons.txt b/wadsrc/static/actors/hexen/demons.txt deleted file mode 100644 index 39da26e1d..000000000 --- a/wadsrc/static/actors/hexen/demons.txt +++ /dev/null @@ -1,385 +0,0 @@ - -// Demon, type 1 (green, like D'Sparil's) ----------------------------------- - -ACTOR Demon1 -{ - Health 250 - Painchance 50 - Speed 13 - Radius 32 - Height 64 - Mass 220 - Monster - +TELESTOMP - +FLOORCLIP - SeeSound "DemonSight" - AttackSound "DemonAttack" - PainSound "DemonPain" - DeathSound "DemonDeath" - ActiveSound "DemonActive" - Obituary "$OB_DEMON1" - const int ChunkFlags = SXF_TRANSFERTRANSLATION | SXF_ABSOLUTEVELOCITY; - States - { - Spawn: - DEMN AA 10 A_Look - Loop - See: - DEMN ABCD 4 A_Chase - Loop - Pain: - DEMN E 4 - DEMN E 4 A_Pain - Goto See - Melee: - DEMN E 6 A_FaceTarget - DEMN F 8 A_FaceTarget - DEMN G 6 A_CustomMeleeAttack(random[DemonAttack1](1,8)*2) - Goto See - Missile: - DEMN E 5 A_FaceTarget - DEMN F 6 A_FaceTarget - DEMN G 5 A_CustomMissile("Demon1FX1", 62, 0) - Goto See - Death: - DEMN HI 6 - DEMN J 6 A_Scream - DEMN K 6 A_NoBlocking - DEMN L 6 A_QueueCorpse - DEMN MNO 6 - DEMN P -1 - Stop - XDeath: - DEMN H 6 - DEMN I 0 A_SpawnItemEx("Demon1Chunk1", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle+90), frandom[DemonChunks](1,4.984375)*sin(Angle+90), 8, 90, ChunkFlags) - DEMN I 0 A_SpawnItemEx("Demon1Chunk2", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags) - DEMN I 0 A_SpawnItemEx("Demon1Chunk3", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags) - DEMN I 0 A_SpawnItemEx("Demon1Chunk4", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags) - DEMN I 6 A_SpawnItemEx("Demon1Chunk5", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags) - Goto Death+2 - Ice: - DEMN Q 5 A_FreezeDeath - DEMN Q 1 A_FreezeDeathChunks - Wait - } -} - -// Demon, type 1, mashed ---------------------------------------------------- - -ACTOR Demon1Mash : Demon1 -{ - +NOBLOOD - +BLASTED - -TELESTOMP - +NOICEDEATH - RenderStyle Translucent - Alpha 0.4 - States - { - Death: - XDeath: - Ice: - Stop - } -} - -// Demon chunk, base class -------------------------------------------------- - -ACTOR DemonChunk -{ - Radius 5 - Height 5 - +NOBLOCKMAP - +DROPOFF - +MISSILE - +CORPSE - +FLOORCLIP - +NOTELEPORT -} - -// Demon, type 1, chunk 1 --------------------------------------------------- - -ACTOR Demon1Chunk1 : DemonChunk -{ - States - { - Spawn: - DEMA A 4 - DEMA A 10 A_QueueCorpse - DEMA A 20 - Wait - Death: - DEMA A -1 - Stop - } -} - -// Demon, type 1, chunk 2 --------------------------------------------------- - -ACTOR Demon1Chunk2 : DemonChunk -{ - States - { - Spawn: - DEMB A 4 - DEMB A 10 A_QueueCorpse - DEMB A 20 - Wait - Death: - DEMB A -1 - Stop - } -} - -ACTOR Demon1Chunk3 : DemonChunk -{ - States - { - Spawn: - DEMC A 4 - DEMC A 10 A_QueueCorpse - DEMC A 20 - Wait - Death: - DEMC A -1 - Stop - } -} - -// Demon, type 1, chunk 4 --------------------------------------------------- - -ACTOR Demon1Chunk4 : DemonChunk -{ - States - { - Spawn: - DEMD A 4 - DEMD A 10 A_QueueCorpse - DEMD A 20 - Wait - Death: - DEMD A -1 - Stop - } -} - -// Demon, type 1, chunk 5 --------------------------------------------------- - -ACTOR Demon1Chunk5 : DemonChunk -{ - States - { - Spawn: - DEME A 4 - DEME A 10 A_QueueCorpse - DEME A 20 - Wait - Death: - DEME A -1 - Stop - } -} - -// Demon, type 1, projectile ------------------------------------------------ - -ACTOR Demon1FX1 -{ - Speed 15 - Radius 10 - Height 6 - Damage 5 - DamageType Fire - Projectile - +SPAWNSOUNDSOURCE - RenderStyle Add - SeeSound "DemonMissileFire" - DeathSound "DemonMissileExplode" - States - { - Spawn: - DMFX ABC 4 Bright - Loop - Death: - DMFX DE 4 Bright - DMFX FGH 3 Bright - Stop - } -} - -// Demon, type 2 (brown) ---------------------------------------------------- - -ACTOR Demon2 : Demon1 -{ - Obituary "$OB_DEMON2" - Species "Demon2" - States - { - Spawn: - DEM2 AA 10 A_Look - Loop - See: - DEM2 ABCD 4 A_Chase - Loop - Pain: - DEM2 E 4 - DEM2 E 4 A_Pain - Goto See - Melee: - DEM2 E 6 A_FaceTarget - DEM2 F 8 A_FaceTarget - DEM2 G 6 A_CustomMeleeAttack(random[DemonAttack1](1,8)*2) - Goto See - Missile: - DEM2 E 5 A_FaceTarget - DEM2 F 6 A_FaceTarget - DEM2 G 5 A_CustomMissile("Demon2FX1", 62, 0) - Goto See - Death: - DEM2 HI 6 - DEM2 J 6 A_Scream - DEM2 K 6 A_NoBlocking - DEM2 L 6 A_QueueCorpse - DEM2 MNO 6 - DEM2 P -1 - Stop - XDeath: - DEM2 H 6 - DEM2 I 0 A_SpawnItemEx("Demon2Chunk1", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle+90), frandom[DemonChunks](1,4.984375)*sin(Angle+90), 8, 90, ChunkFlags) - DEM2 I 0 A_SpawnItemEx("Demon2Chunk2", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags) - DEM2 I 0 A_SpawnItemEx("Demon2Chunk3", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags) - DEM2 I 0 A_SpawnItemEx("Demon2Chunk4", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags) - DEM2 I 6 A_SpawnItemEx("Demon2Chunk5", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags) - Goto Death+2 - } -} - -// Demon, type 2, mashed ---------------------------------------------------- - -ACTOR Demon2Mash : Demon2 -{ - +NOBLOOD - +BLASTED - -TELESTOMP - +NOICEDEATH - RenderStyle Translucent - Alpha 0.4 - States - { - Death: - XDeath: - Ice: - Stop - } -} - -// Demon, type 2, chunk 1 --------------------------------------------------- - -ACTOR Demon2Chunk1 : DemonChunk -{ - States - { - Spawn: - DMBA A 4 - DMBA A 10 A_QueueCorpse - DMBA A 20 - Wait - Death: - DMBA A -1 - Stop - } -} - -// Demon, type 2, chunk 2 --------------------------------------------------- - -ACTOR Demon2Chunk2 : DemonChunk -{ - States - { - Spawn: - DMBB A 4 - DMBB A 10 A_QueueCorpse - DMBB A 20 - Wait - Death: - DMBB A -1 - Stop - } -} - -// Demon, type 2, chunk 3 --------------------------------------------------- - -ACTOR Demon2Chunk3 : DemonChunk -{ - States - { - Spawn: - DMBC A 4 - DMBC A 10 A_QueueCorpse - DMBC A 20 - Wait - Death: - DMBC A -1 - Stop - } -} - -// Demon, type 2, chunk 4 --------------------------------------------------- - -ACTOR Demon2Chunk4 : DemonChunk -{ - States - { - Spawn: - DMBD A 4 - DMBD A 10 A_QueueCorpse - DMBD A 20 - Wait - Death: - DMBD A -1 - Stop - } -} - -// Demon, type 2, chunk 5 --------------------------------------------------- - -ACTOR Demon2Chunk5 : DemonChunk -{ - States - { - Spawn: - DMBE A 4 - DMBE A 10 A_QueueCorpse - DMBE A 20 - Wait - Death: - DMBE A -1 - Stop - } -} - -// Demon, type 2, projectile ------------------------------------------------ - -ACTOR Demon2FX1 -{ - Speed 15 - Radius 10 - Height 6 - Damage 5 - DamageType Fire - Projectile - +SPAWNSOUNDSOURCE - RenderStyle Add - SeeSound "DemonMissileFire" - DeathSound "DemonMissileExplode" - States - { - Spawn: - D2FX ABCDEF 4 Bright - Loop - Death: - D2FX GHIJ 4 Bright - D2FX KL 3 Bright - Stop - } -} - diff --git a/wadsrc/static/actors/hexen/dragon.txt b/wadsrc/static/actors/hexen/dragon.txt deleted file mode 100644 index f6c3746f2..000000000 --- a/wadsrc/static/actors/hexen/dragon.txt +++ /dev/null @@ -1,117 +0,0 @@ - -// Dragon ------------------------------------------------------------------- - -ACTOR Dragon -{ - Health 640 - PainChance 128 - Speed 10 - Height 65 - Mass 0x7fffffff - Monster - +NOGRAVITY +FLOAT +NOBLOOD - +BOSS - +DONTMORPH +NOTARGET - +NOICEDEATH - SeeSound "DragonSight" - AttackSound "DragonAttack" - PainSound "DragonPain" - DeathSound "DragonDeath" - ActiveSound "DragonActive" - Obituary "$OB_DRAGON" - - action native A_DragonInitFlight(); - action native A_DragonFlap(); - action native A_DragonFlight(); - action native A_DragonPain(); - action native A_DragonAttack(); - action native A_DragonCheckCrash(); - - States - { - Spawn: - DRAG D 10 A_Look - Loop - See: - DRAG CB 5 - DRAG A 5 A_DragonInitFlight - DRAG B 3 A_DragonFlap - DRAG BCCDDCCBBAA 3 A_DragonFlight - Goto See + 3 - Pain: - DRAG F 10 A_DragonPain - Goto See + 3 - Missile: - DRAG E 8 A_DragonAttack - Goto See + 3 - Death: - DRAG G 5 A_Scream - DRAG H 4 A_NoBlocking - DRAG I 4 - DRAG J 4 A_DragonCheckCrash - Wait - Crash: - DRAG KL 5 - DRAG M -1 - Stop - } -} - -// Dragon Fireball ---------------------------------------------------------- - -ACTOR DragonFireball -{ - Speed 24 - Radius 12 - Height 10 - Damage 6 - DamageType "Fire" - Projectile - -ACTIVATEIMPACT -ACTIVATEPCROSS - RenderStyle Add - DeathSound "DragonFireballExplode" - - action native A_DragonFX2(); - - States - { - Spawn: - DRFX ABCDEF 4 Bright - Loop - Death: - DRFX GHI 4 Bright - DRFX J 4 Bright A_DragonFX2 - DRFX KL 3 Bright - Stop - } -} - -// Dragon Fireball Secondary Explosion -------------------------------------- - -ACTOR DragonExplosion -{ - Radius 8 - Height 8 - DamageType "Fire" - +NOBLOCKMAP - +NOTELEPORT - +INVISIBLE - RenderStyle Add - DeathSound "DragonFireballExplode" - States - { - Spawn: - CFCF Q 1 Bright - CFCF Q 4 Bright A_UnHideThing - CFCF R 3 Bright A_Scream - CFCF S 4 Bright - CFCF T 3 Bright A_Explode (80, 128, 0) - CFCF U 4 Bright - CFCF V 3 Bright - CFCF W 4 Bright - CFCF X 3 Bright - CFCF Y 4 Bright - CFCF Z 3 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/ettin.txt b/wadsrc/static/actors/hexen/ettin.txt deleted file mode 100644 index 4ce13406c..000000000 --- a/wadsrc/static/actors/hexen/ettin.txt +++ /dev/null @@ -1,106 +0,0 @@ - -// Ettin -------------------------------------------------------------------- - -ACTOR Ettin -{ - Health 175 - Radius 25 - Height 68 - Mass 175 - Speed 13 - Damage 3 - Painchance 60 - Monster - +FLOORCLIP - +TELESTOMP - SeeSound "EttinSight" - AttackSound "EttinAttack" - PainSound "EttinPain" - DeathSound "EttinDeath" - ActiveSound "EttinActive" - HowlSound "PuppyBeat" - Obituary "$OB_ETTIN" - States - { - Spawn: - ETTN AA 10 A_Look - Loop - See: - ETTN ABCD 5 A_Chase - Loop - Pain: - ETTN H 7 A_Pain - Goto See - Melee: - ETTN EF 6 A_FaceTarget - ETTN G 8 A_CustomMeleeAttack(random[EttinAttack](1,8)*2) - Goto See - Death: - ETTN IJ 4 - ETTN K 4 A_Scream - ETTN L 4 A_NoBlocking - ETTN M 4 A_QueueCorpse - ETTN NOP 4 - ETTN Q -1 - Stop - XDeath: - ETTB A 4 - ETTB B 4 A_NoBlocking - ETTB C 4 A_SpawnItemEx("EttinMace", 0,0,8.5, - random[DropMace](-128,127) * 0.03125, - random[DropMace](-128,127) * 0.03125, - 10 + random[DropMace](0,255) * 0.015625, 0, SXF_ABSOLUTEVELOCITY) - ETTB D 4 A_Scream - ETTB E 4 A_QueueCorpse - ETTB FGHIJK 4 - ETTB L -1 - Stop - Ice: - ETTN R 5 A_FreezeDeath - ETTN R 1 A_FreezeDeathChunks - Wait - } -} - -// Ettin mace --------------------------------------------------------------- - -ACTOR EttinMace -{ - Radius 5 - Height 5 - +DROPOFF - +CORPSE - +NOTELEPORT - +FLOORCLIP - States - { - Spawn: - ETTB MNOP 5 - Loop - Crash: - ETTB Q 5 - ETTB R 5 A_QueueCorpse - ETTB S -1 - Stop - } -} - -// Ettin mash --------------------------------------------------------------- - -ACTOR EttinMash : Ettin -{ - +NOBLOOD - +NOICEDEATH - RenderStyle Translucent - Alpha 0.4 - States - { - Death: - XDeath: - Ice: - Stop - } -} - - - diff --git a/wadsrc/static/actors/hexen/fighteraxe.txt b/wadsrc/static/actors/hexen/fighteraxe.txt deleted file mode 100644 index 28642c7d1..000000000 --- a/wadsrc/static/actors/hexen/fighteraxe.txt +++ /dev/null @@ -1,113 +0,0 @@ - -// The Fighter's Axe -------------------------------------------------------- - -ACTOR FWeapAxe : FighterWeapon native -{ - Weapon.SelectionOrder 1500 - +WEAPON.AXEBLOOD +WEAPON.AMMO_OPTIONAL +WEAPON.MELEEWEAPON - Weapon.AmmoUse1 2 - Weapon.AmmoGive1 25 - Weapon.KickBack 150 - Weapon.YAdjust -12 - Weapon.AmmoType1 "Mana1" - Inventory.PickupMessage "$TXT_WEAPON_F2" - Obituary "$OB_MPFWEAPAXE" - Tag "$TAG_FWEAPAXE" - - action native A_FAxeCheckUp(); - action native A_FAxeCheckReady(); - action native A_FAxeCheckAtk(); - action native A_FAxeAttack(); - action native A_FAxeCheckUpG(); - action native A_FAxeCheckReadyG(); - - States - { - Spawn: - WFAX A -1 - Stop - Select: - FAXE A 1 A_FAxeCheckUp - Loop - Deselect: - FAXE A 1 A_Lower - Loop - Ready: - FAXE A 1 A_FAxeCheckReady - Loop - Fire: - FAXE B 4 Offset (15, 32) A_FAxeCheckAtk - FAXE C 3 Offset (15, 32) - FAXE D 2 Offset (15, 32) - FAXE D 1 Offset (-5, 70) A_FAxeAttack - FAXE D 2 Offset (-25, 90) - FAXE E 1 Offset (15, 32) - FAXE E 2 Offset (10, 54) - FAXE E 7 Offset (10, 150) - FAXE A 1 Offset (0, 60) A_ReFire - FAXE A 1 Offset (0, 52) - FAXE A 1 Offset (0, 44) - FAXE A 1 Offset (0, 36) - FAXE A 1 - Goto Ready - SelectGlow: - FAXE L 1 A_FAxeCheckUpG - Loop - DeselectGlow: - FAXE L 1 A_Lower - Loop - ReadyGlow: - FAXE LLL 1 A_FAxeCheckReadyG - FAXE MMM 1 A_FAxeCheckReadyG - Loop - FireGlow: - FAXE N 4 Offset (15, 32) - FAXE O 3 Offset (15, 32) - FAXE P 2 Offset (15, 32) - FAXE P 1 Offset (-5, 70) A_FAxeAttack - FAXE P 2 Offset (-25, 90) - FAXE Q 1 Offset (15, 32) - FAXE Q 2 Offset (10, 54) - FAXE Q 7 Offset (10, 150) - FAXE A 1 Offset (0, 60) A_ReFire - FAXE A 1 Offset (0, 52) - FAXE A 1 Offset (0, 44) - FAXE A 1 Offset (0, 36) - FAXE A 1 - Goto ReadyGlow - } -} - -// Axe Puff ----------------------------------------------------------------- - -ACTOR AxePuff -{ - +NOBLOCKMAP +NOGRAVITY - +PUFFONACTORS - RenderStyle Translucent - Alpha 0.6 - SeeSound "FighterAxeHitThing" - AttackSound "FighterHammerHitWall" - ActiveSound "FighterHammerMiss" - States - { - Spawn: - FHFX STUVW 4 - Stop - } -} - -// Glowing Axe Puff --------------------------------------------------------- - -ACTOR AxePuffGlow : AxePuff -{ - +PUFFONACTORS - RenderStyle Add - Alpha 1 - States - { - Spawn: - FAXE RSTUVWX 4 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/fighterboss.txt b/wadsrc/static/actors/hexen/fighterboss.txt deleted file mode 100644 index 195c0a1a3..000000000 --- a/wadsrc/static/actors/hexen/fighterboss.txt +++ /dev/null @@ -1,80 +0,0 @@ - -// Fighter Boss (Zedek) ----------------------------------------------------- - -ACTOR FighterBoss -{ - health 800 - PainChance 50 - Speed 25 - Radius 16 - Height 64 - Monster - +FLOORCLIP - +TELESTOMP - +DONTMORPH - PainSound "PlayerFighterPain" - DeathSound "PlayerFighterCrazyDeath" - Obituary "$OB_FBOSS" - - action native A_FighterAttack(); - - States - { - Spawn: - PLAY A 2 - PLAY A 3 A_ClassBossHealth - PLAY A 5 A_Look - Wait - See: - PLAY ABCD 4 A_FastChase - Loop - Pain: - PLAY G 4 - PLAY G 4 A_Pain - Goto See - Melee: - Missile: - PLAY E 8 A_FaceTarget - PLAY F 8 A_FighterAttack - Goto See - Death: - PLAY H 6 - PLAY I 6 A_Scream - PLAY JK 6 - PLAY L 6 A_NoBlocking - PLAY M 6 - PLAY N -1 - Stop - XDeath: - PLAY O 5 A_Scream - PLAY P 5 A_SkullPop - PLAY R 5 A_NoBlocking - PLAY STUV 5 - PLAY W -1 - Stop - Ice: - PLAY X 5 A_FreezeDeath - PLAY X 1 A_FreezeDeathChunks - Wait - Burn: - FDTH A 5 Bright A_PlaySound("PlayerFighterBurnDeath") - FDTH B 4 Bright - FDTH G 5 Bright - FDTH H 4 Bright A_Scream - FDTH I 5 Bright - FDTH J 4 Bright - FDTH K 5 Bright - FDTH L 4 Bright - FDTH M 5 Bright - FDTH N 4 Bright - FDTH O 5 Bright - FDTH P 4 Bright - FDTH Q 5 Bright - FDTH R 4 Bright - FDTH S 5 Bright A_NoBlocking - FDTH T 4 Bright - FDTH U 5 Bright - FDTH V 4 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/fighterfist.txt b/wadsrc/static/actors/hexen/fighterfist.txt deleted file mode 100644 index b6a27332d..000000000 --- a/wadsrc/static/actors/hexen/fighterfist.txt +++ /dev/null @@ -1,64 +0,0 @@ - -// Fist (first weapon) ------------------------------------------------------ - -ACTOR FWeapFist : FighterWeapon -{ - +BLOODSPLATTER - Weapon.SelectionOrder 3400 - +WEAPON.MELEEWEAPON - Weapon.KickBack 150 - Obituary "$OB_MPFWEAPFIST" - Tag "$TAG_FWEAPFIST" - - action native A_FPunchAttack(); - - States - { - Select: - FPCH A 1 A_Raise - Loop - Deselect: - FPCH A 1 A_Lower - Loop - Ready: - FPCH A 1 A_WeaponReady - Loop - Fire: - FPCH B 5 Offset (5, 40) - FPCH C 4 Offset (5, 40) - FPCH D 4 Offset (5, 40) A_FPunchAttack - FPCH C 4 Offset (5, 40) - FPCH B 5 Offset (5, 40) A_ReFire - Goto Ready - Fire2: - FPCH DE 4 Offset (5, 40) - FPCH E 1 Offset (15, 50) - FPCH E 1 Offset (25, 60) - FPCH E 1 Offset (35, 70) - FPCH E 1 Offset (45, 80) - FPCH E 1 Offset (55, 90) - FPCH E 1 Offset (65, 90) - FPCH E 10 Offset (0, 150) - Goto Ready - } -} - -// Punch puff --------------------------------------------------------------- - -ACTOR PunchPuff -{ - +NOBLOCKMAP +NOGRAVITY - +PUFFONACTORS - RenderStyle Translucent - Alpha 0.6 - SeeSound "FighterPunchHitThing" - AttackSound "FighterPunchHitWall" - ActiveSound "FighterPunchMiss" - VSpeed 1 - States - { - Spawn: - FHFX STUVW 4 - Stop - } -} diff --git a/wadsrc/static/actors/hexen/fighterhammer.txt b/wadsrc/static/actors/hexen/fighterhammer.txt deleted file mode 100644 index d9932ae5f..000000000 --- a/wadsrc/static/actors/hexen/fighterhammer.txt +++ /dev/null @@ -1,101 +0,0 @@ - -// The Fighter's Hammer ----------------------------------------------------- - -ACTOR FWeapHammer : FighterWeapon -{ - +BLOODSPLATTER - Weapon.SelectionOrder 900 - +WEAPON.AMMO_OPTIONAL +WEAPON.MELEEWEAPON - Weapon.AmmoUse1 3 - Weapon.AmmoGive1 25 - Weapon.KickBack 150 - Weapon.YAdjust -10 - Weapon.AmmoType1 "Mana2" - Inventory.PickupMessage "$TXT_WEAPON_F3" - Obituary "$OB_MPFWEAPHAMMERM" - Tag "$TAG_FWEAPHAMMER" - - action native A_FHammerAttack(); - action native A_FHammerThrow(); - - States - { - Spawn: - WFHM A -1 - Stop - Select: - FHMR A 1 A_Raise - Loop - Deselect: - FHMR A 1 A_Lower - Loop - Ready: - FHMR A 1 A_WeaponReady - Loop - Fire: - FHMR B 6 Offset (5, 0) - FHMR C 3 Offset (5, 0) A_FHammerAttack - FHMR D 3 Offset (5, 0) - FHMR E 2 Offset (5, 0) - FHMR E 10 Offset (5, 150) A_FHammerThrow - FHMR A 1 Offset (0, 60) - FHMR A 1 Offset (0, 55) - FHMR A 1 Offset (0, 50) - FHMR A 1 Offset (0, 45) - FHMR A 1 Offset (0, 40) - FHMR A 1 Offset (0, 35) - FHMR A 1 - Goto Ready - } -} - -// Hammer Missile ----------------------------------------------------------- - -ACTOR HammerMissile -{ - Speed 25 - Radius 14 - Height 20 - Damage 10 - DamageType "Fire" - Projectile - DeathSound "FighterHammerExplode" - Obituary "$OB_MPFWEAPHAMMERR" - - States - { - Spawn: - FHFX A 2 Bright - FHFX B 2 Bright A_PlaySound ("FighterHammerContinuous") - FHFX CDEFGH 2 Bright - Loop - Death: - FHFX I 3 Bright A_SetTranslucent(1,1) - FHFX J 3 Bright - FHFX K 3 Bright A_Explode (128, 128, 0) - FHFX LM 3 Bright - FHFX N 3 - FHFX OPQR 3 Bright - Stop - } -} - -// Hammer Puff (also used by fist) ------------------------------------------ - -ACTOR HammerPuff -{ - +NOBLOCKMAP +NOGRAVITY - +PUFFONACTORS - RenderStyle "Translucent" - Alpha 0.6 - VSpeed 0.8 - SeeSound "FighterHammerHitThing" - AttackSound "FighterHammerHitWall" - ActiveSound "FighterHammerMiss" - States - { - Spawn: - FHFX STUVW 4 - Stop - } -} diff --git a/wadsrc/static/actors/hexen/fighterplayer.txt b/wadsrc/static/actors/hexen/fighterplayer.txt deleted file mode 100644 index 29de1f3a3..000000000 --- a/wadsrc/static/actors/hexen/fighterplayer.txt +++ /dev/null @@ -1,126 +0,0 @@ -// The fighter -------------------------------------------------------------- - -ACTOR FighterPlayer : PlayerPawn -{ - Health 100 - PainChance 255 - Radius 16 - Height 64 - Speed 1 - +NOSKIN - +NODAMAGETHRUST - +NOTHRUSTWHENINVUL - PainSound "PlayerFighterPain" - RadiusDamageFactor 0.25 - Player.JumpZ 9 - Player.Viewheight 48 - Player.SpawnClass "Fighter" - Player.DisplayName "Fighter" - Player.SoundClass "fighter" - Player.ScoreIcon "FITEFACE" - Player.HealRadiusType "Armor" - Player.Hexenarmor 15, 25, 20, 15, 5 - Player.StartItem "FWeapFist" - Player.ForwardMove 1.08, 1.2 - Player.SideMove 1.125, 1.475 - Player.Portrait "P_FWALK1" - Player.WeaponSlot 1, FWeapFist - Player.WeaponSlot 2, FWeapAxe - Player.WeaponSlot 3, FWeapHammer - Player.WeaponSlot 4, FWeapQuietus - - Player.ColorRange 246, 254 - Player.Colorset 0, "Gold", 246, 254, 253 - Player.ColorsetFile 1, "Red", "TRANTBL0", 0xAC - Player.ColorsetFile 2, "Blue", "TRANTBL1", 0x9D - Player.ColorsetFile 3, "Dull Green", "TRANTBL2", 0x3E - Player.ColorsetFile 4, "Green", "TRANTBL3", 0xC8 - Player.ColorsetFile 5, "Gray", "TRANTBL4", 0x2D - Player.ColorsetFile 6, "Brown", "TRANTBL5", 0x6F - Player.ColorsetFile 7, "Purple", "TRANTBL6", 0xEE - - States - { - Spawn: - PLAY A -1 - Stop - See: - PLAY ABCD 4 - Loop - Missile: - Melee: - PLAY EF 8 - Goto Spawn - Pain: - PLAY G 4 - PLAY G 4 A_Pain - Goto Spawn - Death: - PLAY H 6 - PLAY I 6 A_PlayerScream - PLAY JK 6 - PLAY L 6 A_NoBlocking - PLAY M 6 - PLAY N -1 - Stop - XDeath: - PLAY O 5 A_PlayerScream - PLAY P 5 A_SkullPop("BloodyFighterSkull") - PLAY R 5 A_NoBlocking - PLAY STUV 5 - PLAY W -1 - Stop - Ice: - PLAY X 5 A_FreezeDeath - PLAY X 1 A_FreezeDeathChunks - Wait - Burn: - FDTH A 5 BRIGHT A_PlaySound("*burndeath") - FDTH B 4 BRIGHT - FDTH G 5 BRIGHT - FDTH H 4 BRIGHT A_PlayerScream - FDTH I 5 BRIGHT - FDTH J 4 BRIGHT - FDTH K 5 BRIGHT - FDTH L 4 BRIGHT - FDTH M 5 BRIGHT - FDTH N 4 BRIGHT - FDTH O 5 BRIGHT - FDTH P 4 BRIGHT - FDTH Q 5 BRIGHT - FDTH R 4 BRIGHT - FDTH S 5 BRIGHT A_NoBlocking - FDTH T 4 BRIGHT - FDTH U 5 BRIGHT - FDTH V 4 BRIGHT - ACLO E 35 A_CheckPlayerDone - Wait - ACLO E 8 - Stop - } -} - -// The fighter's bloody skull -------------------------------------------------------------- - -Actor BloodyFighterSkull : PlayerChunk -{ - Radius 4 - Height 4 - +NOBLOCKMAP - +DROPOFF - +LOWGRAVITY - +CANNOTPUSH - +SKYEXPLODE - +NOBLOCKMONST - +NOSKIN - States - { - Spawn: - BSKL A 0 - BSKL ABCDFGH 5 A_CheckFloor("Hit") - Goto Spawn+1 - Hit: - BSKL I 16 A_CheckPlayerDone - Wait - } -} diff --git a/wadsrc/static/actors/hexen/fighterquietus.txt b/wadsrc/static/actors/hexen/fighterquietus.txt deleted file mode 100644 index 8d784ebf5..000000000 --- a/wadsrc/static/actors/hexen/fighterquietus.txt +++ /dev/null @@ -1,164 +0,0 @@ - -// Fighter Weapon Piece ----------------------------------------------------- - -ACTOR FighterWeaponPiece : WeaponPiece -{ - Inventory.PickupSound "misc/w_pkup" - Inventory.PickupMessage "$TXT_QUIETUS_PIECE" - Inventory.ForbiddenTo ClericPlayer, MagePlayer - WeaponPiece.Weapon FWeapQuietus - +FLOATBOB -} - -// Fighter Weapon Piece 1 --------------------------------------------------- - -ACTOR FWeaponPiece1 : FighterWeaponPiece -{ - WeaponPiece.Number 1 - States - { - Spawn: - WFR1 A -1 Bright - Stop - } -} - -// Fighter Weapon Piece 2 --------------------------------------------------- - -ACTOR FWeaponPiece2 : FighterWeaponPiece -{ - WeaponPiece.Number 2 - States - { - Spawn: - WFR2 A -1 Bright - Stop - } -} - -// Fighter Weapon Piece 3 --------------------------------------------------- - -ACTOR FWeaponPiece3 : FighterWeaponPiece -{ - WeaponPiece.Number 3 - States - { - Spawn: - WFR3 A -1 Bright - Stop - } -} - -// Quietus Drop ------------------------------------------------------------- - -ACTOR QuietusDrop -{ - States - { - Spawn: - TNT1 A 1 - TNT1 A 1 A_DropWeaponPieces("FWeaponPiece1", "FWeaponPiece2", "FWeaponPiece3") - Stop - } -} - -// The Fighter's Sword (Quietus) -------------------------------------------- - -ACTOR FWeapQuietus : FighterWeapon -{ - Health 3 - Weapon.SelectionOrder 2900 - +WEAPON.PRIMARY_USES_BOTH - +Inventory.NoAttenPickupSound - Weapon.AmmoUse1 14 - Weapon.AmmoUse2 14 - Weapon.AmmoGive1 20 - Weapon.AmmoGive2 20 - Weapon.KickBack 150 - Weapon.YAdjust 10 - Weapon.AmmoType1 "Mana1" - Weapon.AmmoType2 "Mana2" - Inventory.PickupMessage "$TXT_WEAPON_F4" - Inventory.PickupSound "WeaponBuild" - Tag "$TAG_FWEAPQUIETUS" - - action native A_FSwordAttack(); - - States - { - Spawn: - TNT1 A -1 - Stop - Select: - FSRD A 1 Bright A_Raise - Loop - Deselect: - FSRD A 1 Bright A_Lower - Loop - Ready: - FSRD AAAABBBBCCCC 1 Bright A_WeaponReady - Loop - Fire: - FSRD DE 3 Bright Offset (5, 36) - FSRD F 2 Bright Offset (5, 36) - FSRD G 3 Bright Offset (5, 36) A_FSwordAttack - FSRD H 2 Bright Offset (5, 36) - FSRD I 2 Bright Offset (5, 36) - FSRD I 10 Bright Offset (5, 150) - FSRD A 1 Bright Offset (5, 60) - FSRD B 1 Bright Offset (5, 55) - FSRD C 1 Bright Offset (5, 50) - FSRD A 1 Bright Offset (5, 45) - FSRD B 1 Bright Offset (5, 40) - Goto Ready - } -} - -// Fighter Sword Missile ---------------------------------------------------- - -ACTOR FSwordMissile native -{ - Speed 30 - Radius 16 - Height 8 - Damage 8 - Projectile - +EXTREMEDEATH - RenderStyle Add - DeathSound "FighterSwordExplode" - Obituary "$OB_MPFWEAPQUIETUS" - - action native A_FSwordFlames(); - - States - { - Spawn: - FSFX ABC 3 Bright - Loop - Death: - FSFX D 4 Bright - FSFX E 3 Bright A_FSwordFlames - FSFX F 4 Bright A_Explode (64, 128, 0) - FSFX G 3 Bright - FSFX H 4 Bright - FSFX I 3 Bright - FSFX J 4 Bright - FSFX KLM 3 Bright - Stop - } -} - -// Fighter Sword Flame ------------------------------------------------------ - -ACTOR FSwordFlame -{ - +NOBLOCKMAP +NOGRAVITY - RenderStyle Translucent - Alpha 0.6 - States - { - Spawn: - FSFX NOPQRSTUVW 3 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/firedemon.txt b/wadsrc/static/actors/hexen/firedemon.txt deleted file mode 100644 index 3f96d22ac..000000000 --- a/wadsrc/static/actors/hexen/firedemon.txt +++ /dev/null @@ -1,227 +0,0 @@ - -// FireDemon ---------------------------------------------------------------- - -ACTOR FireDemon -{ - Health 80 - ReactionTime 8 - PainChance 1 - Speed 13 - Radius 20 - Height 68 - Mass 75 - Damage 1 - Monster - +DROPOFF +NOGRAVITY +FLOAT - +FLOORCLIP +INVULNERABLE +TELESTOMP - SeeSound "FireDemonSpawn" - PainSound "FireDemonPain" - DeathSound "FireDemonDeath" - ActiveSound "FireDemonActive" - Obituary "$OB_FIREDEMON" - - action native A_FiredRocks(); - action native A_FiredChase(); - action native A_FiredAttack(); - action native A_FiredSplotch(); - - States - { - Spawn: - FDMN X 5 Bright - FDMN EFG 10 Bright A_Look - Goto Spawn + 1 - See: - FDMN E 8 Bright - FDMN F 6 Bright - FDMN G 5 Bright - FDMN F 8 Bright - FDMN E 6 Bright - FDMN G 7 Bright A_FiredRocks - FDMN HI 5 Bright - FDMN J 5 Bright A_UnSetInvulnerable - Chase: - FDMN ABC 5 Bright A_FiredChase - Loop - Pain: - FDMN D 0 Bright A_UnSetInvulnerable - FDMN D 6 Bright A_Pain - Goto Chase - Missile: - FDMN K 3 Bright A_FaceTarget - FDMN KKK 5 Bright A_FiredAttack - Goto Chase - Crash: - XDeath: - FDMN M 5 A_FaceTarget - FDMN N 5 A_NoBlocking - FDMN O 5 A_FiredSplotch - Stop - Death: - FDMN D 4 Bright A_FaceTarget - FDMN L 4 Bright A_Scream - FDMN L 4 Bright A_NoBlocking - FDMN L 200 Bright - Stop - Ice: - FDMN R 5 A_FreezeDeath - FDMN R 1 A_FreezeDeathChunks - Wait - } -} - -// FireDemonSplotch1 ------------------------------------------------------- - -ACTOR FireDemonSplotch1 -{ - Health 1000 - ReactionTime 8 - Radius 3 - Height 16 - Mass 100 - +DROPOFF +CORPSE - +NOTELEPORT +FLOORCLIP - States - { - Spawn: - FDMN P 3 - FDMN P 6 A_QueueCorpse - FDMN Y -1 - Stop - } -} - -// FireDemonSplotch2 ------------------------------------------------------- - -ACTOR FireDemonSplotch2 : FireDemonSplotch1 -{ - States - { - Spawn: - FDMN Q 3 - FDMN Q 6 A_QueueCorpse - FDMN Z -1 - Stop - } -} - -// FireDemonRock1 ------------------------------------------------------------ - -ACTOR FireDemonRock1 -{ - Health 1000 - ReactionTime 8 - Radius 3 - Height 5 - Mass 16 - +NOBLOCKMAP +DROPOFF +MISSILE - +NOTELEPORT - - action native A_SmBounce(); - - States - { - Spawn: - FDMN S 4 - Loop - Death: - FDMN S 5 A_SmBounce - XDeath: - FDMN S 200 - Stop - } -} - -// FireDemonRock2 ------------------------------------------------------------ - -ACTOR FireDemonRock2 : FireDemonRock1 -{ - States - { - Spawn: - FDMN T 4 - Loop - Death: - FDMN T 5 A_SmBounce - XDeath: - FDMN T 200 - Stop - } -} - -// FireDemonRock3 ------------------------------------------------------------ - -ACTOR FireDemonRock3 : FireDemonRock1 -{ - States - { - Spawn: - FDMN U 4 - Loop - Death: - FDMN U 5 A_SmBounce - XDeath: - FDMN U 200 - Stop - } -} - -// FireDemonRock4 ------------------------------------------------------------ - -ACTOR FireDemonRock4 : FireDemonRock1 -{ - States - { - Spawn: - FDMN V 4 - Loop - Death: - FDMN V 5 A_SmBounce - XDeath: - FDMN V 200 - Stop - } -} - -// FireDemonRock5 ------------------------------------------------------------ - -ACTOR FireDemonRock5 : FireDemonRock1 -{ - States - { - Spawn: - FDMN W 4 - Loop - Death: - FDMN W 5 A_SmBounce - XDeath: - FDMN W 200 - Stop - } -} - -// FireDemonMissile ----------------------------------------------------------- - -ACTOR FireDemonMissile -{ - Health 1000 - ReactionTime 8 - Speed 10 - Radius 10 - Height 6 - Mass 5 - Damage 1 - DamageType "Fire" - Projectile - RenderStyle Add - DeathSound "FireDemonMissileHit" - States - { - Spawn: - FDMB A 5 Bright - Loop - Death: - FDMB BCDE 5 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/flame.txt b/wadsrc/static/actors/hexen/flame.txt deleted file mode 100644 index b3e369a2e..000000000 --- a/wadsrc/static/actors/hexen/flame.txt +++ /dev/null @@ -1,106 +0,0 @@ -// Temp Small Flame -------------------------------------------------------- - -ACTOR FlameSmallTemp -{ - +NOTELEPORT - RenderStyle Add - States - { - Spawn: - FFSM AB 3 Bright - FFSM C 2 Bright A_CountdownArg(0) - FFSM C 2 Bright - FFSM D 3 Bright - FFSM E 3 Bright A_CountdownArg(0) - Loop - } -} - - -// Temp Large Flame --------------------------------------------------------- - -ACTOR FlameLargeTemp -{ - +NOTELEPORT - RenderStyle Add - States - { - Spawn: - FFLG A 4 Bright - FFLG B 4 Bright A_CountdownArg(0) - FFLG C 4 Bright - FFLG D 4 Bright A_CountdownArg(0) - FFLG E 4 Bright - FFLG F 4 Bright A_CountdownArg(0) - FFLG G 4 Bright - FFLG H 4 Bright A_CountdownArg(0) - FFLG I 4 Bright - FFLG J 4 Bright A_CountdownArg(0) - FFLG K 4 Bright - FFLG L 4 Bright A_CountdownArg(0) - FFLG M 4 Bright - FFLG N 4 Bright A_CountdownArg(0) - FFLG O 4 Bright - FFLG P 4 Bright A_CountdownArg(0) - Goto Spawn+4 - } -} - -// Small Flame -------------------------------------------------------------- - -ACTOR FlameSmall : SwitchableDecoration -{ - +NOTELEPORT - +INVISIBLE - Radius 15 - RenderStyle Add - States - { - Active: - FFSM A 0 Bright A_PlaySound("Ignite") - Spawn: - FFSM A 3 Bright - FFSM A 3 Bright A_UnHideThing - FFSM ABCDE 3 Bright - Goto Spawn+2 - Inactive: - FFSM A 2 - FFSM B 2 A_HideThing - FFSM C 200 - Wait - } -} - -ACTOR FlameSmall2 : FlameSmall -{ -} - -// Large Flame -------------------------------------------------------------- - -ACTOR FlameLarge : SwitchableDecoration -{ - +NOTELEPORT - +INVISIBLE - Radius 15 - RenderStyle Add - States - { - Active: - FFLG A 0 Bright A_PlaySound("Ignite") - Spawn: - FFLG A 2 Bright - FFLG A 2 Bright A_UnHideThing - FFLG ABCDEFGHIJKLMNOP 4 Bright - Goto Spawn+6 - Inactive: - FFLG DCB 2 - FFLG A 2 A_HideThing - FFLG A 200 - Wait - } -} - -ACTOR FlameLarge2 : FlameLarge -{ -} - diff --git a/wadsrc/static/actors/hexen/flechette.txt b/wadsrc/static/actors/hexen/flechette.txt deleted file mode 100644 index 2c7fbdc2b..000000000 --- a/wadsrc/static/actors/hexen/flechette.txt +++ /dev/null @@ -1,222 +0,0 @@ - -// Poison Bag (Flechette used by Cleric) ------------------------------------ - -ACTOR PoisonBag -{ - Radius 5 - Height 5 - +NOBLOCKMAP +NOGRAVITY - - action native A_PoisonBagInit(); - - States - { - Spawn: - PSBG A 18 Bright - PSBG B 4 Bright - PSBG C 3 - PSBG C 1 A_PoisonBagInit - Stop - } -} - -// Fire Bomb (Flechette used by Mage) --------------------------------------- - -ACTOR FireBomb -{ - DamageType "Fire" - +NOGRAVITY - +FOILINVUL - RenderStyle Translucent - Alpha 0.6 - DeathSound "FlechetteExplode" - - action native A_TimeBomb(); - - States - { - Spawn: - PSBG A 20 - PSBG AA 10 - PSBG B 4 - PSBG C 4 A_Scream - XPL1 A 4 Bright A_TimeBomb - XPL1 BCDEF 4 Bright - Stop - } -} - -// Throwing Bomb (Flechette used by Fighter) -------------------------------- - -ACTOR ThrowingBomb -{ - Health 48 - Speed 12 - Radius 8 - Height 10 - DamageType "Fire" - +NOBLOCKMAP +DROPOFF +MISSILE - BounceType "HexenCompat" - SeeSound "FlechetteBounce" - DeathSound "FlechetteExplode" - - action native A_CheckThrowBomb(); - action native A_CheckThrowBomb2(); - - States - { - Spawn: - THRW A 4 A_CheckThrowBomb - THRW BCDE 3 A_CheckThrowBomb - THRW F 3 A_CheckThrowBomb2 - Loop - THRW G 6 A_CheckThrowBomb - THRW F 4 A_CheckThrowBomb - THRW H 6 A_CheckThrowBomb - THRW F 4 A_CheckThrowBomb - THRW G 6 A_CheckThrowBomb - THRW F 3 A_CheckThrowBomb - Wait - Death: - CFCF Q 4 Bright A_NoGravity - CFCF R 3 Bright A_Scream - CFCF S 4 Bright A_Explode - CFCF T 3 Bright - CFCF U 4 Bright - CFCF W 3 Bright - CFCF X 4 Bright - CFCF Z 3 Bright - Stop - } -} - -// Poison Bag Artifact (Flechette) ------------------------------------------ - -ACTOR ArtiPoisonBag : Inventory native -{ - +FLOATBOB - Inventory.DefMaxAmount - Inventory.PickupFlash "PickupFlash" - +INVBAR +FANCYPICKUPSOUND - Inventory.Icon "ARTIPSBG" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIPOISONBAG" - Tag "$TAG_ARTIPOISONBAG" - States - { - Spawn: - PSBG A -1 - Stop - } -} - -// Poison Bag 1 (The Cleric's) ---------------------------------------------- - -ACTOR ArtiPoisonBag1 : ArtiPoisonBag native -{ - Inventory.Icon "ARTIPSB1" - Tag "$TAG_ARTIPOISONBAG1" -} - -// Poison Bag 2 (The Mage's) ------------------------------------------------ - -ACTOR ArtiPoisonBag2 : ArtiPoisonBag native -{ - Inventory.Icon "ARTIPSB2" - Tag "$TAG_ARTIPOISONBAG2" -} - -// Poison Bag 3 (The Fighter's) --------------------------------------------- - -ACTOR ArtiPoisonBag3 : ArtiPoisonBag native -{ - Inventory.Icon "ARTIPSB3" - Tag "$TAG_ARTIPOISONBAG3" -} - - -// Poison Bag 4 (Custom Giver) ---------------------------------------------- - -ACTOR ArtiPoisonBagGiver : ArtiPoisonBag native -{ - Inventory.Icon "ARTIPSB4" -} - -// Poison Bag 5 (Custom Thrower) -------------------------------------------- - -ACTOR ArtiPoisonBagShooter : ArtiPoisonBag native -{ - Inventory.Icon "ARTIPSB5" -} - -// Poison Cloud ------------------------------------------------------------- - -ACTOR PoisonCloud native -{ - Radius 20 - Height 30 - Mass 0x7fffffff - +NOBLOCKMAP +NOGRAVITY +DROPOFF - +NODAMAGETHRUST - +DONTSPLASH +FOILINVUL +CANBLAST +BLOODLESSIMPACT +BLOCKEDBYSOLIDACTORS - RenderStyle Translucent - Alpha 0.6 - DeathSound "PoisonShroomDeath" - DamageType PoisonCloud - - action native A_PoisonBagDamage(); - action native A_PoisonBagCheck(); - - States - { - Spawn: - PSBG D 1 - PSBG D 1 A_Scream - PSBG DEEEFFFGGGHHHII 2 A_PoisonBagDamage - PSBG I 2 A_PoisonBagCheck - PSBG I 1 A_PoisonBagCheck - Goto Spawn + 3 - Death: - PSBG HG 7 - PSBG FD 6 - Stop - } -} - -// Poison Shroom ------------------------------------------------------------ - -ACTOR ZPoisonShroom : PoisonBag -{ - Radius 6 - Height 20 - PainChance 255 - Health 30 - Mass 0x7fffffff - +SHOOTABLE - +SOLID - +NOBLOOD - +NOICEDEATH - -NOBLOCKMAP - -NOGRAVITY - PainSound "PoisonShroomPain" - DeathSound "PoisonShroomDeath" - - action native A_PoisonShroom(); - - States - { - Spawn: - SHRM A 5 A_PoisonShroom - Goto Pain+1 - Pain: - SHRM A 6 - SHRM B 8 A_Pain - Goto Spawn - Death: - SHRM CD 5 - SHRM E 5 A_PoisonBagInit - SHRM F -1 - Stop - } -} - diff --git a/wadsrc/static/actors/hexen/flies.txt b/wadsrc/static/actors/hexen/flies.txt deleted file mode 100644 index e297cc289..000000000 --- a/wadsrc/static/actors/hexen/flies.txt +++ /dev/null @@ -1,27 +0,0 @@ - -// Buzzy fly ---------------------------------------------------------------- - -ACTOR LittleFly -{ - +NOBLOCKMAP +NOGRAVITY - +CANPASS - - Speed 6 - Radius 5 - Height 5 - Mass 2 - ActiveSound "FlyBuzz" - - action native A_FlySearch(); - action native A_FlyBuzz(); - - States - { - Spawn: - TNT1 A 20 A_FlySearch // [RH] Invisible when not flying - Loop - Buzz: - AFLY ABCD 3 A_FlyBuzz - Loop - } -} diff --git a/wadsrc/static/actors/hexen/fog.txt b/wadsrc/static/actors/hexen/fog.txt deleted file mode 100644 index 18effbb77..000000000 --- a/wadsrc/static/actors/hexen/fog.txt +++ /dev/null @@ -1,72 +0,0 @@ - -// Fog Spawner -------------------------------------------------------------- - -ACTOR FogSpawner -{ - +NOSECTOR +NOBLOCKMAP - +FLOATBOB - +NOGRAVITY - +INVISIBLE - - action native A_FogSpawn(); - - States - { - Spawn: - TNT1 A 20 A_FogSpawn - Loop - } -} - -// Small Fog Patch ---------------------------------------------------------- - -ACTOR FogPatchSmall -{ - Speed 1 - +NOBLOCKMAP +NOGRAVITY +NOCLIP +FLOAT - +NOTELEPORT - RenderStyle Translucent - Alpha 0.6 - - action native A_FogMove(); - - States - { - Spawn: - FOGS ABCDE 7 A_FogMove - Loop - Death: - FOGS E 5 - Stop - } -} - -// Medium Fog Patch --------------------------------------------------------- - -ACTOR FogPatchMedium : FogPatchSmall -{ - States - { - Spawn: - FOGM ABCDE 7 A_FogMove - Loop - Death: - FOGS ABCDE 5 - Goto Super::Death - } -} - -// Large Fog Patch ---------------------------------------------------------- - -ACTOR FogPatchLarge : FogPatchMedium -{ - States - { - Spawn: - FOGL ABCDE 7 A_FogMove - Loop - Death: - FOGM ABCDEF 4 - Goto Super::Death - } -} diff --git a/wadsrc/static/actors/hexen/healingradius.txt b/wadsrc/static/actors/hexen/healingradius.txt deleted file mode 100644 index cc921f59c..000000000 --- a/wadsrc/static/actors/hexen/healingradius.txt +++ /dev/null @@ -1,23 +0,0 @@ - -// Healing Radius Artifact -------------------------------------------------- - -ACTOR ArtiHealingRadius : Inventory native -{ - +COUNTITEM - +FLOATBOB - Inventory.DefMaxAmount - +INVENTORY.INVBAR - +INVENTORY.PICKUPFLASH - +INVENTORY.FANCYPICKUPSOUND - Inventory.Icon "ARTIHRAD" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIHEALINGRADIUS" - Tag "$TAG_ARTIHEALINGRADIUS" - States - { - Spawn: - HRAD ABCDEFGHIJKLMNOP 4 Bright - Loop - } -} - diff --git a/wadsrc/static/actors/hexen/heresiarch.txt b/wadsrc/static/actors/hexen/heresiarch.txt deleted file mode 100644 index 4d32f701e..000000000 --- a/wadsrc/static/actors/hexen/heresiarch.txt +++ /dev/null @@ -1,335 +0,0 @@ - -// The Heresiarch him/itself ------------------------------------------------ - -ACTOR Heresiarch native -{ - Health 5000 - Painchance 10 - Speed 16 - Radius 40 - Height 110 - Mass 500 - Damage 9 - Monster - +FLOORCLIP - +BOSS - +DONTMORPH - +NOTARGET - +NOICEDEATH - +DEFLECT - +NOBLOOD - SeeSound "SorcererSight" - PainSound "SorcererPain" - DeathSound "SorcererDeathScream" - ActiveSound "SorcererActive" - Obituary "$OB_HERESIARCH" - - action native A_SorcSpinBalls(); - action native A_SpeedBalls(); - action native A_SorcBossAttack(); - action native A_SpawnFizzle(); - - States - { - Spawn: - SORC A 3 - SORC A 2 A_SorcSpinBalls - Idle: - SORC A 10 A_Look - Wait - See: - SORC ABCD 5 A_Chase - Loop - Pain: - SORC G 8 - SORC G 8 A_Pain - Goto See - Missile: - SORC F 6 Bright A_FaceTarget - SORC F 6 Bright A_SpeedBalls - SORC F 6 Bright A_FaceTarget - Wait - Attack1: - SORC E 6 Bright - SORC E 6 Bright A_SpawnFizzle - SORC E 5 Bright A_FaceTarget - Goto Attack1+1 - Attack2: - SORC E 2 Bright - SORC E 2 Bright A_SorcBossAttack - Goto See - Death: - SORC H 5 Bright - SORC I 5 Bright A_FaceTarget - SORC J 5 Bright A_Scream - SORC KLMNOPQRST 5 Bright - SORC U 5 Bright A_NoBlocking - SORC VWXY 5 Bright - SORC Z -1 Bright - Stop - } -} - -// Base class for the balls flying around the Heresiarch's head ------------- - -ACTOR SorcBall native -{ - Speed 10 - Radius 5 - Height 5 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - +FULLVOLDEATH - +CANBOUNCEWATER - +NOWALLBOUNCESND - BounceType "HexenCompat" - SeeSound "SorcererBallBounce" - DeathSound "SorcererBigBallExplode" - - action native A_SorcBallOrbit(); - action native A_SorcBallPop(); - action native A_BounceCheck (); -} - -// First ball (purple) - fires projectiles ---------------------------------- - -ACTOR SorcBall1 : SorcBall native -{ - States - { - Spawn: - SBMP ABCDEFGHIJKLMNOP 2 A_SorcBallOrbit - Loop - Pain: - SBMP A 5 A_SorcBallPop - SBMP B 2 A_BounceCheck - Wait - Death: - SBS4 D 0 A_ChangeFlag("NOBOUNCESOUND", 1) - SBS4 D 5 A_Explode(255,255) - SBS4 E 5 - SBS4 FGH 6 - Stop - } -} - - -// Second ball (blue) - generates the shield -------------------------------- - -ACTOR SorcBall2 : SorcBall native -{ - States - { - Spawn: - SBMB ABCDEFGHIJKLMNOP 2 A_SorcBallOrbit - Loop - Pain: - SBMB A 5 A_SorcBallPop - SBMB B 2 A_BounceCheck - Wait - Death: - SBS4 D 0 A_ChangeFlag("NOBOUNCESOUND", 1) - SBS3 D 5 A_Explode(255,255) - SBS3 E 5 - SBS3 FGH 6 - Stop - } -} - -// Third ball (green) - summons Bishops ------------------------------------- - -ACTOR SorcBall3 : SorcBall native -{ - States - { - Spawn: - SBMG ABCDEFGHIJKLMNOP 2 A_SorcBallOrbit - Loop - Pain: - SBMG A 5 A_SorcBallPop - SBMG B 2 A_BounceCheck - Wait - Death: - SBS4 D 0 A_ChangeFlag("NOBOUNCESOUND", 1) - SBS3 D 5 A_Explode(255,255) - SBS3 E 5 - SBS3 FGH 6 - Stop - } -} - - -// Sorcerer spell 1 (The burning, bouncing head thing) ---------------------- - -ACTOR SorcFX1 -{ - Speed 7 - Radius 5 - Height 5 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - -NOGRAVITY - +FULLVOLDEATH - +CANBOUNCEWATER - +NOWALLBOUNCESND - BounceFactor 1.0 - +HEXENBOUNCE - SeeSound "SorcererBallBounce" - DeathSound "SorcererHeadScream" - - action native A_SorcFX1Seek(); - - States - { - Spawn: - SBS1 A 2 Bright - SBS1 BCD 3 Bright A_SorcFX1Seek - Loop - Death: - FHFX S 2 Bright A_Explode(30, 128) - FHFX SS 6 Bright - Stop - } -} - - -// Sorcerer spell 2 (The visible part of the shield) ------------------------ - -ACTOR SorcFX2 -{ - Speed 15 - Radius 5 - Height 5 - +NOBLOCKMAP - +NOGRAVITY - +NOTELEPORT - - action native A_SorcFX2Split(); - action native A_SorcFX2Orbit (); - - states - { - Spawn: - SBS2 A 3 Bright A_SorcFX2Split - Loop - Orbit: - SBS2 A 2 Bright - SBS2 BCDEFGHIJKLMNOPA 2 Bright A_SorcFX2Orbit - Goto Orbit+1 - Death: - SBS2 A 10 - Stop - } -} - -// The translucent trail behind SorcFX2 ------------------------------------- - -ACTOR SorcFX2T1 : SorcFX2 -{ - RenderStyle Translucent - Alpha 0.4 - States - { - Spawn: - Goto Death - } -} - - -// Sorcerer spell 3 (The Bishop spawner) ------------------------------------ - -ACTOR SorcFX3 -{ - Speed 15 - Radius 22 - Height 65 - +NOBLOCKMAP - +MISSILE - +NOTELEPORT - SeeSound "SorcererBishopSpawn" - - action native A_SpawnBishop(); - action native A_SorcererBishopEntry(); - - States - { - Spawn: - SBS3 ABC 2 Bright - Loop - Death: - SBS3 A 4 Bright - BISH P 4 A_SorcererBishopEntry - BISH ON 4 - BISH MLKJIH 3 - BISH G 3 A_SpawnBishop - Stop - } -} - - -// The Bishop spawner's explosion animation --------------------------------- - -ACTOR SorcFX3Explosion -{ - +NOBLOCKMAP - +NOGRAVITY - +NOTELEPORT - RenderStyle Translucent - Alpha 0.4 - States - { - Spawn: - SBS3 DEFGH 3 - Stop - } -} - - -// Sorcerer spell 4 (The purple projectile) --------------------------------- - -ACTOR SorcFX4 -{ - Speed 12 - Radius 10 - Height 10 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - DeathSound "SorcererBallExplode" - - action native A_SorcFX4Check(); - - States - { - Spawn: - SBS4 ABC 2 Bright A_SorcFX4Check - Loop - Death: - SBS4 D 2 Bright - SBS4 E 2 Bright A_Explode(20, 128) - SBS4 FGH 2 Bright - Stop - } -} - - -// Spark that appears when shooting SorcFX4 --------------------------------- - -ACTOR SorcSpark1 -{ - Radius 5 - Height 5 - Gravity 0.125 - +NOBLOCKMAP - +DROPOFF - +NOTELEPORT - RenderStyle Add - States - { - Spawn: - SBFX ABCDEFG 4 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/hexenarmor.txt b/wadsrc/static/actors/hexen/hexenarmor.txt deleted file mode 100644 index 53be60fe0..000000000 --- a/wadsrc/static/actors/hexen/hexenarmor.txt +++ /dev/null @@ -1,65 +0,0 @@ - -// Mesh Armor (1) ----------------------------------------------------------- - -ACTOR MeshArmor : HexenArmor -{ - +NOGRAVITY - Health 0 // Armor class - Inventory.Amount 0 - Inventory.PickupMessage "$TXT_ARMOR1" - States - { - Spawn: - AR_1 A -1 - Stop - } -} - -// Falcon Shield (2) -------------------------------------------------------- - -ACTOR FalconShield : HexenArmor -{ - +NOGRAVITY - Health 1 // Armor class - Inventory.Amount 0 - Inventory.PickupMessage "$TXT_ARMOR2" - States - { - Spawn: - AR_2 A -1 - Stop - } -} - -// Platinum Helm (3) -------------------------------------------------------- - -ACTOR PlatinumHelm : HexenArmor -{ - +NOGRAVITY - Health 2 // Armor class - Inventory.Amount 0 - Inventory.PickupMessage "$TXT_ARMOR3" - States - { - Spawn: - AR_3 A -1 - Stop - } -} - -// Amulet of Warding (4) ---------------------------------------------------- - -ACTOR AmuletOfWarding : HexenArmor -{ - +NOGRAVITY - Health 3 // Armor class - Inventory.Amount 0 - Inventory.PickupMessage "$TXT_ARMOR4" - States - { - Spawn: - AR_4 A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/hexen/hexendecorations.txt b/wadsrc/static/actors/hexen/hexendecorations.txt deleted file mode 100644 index 87af4eff5..000000000 --- a/wadsrc/static/actors/hexen/hexendecorations.txt +++ /dev/null @@ -1,1396 +0,0 @@ -ACTOR ZWingedStatue -{ - Radius 10 - Height 62 - +SOLID - States - { - Spawn: - STTW A -1 - Stop - } -} - -ACTOR ZRock1 -{ - Radius 20 - Height 16 - States - { - Spawn: - RCK1 A -1 - Stop - } -} - -ACTOR ZRock2 -{ - Radius 20 - Height 16 - States - { - Spawn: - RCK2 A -1 - Stop - } -} - -ACTOR ZRock3 -{ - Radius 20 - Height 16 - States - { - Spawn: - RCK3 A -1 - Stop - } -} - -ACTOR ZRock4 -{ - Radius 20 - Height 16 - States - { - Spawn: - RCK4 A -1 - Stop - } -} - -ACTOR ZChandelier -{ - Radius 20 - Height 60 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - CDLR ABC 4 - Loop - } -} - -ACTOR ZChandelierUnlit -{ - Radius 20 - Height 60 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - CDLR D -1 - Stop - } -} - -ACTOR ZTreeDead -{ - Radius 10 - Height 96 - +SOLID - States - { - Spawn: - ZTRE A -1 - Stop - } -} - -ACTOR ZTree -{ - Radius 15 - Height 128 - +SOLID - States - { - Spawn: - ZTRE A -1 - Stop - } -} - -ACTOR ZTreeSwamp150 -{ - Radius 10 - Height 150 - +SOLID - States - { - Spawn: - TRES A -1 - Stop - } -} - -ACTOR ZTreeSwamp120 -{ - Radius 10 - Height 120 - +SOLID - States - { - Spawn: - TRE3 A -1 - Stop - } -} - -ACTOR ZStumpBurned -{ - Radius 12 - Height 20 - +SOLID - States - { - Spawn: - STM1 A -1 - Stop - } -} - -ACTOR ZStumpBare -{ - Radius 12 - Height 20 - +SOLID - States - { - Spawn: - STM2 A -1 - Stop - } -} - -ACTOR ZStumpSwamp1 -{ - Radius 20 - Height 16 - States - { - Spawn: - STM3 A -1 - Stop - } -} - -ACTOR ZStumpSwamp2 -{ - Radius 20 - Height 16 - States - { - Spawn: - STM4 A -1 - Stop - } -} - -ACTOR ZShroomLarge1 -{ - Radius 20 - Height 16 - States - { - Spawn: - MSH1 A -1 - Stop - } -} - -ACTOR ZShroomLarge2 -{ - Radius 20 - Height 16 - States - { - Spawn: - MSH2 A -1 - Stop - } -} - -ACTOR ZShroomLarge3 -{ - Radius 20 - Height 16 - States - { - Spawn: - MSH3 A -1 - Stop - } -} - -ACTOR ZShroomSmall1 -{ - Radius 20 - Height 16 - States - { - Spawn: - MSH4 A -1 - Stop - } -} - -ACTOR ZShroomSmall2 -{ - Radius 20 - Height 16 - States - { - Spawn: - MSH5 A -1 - Stop - } -} - -ACTOR ZShroomSmall3 -{ - Radius 20 - Height 16 - States - { - Spawn: - MSH6 A -1 - Stop - } -} - -ACTOR ZShroomSmall4 -{ - Radius 20 - Height 16 - States - { - Spawn: - MSH7 A -1 - Stop - } -} - -ACTOR ZShroomSmall5 -{ - Radius 20 - Height 16 - States - { - Spawn: - MSH8 A -1 - Stop - } -} - -ACTOR ZStalagmitePillar -{ - Radius 8 - Height 138 - +SOLID - States - { - Spawn: - SGMP A -1 - Stop - } -} - -ACTOR ZStalagmiteLarge -{ - Radius 8 - Height 48 - +SOLID - States - { - Spawn: - SGM1 A -1 - Stop - } -} - -ACTOR ZStalagmiteMedium -{ - Radius 6 - Height 40 - +SOLID - States - { - Spawn: - SGM2 A -1 - Stop - } -} - -ACTOR ZStalagmiteSmall -{ - Radius 8 - Height 36 - +SOLID - States - { - Spawn: - SGM3 A -1 - Stop - } -} - -ACTOR ZStalactiteLarge -{ - Radius 8 - Height 66 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - SLC1 A -1 - Stop - } -} - -ACTOR ZStalactiteMedium -{ - Radius 6 - Height 50 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - SLC2 A -1 - Stop - } -} - -ACTOR ZStalactiteSmall -{ - Radius 8 - Height 40 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - SLC3 A -1 - Stop - } -} - -ACTOR ZMossCeiling1 -{ - Radius 20 - Height 20 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - MSS1 A -1 - Stop - } -} - -ACTOR ZMossCeiling2 -{ - Radius 20 - Height 24 - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - MSS2 A -1 - Stop - } -} - -ACTOR ZSwampVine -{ - Radius 8 - Height 52 - +SOLID - States - { - Spawn: - SWMV A -1 - Stop - } -} - -ACTOR ZCorpseKabob -{ - Radius 10 - Height 92 - +SOLID - States - { - Spawn: - CPS1 A -1 - Stop - } -} - -ACTOR ZCorpseSleeping -{ - Radius 20 - Height 16 - States - { - Spawn: - CPS2 A -1 - Stop - } -} - -ACTOR ZTombstoneRIP -{ - Radius 10 - Height 46 - +SOLID - States - { - Spawn: - TMS1 A -1 - Stop - } -} - -ACTOR ZTombstoneShane -{ - Radius 10 - Height 46 - +SOLID - States - { - Spawn: - TMS2 A -1 - Stop - } -} - -ACTOR ZTombstoneBigCross -{ - Radius 10 - Height 46 - +SOLID - States - { - Spawn: - TMS3 A -1 - Stop - } -} - -ACTOR ZTombstoneBrianR -{ - Radius 10 - Height 52 - +SOLID - States - { - Spawn: - TMS4 A -1 - Stop - } -} - -ACTOR ZTombstoneCrossCircle -{ - Radius 10 - Height 52 - +SOLID - States - { - Spawn: - TMS5 A -1 - Stop - } -} - -ACTOR ZTombstoneSmallCross -{ - Radius 8 - Height 46 - +SOLID - States - { - Spawn: - TMS6 A -1 - Stop - } -} - -ACTOR ZTombstoneBrianP -{ - Radius 8 - Height 46 - +SOLID - States - { - Spawn: - TMS7 A -1 - Stop - } -} - -ACTOR ZCorpseHanging -{ - Radius 6 - Height 75 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - CPS3 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleGreenTall -{ - Radius 14 - Height 108 - +SOLID - States - { - Spawn: - STT2 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleBlueTall -{ - Radius 14 - Height 108 - +SOLID - States - { - Spawn: - STT3 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleGreenShort -{ - Radius 14 - Height 62 - +SOLID - States - { - Spawn: - STT4 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleBlueShort -{ - Radius 14 - Height 62 - +SOLID - States - { - Spawn: - STT5 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleStripeTall -{ - Radius 14 - Height 108 - +SOLID - States - { - Spawn: - GAR1 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleDarkRedTall -{ - Radius 14 - Height 108 - +SOLID - States - { - Spawn: - GAR2 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleRedTall -{ - Radius 14 - Height 108 - +SOLID - States - { - Spawn: - GAR3 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleTanTall -{ - Radius 14 - Height 108 - +SOLID - States - { - Spawn: - GAR4 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleRustTall -{ - Radius 14 - Height 108 - +SOLID - States - { - Spawn: - GAR5 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleDarkRedShort -{ - Radius 14 - Height 62 - +SOLID - States - { - Spawn: - GAR6 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleRedShort -{ - Radius 14 - Height 62 - +SOLID - States - { - Spawn: - GAR7 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleTanShort -{ - Radius 14 - Height 62 - +SOLID - States - { - Spawn: - GAR8 A -1 - Stop - } -} - -ACTOR ZStatueGargoyleRustShort -{ - Radius 14 - Height 62 - +SOLID - States - { - Spawn: - GAR9 A -1 - Stop - } -} - -ACTOR ZBannerTattered -{ - Radius 8 - Height 120 - +SOLID - States - { - Spawn: - BNR1 A -1 - Stop - } -} - -ACTOR ZTreeLarge1 -{ - Radius 15 - Height 180 - +SOLID - States - { - Spawn: - TRE4 A -1 - Stop - } -} - -ACTOR ZTreeLarge2 -{ - Radius 15 - Height 180 - +SOLID - States - { - Spawn: - TRE5 A -1 - Stop - } -} - -ACTOR ZTreeGnarled1 -{ - Radius 22 - Height 100 - +SOLID - States - { - Spawn: - TRE6 A -1 - Stop - } -} - -ACTOR ZTreeGnarled2 -{ - Radius 22 - Height 100 - +SOLID - States - { - Spawn: - TRE7 A -1 - Stop - } -} - -ACTOR ZLog -{ - Radius 20 - Height 25 - +SOLID - States - { - Spawn: - LOGG A -1 - Stop - } -} - -ACTOR ZStalactiteIceLarge -{ - Radius 8 - Height 66 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - ICT1 A -1 - Stop - } -} - -ACTOR ZStalactiteIceMedium -{ - Radius 5 - Height 50 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - ICT2 A -1 - Stop - } -} - -ACTOR ZStalactiteIceSmall -{ - Radius 4 - Height 32 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - ICT3 A -1 - Stop - } -} - -ACTOR ZStalactiteIceTiny -{ - Radius 4 - Height 8 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - ICT4 A -1 - Stop - } -} - -ACTOR ZStalagmiteIceLarge -{ - Radius 8 - Height 66 - +SOLID - States - { - Spawn: - ICM1 A -1 - Stop - } -} - -ACTOR ZStalagmiteIceMedium -{ - Radius 5 - Height 50 - +SOLID - States - { - Spawn: - ICM2 A -1 - Stop - } -} - -ACTOR ZStalagmiteIceSmall -{ - Radius 4 - Height 32 - +SOLID - States - { - Spawn: - ICM3 A -1 - Stop - } -} - -ACTOR ZStalagmiteIceTiny -{ - Radius 4 - Height 8 - +SOLID - States - { - Spawn: - ICM4 A -1 - Stop - } -} - -ACTOR ZRockBrown1 -{ - Radius 17 - Height 72 - +SOLID - States - { - Spawn: - RKBL A -1 - Stop - } -} - -ACTOR ZRockBrown2 -{ - Radius 15 - Height 50 - +SOLID - States - { - Spawn: - RKBS A -1 - Stop - } -} - -ACTOR ZRockBlack -{ - Radius 20 - Height 40 - +SOLID - States - { - Spawn: - RKBK A -1 - Stop - } -} - -ACTOR ZRubble1 -{ - Radius 20 - Height 16 - States - { - Spawn: - RBL1 A -1 - Stop - } -} - -ACTOR ZRubble2 -{ - Radius 20 - Height 16 - States - { - Spawn: - RBL2 A -1 - Stop - } -} - -ACTOR ZRubble3 -{ - Radius 20 - Height 16 - States - { - Spawn: - RBL3 A -1 - Stop - } -} - -ACTOR ZVasePillar -{ - Radius 12 - Height 54 - +SOLID - States - { - Spawn: - VASE A -1 - Stop - } -} - -ACTOR ZCorpseLynched -{ - Radius 11 - Height 95 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - CPS4 A -1 - Stop - } -} - -ACTOR ZCandle -{ - Radius 20 - Height 16 - +NOGRAVITY - +NOBLOCKMAP - States - { - Spawn: - CNDL ABC 4 Bright - Loop - } -} - -ACTOR ZBarrel -{ - Radius 15 - Height 32 - +SOLID - States - { - Spawn: - ZBAR A -1 - Stop - } -} - -ACTOR ZBucket -{ - Radius 8 - Height 72 - +SOLID - +SPAWNCEILING - +NOGRAVITY - States - { - Spawn: - BCKT A -1 - Stop - } -} - -ACTOR FireThing -{ - Radius 5 - Height 10 - +SOLID - States - { - Spawn: - FSKL A 4 Bright - FSKL B 3 Bright - FSKL C 4 Bright - FSKL D 3 Bright - FSKL E 4 Bright - FSKL F 3 Bright - FSKL G 4 Bright - FSKL H 3 Bright - FSKL I 4 Bright - Loop - } -} - -ACTOR BrassTorch -{ - Radius 6 - Height 35 - +SOLID - States - { - Spawn: - BRTR ABCDEFGHIJKLM 4 Bright - Loop - } -} - -ACTOR ZBlueCandle -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - BCAN ABCDE 5 Bright - Loop - } -} - -ACTOR ZIronMaiden -{ - Radius 12 - Height 60 - +SOLID - States - { - Spawn: - IRON A -1 - Stop - } -} - -ACTOR ZChainBit32 -{ - Radius 4 - Height 32 - +SPAWNCEILING - +NOGRAVITY - +NOBLOCKMAP - States - { - Spawn: - CHNS A -1 - Stop - } -} - -ACTOR ZChainBit64 -{ - Radius 4 - Height 64 - +SPAWNCEILING - +NOGRAVITY - +NOBLOCKMAP - States - { - Spawn: - CHNS B -1 - Stop - } -} - -ACTOR ZChainEndHeart -{ - Radius 4 - Height 32 - +SPAWNCEILING - +NOGRAVITY - +NOBLOCKMAP - States - { - Spawn: - CHNS C -1 - Stop - } -} - -ACTOR ZChainEndHook1 -{ - Radius 4 - Height 32 - +SPAWNCEILING - +NOGRAVITY - +NOBLOCKMAP - States - { - Spawn: - CHNS D -1 - Stop - } -} - -ACTOR ZChainEndHook2 -{ - Radius 4 - Height 32 - +SPAWNCEILING - +NOGRAVITY - +NOBLOCKMAP - States - { - Spawn: - CHNS E -1 - Stop - } -} - -ACTOR ZChainEndSpike -{ - Radius 4 - Height 32 - +SPAWNCEILING - +NOGRAVITY - +NOBLOCKMAP - States - { - Spawn: - CHNS F -1 - Stop - } -} - -ACTOR ZChainEndSkull -{ - Radius 4 - Height 32 - +SPAWNCEILING - +NOGRAVITY - +NOBLOCKMAP - States - { - Spawn: - CHNS G -1 - Stop - } -} - -ACTOR TableShit1 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST1 A -1 - Stop - } -} - -ACTOR TableShit2 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST2 A -1 - Stop - } -} - -ACTOR TableShit3 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST3 A -1 - Stop - } -} - -ACTOR TableShit4 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST4 A -1 - Stop - } -} - -ACTOR TableShit5 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST5 A -1 - Stop - } -} - -ACTOR TableShit6 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST6 A -1 - Stop - } -} - -ACTOR TableShit7 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST7 A -1 - Stop - } -} - -ACTOR TableShit8 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST8 A -1 - Stop - } -} - -ACTOR TableShit9 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST9 A -1 - Stop - } -} - -ACTOR TableShit10 -{ - Radius 20 - Height 16 - +NOBLOCKMAP - States - { - Spawn: - TST0 A -1 - Stop - } -} - -ACTOR TeleSmoke -{ - Radius 20 - Height 16 - +NOGRAVITY - +NOBLOCKMAP - RenderStyle Translucent - Alpha 0.6 - States - { - Spawn: - TSMK A 4 - TSMK B 3 - TSMK C 4 - TSMK D 3 - TSMK E 4 - TSMK F 3 - TSMK G 4 - TSMK H 3 - TSMK I 4 - TSMK J 3 - TSMK K 4 - TSMK L 3 - TSMK M 4 - TSMK N 3 - TSMK O 4 - TSMK P 3 - TSMK Q 4 - TSMK R 3 - TSMK S 4 - TSMK T 3 - TSMK U 4 - TSMK V 3 - TSMK W 4 - TSMK X 3 - TSMK Y 4 - TSMK Z 3 - Loop - } -} - diff --git a/wadsrc/static/actors/hexen/hexenkeys.txt b/wadsrc/static/actors/hexen/hexenkeys.txt deleted file mode 100644 index b65d59e16..000000000 --- a/wadsrc/static/actors/hexen/hexenkeys.txt +++ /dev/null @@ -1,139 +0,0 @@ - -ACTOR HexenKey : Key -{ - Radius 8 - Height 20 -} - -ACTOR KeySteel : HexenKey -{ - Inventory.Icon KEYSLOT1 - Inventory.PickupMessage "$TXT_KEY_STEEL" - States - { - Spawn: - KEY1 A -1 - Stop - } -} - -ACTOR KeyCave : HexenKey -{ - Inventory.Icon KEYSLOT2 - Inventory.PickupMessage "$TXT_KEY_CAVE" - States - { - Spawn: - KEY2 A -1 - Stop - } -} - -ACTOR KeyAxe : HexenKey -{ - Inventory.Icon KEYSLOT3 - Inventory.PickupMessage "$TXT_KEY_AXE" - States - { - Spawn: - KEY3 A -1 - Stop - } -} - -ACTOR KeyFire : HexenKey -{ - Inventory.Icon KEYSLOT4 - Inventory.PickupMessage "$TXT_KEY_FIRE" - States - { - Spawn: - KEY4 A -1 - Stop - } -} - -ACTOR KeyEmerald : HexenKey -{ - Inventory.Icon KEYSLOT5 - Inventory.PickupMessage "$TXT_KEY_EMERALD" - States - { - Spawn: - KEY5 A -1 - Stop - } -} - -ACTOR KeyDungeon : HexenKey -{ - Inventory.Icon KEYSLOT6 - Inventory.PickupMessage "$TXT_KEY_DUNGEON" - States - { - Spawn: - KEY6 A -1 - Stop - } -} - -ACTOR KeySilver : HexenKey -{ - Inventory.Icon KEYSLOT7 - Inventory.PickupMessage "$TXT_KEY_SILVER" - States - { - Spawn: - KEY7 A -1 - Stop - } -} - -ACTOR KeyRusted : HexenKey -{ - Inventory.Icon KEYSLOT8 - Inventory.PickupMessage "$TXT_KEY_RUSTED" - States - { - Spawn: - KEY8 A -1 - Stop - } -} - -ACTOR KeyHorn : HexenKey -{ - Inventory.Icon KEYSLOT9 - Inventory.PickupMessage "$TXT_KEY_HORN" - States - { - Spawn: - KEY9 A -1 - Stop - } -} - -ACTOR KeySwamp : HexenKey -{ - Inventory.Icon KEYSLOTA - Inventory.PickupMessage "$TXT_KEY_SWAMP" - States - { - Spawn: - KEYA A -1 - Stop - } -} - -ACTOR KeyCastle : HexenKey -{ - Inventory.Icon KEYSLOTB - Inventory.PickupMessage "$TXT_KEY_CASTLE" - States - { - Spawn: - KEYB A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/hexen/hexenspecialdecs.txt b/wadsrc/static/actors/hexen/hexenspecialdecs.txt deleted file mode 100644 index cd5063385..000000000 --- a/wadsrc/static/actors/hexen/hexenspecialdecs.txt +++ /dev/null @@ -1,684 +0,0 @@ - -// Winged Statue (no skull) ------------------------------------------------- - -ACTOR ZWingedStatueNoSkull : SwitchingDecoration -{ - Radius 10 - Height 62 - +SOLID - States - { - Spawn: - STWN A -1 - Stop - Active: - STWN B -1 - Stop - } -} - - -// Gem pedestal ------------------------------------------------------------- - -ACTOR ZGemPedestal : SwitchingDecoration -{ - Radius 10 - Height 40 - +SOLID - States - { - Spawn: - GMPD A -1 - Stop - Active: - GMPD B -1 - Stop - } -} - - -// Tree (destructible) ------------------------------------------------------ - -ACTOR TreeDestructible -{ - Health 70 - Radius 15 - Height 180 - DeathHeight 24 - Mass 0x7fffffff - PainSound "TreeExplode" - DeathSound "TreeBreak" - +SOLID +SHOOTABLE +NOBLOOD +NOICEDEATH - States - { - Spawn: - TRDT A -1 - Stop - Death: - TRDT B 5 - TRDT C 5 A_Scream - TRDT DEF 5 - TRDT G -1 - Stop - Burn: - TRDT H 5 Bright A_Pain - TRDT IJKL 5 Bright - TRDT M 5 Bright A_Explode(10, 128) - TRDT N 5 Bright - TRDT OP 5 - TRDT Q -1 - Stop - } -} - - -// Pottery1 ------------------------------------------------------------------ - -ACTOR Pottery1 native -{ - Health 15 - Speed 10 - Height 32 - +SOLID +SHOOTABLE +NOBLOOD +DROPOFF - +SLIDESONWALLS +PUSHABLE +TELESTOMP +CANPASS - +NOICEDEATH - - action native A_PotteryExplode(); - - States - { - Spawn: - POT1 A -1 - Loop - Death: - POT1 A 0 A_PotteryExplode - Stop - } -} - -// Pottery2 ----------------------------------------------------------------- - -ACTOR Pottery2 : Pottery1 -{ - Height 25 - States - { - Spawn: - POT2 A -1 - Stop - } -} - -// Pottery3 ----------------------------------------------------------------- - -ACTOR Pottery3 : Pottery1 -{ - Height 25 - States - { - Spawn: - POT3 A -1 - Stop - } -} - -// Pottery Bit -------------------------------------------------------------- - -ACTOR PotteryBit -{ - Radius 5 - Height 5 - +MISSILE - +NOTELEPORT - +NOICEDEATH - - action native A_PotteryChooseBit(); - action native A_PotteryCheck(); - - States - { - Spawn: - PBIT ABCDE -1 - Stop - Death: - PBIT F 0 A_PotteryChooseBit - Stop - Pottery1: - PBIT F 140 - PBIT F 1 A_PotteryCheck - Stop - Pottery2: - PBIT G 140 - PBIT G 1 A_PotteryCheck - Stop - Pottery3: - PBIT H 140 - PBIT H 1 A_PotteryCheck - Stop - Pottery4: - PBIT I 140 - PBIT I 1 A_PotteryCheck - Stop - Pottery5: - PBIT J 140 - PBIT J 1 A_PotteryCheck - Stop - } -} - - -// Blood pool --------------------------------------------------------------- - -ACTOR BloodPool -{ - States - { - Spawn: - BDPL A -1 - Stop - } -} - - -// Lynched corpse (no heart) ------------------------------------------------ - -ACTOR ZCorpseLynchedNoHeart native -{ - Radius 10 - Height 100 - +SOLID +SPAWNCEILING +NOGRAVITY - - action native A_CorpseBloodDrip(); - - States - { - Spawn: - CPS5 A 140 A_CorpseBloodDrip - Loop - } -} - - -// CorpseBloodDrip ---------------------------------------------------------- - -ACTOR CorpseBloodDrip -{ - Radius 1 - Height 4 - Gravity 0.125 - +MISSILE - +NOICEDEATH - DeathSound "Drip" - States - { - Spawn: - BDRP A -1 - Stop - Death: - BDSH AB 3 - BDSH CD 2 - Stop - } -} - - -// Corpse bit --------------------------------------------------------------- - -ACTOR CorpseBit -{ - Radius 5 - Height 5 - +NOBLOCKMAP - +TELESTOMP - States - { - Spawn: - CPB1 A -1 - Stop - CPB2 A -1 - Stop - CPB3 A -1 - Stop - CPB4 A -1 - Stop - } -} - - -// Corpse (sitting, splatterable) ------------------------------------------- - -ACTOR ZCorpseSitting -{ - Health 30 - Radius 15 - Height 35 - +SOLID +SHOOTABLE +NOBLOOD - +NOICEDEATH - DeathSound "FireDemonDeath" - - action native A_CorpseExplode(); - - States - { - Spawn: - CPS6 A -1 - Stop - Death: - CPS6 A 1 A_CorpseExplode - Stop - } -} - - -// Leaf Spawner ------------------------------------------------------------- - -ACTOR LeafSpawner -{ - +NOBLOCKMAP +NOSECTOR - +INVISIBLE - - action native A_LeafSpawn(); - - States - { - Spawn: - TNT1 A 20 A_LeafSpawn - Loop - } -} - - -// Leaf 1 ------------------------------------------------------------------- - -ACTOR Leaf1 -{ - Radius 2 - Height 4 - Gravity 0.125 - +NOBLOCKMAP +MISSILE - +NOTELEPORT +DONTSPLASH - +NOICEDEATH - - action native A_LeafThrust(); - action native A_LeafCheck(); - - States - { - Spawn: - LEF1 ABC 4 - LEF1 D 4 A_LeafThrust - LEF1 EFG 4 - LEF1 H 4 A_LeafThrust - LEF1 I 4 - LEF1 AB 4 - LEF1 C 4 A_LeafThrust - LEF1 DEF 4 - LEF1 G 4 A_LeafThrust - LEF1 HI 4 - Stop - Death: - LEF3 D 10 A_LeafCheck - Wait - } -} - - -// Leaf 2 ------------------------------------------------------------------- - -ACTOR Leaf2 : Leaf1 -{ - States - { - Spawn: - LEF2 ABC 4 - LEF2 D 4 A_LeafThrust - LEF2 EFG 4 - LEF2 H 4 A_LeafThrust - LEF2 I 4 - LEF2 AB 4 - LEF2 C 4 A_LeafThrust - LEF2 DEF 4 - LEF2 G 4 A_LeafThrust - LEF2 HI 4 - Stop - } -} - - -// Twined torch ------------------------------------------------------------- - -ACTOR ZTwinedTorch : SwitchableDecoration -{ - Radius 10 - Height 64 - +SOLID - States - { - Active: - TWTR A 0 Bright A_PlaySound("Ignite") - Spawn: - TWTR ABCDEFGH 4 Bright - Loop - Inactive: - TWTR I -1 - Stop - } -} - -ACTOR ZTwinedTorchUnlit : ZTwinedTorch -{ - States - { - Spawn: - Goto Super::Inactive - } -} - - -// Wall torch --------------------------------------------------------------- - -ACTOR ZWallTorch : SwitchableDecoration -{ - +NOBLOCKMAP - +NOGRAVITY - +FIXMAPTHINGPOS - Radius 6.5 - States - { - Active: - WLTR A 0 Bright A_PlaySound("Ignite") - Spawn: - WLTR ABCDEFGH 5 Bright - Loop - Inactive: - WLTR I -1 - Stop - } -} - -ACTOR ZWallTorchUnlit : ZWallTorch -{ - States - { - Spawn: - Goto Super::Inactive - } -} - - -// Shrub1 ------------------------------------------------------------------- - -ACTOR ZShrub1 -{ - Radius 8 - Height 24 - Health 20 - Mass 0x7fffffff - +SOLID +SHOOTABLE +NOBLOOD +NOICEDEATH - DeathSound "TreeExplode" - States - { - Spawn: - SHB1 A -1 - Stop - Burn: - SHB1 B 7 Bright - SHB1 C 6 Bright A_Scream - SHB1 D 5 Bright - Stop - } -} - - -// Shrub2 ------------------------------------------------------------------- - -ACTOR ZShrub2 -{ - Radius 16 - Height 40 - Health 20 - Mass 0x7fffffff - +SOLID +SHOOTABLE +NOBLOOD +NOICEDEATH - DeathSound "TreeExplode" - States - { - Spawn: - SHB2 A -1 - Stop - Burn: - SHB2 B 7 Bright - SHB2 C 6 Bright A_Scream - SHB2 D 5 Bright A_Explode(30, 64) - SHB2 E 5 Bright - Stop - } -} - - -// Fire Bull ---------------------------------------------------------------- - -ACTOR ZFireBull : SwitchableDecoration -{ - Radius 20 - Height 80 - +SOLID - States - { - Active: - FBUL I 4 Bright A_PlaySound("Ignite") - FBUL J 4 Bright - Spawn: - FBUL ABCDEFG 4 Bright - Loop - Inactive: - FBUL JI 4 Bright - FBUL H -1 - Stop - } -} - -ACTOR ZFireBullUnlit : ZFireBull -{ - States - { - Spawn: - Goto Super::Inactive+2 - } -} - - -// Suit of armor ------------------------------------------------------------ - -ACTOR ZSuitOfArmor -{ - Health 60 - Radius 16 - Height 72 - Mass 0x7fffffff - +SOLID +SHOOTABLE +NOBLOOD - +NOICEDEATH - DeathSound "SuitofArmorBreak" - - action native A_SoAExplode(); - - States - { - Spawn: - ZSUI A -1 - Stop - Death: - ZSUI A 1 A_SoAExplode - Stop - } -} - - -// Armor chunk -------------------------------------------------------------- - -ACTOR ZArmorChunk -{ - Radius 4 - Height 8 - States - { - Spawn: - ZSUI B -1 - Stop - ZSUI C -1 - Stop - ZSUI D -1 - Stop - ZSUI E -1 - Stop - ZSUI F -1 - Stop - ZSUI G -1 - Stop - ZSUI H -1 - Stop - ZSUI I -1 - Stop - ZSUI J -1 - Stop - ZSUI K -1 - Stop - } -} - - -// Bell --------------------------------------------------------------------- - -ACTOR ZBell native -{ - Health 5 - Radius 56 - Height 120 - Mass 0x7fffffff - +SOLID +SHOOTABLE +NOBLOOD +NOGRAVITY +SPAWNCEILING - +NOICEDEATH - DeathSound "BellRing" - - action native A_BellReset1(); - action native A_BellReset2(); - - States - { - Spawn: - BBLL F -1 - Stop - Death: - BBLL A 4 A_BellReset1 - BBLL BC 4 - BBLL D 5 A_Scream - BBLL CB 4 - BBLL A 3 - BBLL E 4 - BBLL F 5 - BBLL G 6 A_Scream - BBLL F 5 - BBLL EA 4 - BBLL BC 5 - BBLL D 6 A_Scream - BBLL CB 5 - BBLL A 4 - BBLL EF 5 - BBLL G 7 A_Scream - BBLL FEA 5 - BBLL B 6 - BBLL C 6 - BBLL D 7 A_Scream - BBLL CB 6 - BBLL A 5 - BBLL EF 6 - BBLL G 7 A_Scream - BBLL FEABC 6 - BBLL B 7 - BBLL A 8 - BBLL E 12 - BBLL A 10 - BBLL B 12 - BBLL A 12 - BBLL E 14 - BBLL A 1 A_BellReset2 - Goto Spawn - } -} - - -// "Christmas" Tree --------------------------------------------------------- - -ACTOR ZXmasTree -{ - Radius 11 - Height 130 - Health 20 - Mass 0x7fffffff - +SOLID +SHOOTABLE +NOBLOOD +NOICEDEATH - DeathSound "TreeExplode" - States - { - Spawn: - XMAS A -1 - Stop - Burn: - XMAS B 6 Bright - XMAS C 6 Bright A_Scream - XMAS D 5 Bright - XMAS E 5 Bright A_Explode(30, 64) - XMAS F 5 Bright - XMAS G 4 Bright - XMAS H 5 - XMAS I 4 A_NoBlocking - XMAS J 4 - XMAS K -1 - Stop - } -} - -// Cauldron ----------------------------------------------------------------- - -ACTOR ZCauldron : SwitchableDecoration -{ - Radius 12 - Height 26 - +SOLID - States - { - Active: - CDRN B 0 Bright A_PlaySound("Ignite") - Spawn: - CDRN BCDEFGH 4 Bright - Loop - Inactive: - CDRN A -1 - Stop - } -} - -ACTOR ZCauldronUnlit : ZCauldron -{ - States - { - Spawn: - Goto Super::Inactive - } -} - - -// Water Drip --------------------------------------------------------------- - -ACTOR HWaterDrip -{ - +MISSILE - +LOWGRAVITY - +NOTELEPORT - Mass 1 - DeathSound "Drip" - States - { - Spawn: - HWAT A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/hexen/iceguy.txt b/wadsrc/static/actors/hexen/iceguy.txt deleted file mode 100644 index 235be474f..000000000 --- a/wadsrc/static/actors/hexen/iceguy.txt +++ /dev/null @@ -1,167 +0,0 @@ - -// Ice Guy ------------------------------------------------------------------ - -ACTOR IceGuy -{ - Health 120 - PainChance 144 - Speed 14 - Radius 22 - Height 75 - Mass 150 - DamageType "Ice" - Monster - +NOBLOOD - +TELESTOMP - +NOICEDEATH - SeeSound "IceGuySight" - AttackSound "IceGuyAttack" - ActiveSound "IceGuyActive" - Obituary "$OB_ICEGUY" - - action native A_IceGuyLook(); - action native A_IceGuyChase(); - action native A_IceGuyAttack(); - - States - { - Spawn: - ICEY A 10 A_IceGuyLook - Loop - See: - ICEY A 4 A_Chase - ICEY B 4 A_IceGuyChase - ICEY CD 4 A_Chase - Loop - Pain: - ICEY A 1 A_Pain - Goto See - Missile: - ICEY EF 3 A_FaceTarget - ICEY G 8 Bright A_IceGuyAttack - ICEY F 4 A_FaceTarget - Goto See - Death: - ICEY A 1 A_IceGuyDie - Stop - Inactive: - ICEY A -1 - Goto See - } -} - -// Ice Guy Projectile ------------------------------------------------------- - -ACTOR IceGuyFX -{ - Speed 14 - Radius 8 - Height 10 - Damage 1 - DamageType "Ice" - Projectile - -ACTIVATEIMPACT -ACTIVATEPCROSS - DeathSound "IceGuyMissileExplode" - - action native A_IceGuyMissileExplode(); - - States - { - Spawn: - ICPR ABC 3 Bright A_SpawnItemEx("IceFXPuff", 0,0,2) - Loop - Death: - ICPR D 4 Bright - ICPR E 4 Bright A_IceGuyMissileExplode - ICPR FG 4 Bright - ICPR H 3 Bright - Stop - } -} - -// Ice Guy Projectile's Puff ------------------------------------------------ - -ACTOR IceFXPuff -{ - Radius 1 - Height 1 - +NOBLOCKMAP +NOGRAVITY +DROPOFF +SHADOW - +NOTELEPORT - RenderStyle Translucent - Alpha 0.4 - States - { - Spawn: - ICPR IJK 3 - ICPR LM 2 - Stop - } -} - -// Secondary Ice Guy Projectile (ejected by the primary projectile) --------- - -ACTOR IceGuyFX2 -{ - Speed 10 - Radius 4 - Height 4 - Damage 1 - DamageType "Ice" - Gravity 0.125 - +NOBLOCKMAP +DROPOFF +MISSILE - +NOTELEPORT - +STRIFEDAMAGE - States - { - Spawn: - ICPR NOP 3 Bright - Loop - } -} - -// Ice Guy Bit -------------------------------------------------------------- - -ACTOR IceGuyBit -{ - Radius 1 - Height 1 - Gravity 0.125 - +NOBLOCKMAP +DROPOFF - +NOTELEPORT - States - { - Spawn: - ICPR Q 50 Bright - Stop - ICPR R 50 Bright - Stop - } -} - -// Ice Guy Wisp 1 ----------------------------------------------------------- - -ACTOR IceGuyWisp1 -{ - +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE - +NOTELEPORT - RenderStyle Translucent - Alpha 0.4 - States - { - Spawn: - ICWS ABCDEFGHI 2 - Stop - } -} - -// Ice Guy Wisp 2 ----------------------------------------------------------- - -ACTOR IceGuyWisp2 : IceGuyWisp1 -{ - States - { - Spawn: - ICWS JKLMNOPQR 2 - Stop - } -} diff --git a/wadsrc/static/actors/hexen/korax.txt b/wadsrc/static/actors/hexen/korax.txt deleted file mode 100644 index a35183ad6..000000000 --- a/wadsrc/static/actors/hexen/korax.txt +++ /dev/null @@ -1,124 +0,0 @@ -ACTOR Korax -{ - Health 5000 - Painchance 20 - Speed 10 - Radius 65 - Height 115 - Mass 2000 - Damage 15 - Monster - +BOSS - +FLOORCLIP - +TELESTOMP - +DONTMORPH - +NOTARGET - +NOICEDEATH - SeeSound "KoraxSight" - AttackSound "KoraxAttack" - PainSound "KoraxPain" - DeathSound "KoraxDeath" - ActiveSound "KoraxActive" - Obituary "$OB_KORAX" // "%o was swept from the board by Korax." - - action native A_KoraxChase(); - action native A_KoraxDecide(); - action native A_KoraxBonePop(); - action native A_KoraxMissile(); - action native A_KoraxCommand(); - - States - { - Spawn: - KORX A 5 A_Look - Loop - See: - KORX AAA 3 A_KoraxChase - KORX B 3 A_Chase - KORX BBB 3 A_KoraxChase - KORX C 0 A_PlaySound("KoraxStep") - KORX C 3 A_Chase - KORX CCC 3 A_KoraxChase - KORX D 3 A_Chase - KORX DDD 3 A_KoraxChase - KORX A 0 A_PlaySound("KoraxStep") - KORX A 3 A_Chase - Loop - Pain: - KORX H 5 A_Pain - KORX H 5 - Goto See - Missile: - KORX E 2 Bright A_FaceTarget - KORX E 5 Bright A_KoraxDecide - Wait - Death: - KORX I 5 - KORX J 5 A_FaceTarget - KORX K 5 A_Scream - KORX LMNOP 5 - KORX Q 10 - KORX R 5 A_KoraxBonePop - KORX S 5 A_NoBlocking - KORX TU 5 - KORX V -1 - Stop - Attack: - KORX E 4 Bright A_FaceTarget - KORX F 8 Bright A_KoraxMissile - KORX E 8 Bright - Goto See - Command: - KORX E 5 Bright A_FaceTarget - KORX W 10 Bright A_FaceTarget - KORX G 15 Bright A_KoraxCommand - KORX W 10 Bright - KORX E 5 Bright - Goto See - } -} - -ACTOR KoraxSpirit -{ - Speed 8 - Projectile - +NOCLIP - -ACTIVATEPCROSS - -ACTIVATEIMPACT - RenderStyle Translucent - Alpha 0.4 - - action native A_KSpiritRoam(); - - States - { - Spawn: - SPIR AB 5 A_KSpiritRoam - Loop - Death: - SPIR DEFGHI 5 - Stop - } -} - -ACTOR KoraxBolt -{ - Radius 15 - Height 35 - Projectile - -ACTIVATEPCROSS - -ACTIVATEIMPACT - RenderStyle Add - - action native A_KBolt(); - action native A_KBoltRaise(); - - States - { - Spawn: - MLFX I 2 Bright - MLFX J 2 Bright A_KBoltRaise - MLFX IJKLM 2 Bright A_KBolt - Stop - } -} diff --git a/wadsrc/static/actors/hexen/mageboss.txt b/wadsrc/static/actors/hexen/mageboss.txt deleted file mode 100644 index 95f36954b..000000000 --- a/wadsrc/static/actors/hexen/mageboss.txt +++ /dev/null @@ -1,83 +0,0 @@ - -// Mage Boss (Menelkir) ----------------------------------------------------- - -ACTOR MageBoss -{ - Health 800 - PainChance 50 - Speed 25 - Radius 16 - Height 64 - Monster - +FLOORCLIP +TELESTOMP - +DONTMORPH - PainSound "PlayerMagePain" - DeathSound "PlayerMageCrazyDeath" - Obituary "$OB_MBOSS" - - action native A_MageAttack(); - - States - { - Spawn: - MAGE A 2 - MAGE A 3 A_ClassBossHealth - MAGE A 5 A_Look - Wait - See: - MAGE ABCD 4 A_FastChase - Loop - Pain: - MAGE G 4 - MAGE G 4 A_Pain - Goto See - Melee: - Missile: - MAGE E 8 A_FaceTarget - MAGE F 8 Bright A_MageAttack - Goto See - Death: - MAGE H 6 - MAGE I 6 A_Scream - MAGE JK 6 - MAGE L 6 A_NoBlocking - MAGE M 6 - MAGE N -1 - Stop - XDeath: - MAGE O 5 A_Scream - MAGE P 5 - MAGE R 5 A_NoBlocking - MAGE S 5 - MAGE T 5 - MAGE U 5 - MAGE V 5 - MAGE W 5 - MAGE X -1 - Stop - Ice: - MAGE Y 5 A_FreezeDeath - MAGE Y 1 A_FreezeDeathChunks - Wait - Burn: - FDTH E 5 Bright A_PlaySound("PlayerMageBurnDeath") - FDTH F 4 Bright - FDTH G 5 Bright - FDTH H 4 Bright A_Scream - FDTH I 5 Bright - FDTH J 4 Bright - FDTH K 5 Bright - FDTH L 4 Bright - FDTH M 5 Bright - FDTH N 4 Bright - FDTH O 5 Bright - FDTH P 4 Bright - FDTH Q 5 Bright - FDTH R 4 Bright - FDTH S 5 Bright A_NoBlocking - FDTH T 4 Bright - FDTH U 5 Bright - FDTH V 4 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/magecone.txt b/wadsrc/static/actors/hexen/magecone.txt deleted file mode 100644 index 72c37c38c..000000000 --- a/wadsrc/static/actors/hexen/magecone.txt +++ /dev/null @@ -1,89 +0,0 @@ - -// The Mage's Frost Cone ---------------------------------------------------- - -ACTOR MWeapFrost : MageWeapon -{ - +BLOODSPLATTER - Weapon.SelectionOrder 1700 - Weapon.AmmoUse1 3 - Weapon.AmmoGive1 25 - Weapon.KickBack 150 - Weapon.YAdjust 20 - Weapon.AmmoType1 "Mana1" - Inventory.PickupMessage "$TXT_WEAPON_M2" - Obituary "$OB_MPMWEAPFROST" - Tag "$TAG_MWEAPFROST" - - action native A_FireConePL1(); - - States - { - Spawn: - WMCS ABC 8 Bright - Loop - Select: - CONE A 1 A_Raise - Loop - Deselect: - CONE A 1 A_Lower - Loop - Ready: - CONE A 1 A_WeaponReady - Loop - Fire: - CONE B 3 - CONE C 4 - Hold: - CONE D 3 - CONE E 5 - CONE F 3 A_FireConePL1 - CONE G 3 - CONE A 9 - CONE A 10 A_ReFire - Goto Ready - } -} - -// Frost Missile ------------------------------------------------------------ - -ACTOR FrostMissile native -{ - Speed 25 - Radius 13 - Height 8 - Damage 1 - DamageType "Ice" - Projectile - DeathSound "MageShardsExplode" - Obituary "$OB_MPMWEAPFROST" - - action native A_ShedShard(); - - States - { - Spawn: - SHRD A 2 Bright - SHRD A 3 Bright A_ShedShard - SHRD B 3 Bright - SHRD C 3 Bright - Loop - Death: - SHEX ABCDE 5 Bright - Stop - } -} - -// Ice Shard ---------------------------------------------------------------- - -ACTOR IceShard : FrostMissile -{ - DamageType "Ice" - -ACTIVATEIMPACT - -ACTIVATEPCROSS - States - { - Spawn: - SHRD ABC 3 Bright - Loop - } -} diff --git a/wadsrc/static/actors/hexen/magelightning.txt b/wadsrc/static/actors/hexen/magelightning.txt deleted file mode 100644 index d12b7d389..000000000 --- a/wadsrc/static/actors/hexen/magelightning.txt +++ /dev/null @@ -1,154 +0,0 @@ - -// The Mage's Lightning Arc of Death ---------------------------------------- - -ACTOR MWeapLightning : MageWeapon -{ - +NOGRAVITY - Weapon.SelectionOrder 1100 - Weapon.AmmoUse1 5 - Weapon.AmmoGive1 25 - Weapon.KickBack 0 - Weapon.YAdjust 20 - Weapon.AmmoType1 "Mana2" - Inventory.PickupMessage "$TXT_WEAPON_M3" - Tag "$TAG_MWEAPLIGHTNING" - - action native A_LightningReady(); - action native A_MLightningAttack(class floor = "LightningFloor", class ceiling = "LightningCeiling"); - - States - { - Spawn: - WMLG ABCDEFGH 4 Bright - Loop - Select: - MLNG A 1 Bright A_Raise - Loop - Deselect: - MLNG A 1 Bright A_Lower - Loop - Ready: - MLNG AAAAA 1 Bright A_WeaponReady - MLNG A 1 Bright A_LightningReady - MLNG BBBBBB 1 Bright A_WeaponReady - MLNG CCCCC 1 Bright A_WeaponReady - MLNG C 1 Bright A_LightningReady - MLNG BBBBBB 1 Bright A_WeaponReady - Loop - Fire: - MLNG DE 3 Bright - MLNG F 4 Bright A_MLightningAttack - MLNG G 4 Bright - MLNG HI 3 Bright - MLNG I 6 Bright Offset (0, 199) - MLNG C 2 Bright Offset (0, 55) - MLNG B 2 Bright Offset (0, 50) - MLNG B 2 Bright Offset (0, 45) - MLNG B 2 Bright Offset (0, 40) - Goto Ready - } -} - -// Ceiling Lightning -------------------------------------------------------- - -ACTOR Lightning native -{ - MissileType "LightningZap" - AttackSound "MageLightningZap" - ActiveSound "MageLightningContinuous" - Obituary "$OB_MPMWEAPLIGHTNING" -} - -ACTOR LightningCeiling : Lightning -{ - Health 144 - Speed 25 - Radius 16 - Height 40 - Damage 8 - Projectile - +CEILINGHUGGER - RenderStyle Add - - action native A_LightningZap(); - action native A_LightningClip(); - action native A_LightningRemove(); - - States - { - Spawn: - MLFX A 2 Bright A_LightningZap - MLFX BCD 2 Bright A_LightningClip - Loop - Death: - MLF2 A 2 Bright A_LightningRemove - MLF2 BCDEKLM 3 Bright - ACLO E 35 - MLF2 NO 3 Bright - MLF2 P 4 Bright - MLF2 QP 3 Bright - MLF2 Q 4 Bright - MLF2 P 3 Bright - MLF2 O 3 Bright - MLF2 P 3 Bright - MLF2 P 1 Bright A_HideThing - ACLO E 1050 - Stop - } -} - -// Floor Lightning ---------------------------------------------------------- - -ACTOR LightningFloor : LightningCeiling -{ - -CEILINGHUGGER - +FLOORHUGGER - RenderStyle Add - - action native A_LastZap(); - - States - { - Spawn: - MLFX E 2 Bright A_LightningZap - MLFX FGH 2 Bright A_LightningClip - Loop - Death: - MLF2 F 2 Bright A_LightningRemove - MLF2 GHIJKLM 3 Bright - ACLO E 20 - MLF2 NO 3 Bright - MLF2 P 4 Bright - MLF2 QP 3 Bright - MLF2 Q 4 Bright A_LastZap - MLF2 POP 3 Bright - MLF2 P 1 Bright A_HideThing - Goto Super::Death + 19 - } -} - -// Lightning Zap ------------------------------------------------------------ - -ACTOR LightningZap native -{ - Radius 15 - Height 35 - Damage 2 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - RenderStyle Add - Obituary "$OB_MPMWEAPLIGHTNING" - - action native A_ZapMimic(); - - States - { - Spawn: - MLFX IJKLM 2 Bright A_ZapMimic - Loop - Death: - MLFX NOPQRSTU 2 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/mageplayer.txt b/wadsrc/static/actors/hexen/mageplayer.txt deleted file mode 100644 index 9cf4117a5..000000000 --- a/wadsrc/static/actors/hexen/mageplayer.txt +++ /dev/null @@ -1,104 +0,0 @@ -// The mage ----------------------------------------------------------------- - -ACTOR MagePlayer : PlayerPawn -{ - Health 100 - ReactionTime 0 - PainChance 255 - Radius 16 - Height 64 - Speed 1 - +NOSKIN - +NODAMAGETHRUST - +NOTHRUSTWHENINVUL - PainSound "PlayerMagePain" - RadiusDamageFactor 0.25 - Player.JumpZ 9 - Player.Viewheight 48 - Player.SpawnClass "Mage" - Player.DisplayName "Mage" - Player.SoundClass "mage" - Player.ScoreIcon "MAGEFACE" - Player.InvulnerabilityMode "Reflective" - Player.HealRadiusType "Mana" - Player.Hexenarmor 5, 5, 15, 10, 25 - Player.StartItem "MWeapWand" - Player.ForwardMove 0.88, 0.92 - Player.SideMove 0.875, 0.925 - Player.Portrait "P_MWALK1" - Player.WeaponSlot 1, MWeapWand - Player.WeaponSlot 2, MWeapFrost - Player.WeaponSlot 3, MWeapLightning - Player.WeaponSlot 4, MWeapBloodscourge - Player.FlechetteType "ArtiPoisonBag2" - - Player.ColorRange 146, 163 - Player.Colorset 0, "Blue", 146, 163, 161 - Player.ColorsetFile 1, "Red", "TRANTBL7", 0xB3 - Player.ColorsetFile 2, "Gold", "TRANTBL8", 0x8C - Player.ColorsetFile 3, "Dull Green", "TRANTBL9", 0x41 - Player.ColorsetFile 4, "Green", "TRANTBLA", 0xC9 - Player.ColorsetFile 5, "Gray", "TRANTBLB", 0x30 - Player.ColorsetFile 6, "Brown", "TRANTBLC", 0x72 - Player.ColorsetFile 7, "Purple", "TRANTBLD", 0xEE - - States - { - Spawn: - MAGE A -1 - Stop - See: - MAGE ABCD 4 - Loop - Missile: - Melee: - MAGE EF 8 - Goto Spawn - Pain: - MAGE G 4 - MAGE G 4 A_Pain - Goto Spawn - Death: - MAGE H 6 - MAGE I 6 A_PlayerScream - MAGE JK 6 - MAGE L 6 A_NoBlocking - MAGE M 6 - MAGE N -1 - Stop - XDeath: - MAGE O 5 A_PlayerScream - MAGE P 5 - MAGE R 5 A_NoBlocking - MAGE STUVW 5 - MAGE X -1 - Stop - Ice: - MAGE Y 5 A_FreezeDeath - MAGE Y 1 A_FreezeDeathChunks - Wait - Burn: - FDTH E 5 BRIGHT A_PlaySound("*burndeath") - FDTH F 4 BRIGHT - FDTH G 5 BRIGHT - FDTH H 4 BRIGHT A_PlayerScream - FDTH I 5 BRIGHT - FDTH J 4 BRIGHT - FDTH K 5 BRIGHT - FDTH L 4 BRIGHT - FDTH M 5 BRIGHT - FDTH N 4 BRIGHT - FDTH O 5 BRIGHT - FDTH P 4 BRIGHT - FDTH Q 5 BRIGHT - FDTH R 4 BRIGHT - FDTH S 5 BRIGHT A_NoBlocking - FDTH T 4 BRIGHT - FDTH U 5 BRIGHT - FDTH V 4 BRIGHT - ACLO E 35 A_CheckPlayerDone - Wait - ACLO E 8 - Stop - } -} diff --git a/wadsrc/static/actors/hexen/magestaff.txt b/wadsrc/static/actors/hexen/magestaff.txt deleted file mode 100644 index 381588ce5..000000000 --- a/wadsrc/static/actors/hexen/magestaff.txt +++ /dev/null @@ -1,142 +0,0 @@ - -// Mage Weapon Piece -------------------------------------------------------- - -ACTOR MageWeaponPiece : WeaponPiece -{ - Inventory.PickupSound "misc/w_pkup" - Inventory.PickupMessage "$TXT_BLOODSCOURGE_PIECE" - Inventory.ForbiddenTo FighterPlayer, ClericPlayer - WeaponPiece.Weapon MWeapBloodscourge - +FLOATBOB -} - -// Mage Weapon Piece 1 ------------------------------------------------------ - -ACTOR MWeaponPiece1 : MageWeaponPiece -{ - WeaponPiece.Number 1 - States - { - Spawn: - WMS1 A -1 Bright - Stop - } -} - -// Mage Weapon Piece 2 ------------------------------------------------------ - -ACTOR MWeaponPiece2 : MageWeaponPiece -{ - WeaponPiece.Number 2 - States - { - Spawn: - WMS2 A -1 Bright - Stop - } -} - -// Mage Weapon Piece 3 ------------------------------------------------------ - -ACTOR MWeaponPiece3 : MageWeaponPiece -{ - WeaponPiece.Number 3 - States - { - Spawn: - WMS3 A -1 Bright - Stop - } -} - -// Bloodscourge Drop -------------------------------------------------------- - -ACTOR BloodscourgeDrop -{ - States - { - Spawn: - TNT1 A 1 - TNT1 A 1 A_DropWeaponPieces("MWeaponPiece1", "MWeaponPiece2", "MWeaponPiece3") - Stop - } -} - -// The Mages's Staff (Bloodscourge) ----------------------------------------- - -ACTOR MWeapBloodscourge : MageWeapon native -{ - Health 3 - Weapon.SelectionOrder 3100 - Weapon.AmmoUse1 15 - Weapon.AmmoUse2 15 - Weapon.AmmoGive1 20 - Weapon.AmmoGive2 20 - Weapon.KickBack 150 - Weapon.YAdjust 20 - Weapon.AmmoType1 "Mana1" - Weapon.AmmoType2 "Mana2" - +WEAPON.PRIMARY_USES_BOTH - +Inventory.NoAttenPickupSound - Inventory.PickupMessage "$TXT_WEAPON_M4" - Inventory.PickupSound "WeaponBuild" - Tag "$TAG_MWEAPBLOODSCOURGE" - - action native A_MStaffAttack(); - action native A_MStaffPalette(); - - States - { - Spawn: - TNT1 A -1 - Stop - Select: - MSTF A 1 A_Raise - Loop - Deselect: - MSTF A 1 A_Lower - Loop - Ready: - MSTF AAAAAABBBBBBCCCCCCDDDDDDEEEEEEFFFFF 1 A_WeaponReady - Loop - Fire: - MSTF G 4 Offset (0, 40) - MSTF H 4 Bright Offset (0, 48) A_MStaffAttack - MSTF H 2 Bright Offset (0, 48) A_MStaffPalette - MSTF II 2 Offset (0, 48) A_MStaffPalette - MSTF I 1 Offset (0, 40) - MSTF J 5 Offset (0, 36) - Goto Ready - } -} - -// Mage Staff FX2 (Bloodscourge) -------------------------------------------- - -ACTOR MageStaffFX2 native -{ - Speed 17 - Height 8 - Damage 4 - DamageType "Fire" - Projectile - +SEEKERMISSILE - +SCREENSEEKER - +EXTREMEDEATH - DeathSound "MageStaffExplode" - Obituary "$OB_MPMWEAPBLOODSCOURGE" - - action native A_MStaffTrack(); - - States - { - Spawn: - MSP2 ABCD 2 Bright A_MStaffTrack - Loop - Death: - MSP2 E 4 Bright A_SetTranslucent(1,1) - MSP2 F 5 Bright A_Explode (80, 192, 0) - MSP2 GH 5 Bright - MSP2 I 4 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/magewand.txt b/wadsrc/static/actors/hexen/magewand.txt deleted file mode 100644 index e9a1f339b..000000000 --- a/wadsrc/static/actors/hexen/magewand.txt +++ /dev/null @@ -1,73 +0,0 @@ - -// The Mage's Wand ---------------------------------------------------------- - -ACTOR MWeapWand : MageWeapon -{ - Weapon.SelectionOrder 3600 - Weapon.KickBack 0 - Weapon.YAdjust 9 - Tag "$TAG_MWEAPWAND" - - States - { - Select: - MWND A 1 A_Raise - Loop - Deselect: - MWND A 1 A_Lower - Loop - Ready: - MWND A 1 A_WeaponReady - Loop - Fire: - MWND A 6 - MWND B 6 Bright Offset (0, 48) A_FireCustomMissile ("MageWandMissile") - MWND A 3 Offset (0, 40) - MWND A 3 Offset (0, 36) A_ReFire - Goto Ready - } -} - -// Wand Smoke --------------------------------------------------------------- - -ACTOR MageWandSmoke -{ - +NOBLOCKMAP +NOGRAVITY +SHADOW - +NOTELEPORT +CANNOTPUSH +NODAMAGETHRUST - RenderStyle Translucent - Alpha 0.6 - States - { - Spawn: - MWND CDCD 4 - Stop - } -} - -// Wand Missile ------------------------------------------------------------- - -ACTOR MageWandMissile : FastProjectile -{ - Speed 184 - Radius 12 - Height 8 - Damage 2 - +RIPPER +CANNOTPUSH +NODAMAGETHRUST - +SPAWNSOUNDSOURCE - MissileType "MageWandSmoke" - SeeSound "MageWandFire" - Obituary "$OB_MPMWEAPWAND" - States - { - Spawn: - MWND CD 4 Bright - Loop - Death: - MWND E 4 Bright - MWND F 3 Bright - MWND G 4 Bright - MWND H 3 Bright - MWND I 4 Bright - Stop - } -} diff --git a/wadsrc/static/actors/hexen/mana.txt b/wadsrc/static/actors/hexen/mana.txt deleted file mode 100644 index 4a50e368a..000000000 --- a/wadsrc/static/actors/hexen/mana.txt +++ /dev/null @@ -1,87 +0,0 @@ -// Blue mana ---------------------------------------------------------------- - -ACTOR Mana1 : Ammo -{ - Inventory.Amount 15 - Inventory.MaxAmount 200 - Ammo.BackpackAmount 15 - Ammo.BackpackMaxAmount 200 - Radius 8 - Height 8 - +FLOATBOB - Inventory.Icon "MAN1I0" - Inventory.PickupMessage "$TXT_MANA_1" - States - { - Spawn: - MAN1 ABCDEFGHI 4 Bright - Loop - } -} - -// Green mana --------------------------------------------------------------- - -ACTOR Mana2 : Ammo -{ - Inventory.Amount 15 - Inventory.MaxAmount 200 - Ammo.BackpackAmount 15 - Ammo.BackpackMaxAmount 200 - Radius 8 - Height 8 - +FLOATBOB - Inventory.Icon "MAN2G0" - Inventory.PickupMessage "$TXT_MANA_2" - States - { - Spawn: - MAN2 ABCDEFGHIJKLMNOP 4 Bright - Loop - } -} - -// Combined mana ------------------------------------------------------------ - -ACTOR Mana3 : CustomInventory -{ - Radius 8 - Height 8 - +FLOATBOB - Inventory.PickupMessage "$TXT_MANA_BOTH" - States - { - Spawn: - MAN3 ABCDEFGHIJKLMNOP 4 Bright - Loop - Pickup: - TNT1 A 0 A_GiveInventory("Mana1", 20) - TNT1 A 0 A_GiveInventory("Mana2", 20) - Stop - } -} - -// Boost Mana Artifact Krater of Might ------------------------------------ - -ACTOR ArtiBoostMana : CustomInventory -{ - +FLOATBOB - +COUNTITEM - +INVENTORY.INVBAR - +INVENTORY.PICKUPFLASH - +INVENTORY.FANCYPICKUPSOUND - Inventory.DefMaxAmount - Inventory.Icon "ARTIBMAN" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIBOOSTMANA" - Tag "$TAG_ARTIBOOSTMANA" - States - { - Spawn: - BMAN A -1 - Stop - Use: - TNT1 A 0 A_GiveInventory("Mana1", 200) - TNT1 A 0 A_GiveInventory("Mana2", 200) - Stop - } -} diff --git a/wadsrc/static/actors/hexen/pig.txt b/wadsrc/static/actors/hexen/pig.txt deleted file mode 100644 index 9d986e7eb..000000000 --- a/wadsrc/static/actors/hexen/pig.txt +++ /dev/null @@ -1,155 +0,0 @@ - - -// Snout puff --------------------------------------------------------------- - -ACTOR SnoutPuff -{ - +NOBLOCKMAP - +NOGRAVITY - Renderstyle Translucent - Alpha 0.6 - States - { - Spawn: - FHFX STUVW 4 - Stop - } -} - - -// Snout -------------------------------------------------------------------- - -ACTOR Snout : Weapon -{ - Weapon.SelectionOrder 10000 - +WEAPON.DONTBOB - +WEAPON.MELEEWEAPON - Weapon.Kickback 150 - Weapon.YAdjust 10 - - action native A_SnoutAttack (); - - States - { - Ready: - WPIG A 1 A_WeaponReady - Loop - Deselect: - WPIG A 1 A_Lower - Loop - Select: - WPIG A 1 A_Raise - Fire: - WPIG A 4 A_SnoutAttack - WPIG B 8 A_SnoutAttack - Goto Ready - Grunt: - WPIG B 8 - Goto Ready - } -} - - -// Pig player --------------------------------------------------------------- - -ACTOR PigPlayer : PlayerPawn native -{ - Health 30 - ReactionTime 0 - PainChance 255 - Radius 16 - Height 24 - Speed 1 - +WINDTHRUST - +NOSKIN - -PICKUP - PainSound "PigPain" - DeathSound "PigDeath" - Player.JumpZ 6 - Player.Viewheight 28 - Player.ForwardMove 0.96, 0.98 - Player.SideMove 0.95833333, 0.975 - Player.SpawnClass "Pig" - Player.SoundClass "Pig" - Player.DisplayName "Pig" - Player.MorphWeapon "Snout" - States - { - Spawn: - PIGY A -1 - Stop - See: - PIGY ABCD 3 - Loop - Pain: - PIGY D 4 A_PigPain - Goto Spawn - Melee: - Missile: - PIGY A 12 - Goto Spawn - Death: - PIGY E 4 A_Scream - PIGY F 3 A_NoBlocking - PIGY G 4 - PIGY H 3 - PIGY IJK 4 - PIGY L -1 - Stop - Ice: - PIGY M 5 A_FreezeDeath - PIGY M 1 A_FreezeDeathChunks - Wait - } -} - - - -// Pig (non-player) --------------------------------------------------------- - -ACTOR Pig : MorphedMonster -{ - Health 25 - Painchance 128 - Speed 10 - Radius 12 - Height 22 - Mass 60 - Monster - -COUNTKILL - +WINDTHRUST - +DONTMORPH - SeeSound "PigActive1" - PainSound "PigPain" - DeathSound "PigDeath" - ActiveSound "PigActive1" - States - { - Spawn: - PIGY B 10 A_Look - Loop - See: - PIGY ABCD 3 A_Chase - Loop - Pain: - PIGY D 4 A_PigPain - Goto See - Melee: - PIGY A 5 A_FaceTarget - PIGY A 10 A_CustomMeleeAttack(random[PigAttack](2,3), "PigAttack") - Goto See - Death: - PIGY E 4 A_Scream - PIGY F 3 A_NoBlocking - PIGY G 4 A_QueueCorpse - PIGY H 3 - PIGY IJK 4 - PIGY L -1 - Stop - Ice: - PIGY M 5 A_FreezeDeath - PIGY M 1 A_FreezeDeathChunks - Wait - } -} - diff --git a/wadsrc/static/actors/hexen/puzzleitems.txt b/wadsrc/static/actors/hexen/puzzleitems.txt deleted file mode 100644 index ad1187da0..000000000 --- a/wadsrc/static/actors/hexen/puzzleitems.txt +++ /dev/null @@ -1,287 +0,0 @@ - -// Yorick's Skull ----------------------------------------------------------- - -ACTOR PuzzSkull : PuzzleItem -{ - PuzzleItem.Number 0 - Inventory.Icon ARTISKLL - Inventory.PickupMessage "$TXT_ARTIPUZZSKULL" - Tag "$TAG_ARTIPUZZSKULL" - States - { - Spawn: - ASKU A -1 - Stop - } -} - - -// Heart of D'Sparil -------------------------------------------------------- - -ACTOR PuzzGemBig : PuzzleItem -{ - PuzzleItem.Number 1 - Inventory.Icon ARTIBGEM - Inventory.PickupMessage "$TXT_ARTIPUZZGEMBIG" - Tag "$TAG_ARTIPUZZGEMBIG" - States - { - Spawn: - ABGM A -1 - Stop - } -} - -// Red Gem (Ruby Planet) ---------------------------------------------------- - -ACTOR PuzzGemRed : PuzzleItem -{ - PuzzleItem.Number 2 - Inventory.Icon ARTIGEMR - Inventory.PickupMessage "$TXT_ARTIPUZZGEMRED" - Tag "$TAG_ARTIPUZZGEMRED" - States - { - Spawn: - AGMR A -1 - Stop - } -} - - -// Green Gem 1 (Emerald Planet) --------------------------------------------- - -ACTOR PuzzGemGreen1 : PuzzleItem -{ - PuzzleItem.Number 3 - Inventory.Icon ARTIGEMG - Inventory.PickupMessage "$TXT_ARTIPUZZGEMGREEN1" - Tag "$TAG_ARTIPUZZGEMGREEN1" - States - { - Spawn: - AGMG A -1 - Stop - } -} - - -// Green Gem 2 (Emerald Planet) --------------------------------------------- - -ACTOR PuzzGemGreen2 : PuzzleItem -{ - PuzzleItem.Number 4 - Inventory.Icon ARTIGMG2 - Inventory.PickupMessage "$TXT_ARTIPUZZGEMGREEN2" - Tag "$TAG_ARTIPUZZGEMGREEN2" - States - { - Spawn: - AGG2 A -1 - Stop - } -} - - -// Blue Gem 1 (Sapphire Planet) --------------------------------------------- - -ACTOR PuzzGemBlue1 : PuzzleItem -{ - PuzzleItem.Number 5 - Inventory.Icon ARTIGEMB - Inventory.PickupMessage "$TXT_ARTIPUZZGEMBLUE1" - Tag "$TAG_ARTIPUZZGEMBLUE1" - States - { - Spawn: - AGMB A -1 - Stop - } -} - - -// Blue Gem 2 (Sapphire Planet) --------------------------------------------- - -ACTOR PuzzGemBlue2 : PuzzleItem -{ - PuzzleItem.Number 6 - Inventory.Icon ARTIGMB2 - Inventory.PickupMessage "$TXT_ARTIPUZZGEMBLUE2" - Tag "$TAG_ARTIPUZZGEMBLUE2" - States - { - Spawn: - AGB2 A -1 - Stop - } -} - - -// Book 1 (Daemon Codex) ---------------------------------------------------- - -ACTOR PuzzBook1 : PuzzleItem -{ - PuzzleItem.Number 7 - Inventory.Icon ARTIBOK1 - Inventory.PickupMessage "$TXT_ARTIPUZZBOOK1" - Tag "$TAG_ARTIPUZZBOOK1" - States - { - Spawn: - ABK1 A -1 - Stop - } -} - - -// Book 2 (Liber Oscura) ---------------------------------------------------- - -ACTOR PuzzBook2 : PuzzleItem -{ - PuzzleItem.Number 8 - Inventory.Icon ARTIBOK2 - Inventory.PickupMessage "$TXT_ARTIPUZZBOOK2" - Tag "$TAG_ARTIPUZZBOOK2" - States - { - Spawn: - ABK2 A -1 - Stop - } -} - - -// Flame Mask --------------------------------------------------------------- - - -ACTOR PuzzFlameMask : PuzzleItem -{ - PuzzleItem.Number 9 - Inventory.Icon ARTISKL2 - Inventory.PickupMessage "$TXT_ARTIPUZZSKULL2" - Tag "$TAG_ARTIPUZZSKULL2" - States - { - Spawn: - ASK2 A -1 - Stop - } -} - -// Fighter Weapon (Glaive Seal) --------------------------------------------- - -ACTOR PuzzFWeapon : PuzzleItem -{ - PuzzleItem.Number 10 - Inventory.Icon ARTIFWEP - Inventory.PickupMessage "$TXT_ARTIPUZZFWEAPON" - Tag "$TAG_ARTIPUZZFWEAPON" - States - { - Spawn: - AFWP A -1 - Stop - } -} - - -// Cleric Weapon (Holy Relic) ----------------------------------------------- - -ACTOR PuzzCWeapon : PuzzleItem -{ - PuzzleItem.Number 11 - Inventory.Icon ARTICWEP - Inventory.PickupMessage "$TXT_ARTIPUZZCWEAPON" - Tag "$TAG_ARTIPUZZCWEAPON" - States - { - Spawn: - ACWP A -1 - Stop - } -} - - -// Mage Weapon (Sigil of the Magus) ----------------------------------------- - -ACTOR PuzzMWeapon : PuzzleItem -{ - PuzzleItem.Number 12 - Inventory.Icon ARTIMWEP - Inventory.PickupMessage "$TXT_ARTIPUZZMWEAPON" - Tag "$TAG_ARTIPUZZMWEAPON" - States - { - Spawn: - AMWP A -1 - Stop - } -} - -// Clock Gear 1 ------------------------------------------------------------- - -ACTOR PuzzGear1 : PuzzleItem -{ - PuzzleItem.Number 13 - Inventory.Icon ARTIGEAR - Inventory.PickupMessage "$TXT_ARTIPUZZGEAR" - Tag "$TAG_ARTIPUZZGEAR1" - States - { - Spawn: - AGER ABCDEFGH 4 Bright - Loop - } -} - - -// Clock Gear 2 ------------------------------------------------------------- - -ACTOR PuzzGear2 : PuzzleItem -{ - PuzzleItem.Number 14 - Inventory.Icon ARTIGER2 - Inventory.PickupMessage "$TXT_ARTIPUZZGEAR" - Tag "$TAG_ARTIPUZZGEAR2" - States - { - Spawn: - AGR2 ABCDEFGH 4 Bright - Loop - } -} - - -// Clock Gear 3 ------------------------------------------------------------- - -ACTOR PuzzGear3 : PuzzleItem -{ - PuzzleItem.Number 15 - Inventory.Icon ARTIGER3 - Inventory.PickupMessage "$TXT_ARTIPUZZGEAR" - Tag "$TAG_ARTIPUZZGEAR3" - States - { - Spawn: - AGR3 ABCDEFGH 4 Bright - Loop - } -} - - -// Clock Gear 4 ------------------------------------------------------------- - -ACTOR PuzzGear4 : PuzzleItem -{ - PuzzleItem.Number 16 - Inventory.Icon ARTIGER4 - Inventory.PickupMessage "$TXT_ARTIPUZZGEAR" - Tag "$TAG_ARTIPUZZGEAR4" - States - { - Spawn: - AGR4 ABCDEFGH 4 Bright - Loop - } -} - diff --git a/wadsrc/static/actors/hexen/scriptprojectiles.txt b/wadsrc/static/actors/hexen/scriptprojectiles.txt deleted file mode 100644 index d031be3ee..000000000 --- a/wadsrc/static/actors/hexen/scriptprojectiles.txt +++ /dev/null @@ -1,123 +0,0 @@ -// Fire Ball ---------------------------------------------------------------- - -ACTOR FireBall -{ - Speed 2 - Radius 8 - Height 8 - Damage 4 - DamageType Fire - +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE - +NOTELEPORT - RenderStyle Add - DeathSound "Fireball" - States - { - Spawn: - FBL1 AB 4 Bright - Loop - Death: - XPL1 ABCDEF 4 Bright - Stop - } -} - -// Arrow -------------------------------------------------------------------- - -ACTOR Arrow -{ - Speed 6 - Radius 8 - Height 4 - Damage 4 - +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE - +NOTELEPORT - States - { - Spawn: - ARRW A -1 - Stop - Death: - ARRW A 1 - Stop - } -} - -// Dart --------------------------------------------------------------------- - -ACTOR Dart -{ - Speed 6 - Radius 8 - Height 4 - Damage 2 - +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE - +NOTELEPORT - States - { - Spawn: - DART A -1 - Stop - Death: - DART A 1 - Stop - } -} - -// Poison Dart -------------------------------------------------------------- - -ACTOR PoisonDart : Dart -{ - PoisonDamage 20 -} - -// Ripper Ball -------------------------------------------------------------- - -ACTOR RipperBall -{ - Speed 6 - Radius 8 - Damage 2 - +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE - +NOTELEPORT +RIPPER - States - { - Spawn: - RIPP ABC 3 - Loop - Death: - CFCF Q 4 Bright - CFCF R 3 Bright - CFCF S 4 Bright - CFCF T 3 Bright - CFCF U 4 Bright - CFCF V 3 Bright - CFCF W 4 Bright - CFCF X 3 Bright - CFCF Y 4 Bright - CFCF Z 3 Bright - Stop - } -} - -// Projectile Blade --------------------------------------------------------- - -ACTOR ProjectileBlade -{ - Speed 6 - Radius 6 - Height 6 - Damage 3 - +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE - +NOTELEPORT - States - { - Spawn: - BLAD A -1 - Stop - Death: - BLAD A 1 - Stop - } -} - diff --git a/wadsrc/static/actors/hexen/serpent.txt b/wadsrc/static/actors/hexen/serpent.txt deleted file mode 100644 index 50d81bf8a..000000000 --- a/wadsrc/static/actors/hexen/serpent.txt +++ /dev/null @@ -1,224 +0,0 @@ - -// Serpent ------------------------------------------------------------------ - -ACTOR Serpent -{ - Health 90 - PainChance 96 - Speed 12 - Radius 32 - Height 70 - Mass 0x7fffffff - Monster - -SHOOTABLE - +NOBLOOD - +CANTLEAVEFLOORPIC +NONSHOOTABLE - +STAYMORPHED +DONTBLAST +NOTELEOTHER - +INVISIBLE - SeeSound "SerpentSight" - AttackSound "SerpentAttack" - PainSound "SerpentPain" - DeathSound "SerpentDeath" - HitObituary "$OB_SERPENTHIT" - - action native A_SerpentHumpDecide(); - action native A_SerpentHide(); - action native A_SerpentCheckForAttack(); - action native A_SerpentSpawnGibs(); - action native A_SerpentUnHide(); - action native A_SerpentRaiseHump(); - action native A_SerpentLowerHump(); - action native A_SerpentChooseAttack(); - action native A_SerpentMeleeAttack(); - - States - { - Spawn: - SSPT H 10 A_Look - Loop - See: - SSPT HH 1 A_Chase("Melee", "None", CHF_NIGHTMAREFAST|CHF_NOPLAYACTIVE) - SSPT H 2 A_SerpentHumpDecide - Loop - Pain: - SSPT L 5 - SSPT L 5 A_Pain - Dive: - SSDV ABC 4 - SSDV D 4 A_UnSetShootable - SSDV E 3 A_PlaySoundEx("SerpentActive", "Body") - SSDV F 3 - SSDV GH 4 - SSDV I 3 - SSDV J 3 A_SerpentHide - Goto See - Melee: - SSPT A 1 A_UnHideThing - SSPT A 1 A_PlaySoundEx("SerpentBirth", "Voice") - SSPT B 3 A_SetShootable - SSPT C 3 - SSPT D 4 A_SerpentCheckForAttack - Goto Dive - Death: - SSPT O 4 - SSPT P 4 A_Scream - SSPT Q 4 A_NoBlocking - SSPT RSTUVWXYZ 4 - Stop - XDeath: - SSXD A 4 - SSXD B 4 A_SpawnItemEx("SerpentHead", 0, 0, 45) - SSXD C 4 A_NoBlocking - SSXD DE 4 - SSXD FG 3 - SSXD H 3 A_SerpentSpawnGibs - Stop - Ice: - SSPT [ 5 A_FreezeDeath - SSPT [ 1 A_FreezeDeathChunks - Wait - Walk: - SSPT IJI 5 A_Chase("Attack", "None", CHF_NIGHTMAREFAST) - SSPT J 5 A_SerpentCheckForAttack - Goto Dive - Hump: - SSPT H 3 A_SerpentUnHide - SSPT EFGEF 3 A_SerpentRaiseHump - SSPT GEF 3 - SSPT GEFGE 3 A_SerpentLowerHump - SSPT F 3 A_SerpentHide - Goto See - Attack: - SSPT K 6 A_FaceTarget - SSPT L 5 A_SerpentChooseAttack - Goto MeleeAttack - MeleeAttack: - SSPT N 5 A_SerpentMeleeAttack - Goto Dive - } -} - -// Serpent Leader ----------------------------------------------------------- - -ACTOR SerpentLeader : Serpent -{ - Mass 200 - Obituary "$OB_SERPENT" - States - { - Missile: - SSPT N 5 A_CustomMissile("SerpentFX", 32, 0) - Goto Dive - } -} - -// Serpent Missile Ball ----------------------------------------------------- - -ACTOR SerpentFX -{ - Speed 15 - Radius 8 - Height 10 - Damage 4 - Projectile - -ACTIVATEIMPACT -ACTIVATEPCROSS - RenderStyle Add - DeathSound "SerpentFXHit" - - States - { - Spawn: - SSFX A 0 - SSFX A 3 Bright A_PlaySoundEx("SerpentFXContinuous", "Body", 1) - SSFX BAB 3 Bright - Goto Spawn+1 - Death: - SSFX C 4 Bright A_StopSoundEx("Body") - SSFX DEFGH 4 Bright - Stop - } -} - -// Serpent Head ------------------------------------------------------------- - -ACTOR SerpentHead -{ - Radius 5 - Height 10 - Gravity 0.125 - +NOBLOCKMAP - - action native A_SerpentHeadCheck(); - - States - { - Spawn: - SSXD IJKLMNOP 4 A_SerpentHeadCheck - Loop - Death: - SSXD S -1 - Loop - } -} - -// Serpent Gib 1 ------------------------------------------------------------ - -ACTOR SerpentGib1 -{ - Radius 3 - Height 3 - +NOBLOCKMAP +NOGRAVITY - - action native A_FloatGib(); - action native A_DelayGib(); - action native A_SinkGib(); - - States - { - Spawn: - SSXD Q 6 - SSXD Q 6 A_FloatGib - SSXD QQ 8 A_FloatGib - SSXD QQ 12 A_FloatGib - SSXD Q 232 A_DelayGib - SSXD QQ 12 A_SinkGib - SSXD QQQ 8 A_SinkGib - Stop - } -} - -// Serpent Gib 2 ------------------------------------------------------------ - -ACTOR SerpentGib2 : SerpentGib1 -{ - States - { - Spawn: - SSXD R 6 - SSXD R 6 A_FloatGib - SSXD RR 8 A_FloatGib - SSXD RR 12 A_FloatGib - SSXD R 232 A_DelayGib - SSXD RR 12 A_SinkGib - SSXD RRR 8 A_SinkGib - Stop - } -} - -// Serpent Gib 3 ------------------------------------------------------------ - -ACTOR SerpentGib3 : SerpentGib1 -{ - States - { - Spawn: - SSXD T 6 - SSXD T 6 A_FloatGib - SSXD TT 8 A_FloatGib - SSXD TT 12 A_FloatGib - SSXD T 232 A_DelayGib - SSXD TT 12 A_SinkGib - SSXD TTT 8 A_SinkGib - Stop - } -} diff --git a/wadsrc/static/actors/hexen/speedboots.txt b/wadsrc/static/actors/hexen/speedboots.txt deleted file mode 100644 index 2ae4dcd01..000000000 --- a/wadsrc/static/actors/hexen/speedboots.txt +++ /dev/null @@ -1,18 +0,0 @@ - - -ACTOR ArtiSpeedBoots : PowerupGiver -{ - +FLOATBOB - +COUNTITEM - +INVENTORY.PICKUPFLASH - Inventory.Icon ARTISPED - Inventory.PickupMessage "$TXT_ARTISPEED" - Tag "$TAG_ARTISPEED" - Powerup.Type Speed - States - { - Spawn: - SPED ABCDEFGH 3 Bright - Loop - } -} diff --git a/wadsrc/static/actors/hexen/spike.txt b/wadsrc/static/actors/hexen/spike.txt deleted file mode 100644 index eaadfe012..000000000 --- a/wadsrc/static/actors/hexen/spike.txt +++ /dev/null @@ -1,104 +0,0 @@ - -// Dirt clump (spawned by spike) -------------------------------------------- - -ACTOR DirtClump -{ - +NOBLOCKMAP - +NOTELEPORT - States - { - Spawn: - TSPK C 20 - Loop - } -} - -// Spike (thrust floor) ----------------------------------------------------- - -ACTOR ThrustFloor native -{ - Radius 20 - Height 128 - - action native A_ThrustRaise(); - action native A_ThrustImpale(); - action native A_ThrustLower(); - action native A_ThrustInitDn(); - action native A_ThrustInitUp(); - - States - { - ThrustRaising: - TSPK A 2 A_ThrustRaise - Loop - BloodThrustRaising: - TSPK B 2 A_ThrustRaise - Loop - ThrustLower: - TSPK A 2 A_ThrustLower - Loop - BloodThrustLower: - TSPK B 2 A_ThrustLower - Loop - ThrustInit1: - TSPK A 3 - TSPK A 4 A_ThrustInitDn - TSPK A -1 - Loop - BloodThrustInit1: - TSPK B 3 - TSPK B 4 A_ThrustInitDn - TSPK B -1 - Loop - ThrustInit2: - TSPK A 3 - TSPK A 4 A_ThrustInitUp - TSPK A 10 - Loop - BloodThrustInit2: - TSPK B 3 - TSPK B 4 A_ThrustInitUp - TSPK B 10 - Loop - ThrustRaise: - TSPK A 8 A_ThrustRaise - TSPK A 6 A_ThrustRaise - TSPK A 4 A_ThrustRaise - TSPK A 3 A_SetSolid - TSPK A 2 A_ThrustImpale - Loop - BloodThrustRaise: - TSPK B 8 A_ThrustRaise - TSPK B 6 A_ThrustRaise - TSPK B 4 A_ThrustRaise - TSPK B 3 A_SetSolid - TSPK B 2 A_ThrustImpale - Loop - } -} - -// Spike up ----------------------------------------------------------------- - -ACTOR ThrustFloorUp : ThrustFloor -{ - +SOLID - +NOTELEPORT +FLOORCLIP - States - { - Spawn: - Goto ThrustInit2 - } -} - -// Spike down --------------------------------------------------------------- - -ACTOR ThrustFloorDown : ThrustFloor -{ - +NOTELEPORT +FLOORCLIP - +INVISIBLE - States - { - Spawn: - Goto ThrustInit1 - } -} diff --git a/wadsrc/static/actors/hexen/summon.txt b/wadsrc/static/actors/hexen/summon.txt deleted file mode 100644 index 7a2971562..000000000 --- a/wadsrc/static/actors/hexen/summon.txt +++ /dev/null @@ -1,61 +0,0 @@ - -// Dark Servant Artifact ---------------------------------------------------- - -ACTOR ArtiDarkServant : Inventory native -{ - +COUNTITEM - +FLOATBOB - Inventory.RespawnTics 4230 - Inventory.DefMaxAmount - Inventory.PickupFlash "PickupFlash" - +INVBAR +FANCYPICKUPSOUND - Inventory.Icon "ARTISUMN" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTISUMMON" - Tag "$TAG_ARTISUMMON" - States - { - Spawn: - SUMN A 350 - Loop - } -} - -// Summoning Doll ----------------------------------------------------------- - -ACTOR SummoningDoll -{ - Speed 20 - +NOBLOCKMAP +DROPOFF +MISSILE - +NOTELEPORT - - action native A_Summon(); - - States - { - Spawn: - SUMN A 4 - Loop - Death: - SUMN AA 4 - SUMN A 4 A_Summon - Stop - } -} - -// Minotaur Smoke ----------------------------------------------------------- - -ACTOR MinotaurSmoke -{ - +NOBLOCKMAP +NOGRAVITY - +NOTELEPORT - RenderStyle Translucent - Alpha 0.6 - - States - { - Spawn: - MNSM ABCDEFGHIJKLMNOPQ 3 - Stop - } -} diff --git a/wadsrc/static/actors/hexen/teleportother.txt b/wadsrc/static/actors/hexen/teleportother.txt deleted file mode 100644 index 7ef86636d..000000000 --- a/wadsrc/static/actors/hexen/teleportother.txt +++ /dev/null @@ -1,112 +0,0 @@ - -// Teleport Other Artifact -------------------------------------------------- - -ACTOR ArtiTeleportOther : Inventory native -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.INVBAR - +INVENTORY.PICKUPFLASH - +INVENTORY.FANCYPICKUPSOUND - Inventory.DefMaxAmount - Inventory.Icon "ARTITELO" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTITELEPORTOTHER" - Tag "$TAG_ARTITELEPORTOTHER" - States - { - Spawn: - TELO ABCD 5 - Loop - } -} - - -// Teleport Other FX -------------------------------------------------------- - -ACTOR TelOtherFX1 native -{ - Damage 10001 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - +BLOODLESSIMPACT - Radius 16 - Height 16 - Speed 20 - - action native A_TeloSpawnA (); - action native A_TeloSpawnB (); - action native A_TeloSpawnC (); - action native A_TeloSpawnD (); - action native A_CheckTeleRing (); - - States - { - Spawn: - TRNG E 5 Bright - TRNG D 4 Bright - TRNG C 3 Bright A_TeloSpawnC - TRNG B 3 Bright A_TeloSpawnB - TRNG A 3 Bright A_TeloSpawnA - TRNG B 3 Bright A_TeloSpawnB - TRNG C 3 Bright A_TeloSpawnC - TRNG D 3 Bright A_TeloSpawnD - Goto Spawn+2 - Death: - TRNG E 3 Bright - Stop - } -} - - -ACTOR TelOtherFX2 : TelOtherFX1 -{ - Speed 16 - States - { - Spawn: - TRNG BCDCB 4 Bright - TRNG A 4 Bright A_CheckTeleRing - Loop - } -} - -ACTOR TelOtherFX3 : TelOtherFX1 -{ - Speed 16 - States - { - Spawn: - TRNG CDCBA 4 Bright - TRNG B 4 Bright A_CheckTeleRing - Loop - } -} - -ACTOR TelOtherFX4 : TelOtherFX1 -{ - Speed 16 - States - { - Spawn: - TRNG DCBAB 4 Bright - TRNG C 4 Bright A_CheckTeleRing - Loop - } - -} - -ACTOR TelOtherFX5 : TelOtherFX1 -{ - Speed 16 - States - { - Spawn: - TRNG CBABC 4 Bright - TRNG D 4 Bright A_CheckTeleRing - Loop - } -} - - diff --git a/wadsrc/static/actors/hexen/wraith.txt b/wadsrc/static/actors/hexen/wraith.txt deleted file mode 100644 index 8d25bc74a..000000000 --- a/wadsrc/static/actors/hexen/wraith.txt +++ /dev/null @@ -1,218 +0,0 @@ - -// Wraith ------------------------------------------------------------------- - -ACTOR Wraith -{ - Health 150 - PainChance 25 - Speed 11 - Height 55 - Mass 75 - Damage 10 - Monster - +NOGRAVITY +DROPOFF +FLOAT - +FLOORCLIP +TELESTOMP - SeeSound "WraithSight" - AttackSound "WraithAttack" - PainSound "WraithPain" - DeathSound "WraithDeath" - ActiveSound "WraithActive" - HitObituary "$OB_WRAITHHIT" - Obituary "$OB_WRAITH" - - action native A_WraithInit(); - action native A_WraithChase(); - action native A_WraithFX3(); - action native A_WraithMelee(); - - States - { - Spawn: - WRTH A 10 - WRTH B 5 A_WraithInit - Goto Look - Look: - WRTH AB 15 A_Look - Loop - See: - WRTH ABCD 4 A_WraithChase - Loop - Pain: - WRTH A 2 - WRTH H 6 A_Pain - Goto See - Melee: - WRTH E 6 A_FaceTarget - WRTH F 6 A_WraithFX3 - WRTH G 6 A_WraithMelee - Goto See - Missile: - WRTH E 6 A_FaceTarget - WRTH F 6 - WRTH G 6 A_CustomMissile("WraithFX1", 32, 0) - Goto See - Death: - WRTH I 4 - WRTH J 4 A_Scream - WRTH KL 4 - WRTH M 4 A_NoBlocking - WRTH N 4 A_QueueCorpse - WRTH O 4 - WRTH PQ 5 - WRTH R -1 - Stop - XDeath: - WRT2 A 5 - WRT2 B 5 A_Scream - WRT2 CD 5 - WRT2 E 5 A_NoBlocking - WRT2 F 5 A_QueueCorpse - WRT2 G 5 - WRT2 H -1 - Stop - Ice: - WRT2 I 5 A_FreezeDeath - WRT2 I 1 A_FreezeDeathChunks - Wait - } -} - -// Buried wraith ------------------------------------------------------------ - -ACTOR WraithBuried : Wraith -{ - Height 68 - -SHOOTABLE - -SOLID - +DONTMORPH - +DONTBLAST - +SPECIALFLOORCLIP - +STAYMORPHED - +INVISIBLE - PainChance 0 - - action native A_WraithRaiseInit(); - action native A_WraithRaise(); - - States - { - Spawn: - Goto Super::Look - See: - WRTH A 2 A_WraithRaiseInit - WRTH A 2 A_WraithRaise - WRTH A 2 A_FaceTarget - WRTH BB 2 A_WraithRaise - Goto See + 1 - Chase: - Goto Super::See - } -} - -// Wraith FX 1 -------------------------------------------------------------- - -ACTOR WraithFX1 -{ - Speed 14 - Radius 10 - Height 6 - Mass 5 - Damage 5 - DamageType "Fire" - Projectile - +FLOORCLIP - SeeSound "WraithMissileFire" - DeathSound "WraithMissileExplode" - - action native A_WraithFX2(); - - States - { - Spawn: - WRBL A 3 Bright - WRBL B 3 Bright A_WraithFX2 - WRBL C 3 Bright - Loop - Death: - WRBL D 4 Bright - WRBL E 4 Bright A_WraithFX2 - WRBL F 4 Bright - WRBL GH 3 Bright A_WraithFX2 - WRBL I 3 Bright - Stop - } -} - -// Wraith FX 2 -------------------------------------------------------------- - -ACTOR WraithFX2 -{ - Radius 2 - Height 5 - Mass 5 - +NOBLOCKMAP +DROPOFF - +FLOORCLIP +NOTELEPORT - States - { - Spawn: - WRBL JKLMNOP 4 Bright - Stop - } -} - -// Wraith FX 3 -------------------------------------------------------------- - -ACTOR WraithFX3 -{ - Radius 2 - Height 5 - Mass 5 - +NOBLOCKMAP +DROPOFF +MISSILE - +FLOORCLIP +NOTELEPORT - DeathSound "Drip" - States - { - Spawn: - WRBL QRS 4 Bright - Loop - Death: - WRBL S 4 Bright - Stop - } -} - -// Wraith FX 4 -------------------------------------------------------------- - -ACTOR WraithFX4 -{ - Radius 2 - Height 5 - Mass 5 - +NOBLOCKMAP +DROPOFF +MISSILE - +NOTELEPORT - DeathSound "Drip" - States - { - Spawn: - WRBL TUVW 4 - Loop - Death: - WRBL W 10 - Stop - } -} - -// Wraith FX 5 -------------------------------------------------------------- - -ACTOR WraithFX5 : WraithFX4 -{ - States - { - Spawn: - WRBL XYZ 7 - Loop - Death: - WRBL Z 35 - Stop - } -} diff --git a/wadsrc/static/actors/raven/artiegg.txt b/wadsrc/static/actors/raven/artiegg.txt deleted file mode 100644 index 1c4a8f190..000000000 --- a/wadsrc/static/actors/raven/artiegg.txt +++ /dev/null @@ -1,102 +0,0 @@ - -// Egg missile -------------------------------------------------------------- - -ACTOR EggFX : MorphProjectile -{ - Radius 8 - Height 8 - Speed 18 - MorphProjectile.PlayerClass "ChickenPlayer" - MorphProjectile.MonsterClass "Chicken" - MorphProjectile.MorphStyle MRF_UNDOBYTOMEOFPOWER - States - { - Spawn: - EGGM ABCDE 4 - Loop - Death: - FX01 FFGH 3 Bright - Stop - } -} - - -// Morph Ovum ---------------------------------------------------------------- - -ACTOR ArtiEgg : CustomInventory -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.INVBAR - +INVENTORY.PICKUPFLASH - +INVENTORY.FANCYPICKUPSOUND - Inventory.Icon "ARTIEGGC" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIEGG" - Inventory.DefMaxAmount - Tag "$TAG_ARTIEGG" - States - { - Spawn: - EGGC ABCB 6 - Loop - Use: - TNT1 A 0 A_FireCustomMissile("EggFX", -15, 0, 0, 0, 1) - TNT1 A 0 A_FireCustomMissile("EggFX", -7.5, 0, 0, 0, 1) - TNT1 A 0 A_FireCustomMissile("EggFX", 0, 0, 0, 0, 1) - TNT1 A 0 A_FireCustomMissile("EggFX", 7.5, 0, 0, 0, 1) - TNT1 A 0 A_FireCustomMissile("EggFX", 15, 0, 0, 0, 1) - Stop - } -} - -// Pork missile -------------------------------------------------------------- - -ACTOR PorkFX : MorphProjectile -{ - Radius 8 - Height 8 - Speed 18 - MorphProjectile.PlayerClass "PigPlayer" - MorphProjectile.MonsterClass "Pig" - MorphProjectile.MorphStyle MRF_UNDOBYTOMEOFPOWER|MRF_UNDOBYCHAOSDEVICE - States - { - Spawn: - PRKM ABCDE 4 - Loop - Death: - FHFX IJKL 3 Bright - Stop - } -} - -// Porkalator --------------------------------------------------------------- - -ACTOR ArtiPork : CustomInventory -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.INVBAR - +INVENTORY.PICKUPFLASH - +INVENTORY.FANCYPICKUPSOUND - Inventory.Icon "ARTIPORK" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIEGG2" - Inventory.DefMaxAmount - Tag "$TAG_ARTIPORK" - States - { - Spawn: - PORK ABCDEFGH 5 - Loop - Use: - TNT1 A 0 A_FireCustomMissile("PorkFX", -15, 0, 0, 0, 1) - TNT1 A 0 A_FireCustomMissile("PorkFX", -7.5, 0, 0, 0, 1) - TNT1 A 0 A_FireCustomMissile("PorkFX", 0, 0, 0, 0, 1) - TNT1 A 0 A_FireCustomMissile("PorkFX", 7.5, 0, 0, 0, 1) - TNT1 A 0 A_FireCustomMissile("PorkFX", 15, 0, 0, 0, 1) - Stop - } -} - diff --git a/wadsrc/static/actors/raven/artitele.txt b/wadsrc/static/actors/raven/artitele.txt deleted file mode 100644 index 569926d16..000000000 --- a/wadsrc/static/actors/raven/artitele.txt +++ /dev/null @@ -1,24 +0,0 @@ - -// Teleport (self) ---------------------------------------------------------- - -ACTOR ArtiTeleport : Inventory native -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.INVBAR - +INVENTORY.PICKUPFLASH - +INVENTORY.FANCYPICKUPSOUND - Inventory.DefMaxAmount - Inventory.Icon "ARTIATLP" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTITELEPORT" - Tag "$TAG_ARTITELEPORT" - States - { - Spawn: - ATLP ABCB 4 - Loop - } -} - - diff --git a/wadsrc/static/actors/raven/minotaur.txt b/wadsrc/static/actors/raven/minotaur.txt deleted file mode 100644 index 134bf9d52..000000000 --- a/wadsrc/static/actors/raven/minotaur.txt +++ /dev/null @@ -1,218 +0,0 @@ -ACTOR Minotaur native -{ - Health 3000 - Radius 28 - Height 100 - Mass 800 - Speed 16 - Damage 7 - Painchance 25 - Monster - +DROPOFF - +FLOORCLIP - +BOSS - +NORADIUSDMG - +DONTMORPH - +NOTARGET - +BOSSDEATH - SeeSound "minotaur/sight" - AttackSound "minotaur/attack1" - PainSound "minotaur/pain" - DeathSound "minotaur/death" - ActiveSound "minotaur/active" - DropItem "ArtiSuperHealth", 51 - DropItem "PhoenixRodAmmo", 84, 10 - - action native A_MinotaurDecide(); - action native A_MinotaurAtk1(); - action native A_MinotaurAtk2(); - action native A_MinotaurAtk3(); - action native A_MinotaurCharge(); - action native A_MinotaurLook(); - action native A_MinotaurRoam(); - action native A_MinotaurChase(); - action native A_MinotaurDeath(); - - States - { - Spawn: - MNTR AB 10 A_MinotaurLook - Loop - Roam: - MNTR ABCD 5 A_MinotaurRoam - Loop - See: - MNTR ABCD 5 A_MinotaurChase - Loop - Melee: - MNTR V 10 A_FaceTarget - MNTR W 7 A_FaceTarget - MNTR X 12 A_MinotaurAtk1 - Goto See - Missile: - MNTR V 10 A_MinotaurDecide - MNTR Y 4 A_FaceTarget - MNTR Z 9 A_MinotaurAtk2 - Goto See - Hammer: - MNTR V 10 A_FaceTarget - MNTR W 7 A_FaceTarget - MNTR X 12 A_MinotaurAtk3 - Goto See - HammerLoop: - MNTR X 12 - Goto Hammer - Charge: - MNTR U 2 A_MinotaurCharge - Loop - Pain: - MNTR E 3 - MNTR E 6 A_Pain - Goto See - Death: - MNTR F 6 A_MinotaurDeath - MNTR G 5 - MNTR H 6 A_Scream - MNTR I 5 - MNTR J 6 - MNTR K 5 - MNTR L 6 - MNTR M 5 A_NoBlocking - MNTR N 6 - MNTR O 5 - MNTR P 6 - MNTR Q 5 - MNTR R 6 - MNTR S 5 - MNTR T -1 A_BossDeath - Stop - FadeOut: - MNTR E 6 - MNTR E 2 A_Scream - MNTR E 5 A_SpawnItemEx("MinotaurSmokeExit") - MNTR E 5 - MNTR E 5 A_NoBlocking - MNTR E 5 - MNTR E 5 A_SetTranslucent(0.66, 0) - MNTR E 5 A_SetTranslucent(0.33, 0) - MNTR E 10 A_BossDeath - Stop - } -} - -ACTOR MinotaurFriend : Minotaur native -{ - Health 2500 - -DROPOFF - -BOSS - -DONTMORPH - +FRIENDLY - +NOTARGETSWITCH - +STAYMORPHED - +TELESTOMP - +SUMMONEDMONSTER - RenderStyle Translucent - Alpha 0.3333 - DropItem "None" - States - { - Spawn: - MNTR A 15 - MNTR A 15 A_SetTranslucent(0.66, 0) - MNTR A 3 A_SetTranslucent(1, 0) - Goto Super::Spawn - Idle: - Goto Super::Spawn - Death: - Goto FadeOut - } -} - -// Minotaur FX 1 ------------------------------------------------------------ - -ACTOR MinotaurFX1 -{ - Radius 10 - Height 6 - Speed 20 - FastSpeed 26 - Damage 3 - DamageType Fire - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - RenderStyle Add - States - { - Spawn: - FX12 AB 6 Bright - Loop - Death: - FX12 CDEFGH 5 Bright - Stop - } -} - - -// Minotaur FX 2 ------------------------------------------------------------ - -ACTOR MinotaurFX2 : MinotaurFX1 -{ - Radius 5 - Height 12 - Speed 14 - FastSpeed 20 - Damage 4 - +FLOORHUGGER - ExplosionDamage 24 - DeathSound "minotaur/fx2hit" - - action native A_MntrFloorFire(); - - states - { - Spawn: - FX13 A 2 Bright A_MntrFloorFire - Loop - Death: - FX13 I 4 Bright A_Explode - FX13 JKLM 4 Bright - Stop - } -} - -// Minotaur FX 3 ------------------------------------------------------------ - -ACTOR MinotaurFX3 : MinotaurFX2 -{ - Radius 8 - Height 16 - Speed 0 - DeathSound "minotaur/fx3hit" - ExplosionDamage 128 - States - { - Spawn: - FX13 DC 4 Bright - FX13 BCDE 5 Bright - FX13 FGH 4 Bright - Stop - } -} - -// Minotaur Smoke Exit ------------------------------------------------------ - -ACTOR MinotaurSmokeExit -{ - +NOBLOCKMAP - +NOTELEPORT - RenderStyle Translucent - Alpha 0.4 - States - { - Spawn: - MNSM ABCDEFGHIJIHGFEDCBA 3 - Stop - } -} - diff --git a/wadsrc/static/actors/raven/ravenambient.txt b/wadsrc/static/actors/raven/ravenambient.txt deleted file mode 100644 index f7312de02..000000000 --- a/wadsrc/static/actors/raven/ravenambient.txt +++ /dev/null @@ -1,36 +0,0 @@ - - -// Wind --------------------------------------------------------------------- - -ACTOR SoundWind -{ - +NOBLOCKMAP - +NOSECTOR - +DONTSPLASH - States - { - Spawn: - TNT1 A 2 A_PlaySoundEx("world/wind", "SoundSlot6", 1) - Loop - } -} - -ACTOR SoundWindHexen : SoundWind -{ -} - - -// Waterfall ---------------------------------------------------------------- - -ACTOR SoundWaterfall -{ - +NOBLOCKMAP - +NOSECTOR - +DONTSPLASH - States - { - Spawn: - TNT1 A 2 A_PlaySoundEx("world/waterfall", "SoundSlot6", 1) - Loop - } -} diff --git a/wadsrc/static/actors/raven/ravenartifacts.txt b/wadsrc/static/actors/raven/ravenartifacts.txt deleted file mode 100644 index 43a5e87fc..000000000 --- a/wadsrc/static/actors/raven/ravenartifacts.txt +++ /dev/null @@ -1,125 +0,0 @@ - -// Health ------------------------------------------------------------------- - -ACTOR ArtiHealth : HealthPickup -{ - Health 25 - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - +INVENTORY.FANCYPICKUPSOUND - Inventory.Icon ARTIPTN2 - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTIHEALTH" - Tag "$TAG_ARTIHEALTH" - HealthPickup.Autouse 1 - States - { - Spawn: - PTN2 ABC 4 - Loop - } -} - -// Super health ------------------------------------------------------------- - -ACTOR ArtiSuperHealth : HealthPickup -{ - Health 100 - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - +INVENTORY.FANCYPICKUPSOUND - Inventory.Icon ARTISPHL - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_ARTISUPERHEALTH" - Tag "$TAG_ARTISUPERHEALTH" - HealthPickup.Autouse 2 - States - { - Spawn: - SPHL A 350 - Loop - } -} - -// Flight ------------------------------------------------------------------- - -ACTOR ArtiFly : PowerupGiver -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - +INVENTORY.INTERHUBSTRIP - Inventory.RespawnTics 4230 - Inventory.Icon ARTISOAR - Inventory.PickupMessage "$TXT_ARTIFLY" - Tag "$TAG_ARTIFLY" - Powerup.Type Flight - States - { - Spawn: - SOAR ABCB 5 - Loop - } -} - -// Invulnerability Heretic (Ring of invincibility) -------------------------- - -ACTOR ArtiInvulnerability : PowerupGiver -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - Inventory.RespawnTics 4230 - Inventory.Icon ARTIINVU - Inventory.PickupMessage "$TXT_ARTIINVULNERABILITY" - Tag "$TAG_ARTIINVULNERABILITY" - Powerup.Type Invulnerable - Powerup.Color GoldMap - States - { - Spawn: - INVU ABCD 3 - Loop - } -} - -// Invulnerability Hexen (Icon of the defender) ----------------------------- - -ACTOR ArtiInvulnerability2 : PowerupGiver -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - Inventory.RespawnTics 4230 - Inventory.Icon ARTIDEFN - Inventory.PickupMessage "$TXT_ARTIINVULNERABILITY2" - Powerup.Type Invulnerable - Tag "$TAG_ARTIDEFENDER" - States - { - Spawn: - DEFN ABCD 3 - Loop - } -} - -// Torch -------------------------------------------------------------------- - -ACTOR ArtiTorch : PowerupGiver -{ - +COUNTITEM - +FLOATBOB - +INVENTORY.PICKUPFLASH - Inventory.Icon ARTITRCH - Inventory.PickupMessage "$TXT_ARTITORCH" - Tag "$TAG_ARTITORCH" - Powerup.Type Torch - States - { - Spawn: - TRCH ABC 3 Bright - Loop - } -} diff --git a/wadsrc/static/actors/raven/ravenhealth.txt b/wadsrc/static/actors/raven/ravenhealth.txt deleted file mode 100644 index 99e6692ba..000000000 --- a/wadsrc/static/actors/raven/ravenhealth.txt +++ /dev/null @@ -1,13 +0,0 @@ -ACTOR CrystalVial : Health -{ - +FLOATBOB - Inventory.Amount 10 - Inventory.PickupMessage "$TXT_ITEMHEALTH" - States - { - Spawn: - PTN1 ABC 3 - Loop - } -} - diff --git a/wadsrc/static/actors/shared/action.txt b/wadsrc/static/actors/shared/action.txt deleted file mode 100644 index fc0e71313..000000000 --- a/wadsrc/static/actors/shared/action.txt +++ /dev/null @@ -1,56 +0,0 @@ - - -//========================================================================== -// -// Ice chunk -// -//========================================================================== - -ACTOR IceChunk -{ - Radius 3 - Height 4 - Mass 5 - Gravity 0.125 - +DROPOFF - +CANNOTPUSH - +FLOORCLIP - +NOTELEPORT - +NOBLOCKMAP - +MOVEWITHSECTOR - - action native A_IceSetTics (); - - States - { - Spawn: - ICEC A 1 - ICEC ABCD 10 A_IceSetTics - Stop - } -} - -//========================================================================== -// -// A chunk of ice that is also a player -// -//========================================================================== - -ACTOR IceChunkHead : PlayerChunk -{ - Radius 3 - Height 4 - Mass 5 - Gravity 0.125 - DamageType Ice - +DROPOFF - +CANNOTPUSH - States - { - Spawn: - ICEC A 0 - ICEC A 10 A_CheckPlayerDone - wait - } -} - diff --git a/wadsrc/static/actors/shared/blood.txt b/wadsrc/static/actors/shared/blood.txt deleted file mode 100644 index ab33fee75..000000000 --- a/wadsrc/static/actors/shared/blood.txt +++ /dev/null @@ -1,69 +0,0 @@ - -// Blood sprite ------------------------------------------------------------ - -ACTOR Blood -{ - Mass 5 - +NOBLOCKMAP - +NOTELEPORT - +ALLOWPARTICLES - States - { - Spawn: - BLUD CBA 8 - Stop - Spray: - SPRY ABCDEF 3 - SPRY G 2 - Stop - } -} - -// Blood splatter ----------------------------------------------------------- - -ACTOR BloodSplatter -{ - Radius 2 - Height 4 - +NOBLOCKMAP - +MISSILE - +DROPOFF - +NOTELEPORT - +CANNOTPUSH - +ALLOWPARTICLES - Mass 5 - States - { - Spawn: - BLUD CBA 8 - Stop - Death: - BLUD A 6 - Stop - } -} - -// Axe Blood ---------------------------------------------------------------- - -ACTOR AxeBlood -{ - Radius 2 - Height 4 - +NOBLOCKMAP - +NOGRAVITY - +DROPOFF - +NOTELEPORT - +CANNOTPUSH - +ALLOWPARTICLES - Mass 5 - States - { - Spawn: - FAXE FGHIJ 3 - Death: - FAXE K 3 - Stop - } -} - - \ No newline at end of file diff --git a/wadsrc/static/actors/shared/botstuff.txt b/wadsrc/static/actors/shared/botstuff.txt deleted file mode 100644 index 4b1992bde..000000000 --- a/wadsrc/static/actors/shared/botstuff.txt +++ /dev/null @@ -1,19 +0,0 @@ - -ACTOR CajunBodyNode -{ - +NOSECTOR - +NOGRAVITY - +INVISIBLE -} - -ACTOR CajunTrace -{ - Speed 12 - Radius 6 - Height 8 - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOGRAVITY - +NOTELEPORT -} diff --git a/wadsrc/static/actors/shared/bridge.txt b/wadsrc/static/actors/shared/bridge.txt deleted file mode 100644 index 97d4c22ad..000000000 --- a/wadsrc/static/actors/shared/bridge.txt +++ /dev/null @@ -1,105 +0,0 @@ -// Bridge ball ------------------------------------------------------------- - -ACTOR BridgeBall -{ - +NOBLOCKMAP - +NOTELEPORT - +NOGRAVITY - - action native A_BridgeOrbit(); - - States - { - Spawn: - TLGL A 2 Bright - TLGL A 1 Bright A_BridgeOrbit - Wait - } - -} - -// The bridge itself ------------------------------------------------------- - -ACTOR CustomBridge native -{ - +SOLID - +NOGRAVITY - +NOLIFTDROP - +ACTLIKEBRIDGE - Radius 32 - Height 2 - RenderStyle None - - action native A_BridgeInit(class balltype = "BridgeBall"); - - states - { - Spawn: - TLGL ABCDE 3 Bright - Loop - See: - TLGL A 2 - TLGL A 2 A_BridgeInit - TLGL A -1 - Stop - Death: - TLGL A 2 - TLGL A 300 - Stop - } -} - -// The Hexen bridge ------------------------------------------------------- - -ACTOR Bridge : CustomBridge -{ - RenderStyle None - Args 32, 2, 3, 0 -} - -// The ZDoom bridge ------------------------------------------------------- - -ACTOR ZBridge : CustomBridge -{ - Args 36, 4, 0, 0 -} - - -// Invisible bridge -------------------------------------------------------- - -ACTOR InvisibleBridge native -{ - RenderStyle None - Radius 32 - Height 4 - +SOLID - +NOGRAVITY - +NOLIFTDROP - +ACTLIKEBRIDGE - States - { - Spawn: - TNT1 A -1 - Stop - } -} - -// And some invisible bridges from Skull Tag ------------------------------- - -ACTOR InvisibleBridge32 : InvisibleBridge -{ - Radius 32 - Height 8 -} - -ACTOR InvisibleBridge16 : InvisibleBridge -{ - Radius 16 - Height 8 -} - -ACTOR InvisibleBridge8 : InvisibleBridge -{ - Radius 8 - Height 8 -} diff --git a/wadsrc/static/actors/shared/camera.txt b/wadsrc/static/actors/shared/camera.txt deleted file mode 100644 index 46816f9ea..000000000 --- a/wadsrc/static/actors/shared/camera.txt +++ /dev/null @@ -1,23 +0,0 @@ -ACTOR DoomBuilderCamera -{ - States - { - Spawn: - TNT1 A 1 - Stop - } -} - - -ACTOR SecurityCamera native -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - RenderStyle None - CameraHeight 0 -} - -ACTOR AimingCamera : SecurityCamera native -{ -} diff --git a/wadsrc/static/actors/shared/damagetypes.txt b/wadsrc/static/actors/shared/damagetypes.txt deleted file mode 100644 index 9e5f1e254..000000000 --- a/wadsrc/static/actors/shared/damagetypes.txt +++ /dev/null @@ -1,4 +0,0 @@ -damagetype Drowning -{ - NoArmor -} diff --git a/wadsrc/static/actors/shared/debris.txt b/wadsrc/static/actors/shared/debris.txt deleted file mode 100644 index 5d14a48fa..000000000 --- a/wadsrc/static/actors/shared/debris.txt +++ /dev/null @@ -1,331 +0,0 @@ - -// Rocks -------------------------------------------------------------------- - -ACTOR Rock1 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK A 20 - Loop - Death: - ROKK A 10 - Stop - } -} - -ACTOR Rock2 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK B 20 - Loop - Death: - ROKK B 10 - Stop - } -} - - -ACTOR Rock3 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK C 20 - Loop - Death: - ROKK C 10 - Stop - } -} - - -// Dirt -------------------------------------------------------------------- - -ACTOR Dirt1 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK D 20 - Loop - Death: - ROKK D 10 - Stop - } -} - -ACTOR Dirt2 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK E 20 - Loop - Death: - ROKK E 10 - Stop - } -} - -ACTOR Dirt3 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK F 20 - Loop - Death: - ROKK F 10 - Stop - } -} - -ACTOR Dirt4 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK G 20 - Loop - Death: - ROKK G 10 - Stop - } -} - -ACTOR Dirt5 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK H 20 - Loop - Death: - ROKK H 10 - Stop - } -} - -ACTOR Dirt6 -{ - +NOBLOCKMAP - +DROPOFF - +MISSILE - +NOTELEPORT - States - { - Spawn: - ROKK I 20 - Loop - Death: - ROKK I 10 - Stop - } -} - -// Stained glass ------------------------------------------------------------ - -ACTOR GlassShard native -{ - Radius 5 - Mass 5 - Projectile - -ACTIVATEPCROSS - -ACTIVATEIMPACT - BounceType "HexenCompat" - BounceFactor 0.3 -} - -ACTOR SGShard1 : GlassShard -{ - States - { - Spawn: - SGSA ABCDE 4 - Loop - Death: - SGSA E 30 - Stop - } -} - -ACTOR SGShard2 : GlassShard -{ - States - { - Spawn: - SGSA FGHIJ 4 - Loop - Death: - SGSA J 30 - Stop - } -} - -ACTOR SGShard3 : GlassShard -{ - States - { - Spawn: - SGSA KLMNO 4 - Loop - Death: - SGSA O 30 - Stop - } -} - -ACTOR SGShard4 : GlassShard -{ - States - { - Spawn: - SGSA PQRST 4 - Loop - Death: - SGSA T 30 - Stop - } -} - -ACTOR SGShard5 : GlassShard -{ - States - { - Spawn: - SGSA UVWXY 4 - Loop - Death: - SGSA Y 30 - Stop - } -} - -ACTOR SGShard6 : GlassShard -{ - States - { - Spawn: - SGSB A 4 - Loop - Death: - SGSB A 30 - Stop - } -} - -ACTOR SGShard7 : GlassShard -{ - States - { - Spawn: - SGSB B 4 - Loop - Death: - SGSB B 30 - Stop - } -} - -ACTOR SGShard8 : GlassShard -{ - States - { - Spawn: - SGSB C 4 - Loop - Death: - SGSB C 30 - Stop - } -} - -ACTOR SGShard9 : GlassShard -{ - States - { - Spawn: - SGSB D 4 - Loop - Death: - SGSB D 30 - Stop - } -} - -ACTOR SGShard0 : GlassShard -{ - States - { - Spawn: - SGSB E 4 - Loop - Death: - SGSB E 30 - Stop - } -} - -ACTOR GlassJunk -{ - +NOCLIP - +NOBLOCKMAP - RenderStyle Translucent - Alpha 0.4 - Health 3 // Number of different shards - States - { - // Are the first three frames used anywhere? - SHAR A 128 - Goto Death - SHAR B 128 - Goto Death - SHAR C 128 - Goto Death - Spawn: - SHAR D 128 - Goto Death - SHAR E 128 - Goto Death - SHAR F 128 - Goto Death - Death: - "----" A 1 A_FadeOut(0.03) - Wait - } -} diff --git a/wadsrc/static/actors/shared/decal.txt b/wadsrc/static/actors/shared/decal.txt deleted file mode 100644 index 25e7062c8..000000000 --- a/wadsrc/static/actors/shared/decal.txt +++ /dev/null @@ -1,3 +0,0 @@ -ACTOR Decal native -{ -} diff --git a/wadsrc/static/actors/shared/dog.txt b/wadsrc/static/actors/shared/dog.txt deleted file mode 100644 index 1004fba20..000000000 --- a/wadsrc/static/actors/shared/dog.txt +++ /dev/null @@ -1,44 +0,0 @@ -ACTOR MBFHelperDog -{ - Health 500 - Speed 10 - PainChance 180 - Radius 12 - Height 28 - Mass 100 - Monster - +JUMPDOWN - ActiveSound "dog/active" - AttackSound "dog/attack" - DeathSound "dog/death" - PainSound "dog/pain" - SeeSound "dog/sight" - Obituary "$OB_DOG" - States - { - Spawn: - DOGS AB 10 A_Look - Loop - See: - DOGS AABBCCDD 2 A_Chase - Loop - Melee: - DOGS EF 8 A_FaceTarget - DOGS G 8 A_SargAttack - Goto See - Pain: - DOGS H 2 - DOGS H 2 A_Pain - Goto See - Death: - DOGS I 8 - DOGS J 8 A_Scream - DOGS K 4 - DOGS L 4 A_Fall - DOGS M 4 - DOGS N -1 - Raise: - DOGS NMLKJI 5 - Goto See - } -} diff --git a/wadsrc/static/actors/shared/fountain.txt b/wadsrc/static/actors/shared/fountain.txt deleted file mode 100644 index d9c31e88e..000000000 --- a/wadsrc/static/actors/shared/fountain.txt +++ /dev/null @@ -1,42 +0,0 @@ -ACTOR ParticleFountain native -{ - Height 0 - +NOBLOCKMAP - +NOGRAVITY - +INVISIBLE -} - -ACTOR RedParticleFountain : ParticleFountain -{ - Health 1 -} - -ACTOR GreenParticleFountain : ParticleFountain -{ - Health 2 -} - -ACTOR BlueParticleFountain : ParticleFountain -{ - Health 3 -} - -ACTOR YellowParticleFountain : ParticleFountain -{ - Health 4 -} - -ACTOR PurpleParticleFountain : ParticleFountain -{ - Health 5 -} - -ACTOR BlackParticleFountain : ParticleFountain -{ - Health 6 -} - -ACTOR WhiteParticleFountain : ParticleFountain -{ - Health 7 -} diff --git a/wadsrc/static/actors/shared/hatetarget.txt b/wadsrc/static/actors/shared/hatetarget.txt deleted file mode 100644 index 75442c65c..000000000 --- a/wadsrc/static/actors/shared/hatetarget.txt +++ /dev/null @@ -1,19 +0,0 @@ - - -// Hate Target -------------------------------------------------------------- - -ACTOR HateTarget native -{ - Radius 20 - Height 56 - +SHOOTABLE - +NOGRAVITY - +NOBLOOD - +DONTSPLASH - Mass 0x7fffffff - States - { - Spawn: - TNT1 A -1 - } -} \ No newline at end of file diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt deleted file mode 100644 index 43a33f93a..000000000 --- a/wadsrc/static/actors/shared/inventory.txt +++ /dev/null @@ -1,376 +0,0 @@ -ACTOR Inventory native -{ - Inventory.Amount 1 - Inventory.MaxAmount 1 - Inventory.InterHubAmount 1 - Inventory.UseSound "misc/invuse" - Inventory.PickupSound "misc/i_pkup" - Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG" - - action native state A_JumpIfNoAmmo(state label); - action native 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 A_FireBullets(float/*angle*/ spread_xy, float/*angle*/ 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 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 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/*angle*/ spread_xy = 0, float/*angle*/ 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 A_Light(int extralight); - action native A_Light0(); - action native A_Light1(); - action native A_Light2(); - action native A_LightInverse(); - action native A_WeaponReady(int flags = 0); - action native A_Lower(); - action native A_Raise(); - action native A_FirePistol(); - action native A_FireShotgun(); - action native A_FireShotgun2(); - action native A_OpenShotgun2(); - action native A_LoadShotgun2(); - action native A_CloseShotgun2(); - action native A_FireCGun(); - action native A_FireSTGrenade(class grenadetype = "Grenade"); - action native A_FireMissile(); - action native A_FirePlasma(); - action native A_FireRailgun(); - action native A_FireRailgunLeft(); - action native A_FireRailgunRight(); - action native A_RailWait(); - action native A_BFGsound(); - action native A_FireBFG(); - action native A_FireOldBFG(); - action native A_ReFire(state flash = ""); - action native A_ClearReFire(); - 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 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 armorbonustype = "ArmorBonus"); - action native state A_CheckForReload(int counter, state label, bool dontincrement = false); - action native A_ResetReloadCounter(); - action native A_RestoreSpecialPosition(); - action native A_RestoreSpecialDoomThing(); - action native A_RestoreSpecialThing1(); - action native A_RestoreSpecialThing2(); - - States - { - HideDoomish: - TNT1 A 1050 - TNT1 A 0 A_RestoreSpecialPosition - TNT1 A 1 A_RestoreSpecialDoomThing - Stop - HideSpecial: - ACLO E 1400 - ACLO A 0 A_RestoreSpecialPosition - ACLO A 4 A_RestoreSpecialThing1 - ACLO BABCBCDC 4 - ACLO D 4 A_RestoreSpecialThing2 - Stop - Held: - TNT1 A -1 - Stop - HoldAndDestroy: - TNT1 A 1 - Stop - } -} - -Actor ScoreItem : Inventory native -{ - Height 10 - +COUNTITEM - Inventory.Amount 1 - +Inventory.ALWAYSPICKUP -} - -Actor Ammo : Inventory native -{ - +INVENTORY.KEEPDEPLETED - Inventory.PickupSound "misc/ammo_pkup" -} - -Actor BackpackItem : Inventory native -{ -} - -ACTOR Armor : Inventory native -{ - Inventory.PickupSound "misc/armor_pkup" -} - -ACTOR BasicArmor : Armor native -{ - +Inventory.KEEPDEPLETED -} - -ACTOR BasicArmorBonus : Armor native -{ - +Inventory.AUTOACTIVATE - +Inventory.ALWAYSPICKUP - Inventory.MaxAmount 0 - Armor.SavePercent 33.335 - -} - -ACTOR BasicArmorPickup : Armor native -{ - +Inventory.AUTOACTIVATE - Inventory.MaxAmount 0 -} - -ACTOR HexenArmor : Armor native -{ - +Inventory.KEEPDEPLETED - +Inventory.UNDROPPABLE -} - -ACTOR DehackedPickup : Inventory native {} - -ACTOR FakeInventory : Inventory native {} - -ACTOR CustomInventory : Inventory native {} - -Actor Health : Inventory native -{ - Inventory.Amount 1 - Inventory.MaxAmount 0 - Inventory.PickupSound "misc/health_pkup" -} - -Actor HealthPickup : Inventory native -{ - Inventory.DefMaxAmount - +INVENTORY.INVBAR -} - -Actor Key : Inventory native -{ - +DONTGIB // Don't disappear due to a crusher - +INVENTORY.INTERHUBSTRIP - Inventory.PickupSound "misc/k_pkup" -} - -ACTOR PowerupGiver : Inventory native -{ - Inventory.DefMaxAmount - +INVENTORY.INVBAR - +INVENTORY.FANCYPICKUPSOUND - Inventory.PickupSound "misc/p_pkup" -} - -ACTOR Powerup : Inventory native {} - -ACTOR PowerInvulnerable : Powerup native -{ - Powerup.Duration -30 - inventory.icon "SPSHLD0" -} - -ACTOR PowerStrength : Powerup native -{ - Powerup.Duration 1 - Powerup.Color 255,0,0,0.5 - +INVENTORY.HUBPOWER -} - -ACTOR PowerInvisibility : Powerup native -{ - +SHADOW - Powerup.Duration -60 - Powerup.Strength 80 - Powerup.Mode "Fuzzy" -} - -ACTOR PowerGhost : PowerInvisibility -{ - +GHOST - Powerup.Duration -60 - Powerup.Strength 60 - Powerup.Mode "None" -} - -ACTOR PowerShadow : PowerInvisibility -{ - +INVENTORY.HUBPOWER - Powerup.Duration -55 - Powerup.Strength 75 - Powerup.Mode "Cumulative" -} - -ACTOR PowerIronFeet : Powerup native -{ - Powerup.Duration -60 - Powerup.Color 0, 255, 0, 0.125 -} - -ACTOR PowerMask : PowerIronFeet native -{ - Powerup.Duration -80 - Powerup.Color 0,0,0,0 - +INVENTORY.HUBPOWER - Inventory.Icon "I_MASK" -} - -ACTOR PowerLightAmp : Powerup native -{ - Powerup.Duration -120 -} - -ACTOR PowerTorch : PowerLightAmp native {} - -ACTOR PowerFlight : Powerup native -{ - Powerup.Duration -60 - +INVENTORY.HUBPOWER -} - -ACTOR PowerWeaponLevel2 : Powerup native -{ - Powerup.Duration -40 - Inventory.Icon "SPINBK0" - +INVENTORY.NOTELEPORTFREEZE -} - -ACTOR PowerSpeed : Powerup native -{ - Powerup.Duration -45 - Speed 1.5 - Inventory.Icon "SPBOOT0" - +INVENTORY.NOTELEPORTFREEZE -} - -// Player Speed Trail (used by the Speed Powerup) ---------------------------- - -ACTOR PlayerSpeedTrail native -{ - +NOBLOCKMAP - +NOGRAVITY - Alpha 0.6 - RenderStyle Translucent -} - -ACTOR PowerMinotaur : Powerup native -{ - Powerup.Duration -25 - Inventory.Icon "SPMINO0" -} - -ACTOR PowerTargeter : Powerup native -{ - Powerup.Duration -160 - +INVENTORY.HUBPOWER - States - { - Targeter: - TRGT A -1 - Stop - TRGT B -1 - Stop - TRGT C -1 - Stop - } -} - -ACTOR PowerFrightener : Powerup native -{ - Powerup.Duration -60 -} - -ACTOR PowerBuddha : Powerup native -{ - Powerup.Duration -60 -} - -ACTOR PowerScanner : Powerup native -{ - Powerup.Duration -80 - +INVENTORY.HUBPOWER -} - -ACTOR PowerTimeFreezer : Powerup native -{ - Powerup.Duration -12 -} - -ACTOR PowerDamage : Powerup native -{ - Powerup.Duration -25 -} - -ACTOR PowerProtection : Powerup native -{ - Powerup.Duration -25 -} - -ACTOR PowerDrain : Powerup native -{ - Powerup.Duration -60 -} - -ACTOR PowerRegeneration : Powerup native -{ - Powerup.Duration -120 - Powerup.Strength 5 -} - -ACTOR PowerHighJump : Powerup native {} - -ACTOR PowerDoubleFiringSpeed : Powerup native {} - -ACTOR PowerMorph : Powerup native -{ - Powerup.Duration -40 -} - -ACTOR PowerInfiniteAmmo : Powerup native -{ - Powerup.Duration -30 -} - -ACTOR MapRevealer : Inventory native {} - -ACTOR PuzzleItem : Inventory native -{ - +NOGRAVITY - +INVENTORY.INVBAR - Inventory.DefMaxAmount - Inventory.UseSound "PuzzleSuccess" - Inventory.PickupSound "misc/i_pkup" -} - -Actor Weapon : Inventory native -{ - Inventory.PickupSound "misc/w_pkup" - Weapon.DefaultKickback - Weapon.BobSpeed 1.0 - Weapon.BobRangeX 1.0 - Weapon.BobRangeY 1.0 - +WEAPONSPAWN - States - { - LightDone: - SHTG E 0 A_Light0 - Stop - } - - action native A_ZoomFactor(float scale = 1, int flags = 0); - const int ZOOM_INSTANT = 1; - const int ZOOM_NOSCALETURNING = 2; - - action native A_SetCrosshair(int xhair); -} - -ACTOR WeaponGiver : Weapon native -{ - Weapon.AmmoGive1 -1 - Weapon.AmmoGive2 -1 -} - -Actor WeaponHolder : Inventory native -{ - +NOBLOCKMAP - +NOSECTOR - +INVENTORY.UNDROPPABLE -} - -Actor WeaponPiece : Inventory native -{ - +WEAPONSPAWN -} diff --git a/wadsrc/static/actors/shared/mapmarker.txt b/wadsrc/static/actors/shared/mapmarker.txt deleted file mode 100644 index 9c5e36b44..000000000 --- a/wadsrc/static/actors/shared/mapmarker.txt +++ /dev/null @@ -1,15 +0,0 @@ - -ACTOR MapMarker native -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - +INVISIBLE - Scale 0.5 - States - { - Spawn: - AMRK A -1 - Stop - } -} \ No newline at end of file diff --git a/wadsrc/static/actors/shared/morph.txt b/wadsrc/static/actors/shared/morph.txt deleted file mode 100644 index f5aac48d2..000000000 --- a/wadsrc/static/actors/shared/morph.txt +++ /dev/null @@ -1,15 +0,0 @@ -ACTOR MorphProjectile native -{ - Damage 1 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS -} - -ACTOR MorphedMonster native -{ - Monster - -COUNTKILL - +FLOORCLIP -} - diff --git a/wadsrc/static/actors/shared/movingcamera.txt b/wadsrc/static/actors/shared/movingcamera.txt deleted file mode 100644 index 4ba229154..000000000 --- a/wadsrc/static/actors/shared/movingcamera.txt +++ /dev/null @@ -1,34 +0,0 @@ -ACTOR InterpolationPoint native -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - RenderStyle None -} - -ACTOR InterpolationSpecial native -{ - +NOBLOCKMAP - +NOSECTOR - +NOGRAVITY - +DONTSPLASH -} - -ACTOR PathFollower native -{ - +NOBLOCKMAP - +NOSECTOR - +NOGRAVITY - +DONTSPLASH -} - -ACTOR ActorMover : PathFollower native -{ -} - -ACTOR MovingCamera : PathFollower native -{ - CameraHeight 0 -} - - diff --git a/wadsrc/static/actors/shared/player.txt b/wadsrc/static/actors/shared/player.txt deleted file mode 100644 index 08d9a252a..000000000 --- a/wadsrc/static/actors/shared/player.txt +++ /dev/null @@ -1,53 +0,0 @@ -Actor PlayerPawn : Actor native -{ - Health 100 - Radius 16 - Height 56 - Mass 100 - Painchance 255 - Speed 1 - +SOLID - +SHOOTABLE - +DROPOFF - +PICKUP - +NOTDMATCH - +FRIENDLY - +SLIDESONWALLS - +CANPASS - +CANPUSHWALLS - +FLOORCLIP - +WINDTHRUST - +TELESTOMP - +NOBLOCKMONST - Player.AttackZOffset 8 - Player.JumpZ 8 - Player.GruntSpeed 12 - Player.FallingScreamSpeed 35,40 - Player.ViewHeight 41 - Player.UseRange 64 - Player.ForwardMove 1,1 - Player.SideMove 1,1 - Player.ColorRange 0,0 - Player.SoundClass "player" - Player.DamageScreenColor "ff 00 00" - Player.MugShotMaxHealth 0 - Player.FlechetteType "ArtiPoisonBag3" - Player.AirCapacity 1 - Player.ViewBob 1 - Obituary "$OB_MPDEFAULT" -} - -Actor PlayerChunk : PlayerPawn native -{ - +NOSKIN - -SOLID - -SHOOTABLE - -PICKUP - -NOTDMATCH - -FRIENDLY - -SLIDESONWALLS - -CANPUSHWALLS - -FLOORCLIP - -WINDTHRUST - -TELESTOMP -} diff --git a/wadsrc/static/actors/shared/secrettrigger.txt b/wadsrc/static/actors/shared/secrettrigger.txt deleted file mode 100644 index 8db323993..000000000 --- a/wadsrc/static/actors/shared/secrettrigger.txt +++ /dev/null @@ -1,9 +0,0 @@ - -ACTOR SecretTrigger native -{ - +NOBLOCKMAP - +NOSECTOR - +NOGRAVITY - +DONTSPLASH -} - diff --git a/wadsrc/static/actors/shared/setcolor.txt b/wadsrc/static/actors/shared/setcolor.txt deleted file mode 100644 index 136b0bbf4..000000000 --- a/wadsrc/static/actors/shared/setcolor.txt +++ /dev/null @@ -1,16 +0,0 @@ -ACTOR ColorSetter native -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - RenderStyle None -} - - -ACTOR FadeSetter native -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - RenderStyle None -} diff --git a/wadsrc/static/actors/shared/sharedmisc.txt b/wadsrc/static/actors/shared/sharedmisc.txt deleted file mode 100644 index fe5ac72d8..000000000 --- a/wadsrc/static/actors/shared/sharedmisc.txt +++ /dev/null @@ -1,178 +0,0 @@ - -// Default actor for unregistered doomednums ------------------------------- - -ACTOR Unknown -{ - Radius 32 - Height 56 - +NOGRAVITY - +NOBLOCKMAP - +DONTSPLASH - States - { - Spawn: - UNKN A -1 - Stop - } -} - -// Route node for monster patrols ------------------------------------------- - -ACTOR PatrolPoint -{ - Radius 8 - Height 8 - Mass 10 - +NOGRAVITY - +NOBLOCKMAP - +DONTSPLASH - RenderStyle None -} - -// A special to execute when a monster reaches a matching patrol point ------ - -ACTOR PatrolSpecial -{ - Radius 8 - Height 8 - Mass 10 - +NOGRAVITY - +NOBLOCKMAP - +DONTSPLASH - RenderStyle None -} - -// Map spot ---------------------------------------------------------------- - -ACTOR MapSpot -{ - +NOBLOCKMAP - +NOSECTOR - +NOGRAVITY - +DONTSPLASH - RenderStyle None - CameraHeight 0 -} - -// same with different editor number for Legacy maps ----------------------- - -ACTOR FS_Mapspot : Mapspot -{ -} - -// Map spot with gravity --------------------------------------------------- - -ACTOR MapSpotGravity : MapSpot -{ - -NOBLOCKMAP - -NOSECTOR - -NOGRAVITY -} - -// Point Pushers ----------------------------------------------------------- - -ACTOR PointPusher -{ - +NOBLOCKMAP - +INVISIBLE - +NOCLIP -} - -ACTOR PointPuller -{ - +NOBLOCKMAP - +INVISIBLE - +NOCLIP -} - -// Bloody gibs ------------------------------------------------------------- - -ACTOR RealGibs -{ - +DROPOFF - +CORPSE - +NOTELEPORT - +DONTGIB - States - { - Spawn: - goto GenericCrush - } -} - -// Gibs that can be placed on a map. --------------------------------------- -// -// These need to be a separate class from the above, in case someone uses -// a deh patch to change the gibs, since ZDoom actually creates a gib actor -// for actors that get crushed instead of changing their state as Doom did. - -ACTOR Gibs : RealGibs -{ - ClearFlags -} - -// Needed for loading Build maps ------------------------------------------- - -ACTOR CustomSprite native -{ - +NOBLOCKMAP - +NOGRAVITY - States - { - Spawn: - TNT1 A -1 - Stop - } -} - -// SwitchableDecoration: Activate and Deactivate change state -------------- - -ACTOR SwitchableDecoration native -{ -} - - -ACTOR SwitchingDecoration : SwitchableDecoration native -{ -} - -// Random spawner ---------------------------------------------------------- - -ACTOR RandomSpawner native -{ - +NOBLOCKMAP - +NOSECTOR - +NOGRAVITY - +THRUACTORS -} - -// Fast projectiles -------------------------------------------------------- - -ACTOR FastProjectile native -{ - Projectile - MissileHeight 0 -} - -// Sector flag setter ------------------------------------------------------ - -ACTOR SectorFlagSetter native -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - RenderStyle None -} - -// Marker for sounds ------------------------------------------------------- - -ACTOR SpeakerIcon : Unknown -{ - States - { - Spawn: - SPKR A -1 BRIGHT - Stop - } - Scale 0.125 -} diff --git a/wadsrc/static/actors/shared/skies.txt b/wadsrc/static/actors/shared/skies.txt deleted file mode 100644 index 89f742573..000000000 --- a/wadsrc/static/actors/shared/skies.txt +++ /dev/null @@ -1,40 +0,0 @@ -ACTOR SkyViewpoint native -{ - +NOSECTOR - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH -} - -ACTOR SkyPicker native -{ - +NOSECTOR - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH -} - -Actor SkyCamCompat : SkyViewpoint native -{ -} - -ACTOR StackPoint : SkyViewpoint native -{ -} - -ACTOR UpperStackLookOnly : StackPoint -{ -} - -ACTOR LowerStackLookOnly : StackPoint -{ -} - - -ACTOR SectorSilencer native -{ - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH - RenderStyle None -} diff --git a/wadsrc/static/actors/shared/soundenvironment.txt b/wadsrc/static/actors/shared/soundenvironment.txt deleted file mode 100644 index 822a723f8..000000000 --- a/wadsrc/static/actors/shared/soundenvironment.txt +++ /dev/null @@ -1,9 +0,0 @@ - -ACTOR SoundEnvironment native -{ - +NOSECTOR - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH -} - diff --git a/wadsrc/static/actors/shared/soundsequence.txt b/wadsrc/static/actors/shared/soundsequence.txt deleted file mode 100644 index 5fe34b326..000000000 --- a/wadsrc/static/actors/shared/soundsequence.txt +++ /dev/null @@ -1,79 +0,0 @@ - -ACTOR AmbientSound native -{ - +NOBLOCKMAP - +NOSECTOR - +DONTSPLASH -} - -ACTOR AmbientSoundNoGravity : AmbientSound -{ - +NOGRAVITY -} - -ACTOR SoundSequenceSlot native -{ - +NOSECTOR - +NOBLOCKMAP - +DONTSPLASH -} - -ACTOR SoundSequence native -{ - +NOSECTOR - +NOBLOCKMAP - +DONTSPLASH -} - -// Heretic Sound sequences ----------------------------------------------------------- - -ACTOR HereticSoundSequence1 : SoundSequence -{ - Args 0 -} - -ACTOR HereticSoundSequence2 : SoundSequence -{ - Args 1 -} - -ACTOR HereticSoundSequence3 : SoundSequence -{ - Args 2 -} - -ACTOR HereticSoundSequence4 : SoundSequence -{ - Args 3 -} - -ACTOR HereticSoundSequence5 : SoundSequence -{ - Args 4 -} - -ACTOR HereticSoundSequence6 : SoundSequence -{ - Args 5 -} - -ACTOR HereticSoundSequence7 : SoundSequence -{ - Args 6 -} - -ACTOR HereticSoundSequence8 : SoundSequence -{ - Args 7 -} - -ACTOR HereticSoundSequence9 : SoundSequence -{ - Args 8 -} - -ACTOR HereticSoundSequence10 : SoundSequence -{ - Args 9 -} - diff --git a/wadsrc/static/actors/shared/spark.txt b/wadsrc/static/actors/shared/spark.txt deleted file mode 100644 index 240d98152..000000000 --- a/wadsrc/static/actors/shared/spark.txt +++ /dev/null @@ -1,8 +0,0 @@ - -ACTOR Spark native -{ - +NOSECTOR - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH -} \ No newline at end of file diff --git a/wadsrc/static/actors/shared/specialspot.txt b/wadsrc/static/actors/shared/specialspot.txt deleted file mode 100644 index fc2bd254a..000000000 --- a/wadsrc/static/actors/shared/specialspot.txt +++ /dev/null @@ -1,5 +0,0 @@ - -ACTOR SpecialSpot native -{ - action native A_SpawnSingleItem(class type, int fail_sp = 0, int fail_co = 0, int fail_dm = 0); -} diff --git a/wadsrc/static/actors/shared/splashes.txt b/wadsrc/static/actors/shared/splashes.txt deleted file mode 100644 index 4c71b4565..000000000 --- a/wadsrc/static/actors/shared/splashes.txt +++ /dev/null @@ -1,237 +0,0 @@ - -// Water -------------------------------------------------------------------- - -ACTOR WaterSplash -{ - Radius 2 - Height 4 - +NOBLOCKMAP - +MISSILE - +DROPOFF - +NOTELEPORT - +LOWGRAVITY - +CANNOTPUSH - +DONTSPLASH - +DONTBLAST - States - { - Spawn: - SPSH ABC 8 - SPSH D 16 - Stop - Death: - SPSH D 10 - Stop - } -} - - -ACTOR WaterSplashBase -{ - +NOBLOCKMAP - +NOCLIP - +NOGRAVITY - +DONTSPLASH - +DONTBLAST - States - { - Spawn: - SPSH EFGHIJK 5 - Stop - } -} - -// Lava --------------------------------------------------------------------- - -ACTOR LavaSplash -{ - +NOBLOCKMAP - +NOCLIP - +NOGRAVITY - +DONTSPLASH - +DONTBLAST - States - { - Spawn: - LVAS ABCDEF 5 Bright - Stop - } -} - -ACTOR LavaSmoke -{ - +NOBLOCKMAP - +NOCLIP - +NOGRAVITY - +DONTSPLASH - RenderStyle Translucent - DefaultAlpha - States - { - Spawn: - LVAS GHIJK 5 Bright - Stop - } -} - -// Sludge ------------------------------------------------------------------- - -ACTOR SludgeChunk -{ - Radius 2 - Height 4 - +NOBLOCKMAP - +MISSILE - +DROPOFF - +NOTELEPORT - +LOWGRAVITY - +CANNOTPUSH - +DONTSPLASH - States - { - Spawn: - SLDG ABCD 8 - Stop - Death: - SLDG D 6 - Stop - } -} - -ACTOR SludgeSplash -{ - +NOBLOCKMAP - +NOCLIP - +NOGRAVITY - +DONTSPLASH - States - { - Spawn: - SLDG EFGH 6 - Stop - } -} - -/* - * These next four classes are not used by me anywhere. - * They are for people who want to use them in a TERRAIN lump. - */ - -// Blood (water with a different sprite) ------------------------------------ - -ACTOR BloodSplash -{ - Radius 2 - Height 4 - +NOBLOCKMAP - +MISSILE - +DROPOFF - +NOTELEPORT - +LOWGRAVITY - +CANNOTPUSH - +DONTSPLASH - +DONTBLAST - States - { - Spawn: - BSPH ABC 8 - BSPH D 16 - Stop - Death: - BSPH D 10 - Stop - } -} - - -ACTOR BloodSplashBase -{ - +NOBLOCKMAP - +NOCLIP - +NOGRAVITY - +DONTSPLASH - +DONTBLAST - States - { - Spawn: - BSPH EFGHIJK 5 - Stop - } -} - -// Slime (sludge with a different sprite) ----------------------------------- - -ACTOR SlimeChunk -{ - Radius 2 - Height 4 - +NOBLOCKMAP - +MISSILE - +DROPOFF - +NOTELEPORT - +LOWGRAVITY - +CANNOTPUSH - +DONTSPLASH - States - { - Spawn: - SLIM ABCD 8 - Stop - Death: - SLIM D 6 - Stop - } -} - -ACTOR SlimeSplash -{ - +NOBLOCKMAP - +NOCLIP - +NOGRAVITY - +DONTSPLASH - States - { - Spawn: - SLIM EFGH 6 - Stop - } -} - -// Smoke trail for rocket ----------------------------------- - -ACTOR RocketSmokeTrail -{ - RenderStyle Translucent - Alpha 0.4 - VSpeed 1 - +NOBLOCKMAP - +NOCLIP - +NOGRAVITY - +DONTSPLASH - +NOTELEPORT - States - { - Spawn: - RSMK ABCDE 5 - Stop - } -} - -ACTOR GrenadeSmokeTrail -{ - RenderStyle Translucent - Alpha 0.4 - +NOBLOCKMAP - +NOCLIP - +DONTSPLASH - +NOTELEPORT - Gravity 0.1 - VSpeed 0.5 - Scale 0.6 - States - { - Spawn: - RSMK ABCDE 4 - Stop - } -} diff --git a/wadsrc/static/actors/shared/teleport.txt b/wadsrc/static/actors/shared/teleport.txt deleted file mode 100644 index 0bce22ea3..000000000 --- a/wadsrc/static/actors/shared/teleport.txt +++ /dev/null @@ -1,42 +0,0 @@ - -ACTOR TeleportFog native -{ - +NOBLOCKMAP - +NOTELEPORT - +NOGRAVITY - RenderStyle Add - States - { - Spawn: - TFOG ABABCDEFGHIJ 6 Bright - Stop - - Raven: - TELE ABCDEFGHGFEDC 6 Bright - Stop - - Strife: - TFOG ABCDEFEDCB 6 Bright - Stop - } -} - - - -ACTOR TeleportDest -{ - +NOBLOCKMAP - +NOSECTOR - +DONTSPLASH -} - -ACTOR TeleportDest2 : TeleportDest -{ - +NOGRAVITY -} - -ACTOR TeleportDest3 : TeleportDest2 -{ - -NOGRAVITY -} - diff --git a/wadsrc/static/actors/shared/waterzone.txt b/wadsrc/static/actors/shared/waterzone.txt deleted file mode 100644 index b6cf4bd29..000000000 --- a/wadsrc/static/actors/shared/waterzone.txt +++ /dev/null @@ -1,7 +0,0 @@ -ACTOR WaterZone native -{ - +NOSECTOR - +NOBLOCKMAP - +NOGRAVITY - +DONTSPLASH -} diff --git a/wadsrc/static/actors/strife/acolyte.txt b/wadsrc/static/actors/strife/acolyte.txt deleted file mode 100644 index f190fb928..000000000 --- a/wadsrc/static/actors/strife/acolyte.txt +++ /dev/null @@ -1,185 +0,0 @@ - -// Base class for the acolytes ---------------------------------------------- - -ACTOR Acolyte : StrifeHumanoid -{ - Health 70 - PainChance 150 - Speed 7 - Radius 24 - Height 64 - Mass 400 - Monster - +SEESDAGGERS - +NOSPLASHALERT - +FLOORCLIP - +NEVERRESPAWN - MinMissileChance 150 - Tag "$TAG_ACOLYTE" - SeeSound "acolyte/sight" - PainSound "acolyte/pain" - AttackSound "acolyte/rifle" - DeathSound "acolyte/death" - ActiveSound "acolyte/active" - Obituary "$OB_ACOLYTE" - - action native A_BeShadowyFoe (); - action native A_AcolyteBits (); - action native A_AcolyteDie (); - - States - { - Spawn: - AGRD A 5 A_Look2 - Wait - AGRD B 8 A_ClearShadow - Loop - AGRD D 8 - Loop - AGRD ABCDABCD 5 A_Wander - Loop - See: - AGRD A 6 Fast Slow A_AcolyteBits - AGRD BCD 6 Fast Slow A_Chase - Loop - Missile: - AGRD E 8 Fast Slow A_FaceTarget - AGRD FE 4 Fast Slow A_ShootGun - AGRD F 6 Fast Slow A_ShootGun - Goto See - Pain: - AGRD O 8 Fast Slow A_Pain - Goto See - Death: - AGRD G 4 - AGRD H 4 A_Scream - AGRD I 4 - AGRD J 3 - AGRD K 3 A_NoBlocking - AGRD L 3 - AGRD M 3 A_AcolyteDie - AGRD N -1 - Stop - XDeath: - GIBS A 5 A_NoBlocking - GIBS BC 5 A_TossGib - GIBS D 4 A_TossGib - GIBS E 4 A_XScream - GIBS F 4 A_TossGib - GIBS GH 4 - GIBS I 5 - GIBS J 5 A_AcolyteDie - GIBS K 5 - GIBS L 1400 - Stop - } -} - - -// Acolyte 1 ---------------------------------------------------------------- - -ACTOR AcolyteTan : Acolyte -{ - +MISSILEMORE +MISSILEEVENMORE - DropItem "ClipOfBullets" -} - -// Acolyte 2 ---------------------------------------------------------------- - -ACTOR AcolyteRed : Acolyte -{ - +MISSILEMORE +MISSILEEVENMORE - Translation 0 -} - -// Acolyte 3 ---------------------------------------------------------------- - -ACTOR AcolyteRust : Acolyte -{ - +MISSILEMORE +MISSILEEVENMORE - Translation 1 -} - -// Acolyte 4 ---------------------------------------------------------------- - -ACTOR AcolyteGray : Acolyte -{ - +MISSILEMORE +MISSILEEVENMORE - Translation 2 -} - -// Acolyte 5 ---------------------------------------------------------------- - -ACTOR AcolyteDGreen : Acolyte -{ - +MISSILEMORE +MISSILEEVENMORE - Translation 3 -} - -// Acolyte 6 ---------------------------------------------------------------- - -ACTOR AcolyteGold : Acolyte -{ - +MISSILEMORE +MISSILEEVENMORE - Translation 4 -} - -// Acolyte 7 ---------------------------------------------------------------- - -ACTOR AcolyteLGreen : Acolyte -{ - Health 60 - Translation 5 -} - -// Acolyte 8 ---------------------------------------------------------------- - -ACTOR AcolyteBlue : Acolyte -{ - Health 60 - Translation 6 -} - -// Shadow Acolyte ----------------------------------------------------------- - -ACTOR AcolyteShadow : Acolyte -{ - +MISSILEMORE - DropItem "ClipOfBullets" - States - { - See: - AGRD A 6 A_BeShadowyFoe - Goto Super::See+1 - Pain: - AGRD O 0 Fast Slow A_SetShadow - AGRD O 8 Fast Slow A_Pain - Goto See - } -} - -// Some guy turning into an acolyte ----------------------------------------- - -ACTOR AcolyteToBe : Acolyte -{ - Health 61 - Radius 20 - Height 56 - DeathSound "becoming/death" - -COUNTKILL - -ISMONSTER - - action native A_HideDecepticon (); - - States - { - Spawn: - ARMR A -1 - Stop - Pain: - ARMR A -1 A_HideDecepticon - Stop - Death: - Goto XDeath - } -} diff --git a/wadsrc/static/actors/strife/alienspectres.txt b/wadsrc/static/actors/strife/alienspectres.txt deleted file mode 100644 index 0476fdfdf..000000000 --- a/wadsrc/static/actors/strife/alienspectres.txt +++ /dev/null @@ -1,202 +0,0 @@ - -// Alien Spectre 1 ----------------------------------------------------------- - -ACTOR AlienSpectre1 : SpectralMonster -{ - Health 1000 - Painchance 250 - Speed 12 - Radius 64 - Height 64 - FloatSpeed 5 - Mass 1000 - MinMissileChance 150 - RenderStyle Translucent - Alpha 0.666 - SeeSound "alienspectre/sight" - AttackSound "alienspectre/blade" - PainSound "alienspectre/pain" - DeathSound "alienspectre/death" - ActiveSound "alienspectre/active" - Obituary "$OB_ALIENSPECTRE" - +NOGRAVITY - +FLOAT - +SHADOW - +NOTDMATCH - +DONTMORPH - +NOBLOCKMONST - +INCOMBAT - +LOOKALLAROUND - +NOICEDEATH - - action native A_AlienSpectreDeath (); - - states - { - Spawn: - ALN1 A 10 A_Look - ALN1 B 10 A_SentinelBob - Loop - See: - ALN1 AB 4 Bright A_Chase - ALN1 C 4 Bright A_SentinelBob - ALN1 DEF 4 Bright A_Chase - ALN1 G 4 Bright A_SentinelBob - ALN1 HIJ 4 Bright A_Chase - ALN1 K 4 Bright A_SentinelBob - Loop - Melee: - ALN1 J 4 Bright A_FaceTarget - ALN1 I 4 Bright A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5) - ALN1 H 4 Bright - Goto See - Missile: - ALN1 J 4 Bright A_FaceTarget - ALN1 I 4 Bright A_SpotLightning - ALN1 H 4 Bright - Goto See+10 - Pain: - ALN1 J 2 A_Pain - Goto See+6 - Death: - AL1P A 6 Bright A_SpectreChunkSmall - AL1P B 6 Bright A_Scream - AL1P C 6 Bright A_SpectreChunkSmall - AL1P DE 6 Bright - AL1P F 6 Bright A_SpectreChunkSmall - AL1P G 6 Bright - AL1P H 6 Bright A_SpectreChunkSmall - AL1P IJK 6 Bright - AL1P LM 5 Bright - AL1P N 5 Bright A_SpectreChunkLarge - AL1P OPQ 5 Bright - AL1P R 5 Bright A_AlienSpectreDeath - Stop - } -} - - -// Alien Spectre 2 ----------------------------------------------------------- - -ACTOR AlienSpectre2 : AlienSpectre1 -{ - Health 1200 - Painchance 50 - Radius 24 - DropItem "Sigil2" - States - { - Missile: - ALN1 F 4 A_FaceTarget - ALN1 I 4 A_CustomMissile("SpectralLightningH3", 32, 0) - ALN1 E 4 - Goto See+10 - } -} - -// Alien Spectre 3 ---------------------------------------------------------- -// This is the Oracle's personal spectre, so it's a little different. - -ACTOR AlienSpectre3 : AlienSpectre1 -{ - Health 1500 - Painchance 50 - Radius 24 - +SPAWNCEILING - DropItem "Sigil3" - DamageFactor "SpectralLow", 0 - states - { - Spawn: - ALN1 ABCDEFGHIJK 5 - Loop - See: - ALN1 AB 5 A_Chase - ALN1 C 5 A_SentinelBob - ALN1 DEF 5 A_Chase - ALN1 G 5 A_SentinelBob - ALN1 HIJ 5 A_Chase - ALN1 K 5 A_SentinelBob - Loop - Melee: - ALN1 J 4 A_FaceTarget - ALN1 I 4 A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5) - ALN1 C 4 - Goto See+2 - Missile: - ALN1 F 4 A_FaceTarget - ALN1 I 4 A_Spectre3Attack - ALN1 E 4 - Goto See+10 - Pain: - ALN1 J 2 A_Pain - Goto See+6 - } -} - - -// Alien Spectre 4 ----------------------------------------------------------- - -ACTOR AlienSpectre4 : AlienSpectre1 -{ - Health 1700 - Painchance 50 - Radius 24 - DropItem "Sigil4" - States - { - Missile: - ALN1 F 4 A_FaceTarget - ALN1 I 4 A_CustomMissile("SpectralLightningBigV2", 32, 0) - ALN1 E 4 - Goto See+10 - } -} - - -// Alien Spectre 5 ----------------------------------------------------------- - -ACTOR AlienSpectre5 : AlienSpectre1 -{ - Health 2000 - Painchance 50 - Radius 24 - DropItem "Sigil5" - States - { - Missile: - ALN1 F 4 A_FaceTarget - ALN1 I 4 A_CustomMissile("SpectralLightningBigBall2", 32, 0) - ALN1 E 4 - Goto See+10 - } -} - -// Small Alien Chunk -------------------------------------------------------- - -ACTOR AlienChunkSmall -{ - +NOBLOCKMAP - +NOCLIP - States - { - Spawn: - NODE ABCDEFG 6 Bright - Stop - } -} - -// Large Alien Chunk -------------------------------------------------------- - -ACTOR AlienChunkLarge -{ - +NOBLOCKMAP - +NOCLIP - States - { - Spawn: - MTHD ABCDEFGHIJK 5 Bright - Stop - } -} - diff --git a/wadsrc/static/actors/strife/beggars.txt b/wadsrc/static/actors/strife/beggars.txt deleted file mode 100644 index eca6e67f4..000000000 --- a/wadsrc/static/actors/strife/beggars.txt +++ /dev/null @@ -1,87 +0,0 @@ - -// Base class for the beggars --------------------------------------------- - -ACTOR Beggar : StrifeHumanoid -{ - Health 20 - PainChance 250 - Speed 3 - Radius 20 - Height 56 - Monster - +JUSTHIT - -COUNTKILL - +NOSPLASHALERT - MinMissileChance 150 - Tag "$TAG_BEGGAR" - MaxStepHeight 16 - MaxDropoffHeight 32 - HitObituary "$OB_BEGGAR" - - AttackSound "beggar/attack" - PainSound "beggar/pain" - DeathSound "beggar/death" - States - { - Spawn: - BEGR A 10 A_Look - Loop - See: - BEGR AABBCC 4 A_Wander - Loop - Melee: - BEGR D 8 - BEGR D 8 A_CustomMeleeAttack(2*random[PeasantAttack](1,5)+2) - BEGR E 1 A_Chase - BEGR D 8 A_SentinelRefire - Loop - Pain: - BEGR A 3 A_Pain - BEGR A 3 A_Chase - Goto Melee - Death: - BEGR F 4 - BEGR G 4 A_Scream - BEGR H 4 - BEGR I 4 A_NoBlocking - BEGR JKLM 4 - BEGR N -1 - Stop - XDeath: - BEGR F 5 A_TossGib - GIBS M 5 A_TossGib - GIBS N 5 A_XScream - GIBS O 5 A_NoBlocking - GIBS PQRST 4 A_TossGib - GIBS U 5 - GIBS V 1400 - Stop - } -} - - -// Beggars ----------------------------------------------------------------- - -ACTOR Beggar1 : Beggar -{ -} - - -ACTOR Beggar2 : Beggar -{ -} - - -ACTOR Beggar3 : Beggar -{ -} - - -ACTOR Beggar4 : Beggar -{ -} - - -ACTOR Beggar5 : Beggar -{ -} diff --git a/wadsrc/static/actors/strife/coin.txt b/wadsrc/static/actors/strife/coin.txt deleted file mode 100644 index b410d25a1..000000000 --- a/wadsrc/static/actors/strife/coin.txt +++ /dev/null @@ -1,84 +0,0 @@ - -// Coin --------------------------------------------------------------------- - -ACTOR Coin : Inventory native -{ - +DROPPED - +NOTDMATCH - +FLOORCLIP - Inventory.MaxAmount 0x7fffffff - +INVENTORY.INVBAR - Tag "$TAG_COIN" - Inventory.Icon "I_COIN" - Inventory.PickupMessage "$TXT_COIN" - States - { - Spawn: - COIN A -1 - Stop - } -} - - -// 10 Gold ------------------------------------------------------------------ - -ACTOR Gold10 : Coin -{ - Inventory.Amount 10 - Tag "$TAG_10GOLD" - Inventory.PickupMessage "$TXT_10GOLD" - States - { - Spawn: - CRED A -1 - Stop - } -} - -// 25 Gold ------------------------------------------------------------------ - -ACTOR Gold25 : Coin -{ - Inventory.Amount 25 - Tag "$TAG_25GOLD" - Inventory.PickupMessage "$TXT_25GOLD" - States - { - Spawn: - SACK A -1 - Stop - } -} - -// 50 Gold ------------------------------------------------------------------ - -ACTOR Gold50 : Coin -{ - Inventory.Amount 50 - Tag "$TAG_50GOLD" - Inventory.PickupMessage "$TXT_50GOLD" - States - { - Spawn: - CHST A -1 - Stop - } -} - -// 300 Gold ------------------------------------------------------------------ - -ACTOR Gold300 : Coin -{ - Inventory.Amount 300 - Tag "$TAG_300GOLD" - Inventory.PickupMessage "$TXT_300GOLD" - Inventory.GiveQuest 3 - +INVENTORY.ALWAYSPICKUP - States - { - Spawn: - TOKN A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/crusader.txt b/wadsrc/static/actors/strife/crusader.txt deleted file mode 100644 index c39747471..000000000 --- a/wadsrc/static/actors/strife/crusader.txt +++ /dev/null @@ -1,122 +0,0 @@ - -// Crusader ----------------------------------------------------------------- - -ACTOR Crusader -{ - Speed 8 - Radius 40 - Height 56 - Mass 400 - Health 400 - Painchance 128 - Monster - +FLOORCLIP - +DONTMORPH - +MISSILEMORE - +INCOMBAT - +NOICEDEATH - +NOBLOOD - MinMissileChance 120 - MaxDropoffHeight 32 - DropItem "EnergyPod", 256, 20 - SeeSound "crusader/sight" - PainSound "crusader/pain" - DeathSound "crusader/death" - ActiveSound "crusader/active" - Obituary "$OB_CRUSADER" - - action native A_CrusaderChoose (); - action native A_CrusaderSweepLeft (); - action native A_CrusaderSweepRight (); - action native A_CrusaderRefire (); - action native A_CrusaderDeath (); - - States - { - Spawn: - ROB2 Q 10 A_Look - Loop - See: - ROB2 AABBCCDD 3 A_Chase - Loop - Missile: - ROB2 E 3 Slow A_FaceTarget - ROB2 F 2 Slow Bright A_CrusaderChoose - ROB2 E 2 Slow Bright A_CrusaderSweepLeft - ROB2 F 3 Slow Bright A_CrusaderSweepLeft - ROB2 EF 2 Slow Bright A_CrusaderSweepLeft - ROB2 EFE 2 Slow Bright A_CrusaderSweepRight - ROB2 F 2 Slow A_CrusaderRefire - Loop - Pain: - ROB2 D 1 Slow A_Pain - Goto See - Death: - ROB2 G 3 A_Scream - ROB2 H 5 A_TossGib - ROB2 I 4 Bright A_TossGib - ROB2 J 4 Bright A_Explode(64,64,1,1) - ROB2 K 4 Bright A_Fall - ROB2 L 4 A_Explode(64,64,1,1) - ROB2 MN 4 A_TossGib - ROB2 O 4 A_Explode(64,64,1,1) - ROB2 P -1 A_CrusaderDeath - Stop - } -} - - -// Fast Flame Projectile (used by Crusader) --------------------------------- - -ACTOR FastFlameMissile : FlameMissile -{ - Mass 50 - Damage 1 - Speed 35 -} - -// Crusader Missile --------------------------------------------------------- -// This is just like the mini missile the player shoots, except it doesn't -// explode when it dies, and it does slightly less damage for a direct hit. - -ACTOR CrusaderMissile -{ - Speed 20 - Radius 10 - Height 14 - Damage 7 - Projectile - +STRIFEDAMAGE - MaxStepHeight 4 - SeeSound "crusader/misl" - DeathSound "crusader/mislx" - States - { - Spawn: - MICR A 6 Bright A_RocketInFlight - Loop - Death: - SMIS A 0 Bright A_SetTranslucent(1,1) - SMIS A 5 Bright - SMIS B 5 Bright - SMIS C 4 Bright - SMIS DEFG 2 Bright - Stop - } -} - - -// Dead Crusader ------------------------------------------------------------ - -ACTOR DeadCrusader -{ - States - { - Spawn: - ROB2 N 4 - ROB2 O 4 - ROB2 P -1 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/entityboss.txt b/wadsrc/static/actors/strife/entityboss.txt deleted file mode 100644 index ddd19d9ef..000000000 --- a/wadsrc/static/actors/strife/entityboss.txt +++ /dev/null @@ -1,199 +0,0 @@ - -// Entity Nest -------------------------------------------------------------- - -ACTOR EntityNest -{ - Radius 84 - Height 47 - +SOLID - +NOTDMATCH - +FLOORCLIP - States - { - Spawn: - NEST A -1 - Stop - } -} - -// Entity Pod --------------------------------------------------------------- - -ACTOR EntityPod -{ - Radius 25 - Height 91 - +SOLID - +NOTDMATCH - SeeSound "misc/gibbed" - - action native A_SpawnEntity (); - - States - { - Spawn: - PODD A 60 A_Look - Loop - See: - PODD A 360 - PODD B 9 A_NoBlocking - PODD C 9 - PODD D 9 A_SpawnEntity - PODD E -1 - Stop - } -} - - -// Entity Boss -------------------------------------------------------------- - -ACTOR EntityBoss : SpectralMonster -{ - Health 2500 - Painchance 255 - Speed 13 - Radius 130 - Height 200 - FloatSpeed 5 - Mass 1000 - Monster - +SPECIAL - +NOGRAVITY - +FLOAT - +SHADOW - +NOTDMATCH - +DONTMORPH - +NOTARGET - +NOBLOCKMONST - +INCOMBAT - +LOOKALLAROUND - +SPECTRAL - +NOICEDEATH - MinMissileChance 150 - RenderStyle Translucent - Alpha 0.5 - SeeSound "entity/sight" - AttackSound "entity/melee" - PainSound "entity/pain" - DeathSound "entity/death" - ActiveSound "entity/active" - Obituary "$OB_ENTITY" - - action native A_EntityAttack(); - action native A_EntityDeath(); - - States - { - Spawn: - MNAM A 100 - MNAM B 60 Bright - MNAM CDEFGHIJKL 4 Bright - MNAL A 4 Bright A_Look - MNAL B 4 Bright A_SentinelBob - Goto Spawn+12 - See: - MNAL AB 4 Bright A_Chase - MNAL C 4 Bright A_SentinelBob - MNAL DEF 4 Bright A_Chase - MNAL G 4 Bright A_SentinelBob - MNAL HIJ 4 Bright A_Chase - MNAL K 4 Bright A_SentinelBob - Loop - Melee: - MNAL J 4 Bright A_FaceTarget - MNAL I 4 Bright A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5) - MNAL C 4 Bright - Goto See+2 - Missile: - MNAL F 4 Bright A_FaceTarget - MNAL I 4 Bright A_EntityAttack - MNAL E 4 Bright - Goto See+10 - Pain: - MNAL J 2 Bright A_Pain - Goto See+6 - Death: - MNAL L 7 Bright A_SpectreChunkSmall - MNAL M 7 Bright A_Scream - MNAL NO 7 Bright A_SpectreChunkSmall - MNAL P 7 Bright A_SpectreChunkLarge - MNAL Q 64 Bright A_SpectreChunkSmall - MNAL Q 6 Bright A_EntityDeath - Stop - } -} - -// Second Entity Boss ------------------------------------------------------- - -ACTOR EntitySecond : SpectralMonster -{ - Health 990 - Painchance 255 - Speed 14 - Radius 130 - Height 200 - FloatSpeed 5 - Mass 1000 - Monster - +SPECIAL - +NOGRAVITY - +FLOAT - +SHADOW - +NOTDMATCH - +DONTMORPH - +NOBLOCKMONST - +INCOMBAT - +LOOKALLAROUND - +SPECTRAL - +NOICEDEATH - MinMissileChance 150 - RenderStyle Translucent - Alpha 0.25 - SeeSound "alienspectre/sight" - AttackSound "alienspectre/blade" - PainSound "alienspectre/pain" - DeathSound "alienspectre/death" - ActiveSound "alienspectre/active" - Obituary "$OB_ENTITY" - - action native A_SubEntityDeath (); - - States - { - Spawn: - MNAL R 10 Bright A_Look - Loop - See: - MNAL R 5 Bright A_SentinelBob - MNAL ST 5 Bright A_Chase - MNAL U 5 Bright A_SentinelBob - MNAL V 5 Bright A_Chase - MNAL W 5 Bright A_SentinelBob - Loop - Melee: - MNAL S 4 Bright A_FaceTarget - MNAL R 4 Bright A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5) - MNAL T 4 Bright A_SentinelBob - Goto See+1 - Missile: - MNAL W 4 Bright A_FaceTarget - MNAL U 4 Bright A_CustomMissile("SpectralLightningH3",32,0) - MNAL V 4 Bright A_SentinelBob - Goto See+4 - Pain: - MNAL R 2 Bright A_Pain - Goto See - Death: - MDTH A 3 Bright A_Scream - MDTH B 3 Bright A_TossGib - MDTH C 3 Bright A_NoBlocking - MDTH DEFGHIJKLMN 3 Bright A_TossGib - MDTH O 3 Bright A_SubEntityDeath - Stop - } -} - - - - - - diff --git a/wadsrc/static/actors/strife/inquisitor.txt b/wadsrc/static/actors/strife/inquisitor.txt deleted file mode 100644 index 5b9495d40..000000000 --- a/wadsrc/static/actors/strife/inquisitor.txt +++ /dev/null @@ -1,141 +0,0 @@ - -// Inquisitor --------------------------------------------------------------- - -ACTOR Inquisitor -{ - Health 1000 - Speed 12 - Radius 40 - Height 110 - Mass 0x7fffffff - Monster - +DROPOFF - +NOBLOOD - +BOSS - +FLOORCLIP - +DONTMORPH - +NORADIUSDMG - MaxDropOffHeight 32 - MinMissileChance 150 - SeeSound "inquisitor/sight" - DeathSound "inquisitor/death" - ActiveSound "inquisitor/active" - Obituary "$OB_INQUISITOR" - - action native A_InquisitorWalk (); - action native A_InquisitorDecide (); - action native A_InquisitorAttack (); - action native A_InquisitorJump (); - action native A_InquisitorCheckLand (); - action native A_TossArm (); - action native A_ReaverRanged (); - - states - { - Spawn: - ROB3 AB 10 A_Look - Loop - See: - ROB3 B 3 A_InquisitorWalk - ROB3 B 3 A_Chase - ROB3 CCDD 4 A_Chase - ROB3 E 3 A_InquisitorWalk - ROB3 E 3 A_InquisitorDecide - Loop - Missile: - ROB3 A 2 A_InquisitorDecide - ROB3 F 6 A_FaceTarget - ROB3 G 8 Bright A_ReaverRanged - ROB3 G 8 A_ReaverRanged - Goto See - Grenade: - ROB3 K 12 A_FaceTarget - ROB3 J 6 Bright A_InquisitorAttack - ROB3 K 12 - Goto See - Jump: - ROB3 H 8 Bright A_InquisitorJump - ROB3 I 4 Bright A_InquisitorCheckLand - ROB3 H 4 Bright A_InquisitorCheckLand - Goto Jump+1 - Death: - ROB3 L 0 A_StopSoundEx("Item") - ROB3 L 4 A_TossGib - ROB3 M 4 A_Scream - ROB3 N 4 A_TossGib - ROB3 O 4 Bright A_Explode(128,128,1,1) - ROB3 P 4 Bright A_TossGib - ROB3 Q 4 Bright A_NoBlocking - ROB3 RSTUV 4 A_TossGib - ROB3 W 4 Bright A_Explode(128,128,1,1) - ROB3 XY 4 Bright A_TossGib - ROB3 Z 4 A_TossGib - ROB3 "[" 4 A_TossGib - ROB3 "\" 3 A_TossGib - ROB3 "]" 3 Bright A_Explode(128,128,1,1) - RBB3 A 3 Bright A_TossArm - RBB3 B 3 Bright A_TossGib - RBB3 CD 3 A_TossGib - RBB3 E -1 - Stop - } -} - -// Inquisitor Shot ---------------------------------------------------------- - -ACTOR InquisitorShot -{ - ReactionTime 15 - Speed 25 - Radius 13 - Height 13 - Mass 15 - Projectile - -ACTIVATEIMPACT - -ACTIVATEPCROSS - -NOGRAVITY - +STRIFEDAMAGE - MaxStepHeight 4 - SeeSound "inquisitor/attack" - DeathSound "inquisitor/atkexplode" - States - { - Spawn: - UBAM AB 3 A_Countdown - Loop - Death: - BNG2 A 0 Bright A_SetTranslucent(1,1) - BNG2 A 4 Bright A_Explode(192, 192, 1, 1) - BNG2 B 4 Bright - BNG2 C 4 Bright - BNG2 D 4 Bright - BNG2 E 4 Bright - BNG2 F 4 Bright - BNG2 G 4 Bright - BNG2 H 4 Bright - BNG2 I 4 Bright - Stop - } - -} - - -// The Dead Inquisitor's Detached Arm --------------------------------------- - -ACTOR InquisitorArm -{ - Speed 25 - +NOBLOCKMAP - +NOCLIP - +NOBLOOD - States - { - Spawn: - RBB3 FG 5 Bright - RBB3 H -1 - Stop - } -} - - - diff --git a/wadsrc/static/actors/strife/loremaster.txt b/wadsrc/static/actors/strife/loremaster.txt deleted file mode 100644 index fd2b400cb..000000000 --- a/wadsrc/static/actors/strife/loremaster.txt +++ /dev/null @@ -1,114 +0,0 @@ - -// Loremaster (aka Priest) -------------------------------------------------- - -ACTOR Loremaster -{ - Health 800 - Speed 10 - Radius 15 - Height 56 - FloatSpeed 5 - Monster - +FLOAT - +NOBLOOD - +NOGRAVITY - +NOTDMATCH - +FLOORCLIP - +NOBLOCKMONST - +INCOMBAT - +LOOKALLAROUND - +NOICEDEATH - +NEVERRESPAWN - DamageFactor "Fire", 0.5 - MinMissileChance 150 - Tag "$TAG_PRIEST" - SeeSound "loremaster/sight" - AttackSound "loremaster/attack" - PainSound "loremaster/pain" - DeathSound "loremaster/death" - ActiveSound "loremaster/active" - Obituary "$OB_LOREMASTER" - DropItem "Junk" - states - { - Spawn: - PRST A 10 A_Look - PRST B 10 A_SentinelBob - Loop - See: - PRST A 4 A_Chase - PRST A 4 A_SentinelBob - PRST B 4 A_Chase - PRST B 4 A_SentinelBob - PRST C 4 A_Chase - PRST C 4 A_SentinelBob - PRST D 4 A_Chase - PRST D 4 A_SentinelBob - Loop - Melee: - PRST E 4 A_FaceTarget - PRST F 4 A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5) - PRST E 4 A_SentinelBob - Goto See - Missile: - PRST E 4 A_FaceTarget - PRST F 4 A_CustomMissile("LoreShot", 32, 0) - PRST E 4 A_SentinelBob - Goto See - Death: - PDED A 6 - PDED B 6 A_Scream - PDED C 6 - PDED D 6 A_Fall - PDED E 6 - PDED FGHIJIJIJKL 5 - PDED MNOP 4 - PDED Q 4 A_SpawnItemEx("AlienSpectre5", 0, 0, 0, 0, 0, random[spectrespawn](0,255)*0.0078125, 0, SXF_NOCHECKPOSITION) - PDED RS 4 - PDED T -1 - Stop - } -} - - -// Loremaster Projectile ---------------------------------------------------- - -ACTOR LoreShot native -{ - Speed 20 - Height 14 - Radius 10 - Projectile - +STRIFEDAMAGE - Damage 2 - MaxStepHeight 4 - SeeSound "loremaster/chain" - ActiveSound "loremaster/swish" - - action native A_LoremasterChain (); - - States - { - Spawn: - OCLW A 2 A_LoremasterChain - Loop - Death: - OCLW A 6 - Stop - } -} - -// Loremaster Subprojectile ------------------------------------------------- - -ACTOR LoreShot2 -{ - +NOBLOCKMAP - +NOGRAVITY - States - { - Spawn: - TEND A 20 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/macil.txt b/wadsrc/static/actors/strife/macil.txt deleted file mode 100644 index 7c03d1f24..000000000 --- a/wadsrc/static/actors/strife/macil.txt +++ /dev/null @@ -1,89 +0,0 @@ - -// Macil (version 1) --------------------------------------------------------- - -ACTOR Macil1 -{ - Health 95 - Radius 20 - Height 56 - Speed 8 - Painchance 250 - Monster - -COUNTKILL - +NOTDMATCH - +NOICEDEATH - +NOSPLASHALERT - +NODAMAGE - +NEVERRESPAWN - DamageFactor "Fire", 0.5 - MinMissileChance 150 - SeeSound "macil/sight" - PainSound "macil/pain" - ActiveSound "macil/active" - CrushPainSound "misc/pcrush" - Tag "$TAG_MACIL1" - Obituary "$OB_MACIL" - DropItem "BoxOfBullets" - MaxStepHeight 16 - MaxDropoffHeight 32 - States - { - Spawn: - LEDR C 5 A_Look2 - Loop - LEDR A 8 - Loop - LEDR B 8 - Loop - LEAD ABCD 6 A_Wander - Loop - See: - LEAD AABBCCDD 3 A_Chase - Loop - Missile: - Death: - LEAD E 2 A_FaceTarget - LEAD F 2 BRIGHT A_ShootGun - LEAD E 1 A_SentinelRefire - Loop - Pain: - LEAD Y 3 - LEAD Y 3 A_Pain - Goto See - } -} - - -// Macil (version 2) --------------------------------------------------------- - -ACTOR Macil2 : Macil1 -{ - Painchance 200 - +COUNTKILL - +SPECTRAL - -NODAMAGE - Tag "$TAG_MACIL2" - DeathSound "macil/slop" - DropItem "None" - DamageFactor "SpectralLow", 0 - States - { - Missile: - LEAD E 4 A_FaceTarget - LEAD F 4 BRIGHT A_ShootGun - LEAD E 2 A_SentinelRefire - Loop - Death: - LEAD G 5 - LEAD H 5 A_Scream - LEAD IJ 4 - LEAD K 3 - LEAD L 3 A_NoBlocking - LEAD MNOPQRSTUV 3 - LEAD W 3 A_SpawnItemEx("AlienSpectre4", 0, 0, 0, 0, 0, random[spectrespawn](0,255)*0.0078125, 0, SXF_NOCHECKPOSITION) - LEAD X -1 - Stop - } -} - - diff --git a/wadsrc/static/actors/strife/merchants.txt b/wadsrc/static/actors/strife/merchants.txt deleted file mode 100644 index 1a843f47a..000000000 --- a/wadsrc/static/actors/strife/merchants.txt +++ /dev/null @@ -1,93 +0,0 @@ -// Base class for the merchants --------------------------------------------- - -ACTOR Merchant -{ - Health 10000000 - PainChance 256 // a merchant should always enter the pain state when getting hurt - Radius 20 - Height 56 - Mass 5000 - CrushPainSound "misc/pcrush" - +SOLID - +SHOOTABLE - +NOTDMATCH - +NOSPLASHALERT - +NODAMAGE - States - { - Spawn: - MRST A 10 A_Look2 - Loop - MRLK A 30 A_ActiveSound - Loop - MRLK B 30 - Loop - MRBD ABCDEDCB 4 - MRBD A 5 - MRBD F 6 - Loop - See: - Pain: - MRPN A 1 - MRPN A 2 A_AlertMonsters - MRPN B 3 A_Pain - MRPN C 3 - MRPN D 9 Door_CloseWaitOpen(999, 64, 960) - MRPN C 4 - MRPN B 3 - MRPN A 3 A_ClearSoundTarget - Goto Spawn - Yes: - MRYS A 20 - // Fall through - Greetings: - MRGT ABCDEFGHI 5 - Goto Spawn - No: - MRNO AB 6 - MRNO C 10 - MRNO BA 6 - Goto Greetings - } -} - - -// Weapon Smith ------------------------------------------------------------- - -ACTOR WeaponSmith : Merchant -{ - PainSound "smith/pain" - Tag "$TAG_WEAPONSMITH" -} - - -// Bar Keep ----------------------------------------------------------------- - -ACTOR BarKeep : Merchant -{ - Translation 4 - PainSound "barkeep/pain" - ActiveSound "barkeep/active" - Tag "$TAG_BARKEEP" -} - - -// Armorer ------------------------------------------------------------------ - -ACTOR Armorer : Merchant -{ - Translation 5 - PainSound "armorer/pain" - Tag "$TAG_ARMORER" -} - - -// Medic -------------------------------------------------------------------- - -ACTOR Medic : Merchant -{ - Translation 6 - PainSound "medic/pain" - Tag "$TAG_MEDIC" -} - diff --git a/wadsrc/static/actors/strife/oracle.txt b/wadsrc/static/actors/strife/oracle.txt deleted file mode 100644 index 8502bae96..000000000 --- a/wadsrc/static/actors/strife/oracle.txt +++ /dev/null @@ -1,35 +0,0 @@ - -// Oracle ------------------------------------------------------------------- - -ACTOR Oracle -{ - Health 1 - Radius 15 - Height 56 - Monster - +NOTDMATCH - +NOBLOOD - +NEVERRESPAWN - DamageFactor "Fire", 0.5 - DamageFactor "SpectralLow", 0 - MaxDropoffHeight 32 - Tag "$TAG_ORACLE" - DropItem "Meat" - - action native A_WakeOracleSpectre (); - - States - { - Spawn: - ORCL A -1 - Stop - Death: - ORCL BCDEFGHIJK 5 - ORCL L 5 A_NoBlocking - ORCL M 5 - ORCL N 5 A_WakeOracleSpectre - ORCL OP 5 - ORCL Q -1 - Stop - } -} diff --git a/wadsrc/static/actors/strife/peasants.txt b/wadsrc/static/actors/strife/peasants.txt deleted file mode 100644 index b5ec89258..000000000 --- a/wadsrc/static/actors/strife/peasants.txt +++ /dev/null @@ -1,182 +0,0 @@ - -// Peasant Base Class ------------------------------------------------------- - -ACTOR Peasant : StrifeHumanoid -{ - Health 31 - PainChance 200 - Speed 8 - Radius 20 - Height 56 - Monster - +NEVERTARGET - -COUNTKILL - +NOSPLASHALERT - +FLOORCLIP - +JUSTHIT - MinMissileChance 150 - MaxStepHeight 16 - MaxDropoffHeight 32 - SeeSound "peasant/sight" - AttackSound "peasant/attack" - PainSound "peasant/pain" - DeathSound "peasant/death" - HitObituary "$OB_PEASANT" - States - { - Spawn: - PEAS A 10 A_Look2 - Loop - See: - PEAS AABBCCDD 5 A_Wander - Goto Spawn - Melee: - PEAS E 10 A_FaceTarget - PEAS F 8 A_CustomMeleeAttack(2*random[PeasantAttack](1,5)+2) - PEAS E 8 - Goto See - Pain: - PEAS O 3 - PEAS O 3 A_Pain - Goto Melee - Wound: - PEAS G 5 - PEAS H 10 A_GetHurt - PEAS I 6 - Goto Wound+1 - Death: - PEAS G 5 - PEAS H 5 A_Scream - PEAS I 6 - PEAS J 5 A_NoBlocking - PEAS K 5 - PEAS L 6 - PEAS M 8 - PEAS N 1400 - GIBS U 5 - GIBS V 1400 - Stop - XDeath: - GIBS M 5 A_TossGib - GIBS N 5 A_XScream - GIBS O 5 A_NoBlocking - GIBS PQRS 4 A_TossGib - Goto Death+8 - } -} - -// Peasant Variant 1 -------------------------------------------------------- - -ACTOR Peasant1 : Peasant -{ - Speed 4 -} - -ACTOR Peasant2 : Peasant -{ - Speed 5 -} - -ACTOR Peasant3 : Peasant -{ - Speed 5 -} - -ACTOR Peasant4 : Peasant -{ - Translation 0 - Speed 7 -} - -ACTOR Peasant5 : Peasant -{ - Translation 0 - Speed 7 -} - -ACTOR Peasant6 : Peasant -{ - Translation 0 - Speed 7 -} - -ACTOR Peasant7 : Peasant -{ - Translation 2 -} - -ACTOR Peasant8 : Peasant -{ - Translation 2 -} - -ACTOR Peasant9 : Peasant -{ - Translation 2 -} - -ACTOR Peasant10 : Peasant -{ - Translation 1 -} - -ACTOR Peasant11 : Peasant -{ - Translation 1 -} - -ACTOR Peasant12 : Peasant -{ - Translation 1 -} - -ACTOR Peasant13 : Peasant -{ - Translation 3 -} - -ACTOR Peasant14 : Peasant -{ - Translation 3 -} - -ACTOR Peasant15 : Peasant -{ - Translation 3 -} - -ACTOR Peasant16 : Peasant -{ - Translation 5 -} - -ACTOR Peasant17 : Peasant -{ - Translation 5 -} - -ACTOR Peasant18 : Peasant -{ - Translation 5 -} - -ACTOR Peasant19 : Peasant -{ - Translation 4 -} - -ACTOR Peasant20 : Peasant -{ - Translation 4 -} - -ACTOR Peasant21 : Peasant -{ - Translation 4 -} - -ACTOR Peasant22 : Peasant -{ - Translation 6 -} - diff --git a/wadsrc/static/actors/strife/programmer.txt b/wadsrc/static/actors/strife/programmer.txt deleted file mode 100644 index d9544af9c..000000000 --- a/wadsrc/static/actors/strife/programmer.txt +++ /dev/null @@ -1,107 +0,0 @@ - -// Programmer --------------------------------------------------------------- - -ACTOR Programmer -{ - Health 1100 - PainChance 50 - Speed 26 - FloatSpeed 5 - Radius 45 - Height 60 - Mass 800 - Damage 4 - Monster - +NOGRAVITY - +FLOAT - +NOBLOOD - +NOTDMATCH - +DONTMORPH - +NOBLOCKMONST - +LOOKALLAROUND - +NOICEDEATH - +NOTARGETSWITCH - DamageFactor "Fire", 0.5 - MinMissileChance 150 - AttackSound "programmer/attack" - PainSound "programmer/pain" - DeathSound "programmer/death" - ActiveSound "programmer/active" - Obituary "$OB_PROGRAMMER" - DropItem "Sigil1" - - action native A_ProgrammerMelee (); - action native A_SpawnProgrammerBase (); - action native A_ProgrammerDeath (); - action native A_SpotLightning(); - - States - { - Spawn: - PRGR A 5 A_Look - PRGR A 1 A_SentinelBob - Loop - See: - PRGR A 160 A_SentinelBob - PRGR BCD 5 A_SentinelBob - PRGR EF 2 A_SentinelBob - PRGR EF 3 A_Chase - Goto See+4 - Melee: - PRGR E 2 A_SentinelBob - PRGR F 3 A_SentinelBob - PRGR E 3 A_FaceTarget - PRGR F 4 A_ProgrammerMelee - Goto See+4 - Missile: - PRGR G 5 A_FaceTarget - PRGR H 5 A_SentinelBob - PRGR I 5 Bright A_FaceTarget - PRGR J 5 Bright A_SpotLightning - Goto See+4 - Pain: - PRGR K 5 A_Pain - PRGR L 5 A_SentinelBob - Goto See+4 - Death: - PRGR L 7 Bright A_TossGib - PRGR M 7 Bright A_Scream - PRGR N 7 Bright A_TossGib - PRGR O 7 Bright A_NoBlocking - PRGR P 7 Bright A_TossGib - PRGR Q 7 Bright A_SpawnProgrammerBase - PRGR R 7 Bright - PRGR S 6 Bright - PRGR TUVW 5 Bright - PRGR X 32 Bright - PRGR X -1 Bright A_ProgrammerDeath - Stop - } -} - - -// The Programmer's base for when he dies ----------------------------------- - -ACTOR ProgrammerBase -{ - +NOBLOCKMAP - +NOCLIP - +NOBLOOD - states - { - Spawn: - BASE A 5 Bright A_Explode(32,32,1,1) - BASE BCD 5 Bright - BASE EFG 5 - BASE H -1 - Stop - } -} - - -// The Programmer level ending thing ---------------------------------------- - -ACTOR ProgLevelEnder : Inventory native -{ - +INVENTORY.UNDROPPABLE -} diff --git a/wadsrc/static/actors/strife/ratbuddy.txt b/wadsrc/static/actors/strife/ratbuddy.txt deleted file mode 100644 index c6a1baf9c..000000000 --- a/wadsrc/static/actors/strife/ratbuddy.txt +++ /dev/null @@ -1,34 +0,0 @@ - -ACTOR RatBuddy -{ - Health 5 - Speed 13 - Radius 10 - Height 16 - +NOBLOOD +FLOORCLIP +CANPASS - +ISMONSTER +INCOMBAT - MinMissileChance 150 - MaxStepHeight 16 - MaxDropoffHeight 32 - Tag "$TAG_RATBUDDY" - SeeSound "rat/sight" - DeathSound "rat/death" - ActiveSound "rat/active" - States - { - Spawn: - RATT A 10 A_Look - Loop - See: - RATT AABB 4 A_Chase - Loop - Melee: - RATT A 8 A_Wander - RATT B 4 A_Wander - Goto See - Death: - MEAT Q 700 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/reaver.txt b/wadsrc/static/actors/strife/reaver.txt deleted file mode 100644 index 816070d47..000000000 --- a/wadsrc/static/actors/strife/reaver.txt +++ /dev/null @@ -1,64 +0,0 @@ - -ACTOR Reaver -{ - Health 150 - Painchance 128 - Speed 12 - Radius 20 - Height 60 - Monster - +NOBLOOD - +INCOMBAT - MinMissileChance 150 - MaxDropoffHeight 32 - Mass 500 - SeeSound "reaver/sight" - PainSound "reaver/pain" - DeathSound "reaver/death" - ActiveSound "reaver/active" - HitObituary "$OB_REAVERHIT" - Obituary "$OB_REAVER" - - action native A_ReaverRanged (); - - States - { - Spawn: - ROB1 A 10 A_Look - Loop - See: - ROB1 BBCCDDEE 3 A_Chase - Loop - Melee: - ROB1 H 6 Slow A_FaceTarget - ROB1 I 8 Slow A_CustomMeleeAttack(random[ReaverMelee](1,8)*3, "reaver/blade") - ROB1 H 6 Slow - Goto See - Missile: - ROB1 F 8 Slow A_FaceTarget - ROB1 G 11 Slow BRIGHT A_ReaverRanged - Goto See - Pain: - ROB1 A 2 Slow - ROB1 A 2 A_Pain - Goto See - Death: - ROB1 J 6 - ROB1 K 6 A_Scream - ROB1 L 5 - ROB1 M 5 A_NoBlocking - ROB1 NOP 5 - ROB1 Q 6 A_Explode(32,32,1,1) - ROB1 R -1 - Stop - XDeath: - ROB1 L 5 A_TossGib - ROB1 M 5 A_Scream - ROB1 N 5 A_TossGib - ROB1 O 5 A_NoBlocking - ROB1 P 5 A_TossGib - Goto Death+7 - } - -} - \ No newline at end of file diff --git a/wadsrc/static/actors/strife/rebels.txt b/wadsrc/static/actors/strife/rebels.txt deleted file mode 100644 index 2dcb5ac1a..000000000 --- a/wadsrc/static/actors/strife/rebels.txt +++ /dev/null @@ -1,131 +0,0 @@ - - -// Base class for the rebels ------------------------------------------------ - -ACTOR Rebel : StrifeHumanoid -{ - Health 60 - Painchance 250 - Speed 8 - Radius 20 - Height 56 - Monster - +FRIENDLY - -COUNTKILL - +NOSPLASHALERT - MinMissileChance 150 - Tag "$TAG_REBEL" - SeeSound "rebel/sight" - PainSound "rebel/pain" - DeathSound "rebel/death" - ActiveSound "rebel/active" - Obituary "$OB_REBEL" - States - { - Spawn: - HMN1 P 5 A_Look2 - Loop - HMN1 Q 8 - Loop - HMN1 R 8 - Loop - HMN1 ABCDABCD 6 A_Wander - Loop - See: - HMN1 AABBCCDD 3 A_Chase - Loop - Missile: - HMN1 E 10 A_FaceTarget - HMN1 F 10 BRIGHT A_ShootGun - HMN1 E 10 A_ShootGun - Goto See - Pain: - HMN1 O 3 - HMN1 O 3 A_Pain - Goto See - Death: - HMN1 G 5 - HMN1 H 5 A_Scream - HMN1 I 3 A_NoBlocking - HMN1 J 4 - HMN1 KLM 3 - HMN1 N -1 - Stop - XDeath: - RGIB A 4 A_TossGib - RGIB B 4 A_XScream - RGIB C 3 A_NoBlocking - RGIB DEF 3 A_TossGib - RGIB G 3 - RGIB H 1400 - Stop - } -} - -// Rebel 1 ------------------------------------------------------------------ - -ACTOR Rebel1 : Rebel -{ - DropItem "ClipOfBullets" -} - -// Rebel 2 ------------------------------------------------------------------ - -ACTOR Rebel2 : Rebel -{ -} - -// Rebel 3 ------------------------------------------------------------------ - -ACTOR Rebel3 : Rebel -{ -} - -// Rebel 4 ------------------------------------------------------------------ - -ACTOR Rebel4 : Rebel -{ -} - -// Rebel 5 ------------------------------------------------------------------ - -ACTOR Rebel5 : Rebel -{ -} - -// Rebel 6 ------------------------------------------------------------------ - -ACTOR Rebel6 : Rebel -{ -} - -// Teleporter Beacon -------------------------------------------------------- - -ACTOR TeleporterBeacon : Inventory native -{ - Health 5 - Radius 16 - Height 16 - Inventory.MaxAmount 3 - +DROPPED - +INVENTORY.INVBAR - Inventory.Icon "I_BEAC" - Tag "$TAG_TELEPORTERBEACON" - Inventory.PickupMessage "$TXT_BEACON" - - action native A_Beacon (); - - States - { - Spawn: - BEAC A -1 - Stop - Drop: - BEAC A 30 - BEAC A 160 A_Beacon - Wait - Death: - BEAC A 1 A_FadeOut(0.015) - Loop - } -} \ No newline at end of file diff --git a/wadsrc/static/actors/strife/sentinel.txt b/wadsrc/static/actors/strife/sentinel.txt deleted file mode 100644 index ca61f2bf8..000000000 --- a/wadsrc/static/actors/strife/sentinel.txt +++ /dev/null @@ -1,95 +0,0 @@ - -// Sentinel ----------------------------------------------------------------- - -ACTOR Sentinel -{ - Health 100 - Painchance 255 - Speed 7 - Radius 23 - Height 53 - Mass 300 - Monster - +SPAWNCEILING - +NOGRAVITY - +DROPOFF - +NOBLOOD - +NOBLOCKMONST - +INCOMBAT - +MISSILEMORE - +LOOKALLAROUND - +NEVERRESPAWN - MinMissileChance 150 - SeeSound "sentinel/sight" - DeathSound "sentinel/death" - ActiveSound "sentinel/active" - Obituary "$OB_SENTINEL" - - action native A_SentinelAttack (); - - States - { - Spawn: - SEWR A 10 A_Look - Loop - See: - SEWR A 6 A_SentinelBob - SEWR A 6 A_Chase - Loop - Missile: - SEWR B 4 A_FaceTarget - SEWR C 8 Bright A_SentinelAttack - SEWR C 4 Bright A_SentinelRefire - Goto Missile+1 - Pain: - SEWR D 5 A_Pain - Goto Missile+2 - Death: - SEWR D 7 A_Fall - SEWR E 8 Bright A_TossGib - SEWR F 5 Bright A_Scream - SEWR GH 4 Bright A_TossGib - SEWR I 4 - SEWR J 5 - Stop - } -} - -// Sentinel FX 1 ------------------------------------------------------------ - -ACTOR SentinelFX1 -{ - Speed 40 - Radius 10 - Height 8 - Damage 0 - DamageType Disintegrate - Projectile - +STRIFEDAMAGE - MaxStepHeight 4 - RenderStyle Add - States - { - Spawn: - SHT1 AB 4 - Loop - Death: - POW1 J 4 - Stop - } -} - -// Sentinel FX 2 ------------------------------------------------------------ - -ACTOR SentinelFX2 : SentinelFX1 -{ - SeeSound "sentinel/plasma" - Damage 1 - States - { - Death: - POW1 FGHI 4 - Goto Super::Death - } -} - diff --git a/wadsrc/static/actors/strife/sigil.txt b/wadsrc/static/actors/strife/sigil.txt deleted file mode 100644 index 4c5f552d5..000000000 --- a/wadsrc/static/actors/strife/sigil.txt +++ /dev/null @@ -1,161 +0,0 @@ - -// The Almighty Sigil! ------------------------------------------------------ - -ACTOR Sigil : Weapon native -{ - - Weapon.Kickback 100 - Weapon.SelectionOrder 4000 - Health 1 - +FLOORCLIP - +WEAPON.CHEATNOTWEAPON - Inventory.PickupSound "weapons/sigilcharge" - Tag "$TAG_SIGIL" - Inventory.Icon "I_SGL1" - Inventory.PickupMessage "$TXT_SIGIL" - - action native A_SelectPiece (); - action native A_SelectSigilView (); - action native A_SelectSigilDown (); - action native A_SelectSigilAttack (); - action native A_SigilCharge (); - action native A_FireSigil1 (); - action native A_FireSigil2 (); - action native A_FireSigil3 (); - action native A_FireSigil4 (); - action native A_FireSigil5 (); - - States - { - Spawn: - SIGL A 1 - SIGL A -1 A_SelectPiece - Stop - SIGL B -1 - Stop - SIGL C -1 - Stop - SIGL D -1 - Stop - SIGL E -1 - Stop - Ready: - SIGH A 0 Bright A_SelectSigilView - Wait - SIGH A 1 Bright A_WeaponReady - Wait - SIGH B 1 Bright A_WeaponReady - Wait - SIGH C 1 Bright A_WeaponReady - Wait - SIGH D 1 Bright A_WeaponReady - Wait - SIGH E 1 Bright A_WeaponReady - Wait - Deselect: - SIGH A 1 Bright A_SelectSigilDown - Wait - SIGH A 1 Bright A_Lower - Wait - SIGH B 1 Bright A_Lower - Wait - SIGH C 1 Bright A_Lower - Wait - SIGH D 1 Bright A_Lower - Wait - SIGH E 1 Bright A_Lower - Wait - Select: - SIGH A 1 Bright A_SelectSigilView - Wait - SIGH A 1 Bright A_Raise - Wait - SIGH B 1 Bright A_Raise - Wait - SIGH C 1 Bright A_Raise - Wait - SIGH D 1 Bright A_Raise - Wait - SIGH E 1 Bright A_Raise - Wait - - Fire: - SIGH A 0 Bright A_SelectSigilAttack - - SIGH A 18 Bright A_SigilCharge - SIGH A 3 Bright A_GunFlash - SIGH A 10 A_FireSigil1 - SIGH A 5 - Goto Ready - - SIGH B 18 Bright A_SigilCharge - SIGH B 3 Bright A_GunFlash - SIGH B 10 A_FireSigil2 - SIGH B 5 - Goto Ready - - SIGH C 18 Bright A_SigilCharge - SIGH C 3 Bright A_GunFlash - SIGH C 10 A_FireSigil3 - SIGH C 5 - Goto Ready - - SIGH D 18 Bright A_SigilCharge - SIGH D 3 Bright A_GunFlash - SIGH D 10 A_FireSigil4 - SIGH D 5 - Goto Ready - - SIGH E 18 Bright A_SigilCharge - SIGH E 3 Bright A_GunFlash - SIGH E 10 A_FireSigil5 - SIGH E 5 - Goto Ready - Flash: - SIGF A 4 Bright A_Light2 - SIGF B 6 Bright A_LightInverse - SIGF C 4 Bright A_Light1 - SIGF C 0 Bright A_Light0 - Stop - } -} - -// Sigil 1 ------------------------------------------------------------------ - -ACTOR Sigil1 : Sigil -{ - Inventory.Icon "I_SGL1" - Health 1 -} - -// Sigil 2 ------------------------------------------------------------------ - -ACTOR Sigil2 : Sigil -{ - Inventory.Icon "I_SGL2" - Health 2 -} - -// Sigil 3 ------------------------------------------------------------------ - -ACTOR Sigil3 : Sigil -{ - Inventory.Icon "I_SGL3" - Health 3 -} - -// Sigil 4 ------------------------------------------------------------------ - -ACTOR Sigil4 : Sigil -{ - Inventory.Icon "I_SGL4" - Health 4 -} - -// Sigil 5 ------------------------------------------------------------------ - -ACTOR Sigil5 : Sigil -{ - Inventory.Icon "I_SGL5" - Health 5 -} diff --git a/wadsrc/static/actors/strife/spectral.txt b/wadsrc/static/actors/strife/spectral.txt deleted file mode 100644 index 6f9c87c0c..000000000 --- a/wadsrc/static/actors/strife/spectral.txt +++ /dev/null @@ -1,262 +0,0 @@ - - -// base for all spectral monsters which hurt when being touched-------------- - -ACTOR SpectralMonster native -{ - Monster - +SPECIAL - +SPECTRAL - +NOICEDEATH - - action native A_SpectreChunkSmall (); - action native A_SpectreChunkLarge (); - action native A_Spectre3Attack (); - action native A_SpotLightning (); -} - - -// Container for all spectral lightning deaths ------------------------------ - -ACTOR SpectralLightningBase -{ - +NOTELEPORT - +ACTIVATEIMPACT - +ACTIVATEPCROSS - +STRIFEDAMAGE - MaxStepHeight 4 - RenderStyle Add - SeeSound "weapons/sigil" - DeathSound "weapons/sigilhit" - States - { - Death: - ZAP1 B 3 A_Explode(32,32) - ZAP1 A 3 A_AlertMonsters - ZAP1 BCDEFE 3 - ZAP1 DCB 2 - ZAP1 A 1 - Stop - } -} - -// Spectral Lightning death that does not explode --------------------------- - -ACTOR SpectralLightningDeath1 : SpectralLightningBase -{ - States - { - Death: - Goto Super::Death+1 - } -} - -// Spectral Lightning death that does not alert monsters -------------------- - -ACTOR SpectralLightningDeath2 : SpectralLightningBase -{ - States - { - Death: - Goto Super::Death+2 - } -} - -// Spectral Lightning death that is shorter than the rest ------------------- - -ACTOR SpectralLightningDeathShort : SpectralLightningBase -{ - States - { - Death: - Goto Super::Death+6 - } -} - -// Spectral Lightning (Ball Shaped #1) -------------------------------------- - -ACTOR SpectralLightningBall1 : SpectralLightningBase -{ - Speed 30 - Radius 8 - Height 16 - Damage 70 - Projectile - +SPECTRAL - States - { - Spawn: - ZOT3 ABCDE 4 Bright - Loop - } -} - -// Spectral Lightning (Ball Shaped #2) -------------------------------------- - -ACTOR SpectralLightningBall2 : SpectralLightningBall1 -{ - Damage 20 -} - -// Spectral Lightning (Horizontal #1) --------------------------------------- - -ACTOR SpectralLightningH1 : SpectralLightningBase -{ - Speed 30 - Radius 8 - Height 16 - Damage 70 - Projectile - +SPECTRAL - - action native A_SpectralLightningTail (); - - States - { - Spawn: - ZAP6 A 4 Bright - ZAP6 BC 4 Bright A_SpectralLightningTail - Loop - } -} - - -// Spectral Lightning (Horizontal #2) ------------------------------------- - -ACTOR SpectralLightningH2 : SpectralLightningH1 -{ - Damage 20 -} - -// Spectral Lightning (Horizontal #3) ------------------------------------- - -ACTOR SpectralLightningH3 : SpectralLightningH1 -{ - Damage 10 -} - -// ASpectralLightningHTail -------------------------------------------------- - -ACTOR SpectralLightningHTail -{ - +NOBLOCKMAP - +NOGRAVITY - +DROPOFF - RenderStyle Add - States - { - Spawn: - ZAP6 ABC 5 Bright - Stop - } -} - -// Spectral Lightning (Big Ball #1) ----------------------------------------- - -ACTOR SpectralLightningBigBall1 : SpectralLightningDeath2 -{ - Speed 18 - Radius 20 - Height 40 - Damage 130 - Projectile - +SPECTRAL - - action native A_SpectralBigBallLightning (); - - States - { - Spawn: - ZAP7 AB 4 Bright A_SpectralBigBallLightning - ZAP7 CDE 6 Bright A_SpectralBigBallLightning - Loop - } -} - - -// Spectral Lightning (Big Ball #2 - less damaging) ------------------------- - -ACTOR SpectralLightningBigBall2 : SpectralLightningBigBall1 -{ - Damage 30 -} - -// Sigil Lightning (Vertical #1) -------------------------------------------- - -ACTOR SpectralLightningV1 : SpectralLightningDeathShort -{ - Speed 22 - Radius 8 - Height 24 - Damage 100 - Projectile - DamageType "SpectralLow" - +SPECTRAL - States - { - Spawn: - ZOT1 AB 4 Bright - ZOT1 CDE 6 Bright - Loop - } -} - -// Sigil Lightning (Vertical #2 - less damaging) ---------------------------- - -ACTOR SpectralLightningV2 : SpectralLightningV1 -{ - Damage 50 -} - -// Sigil Lightning Spot (roams around dropping lightning from above) -------- - -ACTOR SpectralLightningSpot : SpectralLightningDeath1 -{ - Speed 18 - ReactionTime 70 - +NOBLOCKMAP - +NOBLOCKMONST - +NODROPOFF - RenderStyle Translucent - Alpha 0.6 - - action native A_SpectralLightning (); - - States - { - Spawn: - ZAP5 A 4 Bright A_Countdown - ZAP5 B 4 Bright A_SpectralLightning - ZAP5 CD 4 Bright A_Countdown - Loop - } -} - -// Sigil Lightning (Big Vertical #1) ---------------------------------------- - -ACTOR SpectralLightningBigV1 : SpectralLightningDeath1 -{ - Speed 28 - Radius 8 - Height 16 - Damage 120 - Projectile - +SPECTRAL - States - { - Spawn: - ZOT2 ABCDE 4 Bright A_Tracer2 - Loop - } -} - -// Actor 90 ----------------------------------------------------------------- - -ACTOR SpectralLightningBigV2 : SpectralLightningBigV1 -{ - Damage 60 -} - - - - diff --git a/wadsrc/static/actors/strife/stalker.txt b/wadsrc/static/actors/strife/stalker.txt deleted file mode 100644 index 7f469e610..000000000 --- a/wadsrc/static/actors/strife/stalker.txt +++ /dev/null @@ -1,76 +0,0 @@ - - -// Stalker ------------------------------------------------------------------ - -ACTOR Stalker -{ - Health 80 - Painchance 40 - Speed 16 - Radius 31 - Height 25 - Monster - +NOGRAVITY - +DROPOFF - +NOBLOOD - +SPAWNCEILING - +INCOMBAT - +NOVERTICALMELEERANGE - MaxDropOffHeight 32 - MinMissileChance 150 - SeeSound "stalker/sight" - AttackSound "stalker/attack" - PainSound "stalker/pain" - DeathSound "stalker/death" - ActiveSound "stalker/active" - HitObituary "$OB_STALKER" - - action native A_StalkerLookInit (); - action native A_StalkerChaseDecide (); - action native A_StalkerWalk (); - action native A_StalkerDrop (); - action native A_StalkerAttack (); - - states - { - Spawn: - STLK A 1 A_StalkerLookInit - Loop - LookCeiling: - STLK A 10 A_Look - Loop - LookFloor: - STLK J 10 A_Look - Loop - See: - STLK A 1 Slow A_StalkerChaseDecide - STLK ABB 3 Slow A_Chase - STLK C 3 Slow A_StalkerWalk - STLK C 3 Slow A_Chase - Loop - Melee: - STLK J 3 Slow A_FaceTarget - STLK K 3 Slow A_StalkerAttack - SeeFloor: - STLK J 3 A_StalkerWalk - STLK KK 3 A_Chase - STLK L 3 A_StalkerWalk - STLK L 3 A_Chase - Loop - Pain: - STLK L 1 A_Pain - Goto See - Drop: - STLK C 2 A_StalkerDrop - STLK IHGFED 3 - Goto SeeFloor - Death: - STLK O 4 - STLK P 4 A_Scream - STLK QRST 4 - STLK U 4 A_NoBlocking - STLK VW 4 - STLK "XYZ[" 4 Bright - Stop - } -} diff --git a/wadsrc/static/actors/strife/strifeammo.txt b/wadsrc/static/actors/strife/strifeammo.txt deleted file mode 100644 index e432a7144..000000000 --- a/wadsrc/static/actors/strife/strifeammo.txt +++ /dev/null @@ -1,202 +0,0 @@ -// HE-Grenade Rounds -------------------------------------------------------- - -ACTOR HEGrenadeRounds : Ammo -{ - +FLOORCLIP - Inventory.Amount 6 - Inventory.MaxAmount 30 - Ammo.BackpackAmount 6 - Ammo.BackpackMaxAmount 60 - Inventory.Icon "I_GRN1" - Tag "$TAG_HEGRENADES" - Inventory.PickupMessage "$TXT_HEGRENADES" - States - { - Spawn: - GRN1 A -1 - Stop - } -} - -// Phosphorus-Grenade Rounds ------------------------------------------------ - -ACTOR PhosphorusGrenadeRounds : Ammo -{ - +FLOORCLIP - Inventory.Amount 4 - Inventory.MaxAmount 16 - Ammo.BackpackAmount 4 - Ammo.BackpackMaxAmount 32 - Inventory.Icon "I_GRN2" - Tag "$TAG_PHGRENADES" - Inventory.PickupMessage "$TXT_PHGRENADES" - States - { - Spawn: - GRN2 A -1 - Stop - } -} - -// Clip of Bullets ---------------------------------------------------------- - -ACTOR ClipOfBullets : Ammo -{ - +FLOORCLIP - Inventory.Amount 10 - Inventory.MaxAmount 250 - Ammo.BackpackAmount 10 - Ammo.BackpackMaxAmount 500 - Inventory.Icon "I_BLIT" - Tag "$TAG_CLIPOFBULLETS" - Inventory.PickupMessage "$TXT_CLIPOFBULLETS" - States - { - Spawn: - BLIT A -1 - Stop - } -} - -// Box of Bullets ----------------------------------------------------------- - -ACTOR BoxOfBullets : ClipOfBullets -{ - Inventory.Amount 50 - Tag "$TAG_BOXOFBULLETS" - Inventory.PickupMessage "$TXT_BOXOFBULLETS" - States - { - Spawn: - BBOX A -1 - Stop - } -} - -// Mini Missiles ------------------------------------------------------------ - -ACTOR MiniMissiles : Ammo -{ - +FLOORCLIP - Inventory.Amount 4 - Inventory.MaxAmount 100 - Ammo.BackpackAmount 4 - Ammo.BackpackMaxAmount 200 - Inventory.Icon "I_ROKT" - Tag "$TAG_MINIMISSILES" - Inventory.PickupMessage "$TXT_MINIMISSILES" - States - { - Spawn: - MSSL A -1 - Stop - } -} - -// Crate of Missiles -------------------------------------------------------- - -ACTOR CrateOfMissiles : MiniMissiles -{ - Inventory.Amount 20 - Tag "$TAG_CRATEOFMISSILES" - Inventory.PickupMessage "$TXT_CRATEOFMISSILES" - States - { - Spawn: - ROKT A -1 - Stop - } -} - -// Energy Pod --------------------------------------------------------------- - -ACTOR EnergyPod : Ammo -{ - +FLOORCLIP - Inventory.Amount 20 - Inventory.MaxAmount 400 - Ammo.BackpackAmount 20 - Ammo.BackpackMaxAmount 800 - Ammo.DropAmount 20 - Inventory.Icon "I_BRY1" - Tag "$TAG_ENERGYPOD" - Inventory.PickupMessage "$TXT_ENERGYPOD" - States - { - Spawn: - BRY1 AB 6 - Loop - } -} - -// Energy pack --------------------------------------------------------------- - -ACTOR EnergyPack : EnergyPod -{ - Inventory.Amount 100 - Tag "$TAG_ENERGYPACK" - Inventory.PickupMessage "$TXT_ENERGYPACK" - States - { - Spawn: - CPAC AB 6 - Loop - } -} - -// Poison Bolt Quiver ------------------------------------------------------- - -ACTOR PoisonBolts : Ammo -{ - +FLOORCLIP - Inventory.Amount 10 - Inventory.MaxAmount 25 - Ammo.BackpackAmount 2 - Ammo.BackpackMaxAmount 50 - Inventory.Icon "I_PQRL" - Tag "$TAG_POISONBOLTS" - Inventory.PickupMessage "$TXT_POISONBOLTS" - States - { - Spawn: - PQRL A -1 - Stop - } -} - -// Electric Bolt Quiver ------------------------------------------------------- - -ACTOR ElectricBolts : Ammo -{ - +FLOORCLIP - Inventory.Amount 20 - Inventory.MaxAmount 50 - Ammo.BackpackAmount 4 - Ammo.BackpackMaxAmount 100 - Inventory.Icon "I_XQRL" - Tag "$TAG_ELECTRICBOLTS" - Inventory.PickupMessage "$TXT_ELECTRICBOLTS" - States - { - Spawn: - XQRL A -1 - Stop - } -} - -// Ammo Satchel ------------------------------------------------------------- - -ACTOR AmmoSatchel : BackpackItem -{ - +FLOORCLIP - Inventory.Icon "I_BKPK" - Tag "$TAG_AMMOSATCHEL" - Inventory.PickupMessage "$TXT_AMMOSATCHEL" - States - { - Spawn: - BKPK A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/strifearmor.txt b/wadsrc/static/actors/strife/strifearmor.txt deleted file mode 100644 index 3722d9338..000000000 --- a/wadsrc/static/actors/strife/strifearmor.txt +++ /dev/null @@ -1,43 +0,0 @@ - -ACTOR MetalArmor : BasicArmorPickup -{ - Radius 20 - Height 16 - +FLOORCLIP - +INVENTORY.AUTOACTIVATE - +INVENTORY.INVBAR - Inventory.MaxAmount 3 - Inventory.Icon "I_ARM1" - Inventory.PickupMessage "$TXT_METALARMOR" - Armor.SaveAmount 200 - Armor.SavePercent 50 - Tag "$TAG_METALARMOR" - States - { - Spawn: - ARM3 A -1 - Stop - } -} - -ACTOR LeatherArmor : BasicArmorPickup -{ - Radius 20 - Height 16 - +FLOORCLIP - +INVENTORY.AUTOACTIVATE - +INVENTORY.INVBAR - Inventory.MaxAmount 5 - Inventory.Icon "I_ARM2" - Inventory.PickupMessage "$TXT_LEATHERARMOR" - Armor.SaveAmount 100 - Armor.SavePercent 33.335 - Tag "$TAG_LEATHER" - States - { - Spawn: - ARM4 A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/strifebishop.txt b/wadsrc/static/actors/strife/strifebishop.txt deleted file mode 100644 index e64b247b1..000000000 --- a/wadsrc/static/actors/strife/strifebishop.txt +++ /dev/null @@ -1,94 +0,0 @@ - -// Bishop ------------------------------------------------------------------- - -ACTOR StrifeBishop -{ - Health 500 - Painchance 128 - Speed 8 - Radius 40 - Height 56 - Mass 500 - Monster - +NOBLOOD - +NOTDMATCH - +FLOORCLIP - +INCOMBAT - +NOICEDEATH - +NEVERRESPAWN - DamageFactor "Fire", 0.5 - MinMissileChance 150 - MaxDropoffHeight 32 - SeeSound "bishop/sight" - PainSound "bishop/pain" - DeathSound "bishop/death" - ActiveSound "bishop/active" - DropItem "CrateOfMissiles", 256, 20 - Obituary "$OB_STFBISHOP" - States - { - Spawn: - MLDR A 10 A_Look - Loop - See: - MLDR AABBCCDD 3 A_Chase - Loop - Missile: - MLDR E 3 A_FaceTarget - MLDR F 2 Bright A_CustomMissile("BishopMissile", 64, 0, 0, CMF_AIMOFFSET) - Goto See - Pain: - MLDR D 1 A_Pain - Goto See - Death: - MLDR G 3 Bright - MLDR H 5 Bright A_Scream - MLDR I 4 Bright A_TossGib - MLDR J 4 Bright A_Explode(64,64,1,1) - MLDR KL 3 Bright - MLDR M 4 Bright A_NoBlocking - MLDR N 4 Bright - MLDR O 4 Bright A_TossGib - MLDR P 4 Bright - MLDR Q 4 Bright A_TossGib - MLDR R 4 Bright - MLDR S 4 Bright A_TossGib - MLDR T 4 Bright - MLDR U 4 Bright A_TossGib - MLDR V 4 Bright A_SpawnItemEx("AlienSpectre2", 0, 0, 0, 0, 0, random[spectrespawn](0,255)*0.0078125, 0, SXF_NOCHECKPOSITION) - Stop - } -} - - -// The Bishop's missile ----------------------------------------------------- - -ACTOR BishopMissile -{ - Speed 20 - Radius 10 - Height 14 - Damage 10 - Projectile - +SEEKERMISSILE - +STRIFEDAMAGE - MaxStepHeight 4 - SeeSound "bishop/misl" - DeathSound "bishop/mislx" - States - { - Spawn: - MISS A 4 Bright A_RocketInFlight - MISS B 3 Bright A_Tracer2 - Loop - Death: - SMIS A 0 Bright A_SetTranslucent(1,1) - SMIS A 0 Bright // State left for savegame compatibility - SMIS A 5 Bright A_Explode(64,64,1,1) - SMIS B 5 Bright - SMIS C 4 Bright - SMIS DEFG 2 Bright - Stop - } -} - diff --git a/wadsrc/static/actors/strife/strifehumanoid.txt b/wadsrc/static/actors/strife/strifehumanoid.txt deleted file mode 100644 index 716806564..000000000 --- a/wadsrc/static/actors/strife/strifehumanoid.txt +++ /dev/null @@ -1,53 +0,0 @@ - -// Humanoid Base Class ------------------------------------------------------ - - -ACTOR StrifeHumanoid -{ - MaxStepHeight 16 - MaxDropoffHeight 32 - - CrushPainSound "misc/pcrush" - States - { - Burn: - BURN A 3 Bright A_PlaySoundEx("human/imonfire", "Voice") - BURN B 3 Bright A_DropFire - BURN C 3 Bright A_Wander - BURN D 3 Bright A_NoBlocking - BURN E 5 Bright A_DropFire - BURN FGH 5 Bright A_Wander - BURN I 5 Bright A_DropFire - BURN JKL 5 Bright A_Wander - BURN M 5 Bright A_DropFire - BURN N 5 Bright - BURN OPQPQ 5 Bright - BURN RSTU 7 Bright - BURN V -1 - Stop - Disintegrate: - DISR A 5 A_PlaySoundEx("misc/disruptordeath", "Voice") - DISR BC 5 - DISR D 5 A_NoBlocking - DISR EF 5 - DISR GHIJ 4 - MEAT D 700 - Stop - } -} - -// Fire Droplet ------------------------------------------------------------- - -ACTOR FireDroplet -{ - +NOBLOCKMAP - +NOCLIP - States - { - Spawn: - FFOT ABCD 9 Bright - Stop - } -} - - diff --git a/wadsrc/static/actors/strife/strifeitems.txt b/wadsrc/static/actors/strife/strifeitems.txt deleted file mode 100644 index 357d64ad5..000000000 --- a/wadsrc/static/actors/strife/strifeitems.txt +++ /dev/null @@ -1,519 +0,0 @@ -// Med patch ----------------------------------------------------------------- - -ACTOR MedPatch : HealthPickup -{ - Health 10 - +FLOORCLIP - +INVENTORY.INVBAR - Inventory.MaxAmount 20 - Tag "$TAG_MEDPATCH" - Inventory.Icon "I_STMP" - Inventory.PickupMessage "$TXT_MEDPATCH" - HealthPickup.Autouse 3 - States - { - Spawn: - STMP A -1 - Stop - } -} - - -// Medical Kit --------------------------------------------------------------- - -ACTOR MedicalKit : HealthPickup -{ - Health 25 - +FLOORCLIP - +INVENTORY.INVBAR - Inventory.MaxAmount 15 - Tag "$TAG_MEDICALKIT" - Inventory.Icon "I_MDKT" - Inventory.PickupMessage "$TXT_MEDICALKIT" - HealthPickup.Autouse 3 - States - { - Spawn: - MDKT A -1 - Stop - } -} - - -// Surgery Kit -------------------------------------------------------------- - -ACTOR SurgeryKit : HealthPickup -{ - +FLOORCLIP - +INVENTORY.INVBAR - Health -100 - Inventory.MaxAmount 5 - Tag "$TAG_SURGERYKIT" - Inventory.Icon "I_FULL" - Inventory.PickupMessage "$TXT_SURGERYKIT" - States - { - Spawn: - FULL AB 35 - Loop - } -} - - -// StrifeMap ---------------------------------------------------------------- - -ACTOR StrifeMap : MapRevealer -{ - +FLOORCLIP - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_STRIFEMAP" - States - { - Spawn: - SMAP AB 6 Bright - Loop - } -} - - -// Beldin's Ring ------------------------------------------------------------ - -ACTOR BeldinsRing : Inventory -{ - +NOTDMATCH - +FLOORCLIP - +INVENTORY.INVBAR - Tag "$TAG_BELDINSRING" - Inventory.Icon "I_RING" - Inventory.GiveQuest 1 - Inventory.PickupMessage "$TXT_BELDINSRING" - States - { - Spawn: - RING A -1 - Stop - } -} - - -// Offering Chalice --------------------------------------------------------- - -ACTOR OfferingChalice : Inventory -{ - +DROPPED - +FLOORCLIP - +INVENTORY.INVBAR - Radius 10 - Height 16 - Tag "$TAG_OFFERINGCHALICE" - Inventory.Icon "I_RELC" - Inventory.PickupMessage "$TXT_OFFERINGCHALICE" - Inventory.GiveQuest 2 - States - { - Spawn: - RELC A -1 - Stop - } -} - - -// Ear ---------------------------------------------------------------------- - -ACTOR Ear : Inventory -{ - +FLOORCLIP - +INVENTORY.INVBAR - Tag "$TAG_EAR" - Inventory.Icon "I_EARS" - Inventory.PickupMessage "$TXT_EAR" - Inventory.GiveQuest 9 - States - { - Spawn: - EARS A -1 - Stop - } -} - - -// Broken Power Coupling ---------------------------------------------------- - -ACTOR BrokenPowerCoupling : Inventory -{ - Health 40 - +DROPPED - +FLOORCLIP - +INVENTORY.INVBAR - Radius 16 - Height 16 - Tag "$TAG_BROKENCOUPLING" - Inventory.MaxAmount 1 - Inventory.Icon "I_COUP" - Inventory.PickupMessage "$TXT_BROKENCOUPLING" - Inventory.GiveQuest 8 - States - { - Spawn: - COUP C -1 - Stop - } -} - - -// Shadow Armor ------------------------------------------------------------- - -ACTOR ShadowArmor : PowerupGiver -{ - +FLOORCLIP - +VISIBILITYPULSE - +INVENTORY.INVBAR - -INVENTORY.FANCYPICKUPSOUND - RenderStyle Translucent - Tag "$TAG_SHADOWARMOR" - Inventory.MaxAmount 2 - Powerup.Type "Shadow" - Inventory.Icon "I_SHD1" - Inventory.PickupSound "misc/i_pkup" - Inventory.PickupMessage "$TXT_SHADOWARMOR" - States - { - Spawn: - SHD1 A -1 Bright - Stop - } -} - - -// Environmental suit ------------------------------------------------------- - -ACTOR EnvironmentalSuit : PowerupGiver -{ - +FLOORCLIP - +INVENTORY.INVBAR - -INVENTORY.FANCYPICKUPSOUND - Inventory.MaxAmount 5 - Powerup.Type "Mask" - Tag "$TAG_ENVSUIT" - Inventory.Icon "I_MASK" - Inventory.PickupSound "misc/i_pkup" - Inventory.PickupMessage "$TXT_ENVSUIT" - States - { - Spawn: - MASK A -1 - Stop - } -} - - -// Guard Uniform ------------------------------------------------------------ - -ACTOR GuardUniform : Inventory -{ - +FLOORCLIP - +INVENTORY.INVBAR - Tag "$TAG_GUARDUNIFORM" - Inventory.Icon "I_UNIF" - Inventory.PickupMessage "$TXT_GUARDUNIFORM" - Inventory.GiveQuest 15 - States - { - Spawn: - UNIF A -1 - Stop - } -} - - -// Officer's Uniform -------------------------------------------------------- - -ACTOR OfficersUniform : Inventory -{ - +FLOORCLIP - +INVENTORY.INVBAR - Tag "$TAG_OFFICERSUNIFORM" - Inventory.Icon "I_OFIC" - Inventory.PickupMessage "$TXT_OFFICERSUNIFORM" - States - { - Spawn: - OFIC A -1 - Stop - } -} - - -// Flame Thrower Parts ------------------------------------------------------ - -ACTOR FlameThrowerParts : Inventory -{ - +FLOORCLIP - +INVENTORY.INVBAR - Inventory.Icon "I_BFLM" - Tag "$TAG_FTHROWERPARTS" - Inventory.PickupMessage "$TXT_FTHROWERPARTS" - States - { - Spawn: - BFLM A -1 - Stop - } -} - -// InterrogatorReport ------------------------------------------------------- -// SCRIPT32 in strife0.wad has an Acolyte that drops this, but I couldn't -// find that Acolyte in the map. It seems to be totally unused in the -// final game. - -ACTOR InterrogatorReport : Inventory -{ - +FLOORCLIP - Tag "$TAG_REPORT" - Inventory.PickupMessage "$TXT_REPORT" - States - { - Spawn: - TOKN A -1 - Stop - } -} - - -// Info --------------------------------------------------------------------- - -ACTOR Info : Inventory -{ - +FLOORCLIP - +INVENTORY.INVBAR - Tag "$TAG_INFO" - Inventory.Icon "I_TOKN" - Inventory.PickupMessage "$TXT_INFO" - States - { - Spawn: - TOKN A -1 - Stop - } -} - - -// Targeter ----------------------------------------------------------------- - -ACTOR Targeter : PowerupGiver -{ - +FLOORCLIP - +INVENTORY.INVBAR - -INVENTORY.FANCYPICKUPSOUND - Tag "$TAG_TARGETER" - Powerup.Type "Targeter" - Inventory.MaxAmount 5 - Inventory.Icon "I_TARG" - Inventory.PickupSound "misc/i_pkup" - Inventory.PickupMessage "$TXT_TARGETER" - States - { - Spawn: - TARG A -1 - Stop - } -} - -// Communicator ----------------------------------------------------------------- - -ACTOR Communicator : Inventory -{ - +NOTDMATCH - Tag "$TAG_COMMUNICATOR" - Inventory.Icon "I_COMM" - Inventory.PickupSound "misc/p_pkup" - Inventory.PickupMessage "$TXT_COMMUNICATOR" - States - { - Spawn: - COMM A -1 - Stop - } -} - -// Degnin Ore --------------------------------------------------------------- - -ACTOR DegninOre : Inventory native -{ - Health 10 - Radius 16 - Height 16 - Inventory.MaxAmount 10 - +SOLID - +SHOOTABLE - +NOBLOOD - +FLOORCLIP - +INCOMBAT - +INVENTORY.INVBAR - Tag "$TAG_DEGNINORE" - DeathSound "ore/explode" - Inventory.Icon "I_XPRK" - Inventory.PickupMessage "$TXT_DEGNINORE" - States - { - Spawn: - XPRK A -1 - Stop - Death: - XPRK A 1 A_RemoveForceField - BNG3 A 0 A_SetTranslucent(1,1) - BNG3 A 0 A_Scream - BNG3 A 3 Bright A_Explode(192,192,1,1) - BNG3 BCDEFGH 3 Bright - Stop - } -} - -// Gun Training ------------------------------------------------------------- - -ACTOR GunTraining : Inventory -{ - +FLOORCLIP - +INVENTORY.INVBAR - +INVENTORY.UNDROPPABLE - Inventory.MaxAmount 100 - Tag "$TAG_GUNTRAINING" - Inventory.Icon "I_GUNT" - States - { - Spawn: - GUNT A -1 - Stop - } -} - -// Health Training ---------------------------------------------------------- - -ACTOR HealthTraining : Inventory native -{ - +FLOORCLIP - +INVENTORY.INVBAR - +INVENTORY.UNDROPPABLE - Inventory.MaxAmount 100 - Tag "$TAG_HEALTHTRAINING" - Inventory.Icon "I_HELT" - States - { - Spawn: - HELT A -1 - Stop - } -} - - - -// Scanner ------------------------------------------------------------------ - -ACTOR Scanner : PowerupGiver native -{ - +FLOORCLIP - +INVENTORY.FANCYPICKUPSOUND - Inventory.MaxAmount 1 - Tag "$TAG_SCANNER" - Inventory.Icon "I_PMUP" - Powerup.Type "Scanner" - Inventory.PickupSound "misc/i_pkup" - Inventory.PickupMessage "$TXT_SCANNER" - States - { - Spawn: - PMUP AB 6 - Loop - } -} - -// Prison Pass -------------------------------------------------------------- - -ACTOR PrisonPass : Key native -{ - Inventory.Icon "I_TOKN" - Tag "$TAG_PRISONPASS" - Inventory.PickupMessage "$TXT_PRISONPASS" - States - { - Spawn: - TOKN A -1 - Stop - } -} - -//--------------------------------------------------------------------------- -// Dummy items. They are just used by Strife to perform --------------------- -// actions and cannot be held. ---------------------------------------------- -//--------------------------------------------------------------------------- - -ACTOR DummyStrifeItem : Inventory native -{ - States - { - Spawn: - TOKN A -1 - Stop - } -} - -// Sound the alarm! --------------------------------------------------------- - -ACTOR RaiseAlarm : DummyStrifeItem native -{ - Tag "$TAG_ALARM" -} - -// Open door tag 222 -------------------------------------------------------- - -ACTOR OpenDoor222 : DummyStrifeItem native -{ -} - -// Close door tag 222 ------------------------------------------------------- - -ACTOR CloseDoor222 : DummyStrifeItem native -{ -} - -// Open door tag 224 -------------------------------------------------------- - -ACTOR OpenDoor224 : DummyStrifeItem native -{ -} - -// Ammo --------------------------------------------------------------------- - -ACTOR AmmoFillup : DummyStrifeItem native -{ - Tag "$TAG_AMMOFILLUP" -} - -// Health ------------------------------------------------------------------- - -ACTOR HealthFillup : DummyStrifeItem native -{ - Tag "$TAG_HEALTHFILLUP" -} - -// Upgrade Stamina ---------------------------------------------------------- - -ACTOR UpgradeStamina : DummyStrifeItem native -{ - Inventory.Amount 10 - Inventory.MaxAmount 100 -} - -// Upgrade Accuracy --------------------------------------------------------- - -ACTOR UpgradeAccuracy : DummyStrifeItem native -{ -} - -// Start a slideshow -------------------------------------------------------- - -ACTOR SlideshowStarter : DummyStrifeItem native -{ -} - - diff --git a/wadsrc/static/actors/strife/strifekeys.txt b/wadsrc/static/actors/strife/strifekeys.txt deleted file mode 100644 index 1a58505bb..000000000 --- a/wadsrc/static/actors/strife/strifekeys.txt +++ /dev/null @@ -1,460 +0,0 @@ -ACTOR StrifeKey : Key -{ - Radius 20 - Height 16 - +NOTDMATCH - +FLOORCLIP -} - -// Base Key ----------------------------------------------------------------- - -ACTOR BaseKey : StrifeKey -{ - Inventory.Icon "I_FUSL" - Tag "$TAG_BASEKEY" - Inventory.PickupMessage "$TXT_BASEKEY" - States - { - Spawn: - FUSL A -1 - Stop - } -} - - -// Govs Key ----------------------------------------------------------------- - -ACTOR GovsKey : StrifeKey -{ - Inventory.Icon "I_REBL" - Tag "$TAG_GOVSKEY" - Inventory.PickupMessage "$TXT_GOVSKEY" - States - { - Spawn: - REBL A -1 - Stop - } -} - - -// Passcard ----------------------------------------------------------------- - -ACTOR Passcard : StrifeKey -{ - Inventory.Icon "I_TPAS" - Tag "$TAG_PASSCARD" - Inventory.PickupMessage "$TXT_PASSCARD" - States - { - Spawn: - TPAS A -1 - Stop - } -} - - -// ID Badge ----------------------------------------------------------------- - -ACTOR IDBadge : StrifeKey -{ - Inventory.Icon "I_CRD1" - Tag "$TAG_IDBADGE" - Inventory.PickupMessage "$TXT_IDBADGE" - States - { - Spawn: - CRD1 A -1 - Stop - } -} - - -// Prison Key --------------------------------------------------------------- - -ACTOR PrisonKey : StrifeKey -{ - Inventory.Icon "I_PRIS" - Tag "$TAG_PRISONKEY" - Inventory.GiveQuest 11 - Inventory.PickupMessage "$TXT_PRISONKEY" - States - { - Spawn: - PRIS A -1 - Stop - } -} - - -// Severed Hand ------------------------------------------------------------- - -ACTOR SeveredHand : StrifeKey -{ - Inventory.Icon "I_HAND" - Tag "$TAG_SEVEREDHAND" - Inventory.GiveQuest 12 - Inventory.PickupMessage "$TXT_SEVEREDHAND" - States - { - Spawn: - HAND A -1 - Stop - } -} - - -// Power1 Key --------------------------------------------------------------- - -ACTOR Power1Key : StrifeKey -{ - Inventory.Icon "I_PWR1" - Tag "$TAG_POWER1KEY" - Inventory.PickupMessage "$TXT_POWER1KEY" - States - { - Spawn: - PWR1 A -1 - Stop - } -} - - -// Power2 Key --------------------------------------------------------------- - -ACTOR Power2Key : StrifeKey -{ - Inventory.Icon "I_PWR2" - Tag "$TAG_POWER2KEY" - Inventory.PickupMessage "$TXT_POWER2KEY" - States - { - Spawn: - PWR2 A -1 - Stop - } -} - - -// Power3 Key --------------------------------------------------------------- - -ACTOR Power3Key : StrifeKey -{ - Inventory.Icon "I_PWR3" - Tag "$TAG_POWER3KEY" - Inventory.PickupMessage "$TXT_POWER3KEY" - States - { - Spawn: - PWR3 A -1 - Stop - } -} - - -// Gold Key ----------------------------------------------------------------- - -ACTOR GoldKey : StrifeKey -{ - Inventory.Icon "I_KY1G" - Tag "$TAG_GOLDKEY" - Inventory.PickupMessage "$TXT_GOLDKEY" - States - { - Spawn: - KY1G A -1 - Stop - } -} - - -// ID Card ------------------------------------------------------------------ - -ACTOR IDCard : StrifeKey -{ - Inventory.Icon "I_CRD2" - Tag "$TAG_IDCARD" - Inventory.PickupMessage "$TXT_IDCARD" - States - { - Spawn: - CRD2 A -1 - Stop - } -} - - -// Silver Key --------------------------------------------------------------- - -ACTOR SilverKey : StrifeKey -{ - Inventory.Icon "I_KY2S" - Tag "$TAG_SILVERKEY" - Inventory.PickupMessage "$TXT_SILVERKEY" - States - { - Spawn: - KY2S A -1 - Stop - } -} - - -// Oracle Key --------------------------------------------------------------- - -ACTOR OracleKey : StrifeKey -{ - Inventory.Icon "I_ORAC" - Tag "$TAG_ORACLEKEY" - Inventory.PickupMessage "$TXT_ORACLEKEY" - States - { - Spawn: - ORAC A -1 - Stop - } -} - - -// Military ID -------------------------------------------------------------- - -ACTOR MilitaryID : StrifeKey -{ - Inventory.Icon "I_GYID" - Tag "$TAG_MILITARYID" - Inventory.PickupMessage "$TXT_MILITARYID" - States - { - Spawn: - GYID A -1 - Stop - } -} - - -// Order Key ---------------------------------------------------------------- - -ACTOR OrderKey : StrifeKey -{ - Inventory.Icon "I_FUBR" - Tag "$TAG_ORDERKEY" - Inventory.PickupMessage "$TXT_ORDERKEY" - States - { - Spawn: - FUBR A -1 - Stop - } -} - - -// Warehouse Key ------------------------------------------------------------ - -ACTOR WarehouseKey : StrifeKey -{ - Inventory.Icon "I_WARE" - Tag "$TAG_WAREHOUSEKEY" - Inventory.PickupMessage "$TXT_WAREHOUSEKEY" - States - { - Spawn: - WARE A -1 - Stop - } -} - - -// Brass Key ---------------------------------------------------------------- - -ACTOR BrassKey : StrifeKey -{ - Inventory.Icon "I_KY3B" - Tag "$TAG_BRASSKEY" - Inventory.PickupMessage "$TXT_BRASSKEY" - States - { - Spawn: - KY3B A -1 - Stop - } -} - - -// Red Crystal Key ---------------------------------------------------------- - -ACTOR RedCrystalKey : StrifeKey -{ - Inventory.Icon "I_RCRY" - Tag "$TAG_REDCRYSTALKEY" - Inventory.PickupMessage "$TXT_REDCRYSTAL" - States - { - Spawn: - RCRY A -1 Bright - Stop - } -} - - -// Blue Crystal Key --------------------------------------------------------- - -ACTOR BlueCrystalKey : StrifeKey -{ - Inventory.Icon "I_BCRY" - Tag "$TAG_BLUECRYSTALKEY" - Inventory.PickupMessage "$TXT_BLUECRYSTAL" - States - { - Spawn: - BCRY A -1 Bright - Stop - } -} - - -// Chapel Key --------------------------------------------------------------- - -ACTOR ChapelKey : StrifeKey -{ - Inventory.Icon "I_CHAP" - Tag "$TAG_CHAPELKEY" - Inventory.PickupMessage "$TXT_CHAPELKEY" - States - { - Spawn: - CHAP A -1 - Stop - } -} - - -// Catacomb Key ------------------------------------------------------------- - -ACTOR CatacombKey : StrifeKey -{ - Inventory.Icon "I_TUNL" - Tag "$TAG_CATACOMBKEY" - Inventory.GiveQuest 28 - Inventory.PickupMessage "$TXT_CATACOMBKEY" - States - { - Spawn: - TUNL A -1 - Stop - } -} - - -// Security Key ------------------------------------------------------------- - -ACTOR SecurityKey : StrifeKey -{ - Inventory.Icon "I_SECK" - Tag "$TAG_SECURITYKEY" - Inventory.PickupMessage "$TXT_SECURITYKEY" - States - { - Spawn: - SECK A -1 - Stop - } -} - - -// Core Key ----------------------------------------------------------------- - -ACTOR CoreKey : StrifeKey -{ - Inventory.Icon "I_GOID" - Tag "$TAG_COREKEY" - Inventory.PickupMessage "$TXT_COREKEY" - States - { - Spawn: - GOID A -1 - Stop - } -} - - -// Mauler Key --------------------------------------------------------------- - -ACTOR MaulerKey : StrifeKey -{ - Inventory.Icon "I_BLTK" - Tag "$TAG_MAULERKEY" - Inventory.PickupMessage "$TXT_MAULERKEY" - States - { - Spawn: - BLTK A -1 - Stop - } -} - - -// Factory Key -------------------------------------------------------------- - -ACTOR FactoryKey : StrifeKey -{ - Inventory.Icon "I_PROC" - Tag "$TAG_FACTORYKEY" - Inventory.PickupMessage "$TXT_FACTORYKEY" - States - { - Spawn: - PROC A -1 - Stop - } -} - - -// Mine Key ----------------------------------------------------------------- - -ACTOR MineKey : StrifeKey -{ - Inventory.Icon "I_MINE" - Tag "$TAG_MINEKEY" - Inventory.PickupMessage "$TXT_MINEKEY" - States - { - Spawn: - MINE A -1 - Stop - } -} - - -// New Key5 ----------------------------------------------------------------- - -ACTOR NewKey5 : StrifeKey -{ - Inventory.Icon "I_BLTK" - Tag "$TAG_NEWKEY5" - Inventory.PickupMessage "$TXT_NEWKEY5" - States - { - Spawn: - BLTK A -1 - Stop - } -} - - -// Oracle Pass -------------------------------------------------------------- - -ACTOR OraclePass : Inventory -{ - +INVENTORY.INVBAR - Inventory.Icon "I_OTOK" - Inventory.GiveQuest 18 - Inventory.PickupMessage "$TXT_ORACLEPASS" - Tag "$TAG_ORACLEPASS" - States - { - Spawn: - OTOK A -1 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/strifeplayer.txt b/wadsrc/static/actors/strife/strifeplayer.txt deleted file mode 100644 index 77135dcbf..000000000 --- a/wadsrc/static/actors/strife/strifeplayer.txt +++ /dev/null @@ -1,102 +0,0 @@ -// The player --------------------------------------------------------------- - -ACTOR StrifePlayer : PlayerPawn -{ - Health 100 - Radius 18 - Height 56 - Mass 100 - PainChance 255 - Speed 1 - MaxStepHeight 16 - CrushPainSound "misc/pcrush" - Player.DisplayName "Rebel" - Player.StartItem "PunchDagger" - Player.RunHealth 15 - Player.WeaponSlot 1, PunchDagger - Player.WeaponSlot 2, StrifeCrossbow2, StrifeCrossbow - Player.WeaponSlot 3, AssaultGun - Player.WeaponSlot 4, MiniMissileLauncher - Player.WeaponSlot 5, StrifeGrenadeLauncher2, StrifeGrenadeLauncher - Player.WeaponSlot 6, FlameThrower - Player.WeaponSlot 7, Mauler2, Mauler - Player.WeaponSlot 8, Sigil - - Player.ColorRange 128, 143 - Player.Colorset 0, "Brown", 0x80, 0x8F, 0x82 - Player.Colorset 1, "Red", 0x40, 0x4F, 0x42, 0x20, 0x3F, 0x00, 0x1F, 0xF1, 0xF6, 0xE0, 0xE5, 0xF7, 0xFB, 0xF1, 0xF5 - Player.Colorset 2, "Rust", 0xB0, 0xBF, 0xB2, 0x20, 0x3F, 0x00, 0x1F - Player.Colorset 3, "Gray", 0x10, 0x1F, 0x12, 0x20, 0x2F, 0xD0, 0xDF, 0x30, 0x3F, 0xD0, 0xDF - Player.Colorset 4, "Dark Green", 0x30, 0x3F, 0x32, 0x20, 0x2F, 0xD0, 0xDF, 0x30, 0x3F, 0xD0, 0xDF - - Player.Colorset 5, "Gold", 0x50, 0x5F, 0x52, 0x20, 0x3F, 0x00, 0x1F, 0x50, 0x5F, 0x80, 0x8F, 0xC0, 0xCF, 0xA0, 0xAF, 0xD0, 0xDF, 0xB0, 0xBF - Player.Colorset 6, "Bright Green", 0x60, 0x6F, 0x62, 0x20, 0x3F, 0x00, 0x1F, 0x50, 0x5F, 0x10, 0x1F, 0xC0, 0xCF, 0x20, 0x2F, 0xD0, 0xDF, 0x30, 0x3F - Player.Colorset 7, "Blue", 0x90, 0x9F, 0x92, 0x20, 0x3F, 0x00, 0x1F, 0x50, 0x5F, 0x40, 0x4F, 0xC1, 0xCF, 0x01, 0x0F, 0xC0,0xC0,1,1, 0xD0, 0xDF, 0x10, 0x1F - - action native A_ItBurnsItBurns(); - action native A_CrispyPlayer(); - action native A_HandLower(); - - States - { - Spawn: - PLAY A -1 - stop - See: - PLAY ABCD 4 - loop - Missile: - PLAY E 12 - goto Spawn - Melee: - PLAY F 6 - goto Missile - Pain: - PLAY Q 4 - PLAY Q 4 A_Pain - Goto Spawn - Death: - PLAY H 3 - PLAY I 3 A_PlayerScream - PLAY J 3 A_NoBlocking - PLAY KLMNO 4 - PLAY P -1 - Stop - XDeath: - RGIB A 5 A_TossGib - RGIB B 5 A_XScream - RGIB C 5 A_NoBlocking - RGIB DEFG 5 A_TossGib - RGIB H -1 A_TossGib - Burn: - BURN A 3 Bright A_ItBurnsItBurns - BURN B 3 Bright A_DropFire - BURN C 3 Bright A_Wander - BURN D 3 Bright A_NoBlocking - BURN E 5 Bright A_DropFire - BURN FGH 5 Bright A_Wander - BURN I 5 Bright A_DropFire - BURN JKL 5 Bright A_Wander - BURN M 5 Bright A_DropFire - BURN N 5 Bright A_CrispyPlayer - BURN OPQPQ 5 Bright - BURN RSTU 7 Bright - BURN V -1 - Stop - Disintegrate: - DISR A 5 A_PlaySoundEx("misc/disruptordeath", "Voice") - DISR BC 5 - DISR D 5 A_NoBlocking - DISR EF 5 - DISR GHIJ 4 - MEAT D -1 - Stop - Firehands: - WAVE ABCD 3 - Loop - Firehandslower: - WAVE ABCD 3 A_HandLower - Loop - } -} - diff --git a/wadsrc/static/actors/strife/strifestuff.txt b/wadsrc/static/actors/strife/strifestuff.txt deleted file mode 100644 index 95d6d93cd..000000000 --- a/wadsrc/static/actors/strife/strifestuff.txt +++ /dev/null @@ -1,1723 +0,0 @@ -// Tank 1 Huge ------------------------------------------------------------ - -ACTOR Tank1 -{ - Radius 16 - Height 192 - +SOLID - States - { - Spawn: - TNK1 A 15 - TNK1 B 11 - TNK1 C 40 - Loop - } -} - -// Tank 2 Huge ------------------------------------------------------------ - -ACTOR Tank2 -{ - Radius 16 - Height 192 - +SOLID - States - { - Spawn: - TNK2 A 15 - TNK2 B 11 - TNK2 C 40 - Loop - } -} - -// Tank 3 Huge ------------------------------------------------------------ - -ACTOR Tank3 -{ - Radius 16 - Height 192 - +SOLID - States - { - Spawn: - TNK3 A 15 - TNK3 B 11 - TNK3 C 40 - Loop - } -} - -// Tank 4 ------------------------------------------------------------------- - -ACTOR Tank4 -{ - Radius 16 - Height 56 - +SOLID - States - { - Spawn: - TNK4 A 15 - TNK4 B 11 - TNK4 C 40 - Loop - } -} - -// Tank 5 ------------------------------------------------------------------- - -ACTOR Tank5 -{ - Radius 16 - Height 56 - +SOLID - States - { - Spawn: - TNK5 A 15 - TNK5 B 11 - TNK5 C 40 - Loop - } -} - -// Tank 6 ------------------------------------------------------------------- - -ACTOR Tank6 -{ - Radius 16 - Height 56 - +SOLID - States - { - Spawn: - TNK6 A 15 - TNK6 B 11 - TNK6 C 40 - Loop - } -} - -// Water Bottle ------------------------------------------------------------- - -ACTOR WaterBottle -{ - States - { - Spawn: - WATR A -1 - Stop - } -} - -// Mug ---------------------------------------------------------------------- - -ACTOR Mug -{ - States - { - Spawn: - MUGG A -1 - Stop - } -} - -// Wooden Barrel ------------------------------------------------------------ - -ACTOR WoodenBarrel -{ - Health 10 - Radius 10 - Height 32 - +SOLID +SHOOTABLE +NOBLOOD - +INCOMBAT - DeathSound "woodenbarrel/death" - States - { - Spawn: - BARW A -1 - Stop - Death: - BARW B 2 A_Scream - BARW C 2 - BARW D 2 A_NoBlocking - BARW EFG 2 - BARW H -1 - Stop - } -} - -// Strife's explosive barrel ------------------------------------------------ - -ACTOR ExplosiveBarrel2 -{ - Health 30 - Radius 10 - Height 32 - +SOLID +SHOOTABLE +NOBLOOD +OLDRADIUSDMG - DeathSound "world/barrelx" - +INCOMBAT - States - { - Spawn: - BART A -1 - Stop - Death: - BART B 2 Bright A_Scream - BART CD 2 Bright - BART E 2 Bright A_NoBlocking - BART F 2 Bright A_Explode(64, 64, 1, 1) - BART GHIJ 2 Bright - BART K 3 Bright - BART L -1 - Stop - } -} - -// Light Silver, Fluorescent ---------------------------------------------- - -ACTOR LightSilverFluorescent -{ - Radius 2.5 - Height 16 - +NOBLOCKMAP - +FIXMAPTHINGPOS - States - { - Spawn: - LITS A -1 Bright - Stop - } -} - -// Light Brown, Fluorescent ----------------------------------------------- - -ACTOR LightBrownFluorescent -{ - Radius 2.5 - Height 16 - +NOBLOCKMAP - +FIXMAPTHINGPOS - States - { - Spawn: - LITB A -1 Bright - Stop - } -} - -// Light Gold, Fluorescent ------------------------------------------------ - -ACTOR LightGoldFluorescent -{ - Radius 2.5 - Height 16 - +NOBLOCKMAP - +FIXMAPTHINGPOS - States - { - Spawn: - LITG A -1 Bright - Stop - } -} - -// Light Globe -------------------------------------------------------------- - -ACTOR LightGlobe -{ - Radius 16 - Height 16 - +SOLID - States - { - Spawn: - LITE A -1 Bright - Stop - } -} - -// Techno Pillar ------------------------------------------------------------ - -ACTOR PillarTechno -{ - Radius 20 - Height 128 - +SOLID - States - { - Spawn: - MONI A -1 - Stop - } -} - -// Aztec Pillar ------------------------------------------------------------- - -ACTOR PillarAztec -{ - Radius 16 - Height 128 - +SOLID - States - { - Spawn: - STEL A -1 - Stop - } -} - -// Damaged Aztec Pillar ----------------------------------------------------- - -ACTOR PillarAztecDamaged -{ - Radius 16 - Height 80 - +SOLID - States - { - Spawn: - STLA A -1 - Stop - } -} - -// Ruined Aztec Pillar ------------------------------------------------------ - -ACTOR PillarAztecRuined -{ - Radius 16 - Height 40 - +SOLID - States - { - Spawn: - STLE A -1 - Stop - } -} - -// Huge Tech Pillar --------------------------------------------------------- - -ACTOR PillarHugeTech -{ - Radius 24 - Height 192 - +SOLID - States - { - Spawn: - HUGE ABCD 4 - Loop - } -} - -// Alien Power Crystal in a Pillar ------------------------------------------ - -ACTOR PillarAlienPower -{ - Radius 24 - Height 192 - +SOLID - ActiveSound "ambient/alien2" - States - { - Spawn: - APOW A 4 A_LoopActiveSound - Loop - } -} - -// SStalactiteBig ----------------------------------------------------------- - -ACTOR SStalactiteBig -{ - Radius 16 - Height 54 - +SOLID +SPAWNCEILING +NOGRAVITY - States - { - Spawn: - STLG C -1 - Stop - } -} - -// SStalactiteSmall --------------------------------------------------------- - -ACTOR SStalactiteSmall -{ - Radius 16 - Height 40 - +SOLID +SPAWNCEILING +NOGRAVITY - States - { - Spawn: - STLG A -1 - Stop - } -} - -// SStalagmiteBig ----------------------------------------------------------- - -ACTOR SStalagmiteBig -{ - Radius 16 - Height 40 - +SOLID - States - { - Spawn: - STLG B -1 - Stop - } -} - -// Cave Pillar Top ---------------------------------------------------------- - -ACTOR CavePillarTop -{ - Radius 16 - Height 128 - +SOLID +SPAWNCEILING +NOGRAVITY - States - { - Spawn: - STLG D -1 - Stop - } -} - -// Cave Pillar Bottom ------------------------------------------------------- - -ACTOR CavePillarBottom -{ - Radius 16 - Height 128 - +SOLID - States - { - Spawn: - STLG E -1 - Stop - } -} - -// SStalagmiteSmall --------------------------------------------------------- - -ACTOR SStalagmiteSmall -{ - Radius 16 - Height 25 - +SOLID - States - { - Spawn: - STLG F -1 - Stop - } -} - -// Candle ------------------------------------------------------------------- - -ACTOR Candle -{ - States - { - Spawn: - KNDL A -1 Bright - Stop - } -} - -// StrifeCandelabra --------------------------------------------------------- - -ACTOR StrifeCandelabra -{ - Radius 16 - Height 40 - +SOLID - States - { - Spawn: - CLBR A -1 - Stop - } -} - -// Floor Water Drop --------------------------------------------------------- - -ACTOR WaterDropOnFloor -{ - +NOBLOCKMAP - ActiveSound "world/waterdrip" - States - { - Spawn: - DRIP A 6 A_FLoopActiveSound - DRIP BC 4 - DRIP D 4 A_FLoopActiveSound - DRIP EF 4 - DRIP G 4 A_FLoopActiveSound - DRIP H 4 - Loop - } -} - -// Waterfall Splash --------------------------------------------------------- - -ACTOR WaterfallSplash -{ - +NOBLOCKMAP - ActiveSound "world/waterfall" - States - { - Spawn: - SPLH ABCDEFG 4 - SPLH H 4 A_LoopActiveSound - Loop - } -} - -// Ceiling Water Drip ------------------------------------------------------- - -ACTOR WaterDrip -{ - Height 1 - +NOBLOCKMAP +SPAWNCEILING +NOGRAVITY - States - { - Spawn: - CDRP A 10 - CDRP BCD 8 - Loop - } -} - -// WaterFountain ------------------------------------------------------------ - -ACTOR WaterFountain -{ - +NOBLOCKMAP - ActiveSound "world/watersplash" - States - { - Spawn: - WTFT ABC 4 - WTFT D 4 A_LoopActiveSound - Loop - } -} - -// Hearts in Tank ----------------------------------------------------------- - -ACTOR HeartsInTank -{ - Radius 16 - Height 56 - +SOLID - States - { - Spawn: - HERT ABC 4 Bright - Loop - } -} - -// Teleport Swirl ----------------------------------------------------------- - -ACTOR TeleportSwirl -{ - +NOBLOCKMAP - RenderStyle Add - Alpha 0.25 - States - { - Spawn: - TELP ABCD 3 Bright - Loop - } -} - -// Dead Player -------------------------------------------------------------- -// Strife's disappeared. This one doesn't. - -ACTOR DeadStrifePlayer -{ - States - { - Spawn: - PLAY P 700 - RGIB H -1 - Stop - } -} - -// Dead Peasant ------------------------------------------------------------- -// Unlike Strife's, this one does not turn into gibs and disappear. - -ACTOR DeadPeasant -{ - States - { - Spawn: - PEAS N -1 - Stop - } -} - -// Dead Acolyte ------------------------------------------------------------- -// Unlike Strife's, this one does not turn into gibs and disappear. - -ACTOR DeadAcolyte -{ - States - { - Spawn: - AGRD N -1 - Stop - } -} - -// Dead Reaver -------------------------------------------------------------- - -ACTOR DeadReaver -{ - States - { - Spawn: - ROB1 R -1 - Stop - } -} - -// Dead Rebel --------------------------------------------------------------- - -ACTOR DeadRebel -{ - States - { - Spawn: - HMN1 N -1 - Stop - } -} - -// Sacrificed Guy ----------------------------------------------------------- - -ACTOR SacrificedGuy -{ - States - { - Spawn: - SACR A -1 - Stop - } -} - -// Pile of Guts ------------------------------------------------------------- - -ACTOR PileOfGuts -{ - // Strife used a doomednum, which is the same as the Aztec Pillar. Since - // the pillar came first in the mobjinfo list, you could not spawn this - // in a map. Pity. - States - { - Spawn: - DEAD A -1 - Stop - } -} - -// Burning Barrel ----------------------------------------------------------- - -ACTOR StrifeBurningBarrel -{ - Radius 16 - Height 48 - +SOLID - States - { - Spawn: - BBAR ABCD 4 Bright - Loop - } -} - -// Burning Bowl ----------------------------------------------------------- - -ACTOR BurningBowl -{ - Radius 16 - Height 16 - +SOLID - ActiveSound "world/smallfire" - States - { - Spawn: - BOWL ABCD 4 Bright - Loop - } -} - -// Burning Brazier ----------------------------------------------------------- - -ACTOR BurningBrazier -{ - Radius 10 - Height 32 - +SOLID - ActiveSound "world/smallfire" - States - { - Spawn: - BRAZ ABCD 4 Bright - Loop - } -} - -// Small Torch Lit -------------------------------------------------------- - -ACTOR SmallTorchLit -{ - Radius 2.5 - Height 16 - +NOBLOCKMAP - +FIXMAPTHINGPOS - - // It doesn't have any action functions, so how does it use this sound? - ActiveSound "world/smallfire" - States - { - Spawn: - TRHL ABCD 4 Bright - Loop - } -} - -// Small Torch Unlit -------------------------------------------------------- - -ACTOR SmallTorchUnlit -{ - Radius 2.5 - Height 16 - +NOBLOCKMAP - +FIXMAPTHINGPOS - States - { - Spawn: - TRHO A -1 - Stop - } -} - -// Ceiling Chain ------------------------------------------------------------ - -ACTOR CeilingChain -{ - Radius 20 - Height 93 - +NOBLOCKMAP +SPAWNCEILING +NOGRAVITY - States - { - Spawn: - CHAN A -1 - Stop - } -} - -// Cage Light --------------------------------------------------------------- - -ACTOR CageLight -{ - // No, it's not bright even though it's a light. - Height 3 - +NOBLOCKMAP +SPAWNCEILING +NOGRAVITY - States - { - Spawn: - CAGE A -1 - Stop - } -} - -// Statue ------------------------------------------------------------------- - -ACTOR Statue -{ - Radius 20 - Height 64 - +SOLID - States - { - Spawn: - STAT A -1 - Stop - } -} - -// Ruined Statue ------------------------------------------------------------ - -ACTOR StatueRuined -{ - Radius 20 - Height 56 - +SOLID - States - { - Spawn: - DSTA A -1 - Stop - } -} - -// Medium Torch ------------------------------------------------------------- - -ACTOR MediumTorch -{ - Radius 4 - Height 72 - +SOLID - States - { - Spawn: - LTRH ABCD 4 - Loop - } -} - -// Outside Lamp ------------------------------------------------------------- - -ACTOR OutsideLamp -{ - // No, it's not bright. - Radius 3 - Height 80 - +SOLID - States - { - Spawn: - LAMP A -1 - Stop - } -} - -// Pole Lantern ------------------------------------------------------------- - -ACTOR PoleLantern -{ - // No, it's not bright. - Radius 3 - Height 80 - +SOLID - States - { - Spawn: - LANT A -1 - Stop - } -} - -// Rock 1 ------------------------------------------------------------------- - -ACTOR SRock1 -{ - +NOBLOCKMAP - States - { - Spawn: - ROK1 A -1 - Stop - } -} - -// Rock 2 ------------------------------------------------------------------- - -ACTOR SRock2 -{ - +NOBLOCKMAP - States - { - Spawn: - ROK2 A -1 - Stop - } -} - -// Rock 3 ------------------------------------------------------------------- - -ACTOR SRock3 -{ - +NOBLOCKMAP - States - { - Spawn: - ROK3 A -1 - Stop - } -} - -// Rock 4 ------------------------------------------------------------------- - -ACTOR SRock4 -{ - +NOBLOCKMAP - States - { - Spawn: - ROK4 A -1 - Stop - } -} - -// Stick in Water ----------------------------------------------------------- - -ACTOR StickInWater -{ - +NOBLOCKMAP - +FLOORCLIP - ActiveSound "world/river" - States - { - Spawn: - LOGW ABCD 5 A_LoopActiveSound - Loop - } -} - -// Rubble 1 ----------------------------------------------------------------- - -ACTOR Rubble1 -{ - +NOBLOCKMAP +NOCLIP - States - { - Spawn: - RUB1 A -1 - Stop - } -} - -// Rubble 2 ----------------------------------------------------------------- - -ACTOR Rubble2 -{ - +NOBLOCKMAP +NOCLIP - States - { - Spawn: - RUB2 A -1 - Stop - } -} - -// Rubble 3 ----------------------------------------------------------------- - -ACTOR Rubble3 -{ - +NOBLOCKMAP +NOCLIP - States - { - Spawn: - RUB3 A -1 - Stop - } -} - -// Rubble 4 ----------------------------------------------------------------- - -ACTOR Rubble4 -{ - +NOBLOCKMAP +NOCLIP - States - { - Spawn: - RUB4 A -1 - Stop - } -} - -// Rubble 5 ----------------------------------------------------------------- - -ACTOR Rubble5 -{ - +NOBLOCKMAP +NOCLIP - States - { - Spawn: - RUB5 A -1 - Stop - } -} - -// Rubble 6 ----------------------------------------------------------------- - -ACTOR Rubble6 -{ - +NOBLOCKMAP +NOCLIP - States - { - Spawn: - RUB6 A -1 - Stop - } -} - -// Rubble 7 ----------------------------------------------------------------- - -ACTOR Rubble7 -{ - +NOBLOCKMAP +NOCLIP - States - { - Spawn: - RUB7 A -1 - Stop - } -} - -// Rubble 8 ----------------------------------------------------------------- - -ACTOR Rubble8 -{ - +NOBLOCKMAP +NOCLIP - States - { - Spawn: - RUB8 A -1 - Stop - } -} - -// Surgery Crab ------------------------------------------------------------- - -ACTOR SurgeryCrab -{ - +SOLID +SPAWNCEILING +NOGRAVITY - Radius 20 - Height 16 - States - { - Spawn: - CRAB A -1 - Stop - } -} - -// Large Torch -------------------------------------------------------------- - -ACTOR LargeTorch -{ - Radius 10 - Height 72 - +SOLID - ActiveSound "world/smallfire" - States - { - Spawn: - LMPC ABCD 4 Bright - Loop - } -} - -// Huge Torch -------------------------------------------------------------- - -ACTOR HugeTorch -{ - Radius 10 - Height 80 - +SOLID - ActiveSound "world/smallfire" - States - { - Spawn: - LOGS ABCD 4 - Loop - } -} - -// Palm Tree ---------------------------------------------------------------- - -ACTOR PalmTree -{ - Radius 15 - Height 109 - +SOLID - States - { - Spawn: - TREE A -1 - Stop - } -} - -// Big Tree ---------------------------------------------------------------- - -ACTOR BigTree2 -{ - Radius 15 - Height 109 - +SOLID - States - { - Spawn: - TREE B -1 - Stop - } -} - -// Potted Tree ---------------------------------------------------------------- - -ACTOR PottedTree -{ - Radius 15 - Height 64 - +SOLID - States - { - Spawn: - TREE C -1 - Stop - } -} - -// Tree Stub ---------------------------------------------------------------- - -ACTOR TreeStub -{ - Radius 15 - Height 80 - +SOLID - States - { - Spawn: - TRET A -1 - Stop - } -} - -// Short Bush --------------------------------------------------------------- - -ACTOR ShortBush -{ - Radius 15 - Height 40 - +SOLID - States - { - Spawn: - BUSH A -1 - Stop - } -} - -// Tall Bush --------------------------------------------------------------- - -ACTOR TallBush -{ - Radius 20 - Height 64 - +SOLID - States - { - Spawn: - SHRB A -1 - Stop - } -} - -// Chimney Stack ------------------------------------------------------------ - -ACTOR ChimneyStack -{ - Radius 20 - Height 64 // This height does not fit the sprite - +SOLID - States - { - Spawn: - STAK A -1 - Stop - } -} - -// Barricade Column --------------------------------------------------------- - -ACTOR BarricadeColumn -{ - Radius 16 - Height 128 - +SOLID - States - { - Spawn: - BARC A -1 - Stop - } -} - -// Pot ---------------------------------------------------------------------- - -ACTOR Pot -{ - Radius 12 - Height 24 - +SOLID - States - { - Spawn: - VAZE A -1 - Stop - } -} - -// Pitcher ------------------------------------------------------------------ - -ACTOR Pitcher -{ - Radius 12 - Height 32 - +SOLID - States - { - Spawn: - VAZE B -1 - Stop - } -} - -// Stool -------------------------------------------------------------------- - -ACTOR Stool -{ - Radius 6 - Height 24 - +SOLID - States - { - Spawn: - STOL A -1 - Stop - } -} - -// Metal Pot ---------------------------------------------------------------- - -ACTOR MetalPot -{ - +NOBLOCKMAP - States - { - Spawn: - MPOT A -1 - Stop - } -} - -// Tub ---------------------------------------------------------------------- - -ACTOR Tub -{ - +NOBLOCKMAP - States - { - Spawn: - TUB1 A -1 - Stop - } -} - -// Anvil -------------------------------------------------------------------- - -ACTOR Anvil -{ - Radius 16 - Height 32 - +SOLID - States - { - Spawn: - ANVL A -1 - Stop - } -} - -// Silver Tech Lamp ---------------------------------------------------------- - -ACTOR TechLampSilver -{ - Radius 11 - Height 64 - +SOLID - States - { - Spawn: - TECH A -1 - Stop - } -} - -// Brass Tech Lamp ---------------------------------------------------------- - -ACTOR TechLampBrass -{ - Radius 8 - Height 64 - +SOLID - States - { - Spawn: - TECH B -1 - Stop - } -} - -// Tray -------------------------------------------------------------------- - -ACTOR Tray -{ - Radius 24 - Height 40 - +SOLID - States - { - Spawn: - TRAY A -1 - Stop - } -} - -// AmmoFiller --------------------------------------------------------------- - -ACTOR AmmoFiller -{ - Radius 12 - Height 24 - +SOLID - States - { - Spawn: - AFED A -1 - Stop - } -} - -// Sigil Banner ------------------------------------------------------------- - -ACTOR SigilBanner -{ - Radius 24 - Height 96 - +NOBLOCKMAP // I take it this was once solid, yes? - States - { - Spawn: - SBAN A -1 - Stop - } -} - -// RebelBoots --------------------------------------------------------------- - -ACTOR RebelBoots -{ - +NOBLOCKMAP - States - { - Spawn: - BOTR A -1 - Stop - } -} - -// RebelHelmet -------------------------------------------------------------- - -ACTOR RebelHelmet -{ - +NOBLOCKMAP - States - { - Spawn: - HATR A -1 - Stop - } -} - -// RebelShirt --------------------------------------------------------------- - -ACTOR RebelShirt -{ - +NOBLOCKMAP - States - { - Spawn: - TOPR A -1 - Stop - } -} - -// Alien Bubble Column ------------------------------------------------------ - -ACTOR AlienBubbleColumn -{ - Radius 16 - Height 128 - +SOLID - ActiveSound "ambient/alien5" - States - { - Spawn: - BUBB A 4 A_LoopActiveSound - Loop - } -} - -// Alien Floor Bubble ------------------------------------------------------- - -ACTOR AlienFloorBubble -{ - Radius 16 - Height 72 - +SOLID - ActiveSound "ambient/alien6" - States - { - Spawn: - BUBF A 4 A_LoopActiveSound - Loop - } -} - -// Alien Ceiling Bubble ----------------------------------------------------- - -ACTOR AlienCeilingBubble -{ - Radius 16 - Height 72 - +SOLID +SPAWNCEILING +NOGRAVITY - ActiveSound "ambient/alien4" - States - { - Spawn: - BUBC A 4 A_LoopActiveSound - Loop - } -} - -// Alien Asp Climber -------------------------------------------------------- - -ACTOR AlienAspClimber -{ - Radius 16 - Height 128 - +SOLID - ActiveSound "ambient/alien3" - States - { - Spawn: - ASPR A 4 A_LoopActiveSound - Loop - } -} - -// Alien Spider Light ------------------------------------------------------- - -ACTOR AlienSpiderLight -{ - Radius 32 - Height 56 - +SOLID - ActiveSound "ambient/alien1" - States - { - Spawn: - SPDL ABC 5 A_LoopActiveSound - Loop - } -} - -// Target Practice ----------------------------------------------------------- - -ACTOR TargetPractice -{ - Health 99999999 - PainChance 255 - Radius 10 - Height 72 - Mass 9999999 - +SOLID +SHOOTABLE +NOBLOOD - +INCOMBAT +NODAMAGE - PainSound "misc/metalhit" - States - { - Spawn: - HOGN A 2 A_CheckTerrain - Loop - Pain: - HOGN B 1 A_CheckTerrain - HOGN C 1 A_Pain - Goto Spawn - } -} - -// Force Field Guard -------------------------------------------------------- - -ACTOR ForceFieldGuard native -{ - Health 10 - Radius 2 - Height 1 - Mass 10000 - +SHOOTABLE - +NOSECTOR - +NOBLOOD - +INCOMBAT - States - { - Spawn: - TNT1 A -1 - Stop - Death: - TNT1 A 1 A_RemoveForceField - Stop - } -} - -// Kneeling Guy ------------------------------------------------------------- - -ACTOR KneelingGuy -{ - Health 51 - Painchance 255 - Radius 6 - Height 17 - Mass 50000 - +SOLID - +SHOOTABLE - +NOBLOOD - +ISMONSTER - +INCOMBAT - PainSound "misc/static" - DeathSound "misc/static" - ActiveSound "misc/chant" - states - { - Spawn: - See: - NEAL A 15 A_LoopActiveSound - NEAL B 40 A_LoopActiveSound - Loop - Pain: - NEAL C 5 A_SetShadow - NEAL B 4 A_Pain - NEAL C 5 A_ClearShadow - Goto Spawn - Wound: - NEAL B 6 - NEAL C 13 A_GetHurt - Loop - Death: - NEAL D 5 - NEAL E 5 A_Scream - NEAL F 6 - NEAL G 5 A_NoBlocking - NEAL H 5 - NEAL I 6 - NEAL J -1 - Stop - } - - -} - -// Klaxon Warning Light ----------------------------------------------------- - -ACTOR KlaxonWarningLight -{ - ReactionTime 60 - Radius 5 - +NOBLOCKMAP +AMBUSH - +SPAWNCEILING +NOGRAVITY - +FIXMAPTHINGPOS +NOSPLASHALERT - +SYNCHRONIZED - States - { - Spawn: - KLAX A 5 A_TurretLook - Loop - See: - KLAX B 6 A_KlaxonBlare - KLAX C 60 - Loop - } - -} - -// CeilingTurret ------------------------------------------------------------ - -ACTOR CeilingTurret -{ - Health 125 - Speed 0 - Painchance 0 - Mass 10000000 - Monster - -SOLID - -CANPASS - +AMBUSH - +SPAWNCEILING - +NOGRAVITY - +NOBLOOD - +NOSPLASHALERT - +DONTFALL - MinMissileChance 150 - DeathSound "turret/death" - States - { - Spawn: - TURT A 5 A_TurretLook - Loop - See: - TURT A 2 A_Chase - Loop - Missile: - Pain: - TURT B 4 Slow A_ShootGun - TURT D 3 Slow A_SentinelRefire - TURT A 4 A_SentinelRefire - Loop - Death: - BALL A 6 Bright A_Scream - BALL BCDE 6 Bright - TURT C -1 - Stop - } -} - - -// Power Coupling ----------------------------------------------------------- - -ACTOR PowerCoupling native -{ - Health 40 - Radius 17 - Height 64 - Mass 999999 - +SOLID - +SHOOTABLE - +DROPPED - +NOBLOOD - +NOTDMATCH - +INCOMBAT - States - { - Spawn: - COUP AB 5 - Loop - } -} - -// Gibs for things that bleed ----------------------------------------------- - -ACTOR Meat native -{ - +NOCLIP - States - { - Spawn: - MEAT A 700 - Stop - MEAT B 700 - Stop - MEAT C 700 - Stop - MEAT D 700 - Stop - MEAT E 700 - Stop - MEAT F 700 - Stop - MEAT G 700 - Stop - MEAT H 700 - Stop - MEAT I 700 - Stop - MEAT J 700 - Stop - MEAT K 700 - Stop - MEAT L 700 - Stop - MEAT M 700 - Stop - MEAT N 700 - Stop - MEAT O 700 - Stop - MEAT P 700 - Stop - MEAT Q 700 - Stop - MEAT R 700 - Stop - MEAT S 700 - Stop - MEAT T 700 - Stop - } -} - -// Gibs for things that don't bleed ----------------------------------------- - -ACTOR Junk : Meat -{ -states -{ - Spawn: - JUNK A 700 - Stop - JUNK B 700 - Stop - JUNK C 700 - Stop - JUNK D 700 - Stop - JUNK E 700 - Stop - JUNK F 700 - Stop - JUNK G 700 - Stop - JUNK H 700 - Stop - JUNK I 700 - Stop - JUNK J 700 - Stop - JUNK K 700 - Stop - JUNK L 700 - Stop - JUNK M 700 - Stop - JUNK N 700 - Stop - JUNK O 700 - Stop - JUNK P 700 - Stop - JUNK Q 700 - Stop - JUNK R 700 - Stop - JUNK S 700 - Stop - JUNK T 700 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/strifeweapons.txt b/wadsrc/static/actors/strife/strifeweapons.txt deleted file mode 100644 index b807f110a..000000000 --- a/wadsrc/static/actors/strife/strifeweapons.txt +++ /dev/null @@ -1,813 +0,0 @@ - -ACTOR StrifeWeapon : Weapon -{ - Weapon.Kickback 100 -} - -// Same as the bullet puff for Doom ----------------------------------------- - -ACTOR StrifePuff -{ - +NOBLOCKMAP - +NOGRAVITY - +ALLOWPARTICLES - RenderStyle Translucent - Alpha 0.25 - - states - { - Spawn: - POW3 ABCDEFGH 3 - Stop - Crash: - PUFY A 4 Bright - PUFY BCD 4 - Stop - } -} - - -// A spark when you hit something that doesn't bleed ------------------------ -// Only used by the dagger. - -ACTOR StrifeSpark : StrifePuff -{ - RenderStyle Add - States - { - Crash: - POW2 ABCD 4 - Stop - } -} - -// Punch Dagger ------------------------------------------------------------- - -ACTOR PunchDagger : StrifeWeapon -{ - Weapon.SelectionOrder 3900 - +WEAPON.NOALERT - Obituary "$OB_MPPUNCHDAGGER" - Tag "$TAG_PUNCHDAGGER" - - action native A_JabDagger (); - - States - { - Ready: - PNCH A 1 A_WeaponReady - Loop - Deselect: - PNCH A 1 A_Lower - Loop - Select: - PNCH A 1 A_Raise - Loop - Fire: - PNCH B 4 - PNCH C 4 A_JabDagger - PNCH D 5 - PNCH C 4 - PNCH B 5 A_ReFire - Goto Ready - } - -} - - -// The base for Strife projectiles that die with ZAP1 ----------------------- - -ACTOR StrifeZap1 -{ - +NOBLOCKMAP - +NOGRAVITY - +DROPOFF - States - { - Spawn: - Death: - ZAP1 A 3 A_AlertMonsters - ZAP1 BCDEFE 3 - ZAP1 DCB 2 - ZAP1 A 1 - Stop - } -} - - -// Electric Bolt ------------------------------------------------------------ - -ACTOR ElectricBolt : StrifeZap1 -{ - Speed 30 - Radius 10 - Height 10 - Damage 10 - Projectile - +STRIFEDAMAGE - MaxStepHeight 4 - SeeSound "misc/swish" - ActiveSound "misc/swish" - DeathSound "weapons/xbowhit" - Obituary "$OB_MPELECTRICBOLT" - States - { - Spawn: - AROW A 10 A_LoopActiveSound - Loop - } -} - - -// Poison Bolt -------------------------------------------------------------- - -ACTOR PoisonBolt native -{ - Speed 30 - Radius 10 - Height 10 - Damage 500 - Projectile - +STRIFEDAMAGE - MaxStepHeight 4 - SeeSound "misc/swish" - ActiveSound "misc/swish" - Obituary "$OB_MPPOISONBOLT" - States - { - Spawn: - ARWP A 10 A_LoopActiveSound - Loop - Death: - AROW A 1 - Stop - } -} - - -// Strife's Crossbow -------------------------------------------------------- - -ACTOR StrifeCrossbow : StrifeWeapon -{ - +FLOORCLIP - Weapon.SelectionOrder 1200 - +WEAPON.NOALERT - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 8 - Weapon.AmmoType1 "ElectricBolts" - Weapon.SisterWeapon "StrifeCrossbow2" - Inventory.PickupMessage "$TXT_STRIFECROSSBOW" - Tag "$TAG_STRIFECROSSBOW1" - Inventory.Icon "CBOWA0" - - action native A_ClearFlash (); - action native A_ShowElectricFlash (); - action native A_FireArrow (class proj); - - states - { - Spawn: - CBOW A -1 - Stop - Ready: - XBOW A 0 A_ShowElectricFlash - XBOW A 1 A_WeaponReady - Wait - Deselect: - XBOW A 1 A_Lower - Loop - Select: - XBOW A 1 A_Raise - Loop - Fire: - XBOW A 3 A_ClearFlash - XBOW B 6 A_FireArrow("ElectricBolt") - XBOW C 4 - XBOW D 6 - XBOW E 3 - XBOW F 5 - XBOW G 0 A_ShowElectricFlash - XBOW G 5 A_CheckReload - Goto Ready+1 - Flash: - XBOW KLM 5 - Loop - } -} - - -ACTOR StrifeCrossbow2 : StrifeCrossbow -{ - Weapon.SelectionOrder 2700 - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 0 - Weapon.AmmoType1 "PoisonBolts" - Weapon.SisterWeapon "StrifeCrossbow" - Tag "$TAG_STRIFECROSSBOW2" - - States - { - Ready: - XBOW H 1 A_WeaponReady - Loop - Deselect: - XBOW H 1 A_Lower - Loop - Select: - XBOW H 1 A_Raise - Loop - Fire: - XBOW H 3 - XBOW B 6 A_FireArrow("PoisonBolt") - XBOW C 4 - XBOW D 6 - XBOW E 3 - XBOW I 5 - XBOW J 5 A_CheckReload - Goto Ready - Flash: - Stop - } -} - -// Assault Gun -------------------------------------------------------------- - -actor AssaultGun : StrifeWeapon -{ - +FLOORCLIP - Weapon.SelectionOrder 600 - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 20 - Weapon.AmmoType1 "ClipOfBullets" - Inventory.Icon "RIFLA0" - Tag "$TAG_ASSAULTGUN" - Inventory.PickupMessage "$TXT_ASSAULTGUN" - Obituary "$OB_MPASSAULTGUN" - States - { - Spawn: - RIFL A -1 - Stop - Ready: - RIFG A 1 A_WeaponReady - Loop - Deselect: - RIFG B 1 A_Lower - Loop - Select: - RIFG A 1 A_Raise - Loop - Fire: - RIFF AB 3 A_FireAssaultGun - RIFG D 3 A_FireAssaultGun - RIFG C 0 A_ReFire - RIFG B 2 A_Light0 - Goto Ready - } -} - - -// Standing variant of the assault gun -------------------------------------- - -ACTOR AssaultGunStanding : WeaponGiver -{ - DropItem "AssaultGun" - Inventory.PickupMessage "$TXT_ASSAULTGUN" - States - { - Spawn: - RIFL B -1 - Stop - } -} - - -// Mini-Missile Launcher ---------------------------------------------------- - - -ACTOR MiniMissileLauncher : StrifeWeapon -{ - +FLOORCLIP - Weapon.SelectionOrder 1800 - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 8 - Weapon.AmmoType1 "MiniMissiles" - Inventory.Icon "MMSLA0" - Tag "$TAG_MMLAUNCHER" - Inventory.PickupMessage "$TXT_MMLAUNCHER" - - action native A_FireMiniMissile (); - - States - { - Spawn: - MMSL A -1 - Stop - Ready: - MMIS A 1 A_WeaponReady - Loop - Deselect: - MMIS A 1 A_Lower - Loop - Select: - MMIS A 1 A_Raise - Loop - Fire: - MMIS A 4 A_FireMiniMissile - MMIS B 4 A_Light1 - MMIS C 5 Bright - MMIS D 2 Bright A_Light2 - MMIS E 2 Bright - MMIS F 2 Bright A_Light0 - MMIS F 0 A_ReFire - Goto Ready - } -} - - -// Rocket Trail ------------------------------------------------------------- - -ACTOR RocketTrail -{ - +NOBLOCKMAP - +NOGRAVITY - RenderStyle Translucent - Alpha 0.25 - SeeSound "misc/missileinflight" - States - { - Spawn: - PUFY BCBCD 4 - Stop - } -} - -// Rocket Puff -------------------------------------------------------------- - -ACTOR MiniMissilePuff : StrifePuff -{ - -ALLOWPARTICLES - States - { - Spawn: - Goto Crash - } -} - -// Mini Missile ------------------------------------------------------------- - -ACTOR MiniMissile -{ - Speed 20 - Radius 10 - Height 14 - Damage 10 - Projectile - +STRIFEDAMAGE - MaxStepHeight 4 - SeeSound "weapons/minimissile" - DeathSound "weapons/minimissilehit" - Obituary "$OB_MPMINIMISSILELAUNCHER" - States - { - Spawn: - MICR A 6 Bright A_RocketInFlight - Loop - Death: - SMIS A 0 Bright A_SetTranslucent(1,1) - SMIS A 0 Bright // State left for savegame compatibility - SMIS A 5 Bright A_Explode(64,64,1,1) - SMIS B 5 Bright - SMIS C 4 Bright - SMIS DEFG 2 Bright - Stop - } -} - -// Flame Thrower ------------------------------------------------------------ - -ACTOR FlameThrower : StrifeWeapon -{ - +FLOORCLIP - Weapon.SelectionOrder 2100 - Weapon.Kickback 0 - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 100 - Weapon.UpSound "weapons/flameidle" - Weapon.ReadySound "weapons/flameidle" - Weapon.AmmoType1 "EnergyPod" - Inventory.Icon "FLAMA0" - Tag "$TAG_FLAMER" - Inventory.PickupMessage "$TXT_FLAMER" - - action native A_FireFlamer (); - - States - { - Spawn: - FLAM A -1 - Stop - Ready: - FLMT AB 3 A_WeaponReady - Loop - Deselect: - FLMT A 1 A_Lower - Loop - Select: - FLMT A 1 A_Raise - Loop - Fire: - FLMF A 2 A_FireFlamer - FLMF B 3 A_ReFire - Goto Ready - } -} - - -// Flame Thrower Projectile ------------------------------------------------- - -ACTOR FlameMissile -{ - Speed 15 - Height 11 - Radius 8 - Mass 10 - Damage 4 - DamageType Fire - ReactionTime 8 - Projectile - -NOGRAVITY - +STRIFEDAMAGE - MaxStepHeight 4 - RenderStyle Add - SeeSound "weapons/flamethrower" - Obituary "$OB_MPFLAMETHROWER" - - action native A_FlameDie (); - - States - { - Spawn: - FRBL AB 3 Bright - FRBL C 3 Bright A_Countdown - Loop - Death: - FRBL D 5 Bright A_FlameDie - FRBL EFGHI 5 Bright - Stop - } - -} - - -// Mauler ------------------------------------------------------------------- -// The scatter version - -ACTOR Mauler : StrifeWeapon -{ - +FLOORCLIP - Weapon.SelectionOrder 300 - Weapon.AmmoUse1 20 - Weapon.AmmoGive1 40 - Weapon.AmmoType1 "EnergyPod" - Weapon.SisterWeapon "Mauler2" - Inventory.Icon "TRPDA0" - Tag "$TAG_MAULER1" - Inventory.PickupMessage "$TXT_MAULER" - Obituary "$OB_MPMAULER1" - - action native A_FireMauler1 (); - - States - { - Ready: - MAUL FGHA 6 A_WeaponReady - Loop - Deselect: - MAUL A 1 A_Lower - Loop - Select: - MAUL A 1 A_Raise - Loop - Fire: - BLSF A 5 Bright A_FireMauler1 - MAUL B 3 Bright A_Light1 - MAUL C 2 A_Light2 - MAUL DE 2 - MAUL A 7 A_Light0 - MAUL H 7 - MAUL G 7 A_CheckReload - Goto Ready - Spawn: - TRPD A -1 - Stop - } -} - - -// Mauler Torpedo version --------------------------------------------------- - -ACTOR Mauler2 : Mauler -{ - Weapon.SelectionOrder 3300 - Weapon.AmmoUse1 30 - Weapon.AmmoGive1 0 - Weapon.AmmoType1 "EnergyPod" - Weapon.SisterWeapon "Mauler" - Tag "$TAG_MAULER2" - - action native A_FireMauler2Pre (); - action native A_FireMauler2 (); - - States - { - Ready: - MAUL IJKL 7 A_WeaponReady - Loop - Deselect: - MAUL I 1 A_Lower - Loop - Select: - MAUL I 1 A_Raise - Loop - Fire: - MAUL I 20 A_FireMauler2Pre - MAUL J 10 A_Light1 - BLSF A 10 Bright A_FireMauler2 - MAUL B 10 Bright A_Light2 - MAUL C 2 - MAUL D 2 A_Light0 - MAUL E 2 A_ReFire - Goto Ready - } -} - - -// Mauler "Bullet" Puff ----------------------------------------------------- - -ACTOR MaulerPuff -{ - +NOBLOCKMAP - +NOGRAVITY - +PUFFONACTORS - RenderStyle Add - DamageType Disintegrate - states - { - Spawn: - MPUF AB 5 - POW1 ABCDE 4 - Stop - } -} - -// The Mauler's Torpedo ----------------------------------------------------- - -ACTOR MaulerTorpedo -{ - Speed 20 - Height 8 - Radius 13 - Damage 1 - DamageType Disintegrate - Projectile - +STRIFEDAMAGE - MaxStepHeight 4 - RenderStyle Add - SeeSound "weapons/mauler2fire" - DeathSound "weapons/mauler2hit" - Obituary "$OB_MPMAULER" - - action native A_MaulerTorpedoWave (); - - States - { - Spawn: - TORP ABCD 4 Bright - Loop - Death: - THIT AB 8 Bright - THIT C 8 Bright A_MaulerTorpedoWave - THIT DE 8 Bright - Stop - } -} - - -// The mini torpedoes shot by the big torpedo -------------------------------- - -ACTOR MaulerTorpedoWave -{ - Speed 35 - Radius 13 - Height 13 - Damage 10 - DamageType Disintegrate - Projectile - +STRIFEDAMAGE - MaxStepHeight 4 - RenderStyle Add - Obituary "$OB_MPMAULER" - States - { - Spawn: - TWAV AB 9 Bright - Death: - TWAV C 9 Bright - Stop - } -} - - -// High-Explosive Grenade --------------------------------------------------- - -ACTOR HEGrenade -{ - Speed 15 - Radius 13 - Height 13 - Mass 20 - Damage 1 - Reactiontime 30 - Projectile - -NOGRAVITY - +STRIFEDAMAGE - +BOUNCEONACTORS - +EXPLODEONWATER - MaxStepHeight 4 - BounceType "Doom" - BounceFactor 0.5 - BounceCount 2 - SeeSound "weapons/hegrenadeshoot" - DeathSound "weapons/hegrenadebang" - Obituary "$OB_MPSTRIFEGRENADE" - States - { - Spawn: - GRAP AB 3 A_Countdown - Loop - Death: - BNG4 A 0 Bright A_NoGravity - BNG4 A 0 Bright A_SetTranslucent(1,1) - BNG4 A 2 Bright A_Explode(192,192,1,1) - BNG4 BCDEFGHIJKLMN 3 Bright - Stop - } -} - -// White Phosphorous Grenade ------------------------------------------------ - -ACTOR PhosphorousGrenade -{ - Speed 15 - Radius 13 - Height 13 - Mass 20 - Damage 1 - Reactiontime 40 - Projectile - -NOGRAVITY - +STRIFEDAMAGE - +BOUNCEONACTORS - +EXPLODEONWATER - BounceType "Doom" - MaxStepHeight 4 - BounceFactor 0.5 - BounceCount 2 - SeeSound "weapons/phgrenadeshoot" - DeathSound "weapons/phgrenadebang" - Obituary "$OB_MPPHOSPHOROUSGRENADE" - States - { - Spawn: - GRIN AB 3 A_Countdown - Loop - Death: - BNG3 A 2 A_SpawnItemEx("PhosphorousFire") - Stop - } -} - -// Fire from the Phoshorous Grenade ----------------------------------------- - -ACTOR PhosphorousFire native -{ - Reactiontime 120 - DamageType Fire - +NOBLOCKMAP - +FLOORCLIP - +NOTELEPORT - +NODAMAGETHRUST - +DONTSPLASH - RenderStyle Add - Obituary "$OB_MPPHOSPHOROUSGRENADE" - - action native A_Burnarea (); - action native A_Burnination (); - - states - { - Spawn: - BNG3 B 2 Bright A_Burnarea - BNG3 C 2 Bright A_Countdown - FLBE A 2 Bright A_Burnination - FLBE B 2 Bright A_Countdown - FLBE C 2 Bright A_Burnarea - FLBE D 3 Bright A_Countdown - FLBE E 3 Bright A_Burnarea - FLBE F 3 Bright A_Countdown - FLBE G 3 Bright A_Burnination - Goto Spawn+5 - Death: - FLBE H 2 Bright - FLBE I 2 Bright A_Burnination - FLBE JK 2 Bright - Stop - } -} - -// High-Explosive Grenade Launcher ------------------------------------------ - -ACTOR StrifeGrenadeLauncher : StrifeWeapon -{ - +FLOORCLIP - Weapon.SelectionOrder 2400 - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 12 - Weapon.AmmoType1 "HEGrenadeRounds" - Weapon.SisterWeapon "StrifeGrenadeLauncher2" - Inventory.Icon "GRNDA0" - Tag "$TAG_GLAUNCHER1" - Inventory.PickupMessage "$TXT_GLAUNCHER" - - action native A_FireGrenade (class grenadetype, float angleofs, state flash); - - States - { - Spawn: - GRND A -1 - Stop - Ready: - GREN A 1 A_WeaponReady - Loop - Deselect: - GREN A 1 A_Lower - Loop - Select: - GREN A 1 A_Raise - Loop - Fire: - GREN A 5 A_FireGrenade("HEGrenade", -90, "Flash") - GREN B 10 - GREN A 5 A_FireGrenade("HEGrenade", 90, "Flash2") - GREN C 10 - GREN A 0 A_ReFire - Goto Ready - Flash: - GREF A 5 Bright A_Light1 - Goto LightDone - Flash2: - GREF B 5 Bright A_Light2 - Goto LightDone - } - -} - -// White Phosphorous Grenade Launcher --------------------------------------- - -ACTOR StrifeGrenadeLauncher2 : StrifeGrenadeLauncher -{ - Weapon.SelectionOrder 3200 - Weapon.AmmoUse1 1 - Weapon.AmmoGive1 0 - Weapon.AmmoType1 "PhosphorusGrenadeRounds" - Weapon.SisterWeapon "StrifeGrenadeLauncher" - Tag "$TAG_GLAUNCHER2" - - States - { - Ready: - GREN D 1 A_WeaponReady - Loop - Deselect: - GREN D 1 A_Lower - Loop - Select: - GREN D 1 A_Raise - Loop - Fire: - GREN D 5 A_FireGrenade("PhosphorousGrenade", -90, "Flash") - GREN E 10 - GREN D 5 A_FireGrenade("PhosphorousGrenade", 90, "Flash2") - GREN F 10 - GREN A 0 A_ReFire - Goto Ready - Flash: - GREF C 5 Bright A_Light1 - Goto LightDone - Flash2: - GREF D 5 Bright A_Light2 - Goto LightDone - } -} - diff --git a/wadsrc/static/actors/strife/templar.txt b/wadsrc/static/actors/strife/templar.txt deleted file mode 100644 index f15195c3d..000000000 --- a/wadsrc/static/actors/strife/templar.txt +++ /dev/null @@ -1,66 +0,0 @@ - -ACTOR Templar -{ - Health 300 - Painchance 100 - Speed 8 - Radius 20 - Height 60 - Mass 500 - Monster - +NOBLOOD - +SEESDAGGERS - +NOSPLASHALERT - MaxdropoffHeight 32 - MinMissileChance 200 - SeeSound "templar/sight" - PainSound "templar/pain" - DeathSound "templar/death" - ActiveSound "templar/active" - CrushPainSound "misc/pcrush" - Tag "$TAG_TEMPLAR" - HitObituary "$OB_TEMPLARHIT" - Obituary "$OB_TEMPLAR" - DropItem "EnergyPod" - - action native A_TemplarAttack(); - - States - { - Spawn: - PGRD A 5 A_Look2 - Loop - PGRD B 10 - Loop - PGRD C 10 - Loop - PGRD B 10 A_Wander - Loop - See: - PGRD AABBCCDD 3 A_Chase - Loop - Melee: - PGRD E 8 A_FaceTarget - PGRD F 8 A_CustomMeleeAttack(random[ReaverMelee](1,8)*3, "reaver/blade") - Goto See - Missile: - PGRD G 8 BRIGHT A_FaceTarget - PGRD H 8 BRIGHT A_TemplarAttack - Goto See - Pain: - PGRD A 2 - PGRD A 2 A_Pain - Goto See - Death: - PGRD I 4 A_TossGib - PGRD J 4 A_Scream - PGRD K 4 A_TossGib - PGRD L 4 A_NoBlocking - PGRD MN 4 - PGRD O 4 A_TossGib - PGRD "PQRSTUVWXYZ[" 4 - PGRD "\" -1 - Stop - } -} - diff --git a/wadsrc/static/actors/strife/thingstoblowup.txt b/wadsrc/static/actors/strife/thingstoblowup.txt deleted file mode 100644 index 8f8148809..000000000 --- a/wadsrc/static/actors/strife/thingstoblowup.txt +++ /dev/null @@ -1,141 +0,0 @@ - - -// A Cloud used for varius explosions --------------------------------------- -// This actor has no direct equivalent in strife. To create this, Strife -// spawned a spark and then changed its state to that of this explosion -// cloud. Weird. - -ACTOR Bang4Cloud -{ - +NOBLOCKMAP - +NOGRAVITY - RenderStyle Add - VSpeed 1 - States - { - Spawn: - BNG4 BCDEFGHIJKLMN 3 Bright - Stop - } -} - -// Piston ------------------------------------------------------------------- - -ACTOR Piston -{ - Health 100 - Speed 16 - Radius 20 - Height 76 - Mass 10000000 - +SOLID - +SHOOTABLE - +NOBLOOD - +FLOORCLIP - +INCOMBAT - DeathSound "misc/explosion" - states - { - Spawn: - PSTN AB 8 - Loop - Death: - PSTN A 4 Bright A_Scream - PSTN B 4 Bright A_NoBlocking - PSTN C 4 Bright A_GiveQuestItem(16) - PSTN D 4 Bright A_Bang4Cloud - PSTN E 4 Bright A_TossGib - PSTN F 4 Bright - PSTN G 4 Bright A_Bang4Cloud - PSTN H 4 - PSTN I -1 - Stop - } - -} - -// Computer ----------------------------------------------------------------- - -ACTOR Computer -{ - Health 80 - Speed 27 - Radius 26 - Height 128 - Mass 10000000 - +SOLID - +SHOOTABLE - +NOBLOOD - +FLOORCLIP - +INCOMBAT - DeathSound "misc/explosion" - states - { - Spawn: - SECR ABCD 4 Bright - Loop - Death: - SECR E 5 Bright A_Bang4Cloud - SECR F 5 Bright A_NoBlocking - SECR G 5 Bright A_GiveQuestItem(27) - SECR H 5 Bright A_TossGib - SECR I 5 Bright A_Bang4Cloud - SECR J 5 - SECR K 5 A_Bang4Cloud - SECR L 5 - SECR M 5 A_Bang4Cloud - SECR N 5 - SECR O 5 A_Bang4Cloud - SECR P -1 - Stop - } -} - - -// Power Crystal ------------------------------------------------------------ - -ACTOR PowerCrystal -{ - Health 50 - Speed 14 - Radius 20 - Height 16 - Mass 99999999 - +SOLID - +SHOOTABLE - +NOGRAVITY - +NOBLOOD - +FLOORCLIP - DeathSound "misc/explosion" - ActiveSound "misc/reactor" - - action native A_ExtraLightOff (); - action native A_Explode512 (); - action native A_LightGoesOut (); - - States - { - Spawn: - CRYS A 16 A_LoopActiveSound - CRYS B 5 A_LoopActiveSound - CRYS CDEF 4 A_LoopActiveSound - Loop - Death: - BOOM A 0 Bright A_Scream - BOOM A 1 Bright A_Explode512 - BOOM B 3 Bright A_GiveQuestItem(14) - BOOM C 2 Bright A_LightGoesOut - BOOM D 3 Bright A_Bang4Cloud - BOOM EF 3 Bright - BOOM G 3 Bright A_Bang4Cloud - BOOM H 1 Bright A_Explode512 - BOOM I 3 Bright - BOOM JKL 3 Bright A_Bang4Cloud - BOOM MN 3 Bright - BOOM O 3 Bright A_Bang4Cloud - BOOM PQRST 3 Bright - BOOM U 3 Bright A_ExtraLightOff - BOOM VWXY 3 Bright - Stop - } -} diff --git a/wadsrc/static/actors/strife/zombie.txt b/wadsrc/static/actors/strife/zombie.txt deleted file mode 100644 index 54683b824..000000000 --- a/wadsrc/static/actors/strife/zombie.txt +++ /dev/null @@ -1,58 +0,0 @@ - -// Zombie ------------------------------------------------------------------- - -ACTOR Zombie : StrifeHumanoid -{ - Health 31 - Radius 20 - Height 56 - PainChance 0 - +SOLID - +SHOOTABLE - +FLOORCLIP - +CANPASS - +CANPUSHWALLS - +ACTIVATEMCROSS - MinMissileChance 150 - MaxStepHeight 16 - MaxDropOffHeight 32 - Translation 0 - DeathSound "zombie/death" - CrushPainSound "misc/pcrush" - States - { - Spawn: - PEAS A 5 A_CheckTerrain - Loop - Pain: - AGRD A 5 A_CheckTerrain - Loop - Death: - GIBS M 5 A_TossGib - GIBS N 5 A_XScream - GIBS O 5 A_NoBlocking - GIBS PQRST 4 A_TossGib - GIBS U 5 - GIBS V -1 - Stop - } -} - - -// Zombie Spawner ----------------------------------------------------------- - -ACTOR ZombieSpawner -{ - Health 20 - +SHOOTABLE - +NOSECTOR - RenderStyle None - ActiveSound "zombie/spawner" // Does Strife use this somewhere else? - States - { - Spawn: - TNT1 A 175 A_SpawnItemEx("Zombie") - Loop - } -} - diff --git a/wadsrc/static/decorate.txt b/wadsrc/static/decorate.txt deleted file mode 100644 index 71c7d549b..000000000 --- a/wadsrc/static/decorate.txt +++ /dev/null @@ -1,181 +0,0 @@ -#include "actors/constants.txt" -#include "actors/actor.txt" - -#include "actors/shared/inventory.txt" -#include "actors/shared/player.txt" -#include "actors/shared/morph.txt" -#include "actors/shared/botstuff.txt" -#include "actors/shared/sharedmisc.txt" -#include "actors/shared/blood.txt" -#include "actors/shared/debris.txt" -#include "actors/shared/decal.txt" -#include "actors/shared/splashes.txt" -#include "actors/shared/pickups.txt" -#include "actors/shared/fountain.txt" -#include "actors/shared/spark.txt" -#include "actors/shared/soundsequence.txt" -#include "actors/shared/soundenvironment.txt" -#include "actors/shared/bridge.txt" -#include "actors/shared/specialspot.txt" -#include "actors/shared/teleport.txt" -#include "actors/shared/camera.txt" -#include "actors/shared/movingcamera.txt" -#include "actors/shared/mapmarker.txt" -#include "actors/shared/waterzone.txt" -#include "actors/shared/skies.txt" -#include "actors/shared/hatetarget.txt" -#include "actors/shared/secrettrigger.txt" -#include "actors/shared/setcolor.txt" -#include "actors/shared/sectoraction.txt" -#include "actors/shared/action.txt" -#include "actors/shared/dog.txt" -#include "actors/shared/damagetypes.txt" -#include "actors/shared/dynlights.txt" - -#include "actors/doom/doomplayer.txt" -#include "actors/doom/possessed.txt" -#include "actors/doom/doomimp.txt" -#include "actors/doom/demon.txt" -#include "actors/doom/lostsoul.txt" -#include "actors/doom/cacodemon.txt" -#include "actors/doom/bruiser.txt" -#include "actors/doom/revenant.txt" -#include "actors/doom/arachnotron.txt" -#include "actors/doom/fatso.txt" -#include "actors/doom/painelemental.txt" -#include "actors/doom/archvile.txt" -#include "actors/doom/cyberdemon.txt" -#include "actors/doom/spidermaster.txt" -#include "actors/doom/keen.txt" -#include "actors/doom/bossbrain.txt" - -#include "actors/doom/deadthings.txt" -#include "actors/doom/doomammo.txt" -#include "actors/doom/doomarmor.txt" -#include "actors/doom/doomartifacts.txt" -#include "actors/doom/doomhealth.txt" -#include "actors/doom/doomkeys.txt" -#include "actors/doom/doommisc.txt" -#include "actors/doom/doomdecorations.txt" -#include "actors/doom/doomweapons.txt" -#include "actors/doom/stealthmonsters.txt" -#include "actors/doom/scriptedmarine.txt" - -#include "actors/raven/artiegg.txt" -#include "actors/raven/artitele.txt" -#include "actors/raven/ravenartifacts.txt" -#include "actors/raven/ravenhealth.txt" -#include "actors/raven/ravenambient.txt" -#include "actors/raven/minotaur.txt" - -#include "actors/heretic/hereticplayer.txt" -#include "actors/heretic/hereticammo.txt" -#include "actors/heretic/hereticarmor.txt" -#include "actors/heretic/hereticartifacts.txt" -#include "actors/heretic/heretickeys.txt" -#include "actors/heretic/hereticdecorations.txt" -#include "actors/heretic/hereticmisc.txt" -#include "actors/heretic/hereticweaps.txt" -#include "actors/heretic/mummy.txt" -#include "actors/heretic/clink.txt" -#include "actors/heretic/beast.txt" -#include "actors/heretic/snake.txt" -#include "actors/heretic/hereticimp.txt" -#include "actors/heretic/knight.txt" -#include "actors/heretic/wizard.txt" -#include "actors/heretic/ironlich.txt" -#include "actors/heretic/dsparil.txt" -#include "actors/heretic/chicken.txt" - -#include "actors/hexen/baseweapons.txt" -#include "actors/hexen/korax.txt" -#include "actors/hexen/fighterplayer.txt" -#include "actors/hexen/clericplayer.txt" -#include "actors/hexen/mageplayer.txt" -#include "actors/hexen/pig.txt" -#include "actors/hexen/flame.txt" -#include "actors/hexen/flies.txt" -#include "actors/hexen/hexenarmor.txt" -#include "actors/hexen/hexendecorations.txt" -#include "actors/hexen/hexenkeys.txt" -#include "actors/hexen/hexenspecialdecs.txt" -#include "actors/hexen/mana.txt" -#include "actors/hexen/puzzleitems.txt" -#include "actors/hexen/scriptprojectiles.txt" -#include "actors/hexen/speedboots.txt" -#include "actors/hexen/ettin.txt" -#include "actors/hexen/centaur.txt" -#include "actors/hexen/demons.txt" -#include "actors/hexen/firedemon.txt" -#include "actors/hexen/fog.txt" -#include "actors/hexen/summon.txt" -#include "actors/hexen/flechette.txt" -#include "actors/hexen/clericboss.txt" -#include "actors/hexen/fighterboss.txt" -#include "actors/hexen/mageboss.txt" -#include "actors/hexen/bats.txt" -#include "actors/hexen/bishop.txt" -#include "actors/hexen/blastradius.txt" -#include "actors/hexen/boostarmor.txt" -#include "actors/hexen/clericmace.txt" -#include "actors/hexen/clericflame.txt" -#include "actors/hexen/clericholy.txt" -#include "actors/hexen/clericstaff.txt" -#include "actors/hexen/magewand.txt" -#include "actors/hexen/magecone.txt" -#include "actors/hexen/magelightning.txt" -#include "actors/hexen/magestaff.txt" -#include "actors/hexen/fighterfist.txt" -#include "actors/hexen/fighteraxe.txt" -#include "actors/hexen/fighterhammer.txt" -#include "actors/hexen/fighterquietus.txt" -#include "actors/hexen/dragon.txt" -#include "actors/hexen/healingradius.txt" -#include "actors/hexen/teleportother.txt" -#include "actors/hexen/iceguy.txt" -#include "actors/hexen/serpent.txt" -#include "actors/hexen/spike.txt" -#include "actors/hexen/wraith.txt" -#include "actors/hexen/heresiarch.txt" - -#include "actors/strife/strifehumanoid.txt" -#include "actors/strife/strifeplayer.txt" -#include "actors/strife/strifeweapons.txt" -#include "actors/strife/spectral.txt" -#include "actors/strife/acolyte.txt" -#include "actors/strife/alienspectres.txt" -#include "actors/strife/beggars.txt" -#include "actors/strife/coin.txt" -#include "actors/strife/crusader.txt" -#include "actors/strife/entityboss.txt" -#include "actors/strife/inquisitor.txt" -#include "actors/strife/loremaster.txt" -#include "actors/strife/macil.txt" -#include "actors/strife/merchants.txt" -#include "actors/strife/peasants.txt" -#include "actors/strife/strifebishop.txt" -#include "actors/strife/oracle.txt" -#include "actors/strife/programmer.txt" -#include "actors/strife/questitems.txt" -#include "actors/strife/ratbuddy.txt" -#include "actors/strife/rebels.txt" -#include "actors/strife/reaver.txt" -#include "actors/strife/sentinel.txt" -#include "actors/strife/stalker.txt" -#include "actors/strife/strifeammo.txt" -#include "actors/strife/strifearmor.txt" -#include "actors/strife/strifeitems.txt" -#include "actors/strife/strifekeys.txt" -#include "actors/strife/strifestuff.txt" -#include "actors/strife/thingstoblowup.txt" -#include "actors/strife/templar.txt" -#include "actors/strife/zombie.txt" -#include "actors/strife/sigil.txt" - -#include "actors/chex/chexmonsters.txt" -#include "actors/chex/chexkeys.txt" -#include "actors/chex/chexammo.txt" -#include "actors/chex/chexweapons.txt" -#include "actors/chex/chexitems.txt" -#include "actors/chex/chexdecorations.txt" -#include "actors/chex/chexplayer.txt" diff --git a/wadsrc/static/dehsupp.txt b/wadsrc/static/dehsupp.txt index 78948677f..436e894b4 100644 --- a/wadsrc/static/dehsupp.txt +++ b/wadsrc/static/dehsupp.txt @@ -327,7 +327,7 @@ StateMap BossEye, Spawn, 3, // S_BRAINEYE - S_BRAINEYE1 SpawnShot, Spawn, 4, // S_SPAWN1 - S_SPAWN4 SpawnFire, Spawn, 8, // S_SPAWNFIRE1 - S_SPAWNFIRE8 - BossBrain, BrainExplode, 3, // S_BRAINEXPLODE1 - S_BRAINEXPLODE3 + Rocket, BrainExplode, 3, // S_BRAINEXPLODE1 - S_BRAINEXPLODE3 GreenArmor, Spawn, 2, // S_ARM1 - S_ARM1A BlueArmor, Spawn, 2, // S_ARM2 - S_ARM2A ExplosiveBarrel, Spawn, 7, // S_BAR1 - S_BEXP5 diff --git a/wadsrc/static/mapinfo/common.txt b/wadsrc/static/mapinfo/common.txt index 5e69a3ef9..81a791de6 100644 --- a/wadsrc/static/mapinfo/common.txt +++ b/wadsrc/static/mapinfo/common.txt @@ -585,3 +585,8 @@ Intermission Inter_Chess Position = 5, 135 } } + +DamageType Drowning +{ + NoArmor +} diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt new file mode 100644 index 000000000..42f32a447 --- /dev/null +++ b/wadsrc/static/zscript.txt @@ -0,0 +1,181 @@ +zscript/base.txt +zscript/constants.txt +zscript/actor.txt +zscript/actor_checks.txt + +zscript/shared/inventory.txt +zscript/shared/player.txt +zscript/shared/morph.txt +zscript/shared/botstuff.txt +zscript/shared/sharedmisc.txt +zscript/shared/blood.txt +zscript/shared/debris.txt +zscript/shared/decal.txt +zscript/shared/splashes.txt +zscript/shared/pickups.txt +zscript/shared/fountain.txt +zscript/shared/spark.txt +zscript/shared/soundsequence.txt +zscript/shared/soundenvironment.txt +zscript/shared/bridge.txt +zscript/shared/specialspot.txt +zscript/shared/teleport.txt +zscript/shared/camera.txt +zscript/shared/movingcamera.txt +zscript/shared/mapmarker.txt +zscript/shared/waterzone.txt +zscript/shared/skies.txt +zscript/shared/hatetarget.txt +zscript/shared/secrettrigger.txt +zscript/shared/setcolor.txt +zscript/shared/sectoraction.txt +zscript/shared/ice.txt +zscript/shared/dog.txt + +zscript/doom/doomplayer.txt +zscript/doom/possessed.txt +zscript/doom/doomimp.txt +zscript/doom/demon.txt +zscript/doom/lostsoul.txt +zscript/doom/cacodemon.txt +zscript/doom/bruiser.txt +zscript/doom/revenant.txt +zscript/doom/arachnotron.txt +zscript/doom/fatso.txt +zscript/doom/painelemental.txt +zscript/doom/archvile.txt +zscript/doom/cyberdemon.txt +zscript/doom/spidermaster.txt +zscript/doom/keen.txt +zscript/doom/bossbrain.txt + +zscript/doom/deadthings.txt +zscript/doom/doomammo.txt +zscript/doom/doomarmor.txt +zscript/doom/doomartifacts.txt +zscript/doom/doomhealth.txt +zscript/doom/doomkeys.txt +zscript/doom/doommisc.txt +zscript/doom/doomdecorations.txt +zscript/doom/doomweapons.txt +zscript/doom/stealthmonsters.txt +zscript/doom/scriptedmarine.txt + +zscript/raven/artiegg.txt +zscript/raven/artitele.txt +zscript/raven/ravenartifacts.txt +zscript/raven/ravenhealth.txt +zscript/raven/ravenambient.txt +zscript/raven/minotaur.txt + +zscript/heretic/hereticplayer.txt +zscript/heretic/hereticammo.txt +zscript/heretic/hereticarmor.txt +zscript/heretic/hereticartifacts.txt +zscript/heretic/heretickeys.txt +zscript/heretic/hereticdecorations.txt +zscript/heretic/hereticmisc.txt +zscript/heretic/hereticweaps.txt +zscript/heretic/mummy.txt +zscript/heretic/clink.txt +zscript/heretic/beast.txt +zscript/heretic/snake.txt +zscript/heretic/hereticimp.txt +zscript/heretic/knight.txt +zscript/heretic/wizard.txt +zscript/heretic/ironlich.txt +zscript/heretic/dsparil.txt +zscript/heretic/chicken.txt + +zscript/hexen/baseweapons.txt +zscript/hexen/korax.txt +zscript/hexen/fighterplayer.txt +zscript/hexen/clericplayer.txt +zscript/hexen/mageplayer.txt +zscript/hexen/pig.txt +zscript/hexen/flame.txt +zscript/hexen/flies.txt +zscript/hexen/hexenarmor.txt +zscript/hexen/hexendecorations.txt +zscript/hexen/hexenkeys.txt +zscript/hexen/hexenspecialdecs.txt +zscript/hexen/mana.txt +zscript/hexen/puzzleitems.txt +zscript/hexen/scriptprojectiles.txt +zscript/hexen/speedboots.txt +zscript/hexen/ettin.txt +zscript/hexen/centaur.txt +zscript/hexen/demons.txt +zscript/hexen/firedemon.txt +zscript/hexen/fog.txt +zscript/hexen/summon.txt +zscript/hexen/flechette.txt +zscript/hexen/clericboss.txt +zscript/hexen/fighterboss.txt +zscript/hexen/mageboss.txt +zscript/hexen/bats.txt +zscript/hexen/bishop.txt +zscript/hexen/blastradius.txt +zscript/hexen/boostarmor.txt +zscript/hexen/clericmace.txt +zscript/hexen/clericflame.txt +zscript/hexen/clericholy.txt +zscript/hexen/clericstaff.txt +zscript/hexen/magewand.txt +zscript/hexen/magecone.txt +zscript/hexen/magelightning.txt +zscript/hexen/magestaff.txt +zscript/hexen/fighterfist.txt +zscript/hexen/fighteraxe.txt +zscript/hexen/fighterhammer.txt +zscript/hexen/fighterquietus.txt +zscript/hexen/dragon.txt +zscript/hexen/healingradius.txt +zscript/hexen/teleportother.txt +zscript/hexen/iceguy.txt +zscript/hexen/serpent.txt +zscript/hexen/spike.txt +zscript/hexen/wraith.txt +zscript/hexen/heresiarch.txt + +zscript/strife/strifehumanoid.txt +zscript/strife/strifeplayer.txt +zscript/strife/strifeweapons.txt +zscript/strife/spectral.txt +zscript/strife/acolyte.txt +zscript/strife/alienspectres.txt +zscript/strife/beggars.txt +zscript/strife/coin.txt +zscript/strife/crusader.txt +zscript/strife/entityboss.txt +zscript/strife/inquisitor.txt +zscript/strife/loremaster.txt +zscript/strife/macil.txt +zscript/strife/merchants.txt +zscript/strife/peasants.txt +zscript/strife/strifebishop.txt +zscript/strife/oracle.txt +zscript/strife/programmer.txt +zscript/strife/questitems.txt +zscript/strife/ratbuddy.txt +zscript/strife/rebels.txt +zscript/strife/reaver.txt +zscript/strife/sentinel.txt +zscript/strife/stalker.txt +zscript/strife/strifeammo.txt +zscript/strife/strifearmor.txt +zscript/strife/strifeitems.txt +zscript/strife/strifekeys.txt +zscript/strife/strifestuff.txt +zscript/strife/thingstoblowup.txt +zscript/strife/templar.txt +zscript/strife/zombie.txt +zscript/strife/sigil.txt + +zscript/chex/chexmonsters.txt +zscript/chex/chexkeys.txt +zscript/chex/chexammo.txt +zscript/chex/chexweapons.txt +zscript/chex/chexitems.txt +zscript/chex/chexdecorations.txt +zscript/chex/chexplayer.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt new file mode 100644 index 000000000..09b5683c8 --- /dev/null +++ b/wadsrc/static/zscript/actor.txt @@ -0,0 +1,514 @@ +class Actor : Thinker native +{ + const DEFAULT_HEALTH = 1000; + + Default + { + Scale 1; + Health DEFAULT_HEALTH; + Reactiontime 8; + Radius 20; + Height 16; + Mass 100; + RenderStyle 'Normal'; + Alpha 1; + MinMissileChance 200; + MeleeRange 64 - 20; + MaxDropoffHeight 24; + MaxStepHeight 24; + BounceFactor 0.7; + WallBounceFactor 0.75; + BounceCount -1; + FloatSpeed 4; + FloatBobPhase -1; // randomly initialize by default + Gravity 1; + Friction 1; + DamageFactor 1.0; // damage multiplier as target of damage. + DamageMultiply 1.0; // damage multiplier as source of damage. + PushFactor 0.25; + WeaveIndexXY 0; + WeaveIndexZ 16; + DesignatedTeam 255; + PainType "Normal"; + DeathType "Normal"; + TeleFogSourceType "TeleportFog"; + TeleFogDestType 'TeleportFog'; + RipperLevel 0; + RipLevelMin 0; + RipLevelMax 0; + DefThreshold 100; + BloodType "Blood", "BloodSplatter", "AxeBlood"; + ExplosionDamage 128; + MissileHeight 32; + SpriteAngle 0; + SpriteRotation 0; + StencilColor "00 00 00"; + VisibleAngles 0, 0; + VisiblePitch 0, 0; + DefaultStateUsage SUF_ACTOR|SUF_OVERLAY; + } + + // Functions + + bool IsPointerEqual(int ptr_select1, int ptr_select2) + { + return GetPointer(ptr_select1) == GetPointer(ptr_select2); + } + + static double BobSin(double fb) + { + return sin(fb * (180./32)) * 8; + } + + + native static readonly GetDefaultByType(class cls); + native static float deltaangle(float ang1, float ang2); + native static float GetDefaultSpeed(class type); + native float GetBobOffset(float frac = 0); + native void SetDamage(int dmg); + native static bool isDehState(state st); + native double Distance2D(Actor other); + native void SetOrigin(vector3 newpos, bool moving); + native void SetXYZ(vector3 newpos); + native Actor GetPointer(int aaptr); + native void FaceMovementDirection(); + native Actor AimTarget(); + native static Actor Spawn(class type, vector3 pos = (0,0,0), int replace = NO_REPLACE); + native Actor SpawnMissile(Actor dest, class type, Actor owner = null); + native Actor SpawnMissileZ (double z, Actor dest, class type); + native Actor SpawnMissileAngleZSpeed (double z, class type, float angle, double vz, double speed, Actor owner = null, bool checkspawn = true); + + native Actor OldSpawnMissile(Actor dest, class type, Actor owner = null); + native Actor SpawnPuff(class pufftype, vector3 pos, float hitdir, float particledir, int updown, int flags = 0, Actor vict = null); + + native void TraceBleed(int damage, Actor missile); + native bool CheckMeleeRange(); + native int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0); + native double AimLineAttack(double angle, double distance, out FTranslatedLineTarget pLineTarget = null, double vrange = 0., int flags = 0, Actor target = null, Actor friender = null); + native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class pufftype, int flags = 0, out FTranslatedLineTarget victim = null); + native bool CheckSight(Actor target, int flags = 0); + native bool HitFriend(); + native bool MonsterMove(); + native void NewChaseDir(); + native bool CheckMissileRange(); + native bool SetState(state st, bool nofunction = false); + native state FindState(statelabel st); // do we need exact later? + bool SetStateLabel(statelabel st, bool nofunction = false) { return SetState(FindState(st), nofunction); } + native action state ResolveState(statelabel st); // this one, unlike FindState, is context aware. + native void LinkToWorld(); + native void UnlinkFromWorld(); + native bool CanSeek(Actor target); + native double AngleTo(Actor target, bool absolute = false); + native void AddZ(float zadd); + native void SetZ(float z); + native vector3 Vec3Offset(float x, float y, float z, bool absolute = false); + native vector3 Vec3Angle(float length, float angle, float z = 0, bool absolute = false); + native vector3 Vec2OffsetZ(float x, float y, float atz, bool absolute = false); + native void VelFromAngle(float speed = 0, float angle = 0); + native void Thrust(float speed = 0, float angle = 0); + native bool isFriend(Actor other); + native void AdjustFloorClip(); + native DropItem GetDropItems(); + native void CopyFriendliness (Actor other, bool changeTarget, bool resetHealth = true); + native bool LookForPlayers(bool allaround); + native bool TeleportMove(Vector3 pos, bool telefrag, bool modifyactor = true); + native double DistanceBySpeed(Actor other, double speed); + native name GetSpecies(); + native void PlayActiveSound(); + + // DECORATE compatible functions + native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); + native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); + native float GetDistance(bool checkz, int ptr = AAPTR_TARGET); + native float GetAngle(int flags, int ptr = AAPTR_DEFAULT); + native float GetZAt(float px = 0, float py = 0, float angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); + native int GetSpawnHealth(); + native int GetGibHealth(); + native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); + native float GetCVar(string cvar); + native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); + native int CountProximity(class classname, float distance, int flags = 0, int ptr = AAPTR_DEFAULT); + native float GetSpriteAngle(int ptr = AAPTR_DEFAULT); + native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); + native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT); + action native int OverlayID(); + action native float OverlayX(int layer = 0); + action native float OverlayY(int layer = 0); + + // DECORATE setters - it probably makes more sense to set these values directly now... + void A_SetMass(int newmass) { mass = newmass; } + void A_SetInvulnerable() { bInvulnerable = true; } + void A_UnSetInvulnerable() { bInvulnerable = false; } + void A_SetReflective() { bReflective = true; } + void A_UnSetReflective() { bReflective = false; } + void A_SetReflectiveInvulnerable() { bInvulnerable = true; bReflective = true; } + void A_UnSetReflectiveInvulnerable() { bInvulnerable = false; bReflective = false; } + void A_SetShootable() { bShootable = true; bNonShootable = false; } + void A_UnSetShootable() { bShootable = false; bNonShootable = true; } + void A_NoGravity() { bNoGravity = true; } + void A_Gravity() { bNoGravity = false; Gravity = 1; } + void A_LowGravity() { bNoGravity = false; Gravity = 0.125; } + void A_SetGravity(float newgravity) { gravity = clamp(newgravity, 0., 10.); } + void A_SetFloorClip() { bFloorClip = true; AdjustFloorClip(); } + void A_UnSetFloorClip() { bFloorClip = false; FloorClip = 0; } + void A_HideThing() { bInvisible = true; } + void A_UnHideThing() { bInvisible = false; } + void A_SetArg(int arg, int val) { if (arg >= 0 && arg < 5) args[arg] = val; } + void A_Turn(float turn = 0) { angle += turn; } + void A_SetDamageType(name newdamagetype) { damagetype = newdamagetype; } + void A_SetSolid() { bSolid = true; } + void A_UnsetSolid() { bSolid = false; } + void A_SetFloat() { bFloat = true; } + void A_UnsetFloat() { bFloat = false; } + void A_SetFloatBobPhase(int bob) { if (bob >= 0 && bob <= 63) FloatBobPhase = bob; } + void A_SetRipperLevel(int level) { RipperLevel = level; } + void A_SetRipMin(int minimum) { RipLevelMin = minimum; } + void A_SetRipMax(int maximum) { RipLevelMax = maximum; } + void A_ScreamAndUnblock() { A_Scream(); A_NoBlocking(); } + void A_ActiveAndUnblock() { A_ActiveSound(); A_NoBlocking(); } + + //--------------------------------------------------------------------------- + // + // FUNC P_SpawnMissileAngle + // + // Returns NULL if the missile exploded immediately, otherwise returns + // a mobj_t pointer to the missile. + // + //--------------------------------------------------------------------------- + + Actor SpawnMissileAngle (class type, float angle, double vz) + { + return SpawnMissileAngleZSpeed (pos.z + 32 + GetBobOffset(), type, angle, vz, GetDefaultSpeed (type)); + } + + Actor SpawnMissileAngleZ (double z, class type, double angle, double vz) + { + return SpawnMissileAngleZSpeed (z, type, angle, vz, GetDefaultSpeed (type)); + } + + + void A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false) + { + Actor aptr = GetPointer(ptr); + if (aptr) + { + aptr.Scale.X = scalex; + aptr.Scale.Y = scaley != 0 || usezero? scaley : scalex; // use scalex here, too, if only one parameter. + } + } + void A_SetSpeed(float speed, int ptr = AAPTR_DEFAULT) + { + Actor aptr = GetPointer(ptr); + if (aptr) aptr.Speed = speed; + } + void A_SetFloatSpeed(float speed, int ptr = AAPTR_DEFAULT) + { + Actor aptr = GetPointer(ptr); + if (aptr) aptr.FloatSpeed = speed; + } + void A_SetPainThreshold(int threshold, int ptr = AAPTR_DEFAULT) + { + Actor aptr = GetPointer(ptr); + if (aptr) aptr.PainThreshold = threshold; + } + bool A_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT) + { + Actor aptr = GetPointer(ptr); + if (!aptr) return false; + aptr.SpriteAngle = angle; + return true; + } + bool A_SetSpriteRotation(float angle = 0, int ptr = AAPTR_DEFAULT) + { + Actor aptr = GetPointer(ptr); + if (!aptr) return false; + aptr.SpriteRotation = angle; + return true; + } + + deprecated void A_FaceConsolePlayer(float MaxTurnAngle = 0) {} + + void A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0) + { + special = spec; + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + args[3] = arg3; + args[4] = arg4; + } + + void A_ClearTarget() + { + target = null; + lastheard = null; + lastenemy = null; + } + + void A_ChangeLinkFlags(int blockmap = FLAG_NO_CHANGE, int sector = FLAG_NO_CHANGE) + { + UnlinkFromWorld(); + if (blockmap != FLAG_NO_CHANGE) bNoBlockmap = blockmap; + if (sector != FLAG_NO_CHANGE) bNoSector = sector; + LinkToWorld(); + } + + // killough 11/98: kill an object + void A_Die(name damagetype = "none") + { + DamageMobj(null, null, health, damagetype, DMG_FORCED); + } + + + native void A_Face(Actor faceto, float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); + + 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) + { + A_Face(target, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_ofs); + } + 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) + { + A_Face(tracer, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_ofs); + } + 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) + { + A_Face(master, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_ofs); + } + + // Action functions + // Meh, MBF redundant functions. Only for DeHackEd support. + native bool A_LineEffect(int boomspecial = 0, int tag = 0); + // End of MBF redundant functions. + + native void A_MonsterRail(); + native void A_BFGSpray(class spraytype = "BFGExtra", int numrays = 40, int damagecount = 15, float angle = 90, float distance = 16*64, float vrange = 32, int damage = 0, int flags = 0); + native void A_Pain(); + native void A_NoBlocking(bool drop = true); + void A_Fall() { A_NoBlocking(); } + native void A_XScream(); + native void A_Look(); + native void A_Chase(statelabel melee = null, statelabel missile = null, int flags = 0); + native void A_Scream(); + native void A_VileChase(); + native void A_BossDeath(); + native void A_Detonate(); + native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0); + + native void A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); + + native void A_ActiveSound(); + + native void A_FastChase(); + native void A_FreezeDeath(); + native void A_FreezeDeathChunks(); + native void A_GenericFreezeDeath(); + native void A_IceGuyDie(); + native void A_CStaffMissileSlither(); + native void A_PlayerScream(); + native void A_SkullPop(class skulltype = "BloodySkull"); + native void A_CheckPlayerDone(); + + native void A_Wander(int flags = 0); + native void A_Look2(); + native void A_TossGib(); + native void A_SentinelBob(); + native void A_SentinelRefire(); + native void A_Tracer2(); + native void A_SetShadow(); + native void A_ClearShadow(); + native void A_GetHurt(); + native void A_TurretLook(); + native void A_KlaxonBlare(); + native void A_Countdown(); + native void A_AlertMonsters(float maxdist = 0, int flags = 0); + native void A_ClearSoundTarget(); + native void A_CheckTerrain(); + + deprecated native void A_MissileAttack(); + deprecated native void A_MeleeAttack(); + deprecated native void A_ComboAttack(); + deprecated native void A_BulletAttack(); + native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", float snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, float runspeed = 160.0, class pufftype = "BulletPuff"); + native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM, bool local = false); + deprecated void A_PlayWeaponSound(sound whattoplay) { A_PlaySound(whattoplay, CHAN_WEAPON); } + native void A_FLoopActiveSound(); + native void A_LoopActiveSound(); + native void A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was... + deprecated native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0); + deprecated native void A_StopSoundEx(name slot); + native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); + native action state A_Jump(int chance, statelabel 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 = 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 = null, float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + native bool A_SetInventory(class itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false); + native bool A_GiveInventory(class itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); + 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 = "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); + native void A_SetTranslucent(float alpha, int style = 0); + native void A_SetRenderStyle(float alpha, int style); + native void A_FadeIn(float reduce = 0.1, int flags = 0); + native void A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true + native void A_FadeTo(float target, float amount = 0.1, int flags = 0); + native void A_SpawnDebris(class spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1); + native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, float 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, float sizestep = 0); + 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 = 0); + deprecated native void A_ChangeFlag(string flagname, bool value); + native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); + native void A_RaiseMaster(bool copy = 0); + native void A_RaiseChildren(bool copy = 0); + native void A_RaiseSiblings(bool copy = 0); + deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); + 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); + + + action native state, bool A_Teleport(statelabel teleportstate = null, class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 128, 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, statelabel success_state = null, float heightoffset = 0, float radiusoffset = 0, float pitch = 0); + native void A_CountdownArg(int argnum, statelabel targstate = null); + native state A_MonsterRefire(int chance, statelabel label); + native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, statelabel label = null); + + native void A_Recoil(float xyvel); + 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 = null, name species = "None", float mindist = 0, int limit = 0); + 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); + action native void A_Blast(int flags = 0, float strength = 255, float radius = 255, float speed = 20, class blasteffect = "BlastEffect", sound blastsound = "BlastRadius"); + native void A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0); + native void A_RadiusDamageSelf(int damage = 128, float distance = 128, int flags = 0, class flashtype = null); + native int A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class pufftype = "BulletPuff", name damagetype = "none"); + native void A_Stop(); + native void A_Respawn(int flags = 1); + native void A_QueueCorpse(); + native void A_DeQueueCorpse(); + native void A_ClearLastHeard(); + native bool A_SelectWeapon(class whichweapon, int flags = 0); + action native void A_Punch(); + native void A_Feathers(); + native void A_ClassBossHealth(); + native void A_ShootGun(); + native void A_RocketInFlight(); + native void A_Bang4Cloud(); + native void A_DropFire(); + native void A_GiveQuestItem(int itemno); + native void A_RemoveForcefield(); + native void A_DropWeaponPieces(class p1, class p2, class p3); + native void A_PigPain (); + native void A_SetAngle(float angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + native void A_SetPitch(float pitch, int flags = 0, int ptr = AAPTR_DEFAULT); + native void A_SetRoll(float roll, int flags = 0, int ptr = AAPTR_DEFAULT); + native void A_ScaleVelocity(float scale, int ptr = AAPTR_DEFAULT); + native void A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + deprecated native void A_SetUserVar(name varname, int value); + deprecated native void A_SetUserArray(name varname, int index, int value); + deprecated native void A_SetUserVarFloat(name varname, float value); + deprecated native void A_SetUserArrayFloat(name varname, int index, float value); + native void A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); + native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, float mulWaveX = 1, float mulWaveY = 1, float mulWaveZ = 1, int falloff = 0, int highpoint = 0, float rollIntensity = 0, float rollWave = 0); + action native void A_SetTics(int tics); + native void A_DropItem(class item, int dropamount = -1, int chance = 256); + native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageTracer(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageSiblings(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillTarget(name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillMaster(name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillTracer(name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillChildren(name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillSiblings(name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_RemoveTarget(int flags = 0, class filter = null, name species = "None"); + native void A_RemoveMaster(int flags = 0, class filter = null, name species = "None"); + native void A_RemoveTracer(int flags = 0, class filter = null, name species = "None"); + native void A_RemoveChildren(bool removeall = false, int flags = 0, class filter = null, name species = "None"); + native void A_RemoveSiblings(bool removeall = false, int flags = 0, class filter = null, name species = "None"); + native void A_Remove(int removee, int flags = 0, class filter = null, name species = "None"); + native int A_GiveToChildren(class itemtype, int amount = 0); + native int A_GiveToSiblings(class itemtype, int amount = 0); + native int A_TakeFromChildren(class itemtype, int amount = 0); + native int A_TakeFromSiblings(class itemtype, int amount = 0); + native void A_SetTeleFog(class oldpos, class newpos); + native void A_SwapTeleFog(); + native void A_SetHealth(int health, int ptr = AAPTR_DEFAULT); + native void A_ResetHealth(int ptr = AAPTR_DEFAULT); + native void A_SetSpecies(name species, int ptr = AAPTR_DEFAULT); + native void A_SetChaseThreshold(int threshold, bool def = false, int ptr = AAPTR_DEFAULT); + native bool A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + native int A_ClearOverlays(int sstart = 0, int sstop = 0, bool safety = true); + native bool A_CopySpriteFrame(int from, int to, int flags = 0); + native bool A_SetVisibleRotation(float anglestart = 0, float angleend = 0, float pitchstart = 0, float pitchend = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + native void A_SetTranslation(string transname); + + native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0); + 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, statelabel 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); + + int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0) + { + return ACS_Execute(-int(script), mapnum, arg1, arg2, arg3); + } + int ACS_NamedSuspend(name script, int mapnum=0) + { + return ACS_Suspend(-int(script), mapnum); + } + int ACS_NamedTerminate(name script, int mapnum=0) + { + return ACS_Terminate(-int(script), mapnum); + } + int ACS_NamedLockedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0) + { + return ACS_LockedExecute(-int(script), mapnum, arg1, arg2, lock); + } + int ACS_NamedLockedExecuteDoor(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0) + { + return ACS_LockedExecuteDoor(-int(script), mapnum, arg1, arg2, lock); + } + int ACS_NamedExecuteWithResult(name script, int arg1=0, int arg2=0, int arg3=0, int arg4=0) + { + return ACS_ExecuteWithResult(-int(script), arg1, arg2, arg3, arg4); + } + int ACS_NamedExecuteAlways(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0) + { + return ACS_ExecuteAlways(-int(script), mapnum, arg1, arg2, arg3); + } + + States(Actor, Overlay, Weapon, Item) + { + Spawn: + TNT1 A -1; + Stop; + Null: + TNT1 A 1; + Stop; + GenericFreezeDeath: + // Generic freeze death frames. Woo! + #### # 5 A_GenericFreezeDeath; + ---- A 1 A_FreezeDeathChunks; + Wait; + GenericCrush: + POL5 A -1; + Stop; + } + + // Internal functions + deprecated private native int __decorate_internal_int__(int i); + deprecated private native bool __decorate_internal_bool__(bool b); + deprecated private native float __decorate_internal_float__(float f); +} diff --git a/wadsrc/static/zscript/actor_checks.txt b/wadsrc/static/zscript/actor_checks.txt new file mode 100644 index 000000000..806539753 --- /dev/null +++ b/wadsrc/static/zscript/actor_checks.txt @@ -0,0 +1,274 @@ +extend class Actor +{ + //========================================================================== + // + // This file contains all the A_Jump* checker functions, all split up + // into an actual checker and a simple wrapper around ResolveState. + // + //========================================================================== + + action state A_JumpIf(bool expression, statelabel label) + { + return expression? ResolveState(label) : null; + } + + + //========================================================================== + // + // + // + //========================================================================== + + action state A_JumpIfHealthLower(int health, statelabel label, int ptr_selector = AAPTR_DEFAULT) + { + Actor aptr = GetPointer(ptr_selector); + return aptr && aptr.health < health? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + bool CheckIfCloser(Actor targ, float dist, bool noz = false) + { + if (!targ) return false; + return + (Distance2D(target) < dist && (noz || + ((pos.z > targ.pos.z && pos.z - targ.pos.z - targ.height < dist) || + (pos.z <= targ.pos.z && targ.pos.z - pos.z - height < dist) + ) + )); + } + + action state A_JumpIfCloser(float distance, statelabel label, bool noz = false) + { + Actor targ; + + if (player == NULL) + { + targ = target; + } + else + { + // Does the player aim at something that can be shot? + targ = AimTarget(); + } + + return CheckIfCloser(targ, distance, noz)? ResolveState(label) : null; + } + + action state A_JumpIfTracerCloser(float distance, statelabel label, bool noz = false) + { + return CheckIfCloser(tracer, distance, noz)? ResolveState(label) : null; + } + + action state A_JumpIfMasterCloser(float distance, statelabel label, bool noz = false) + { + return CheckIfCloser(master, distance, noz)? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + action state A_JumpIfTargetOutsideMeleeRange(statelabel label) + { + return CheckMeleeRange()? null : ResolveState(label); + } + + action state A_JumpIfTargetInsideMeleeRange(statelabel label) + { + return CheckMeleeRange()? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + native bool CheckInventory(class itemtype, int itemamount, int owner = AAPTR_DEFAULT); + + action state A_JumpIfInventory(class itemtype, int itemamount, statelabel label, int owner = AAPTR_DEFAULT) + { + return CheckInventory(itemtype, itemamount, owner)? ResolveState(label) : null; + } + + action state A_JumpIfInTargetInventory(class itemtype, int amount, statelabel label, int forward_ptr = AAPTR_DEFAULT) + { + if (target == null) return null; + return target.CheckInventory(itemtype, amount, forward_ptr)? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + native bool CheckArmorType(name Type, int amount = 1); + + action state A_JumpIfArmorType(name Type, statelabel label, int amount = 1) + { + return CheckArmorType(Type, amount)? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + native bool CheckIfSeen(); + native bool CheckSightOrRange(float distance, bool two_dimension = false); + native bool CheckRange(float distance, bool two_dimension = false); + + action state A_CheckSight(statelabel label) + { + return CheckIfSeen()? ResolveState(label) : null; + } + + action state A_CheckSightOrRange(float distance, statelabel label, bool two_dimension = false) + { + return CheckSightOrRange(distance, two_dimension)? ResolveState(label) : null; + } + + action state A_CheckRange(float distance, statelabel label, bool two_dimension = false) + { + return CheckRange(distance, two_dimension)? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + action state A_CheckFloor(statelabel label) + { + return pos.z <= floorz? ResolveState(label) : null; + } + + action state A_CheckCeiling(statelabel label) + { + return pos.z + height >= ceilingz? ResolveState(label) : null; + } + + //========================================================================== + // + // since this is deprecated the checker is private. + // + //========================================================================== + + private native bool CheckFlag(string flagname, int check_pointer = AAPTR_DEFAULT); + + deprecated action state A_CheckFlag(string flagname, statelabel label, int check_pointer = AAPTR_DEFAULT) + { + return CheckFlag(flagname, check_pointer)? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + native bool PlayerSkinCheck(); + + action state A_PlayerSkinCheck(statelabel label) + { + return PlayerSkinCheck()? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + action state A_CheckSpecies(statelabel label, name species = 'none', int ptr = AAPTR_DEFAULT) + { + Actor aptr = GetPointer(ptr); + return aptr && aptr.GetSpecies() == species? ResolveState(label) : null; + } + + //========================================================================== + // + // + // + //========================================================================== + + native bool CheckLOF(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); + native bool CheckIfTargetInLOS (float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); + native bool CheckIfInTargetLOS (float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); + native bool CheckProximity(class classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT); + native bool CheckBlock(int flags = 0, int ptr = AAPTR_DEFAULT, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0); + + action state A_CheckLOF(statelabel label, 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) + { + return CheckLOF(flags, range, minrange, angle, pitch, offsetheight, offsetwidth, ptr_target, offsetforward)? ResolveState(label) : null; + } + + action state A_JumpIfTargetInLOS (statelabel label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0) + { + return CheckIfTargetInLOS(fov, flags, dist_max, dist_close)? ResolveState(label) : null; + } + + action state A_JumpIfInTargetLOS (statelabel label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0) + { + return CheckIfInTargetLOS(fov, flags, dist_max, dist_close)? ResolveState(label) : null; + } + + action state A_CheckProximity(statelabel label, class classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT) + { + // This one was doing some weird stuff that needs to be preserved. + state jumpto = ResolveState(label); + if (!jumpto) + { + if (!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER))) + { + return null; + } + } + return CheckProximity(classname, distance, count, flags, ptr)? jumpto : null; + } + + action state A_CheckBlock(statelabel label, int flags = 0, int ptr = AAPTR_DEFAULT, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0) + { + return CheckBlock(flags, ptr, xofs, yofs, zofs, angle)? ResolveState(label) : null; + } + + //=========================================================================== + // A_JumpIfHigherOrLower + // + // Jumps if a target, master, or tracer is higher or lower than the calling + // actor. Can also specify how much higher/lower the actor needs to be than + // itself. Can also take into account the height of the actor in question, + // depending on which it's checking. This means adding height of the + // calling actor's self if the pointer is higher, or height of the pointer + // if its lower. + //=========================================================================== + + action state A_JumpIfHigherOrLower(statelabel high, statelabel low, float offsethigh = 0, float offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET) + { + Actor mobj = GetPointer(ptr); + + if (mobj != null && mobj != self) //AAPTR_DEFAULT is completely useless in this regard. + { + if ((high) && (mobj.pos.z > ((includeHeight ? Height : 0) + pos.z + offsethigh))) + { + return ResolveState(high); + } + else if ((low) && (mobj.pos.z + (includeHeight ? mobj.Height : 0)) < (pos.z + offsetlow)) + { + return ResolveState(low); + } + } + return null; + } + +} \ No newline at end of file diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt new file mode 100644 index 000000000..33c1c6135 --- /dev/null +++ b/wadsrc/static/zscript/base.txt @@ -0,0 +1,32 @@ +class Object native +{ + virtual native void Destroy(); + native class GetClass(); +} + +class Thinker : Object native +{ +} + +class ThinkerIterator : Object native +{ + enum EStatnums + { + MAX_STATNUM = 127 + } + + native static ThinkerIterator Create(class type = "Actor", int statnum=MAX_STATNUM+1); + native Thinker Next(bool exact = false); + native void Reinit(); +} + +class DropItem : Object native +{ + /* native fields listed for reference only for now + native readonly DropItem Next; + native readonly name Name; + native readonly int Probability; + native readonly int Amount; + */ +} + diff --git a/wadsrc/static/zscript/chex/chexammo.txt b/wadsrc/static/zscript/chex/chexammo.txt new file mode 100644 index 000000000..23c3cccd5 --- /dev/null +++ b/wadsrc/static/zscript/chex/chexammo.txt @@ -0,0 +1,101 @@ +// Renaming and changing messages + +// Mini Zorch ----------------------------------------------------------------- + +class MiniZorchRecharge : Clip +{ + Default + { + inventory.pickupmessage "$GOTZORCHRECHARGE"; + } +} + +class MiniZorchPack : Clip +{ + Default + { + Inventory.PickupMessage "$GOTMINIZORCHPACK"; + Inventory.Amount 50; + } + States + { + Spawn: + AMMO A -1; + Stop; + } +} + +// Large Zorch ---------------------------------------------------------------- + +class LargeZorchRecharge : Shell +{ + Default + { + inventory.pickupmessage "$GOTLARGEZORCHERRECHARGE"; + } +} + +class LargeZorchPack : Shell +{ + Default + { + Inventory.PickupMessage "$GOTLARGEZORCHERPACK"; + Inventory.Amount 20; + } + States + { + Spawn: + SBOX A -1; + Stop; + } +} + +// Zorch Propulsor ------------------------------------------------------------ + +class PropulsorZorch : RocketAmmo +{ + Default + { + inventory.pickupmessage "$GOTPROPULSORRECHARGE"; + } +} + +class PropulsorZorchPack : RocketAmmo +{ + Default + { + Inventory.PickupMessage "$GOTPROPULSORPACK"; + Inventory.Amount 5; + } + States + { + Spawn: + BROK A -1; + Stop; + } +} + +// Phasing Zorch -------------------------------------------------------------- + +class PhasingZorch : Cell +{ + Default + { + inventory.pickupmessage "$GOTPHASINGZORCHERRECHARGE"; + } +} + +class PhasingZorchPack : Cell +{ + Default + { + Inventory.PickupMessage "$GOTPHASINGZORCHERPACK"; + Inventory.Amount 100; + } + States + { + Spawn: + CELP A -1; + Stop; + } +} diff --git a/wadsrc/static/zscript/chex/chexdecorations.txt b/wadsrc/static/zscript/chex/chexdecorations.txt new file mode 100644 index 000000000..2db19181d --- /dev/null +++ b/wadsrc/static/zscript/chex/chexdecorations.txt @@ -0,0 +1,180 @@ +// Doom items renamed with height changes + +// Civilians ------------------------------------------------------------------ + +class ChexCivilian1 : GreenTorch +{ + Default + { + height 54; + } +} + +class ChexCivilian2 : ShortGreenTorch +{ + Default + { + height 54; + } +} + +class ChexCivilian3 : ShortRedTorch +{ + Default + { + height 48; + } +} + +// Landing Zone --------------------------------------------------------------- + +class ChexLandingLight : Column +{ + Default + { + height 35; + } +} + +class ChexSpaceship : TechPillar +{ + Default + { + height 52; + } +} + +// Trees and Plants ----------------------------------------------------------- + +class ChexAppleTree : Stalagtite +{ + Default + { + height 92; + } +} + +class ChexBananaTree : BigTree +{ + Default + { + height 108; + } +} + +class ChexOrangeTree : TorchTree +{ + Default + { + height 92; + } +} + +class ChexSubmergedPlant : ShortGreenColumn +{ + Default + { + height 42; + } +} + +class ChexTallFlower : HeadsOnAStick +{ + Default + { + height 25; + } +} + +class ChexTallFlower2 : DeadStick +{ + Default + { + height 25; + } +} + +// Slime Fountain ------------------------------------------------------------- + +class ChexSlimeFountain : BlueTorch +{ + Default + { + height 48; + } + States + { + Spawn: + TBLU ABCD 4; + Loop; + } +} + +// Cavern Decorations --------------------------------------------------------- + +class ChexCavernColumn : TallRedColumn +{ + Default + { + height 128; + } +} + +class ChexCavernStalagmite : TallGreenColumn +{ + Default + { + height 60; + } +} + +// Misc. Props ---------------------------------------------------------------- + +class ChexChemicalBurner : EvilEye +{ + Default + { + height 25; + } +} + +class ChexChemicalFlask : Candlestick +{ + Default + { + RenderStyle "Translucent"; + alpha 0.75; + } +} + +class ChexFlagOnPole : SkullColumn +{ + Default + { + height 128; + } +} + +class ChexGasTank : Candelabra +{ + Default + { + height 36; + } +} + +class ChexLightColumn : ShortBlueTorch +{ + Default + { + height 86; + } +} + +class ChexMineCart : ShortRedColumn +{ + Default + { + height 30; + } +} diff --git a/wadsrc/static/zscript/chex/chexitems.txt b/wadsrc/static/zscript/chex/chexitems.txt new file mode 100644 index 000000000..fc5d4c817 --- /dev/null +++ b/wadsrc/static/zscript/chex/chexitems.txt @@ -0,0 +1,89 @@ + +// General Pickups ============================================================ + +// Health --------------------------------------------------------------------- + +class GlassOfWater : HealthBonus +{ + Default + { + inventory.pickupmessage "$GOTWATER"; + } +} + +class BowlOfFruit : Stimpack +{ + Default + { + inventory.pickupmessage "$GOTFRUIT"; + } +} + +class BowlOfVegetables : Medikit +{ + Default + { + inventory.pickupmessage "$GOTVEGETABLES"; + health.lowmessage 25, "$GOTVEGETABLESNEED"; + } +} + +class SuperchargeBreakfast : Soulsphere +{ + Default + { + inventory.pickupmessage "$GOTBREAKFAST"; + } +} + +// Armor ---------------------------------------------------------------------- + +class SlimeRepellent : ArmorBonus +{ + Default + { + inventory.pickupmessage "$GOTREPELLENT"; + } +} + +class ChexArmor : GreenArmor +{ + Default + { + inventory.pickupmessage "$GOTCHEXARMOR"; + } +} + +class SuperChexArmor : BlueArmor +{ + Default + { + inventory.pickupmessage "$GOTSUPERCHEXARMOR"; + } +} + +// Powerups =================================================================== + +class ComputerAreaMap : Allmap +{ + Default + { + inventory.pickupmessage "$GOTCHEXMAP"; + } +} + +class SlimeProofSuit : RadSuit +{ + Default + { + inventory.pickupmessage "$GOTSLIMESUIT"; + } +} + +class Zorchpack : Backpack +{ + Default + { + inventory.pickupmessage "$GOTZORCHPACK"; + } +} diff --git a/wadsrc/static/zscript/chex/chexkeys.txt b/wadsrc/static/zscript/chex/chexkeys.txt new file mode 100644 index 000000000..5ac28330e --- /dev/null +++ b/wadsrc/static/zscript/chex/chexkeys.txt @@ -0,0 +1,25 @@ +// These are merely renames of the Doom cards + +class ChexBlueCard : BlueCard +{ + Default + { + inventory.pickupmessage "$GOTCBLUEKEY"; + } +} + +class ChexYellowCard : YellowCard +{ + Default + { + inventory.pickupmessage "$GOTCYELLOWKEY"; + } +} + +class ChexRedCard : RedCard +{ + Default + { + inventory.pickupmessage "$GOTCREDKEY"; + } +} diff --git a/wadsrc/static/actors/chex/chexmonsters.txt b/wadsrc/static/zscript/chex/chexmonsters.txt similarity index 62% rename from wadsrc/static/actors/chex/chexmonsters.txt rename to wadsrc/static/zscript/chex/chexmonsters.txt index 0ee3c34c5..22e397702 100644 --- a/wadsrc/static/actors/chex/chexmonsters.txt +++ b/wadsrc/static/zscript/chex/chexmonsters.txt @@ -5,16 +5,19 @@ // //=========================================================================== -actor FlemoidusCommonus : ZombieMan +class FlemoidusCommonus : ZombieMan { - DropItem "" - Obituary "$OB_COMMONUS" + Default + { + DropItem ""; + Obituary "$OB_COMMONUS"; + } States { Missile: - stop + Stop; Melee: - goto Super::Missile + goto Super::Missile; } } @@ -24,16 +27,19 @@ actor FlemoidusCommonus : ZombieMan // //=========================================================================== -actor FlemoidusBipedicus : ShotgunGuy +class FlemoidusBipedicus : ShotgunGuy { - DropItem "" - Obituary "$OB_BIPEDICUS" + Default + { + DropItem ""; + Obituary "$OB_BIPEDICUS"; + } States { Missile: - stop + Stop; Melee: - goto Super::Missile + goto Super::Missile; } } @@ -43,10 +49,13 @@ actor FlemoidusBipedicus : ShotgunGuy // //=========================================================================== -actor ArmoredFlemoidusBipedicus : DoomImp +class ArmoredFlemoidusBipedicus : DoomImp { - Obituary "$OB_BIPEDICUS2" - HitObituary "$OB_BIPEDICUS2" + Default + { + Obituary "$OB_BIPEDICUS2"; + HitObituary "$OB_BIPEDICUS2"; + } } //=========================================================================== @@ -55,9 +64,12 @@ actor ArmoredFlemoidusBipedicus : DoomImp // //=========================================================================== -actor FlemoidusCycloptisCommonus : Demon +class FlemoidusCycloptisCommonus : Demon { - Obituary "$OB_CYCLOPTIS" + Default + { + Obituary "$OB_CYCLOPTIS"; + } } //=========================================================================== @@ -66,24 +78,30 @@ actor FlemoidusCycloptisCommonus : Demon // //=========================================================================== -actor Flembrane : BaronOfHell +class Flembrane : BaronOfHell { - radius 44 - height 100 - speed 0 - Obituary "$OB_FLEMBRANE" + Default + { + radius 44; + height 100; + speed 0; + Obituary "$OB_FLEMBRANE"; + } States { Missile: - BOSS EF 3 A_FaceTarget - BOSS G 0 A_BruisAttack - goto See + BOSS EF 3 A_FaceTarget; + BOSS G 0 A_BruisAttack; + goto See; } } //=========================================================================== -actor ChexSoul : LostSoul +class ChexSoul : LostSoul { - height 0 + Default + { + height 0; + } } diff --git a/wadsrc/static/zscript/chex/chexplayer.txt b/wadsrc/static/zscript/chex/chexplayer.txt new file mode 100644 index 000000000..43f7fc1ee --- /dev/null +++ b/wadsrc/static/zscript/chex/chexplayer.txt @@ -0,0 +1,32 @@ +// Chex Warrior + +class ChexPlayer : DoomPlayer +{ + Default + { + player.displayname "Chex Warrior"; + player.crouchsprite ""; + player.colorrange 192, 207; //Not perfect, but its better than everyone being blue. + player.startitem "MiniZorcher"; + player.startitem "Bootspoon"; + player.startitem "MiniZorchRecharge", 50; + player.damagescreencolor "60 b0 58"; + player.WeaponSlot 1, "Bootspoon", "SuperBootspork"; + player.WeaponSlot 2, "MiniZorcher"; + player.WeaponSlot 3, "LargeZorcher", "SuperLargeZorcher"; + player.WeaponSlot 4, "RapidZorcher"; + player.WeaponSlot 5, "ZorchPropulsor"; + player.WeaponSlot 6, "PhasingZorcher"; + player.WeaponSlot 7, "LAZDevice"; + + Player.Colorset 0, "Light Blue", 0xC0, 0xCF, 0xC2; + Player.Colorset 1, "Green", 0x70, 0x7F, 0x72; + Player.Colorset 2, "Gray", 0x60, 0x6F, 0x62; + Player.Colorset 3, "Brown", 0x40, 0x4F, 0x42; + Player.Colorset 4, "Red", 0x20, 0x2F, 0x22; + Player.Colorset 5, "Light Gray", 0x58, 0x67, 0x5A; + Player.Colorset 6, "Light Brown", 0x38, 0x47, 0x3A; + Player.Colorset 7, "Light Red", 0xB0, 0xBF, 0xB2; + } + +} diff --git a/wadsrc/static/zscript/chex/chexweapons.txt b/wadsrc/static/zscript/chex/chexweapons.txt new file mode 100644 index 000000000..a4c862d64 --- /dev/null +++ b/wadsrc/static/zscript/chex/chexweapons.txt @@ -0,0 +1,160 @@ +// Same as Doom weapons, but the obituaries are removed. + +class Bootspoon : Fist +{ + Default + { + obituary "$OB_MPSPOON"; + Tag "$TAG_SPOON"; + } +} + +class SuperBootspork : Chainsaw +{ + Default + { + obituary "$OB_MPBOOTSPORK"; + Inventory.PickupMessage "$GOTSUPERBOOTSPORK"; + Tag "$TAG_SPORK"; + } +} + +class MiniZorcher : Pistol +{ + Default + { + obituary "$OB_MPZORCH"; + inventory.pickupmessage "$GOTMINIZORCHER"; + Tag "$TAG_MINIZORCHER"; + } + States + { + Spawn: + MINZ A -1; + Stop; + } +} + +class LargeZorcher : Shotgun +{ + Default + { + obituary "$OB_MPZORCH"; + inventory.pickupmessage "$GOTLARGEZORCHER"; + Tag "$TAG_LARGEZORCHER"; + } +} + +class SuperLargeZorcher : SuperShotgun +{ + Default + { + obituary "$OB_MPMEGAZORCH"; + inventory.pickupmessage "$GOTSUPERLARGEZORCHER"; + Tag "$TAG_SUPERLARGEZORCHER"; + } +} + +class RapidZorcher : Chaingun +{ + Default + { + obituary "$OB_MPRAPIDZORCH"; + inventory.pickupmessage "$GOTRAPIDZORCHER"; + Tag "$TAG_RAPIDZORCHER"; + } +} + +class ZorchPropulsor : RocketLauncher +{ + Default + { + obituary ""; + inventory.pickupmessage "$GOTZORCHPROPULSOR"; + Tag "$TAG_ZORCHPROPULSOR"; + } + States + { + Fire: + MISG B 8 A_GunFlash; + MISG B 12 A_FireCustomMissile("PropulsorMissile"); + MISG B 0 A_ReFire; + Goto Ready; + } +} + +class PropulsorMissile : Rocket +{ + Default + { + -ROCKETTRAIL + -DEHEXPLOSION + RenderStyle "Translucent"; + Obituary "$OB_MPPROPULSOR"; + Alpha 0.75; + } +} + +class PhasingZorcher : PlasmaRifle +{ + Default + { + obituary ""; + inventory.pickupmessage "$GOTPHASINGZORCHER"; + Tag "$TAG_PHASINGZORCHER"; + } + States + { + Fire: + PLSG A 0 A_GunFlash; + PLSG A 3 A_FireCustomMissile("PhaseZorchMissile"); + PLSG B 20 A_ReFire; + Goto Ready; + Flash: + PLSF A 0 A_Jump(128, "Flash2"); + PLSF A 3 Bright A_Light1; + Goto LightDone; + Flash2: + PLSF B 3 Bright A_Light1; + Goto LightDone; + } +} + +class PhaseZorchMissile : PlasmaBall +{ + Default + { + RenderStyle "Translucent"; + Obituary "$OB_MPPHASEZORCH"; + Alpha 0.75; + } +} + +class LAZDevice : BFG9000 +{ + Default + { + obituary ""; + inventory.pickupmessage "$GOTLAZDEVICE"; + Tag "$TAG_LAZDEVICE"; + } + States + { + Fire: + BFGG A 20 A_BFGsound; + BFGG B 10 A_GunFlash; + BFGG B 10 A_FireCustomMissile("LAZBall"); + BFGG B 20 A_ReFire; + Goto Ready; + } +} + +class LAZBall : BFGBall +{ + Default + { + RenderStyle "Translucent"; + Obituary "$OB_MPLAZ_BOOM"; + Alpha 0.75; + } +} diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/zscript/constants.txt similarity index 52% rename from wadsrc/static/actors/constants.txt rename to wadsrc/static/zscript/constants.txt index df3bb860b..5e47bbc7e 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,92 +1,132 @@ +// for flag changer functions. +const FLAG_NO_CHANGE = -1; + +enum EStateUseFlags +{ + SUF_ACTOR = 1, + SUF_OVERLAY = 2, + SUF_WEAPON = 4, + SUF_ITEM = 8, +}; // Flags for A_PainAttack -const int PAF_NOSKULLATTACK = 1; -const int PAF_AIMFACING = 2; -const int PAF_NOTARGET = 4; +enum EPainAttackFlags +{ + PAF_NOSKULLATTACK = 1, + PAF_AIMFACING = 2, + PAF_NOTARGET = 4, +}; // Flags for A_VileAttack -const int VAF_DMGTYPEAPPLYTODIRECT = 1; +enum EVileAttackFlags +{ + VAF_DMGTYPEAPPLYTODIRECT = 1, +}; // Flags for A_Saw -const int SF_NORANDOM = 1; -const int SF_RANDOMLIGHTMISS = 2; -const int SF_RANDOMLIGHTHIT = 4; -const int SF_RANDOMLIGHTBOTH = 6; -const int SF_NOUSEAMMOMISS = 8; -const int SF_NOUSEAMMO = 16; -const int SF_NOPULLIN = 32; -const int SF_NOTURN = 64; -const int SF_STEALARMOR = 128; +enum ESawFlags +{ + SF_NORANDOM = 1, + SF_RANDOMLIGHTMISS = 2, + SF_RANDOMLIGHTHIT = 4, + SF_RANDOMLIGHTBOTH = 6, + SF_NOUSEAMMOMISS = 8, + SF_NOUSEAMMO = 16, + SF_NOPULLIN = 32, + SF_NOTURN = 64, + SF_STEALARMOR = 128, +}; // Flags for A_BFGSpray -const int BFGF_HURTSOURCE = 1; -const int BFGF_MISSILEORIGIN = 2; +enum EBFGSprayFlags +{ + BFGF_HURTSOURCE = 1, + BFGF_MISSILEORIGIN = 2, +}; // Flags for A_CustomMissile -const int CMF_AIMOFFSET = 1; -const int CMF_AIMDIRECTION = 2; -const int CMF_TRACKOWNER = 4; -const int CMF_CHECKTARGETDEAD = 8; -const int CMF_ABSOLUTEPITCH = 16; -const int CMF_OFFSETPITCH = 32; -const int CMF_SAVEPITCH = 64; -const int CMF_ABSOLUTEANGLE = 128; +enum ECustomMissileFlags +{ + CMF_AIMOFFSET = 1, + CMF_AIMDIRECTION = 2, + CMF_TRACKOWNER = 4, + CMF_CHECKTARGETDEAD = 8, + CMF_ABSOLUTEPITCH = 16, + CMF_OFFSETPITCH = 32, + CMF_SAVEPITCH = 64, + CMF_ABSOLUTEANGLE = 128, +}; // Flags for A_CustomBulletAttack -const int CBAF_AIMFACING = 1; -const int CBAF_NORANDOM = 2; -const int CBAF_EXPLICITANGLE = 4; -const int CBAF_NOPITCH = 8; -const int CBAF_NORANDOMPUFFZ = 16; -const int CBAF_PUFFTARGET = 32; -const int CBAF_PUFFMASTER = 64; -const int CBAF_PUFFTRACER = 128; +enum ECustomBulletAttackFlags +{ + CBAF_AIMFACING = 1, + CBAF_NORANDOM = 2, + CBAF_EXPLICITANGLE = 4, + CBAF_NOPITCH = 8, + CBAF_NORANDOMPUFFZ = 16, + CBAF_PUFFTARGET = 32, + CBAF_PUFFMASTER = 64, + CBAF_PUFFTRACER = 128, +}; // Flags for A_GunFlash -const int GFF_NOEXTCHANGE = 1; +enum EGunFlashFlags +{ + GFF_NOEXTCHANGE = 1, +}; // Flags for A_FireBullets -const int FBF_USEAMMO = 1; -const int FBF_NORANDOM = 2; -const int FBF_EXPLICITANGLE = 4; -const int FBF_NOPITCH = 8; -const int FBF_NOFLASH = 16; -const int FBF_NORANDOMPUFFZ = 32; +enum EFireBulletsFlags +{ + FBF_USEAMMO = 1, + FBF_NORANDOM = 2, + FBF_EXPLICITANGLE = 4, + FBF_NOPITCH = 8, + FBF_NOFLASH = 16, + FBF_NORANDOMPUFFZ = 32, + FBF_PUFFTARGET = 64, + FBF_PUFFMASTER = 128, + FBF_PUFFTRACER = 256, +}; // Flags for A_SpawnItemEx -const int SXF_TRANSFERTRANSLATION = 1 << 0; -const int SXF_ABSOLUTEPOSITION = 1 << 1; -const int SXF_ABSOLUTEANGLE = 1 << 2; -const int SXF_ABSOLUTEMOMENTUM = 1 << 3; //Since "momentum" is declared to be deprecated in the expressions, for compatibility -const int SXF_ABSOLUTEVELOCITY = 1 << 3; //purposes, this was made. It does the same thing though. Do not change the value. -const int SXF_SETMASTER = 1 << 4; -const int SXF_NOCHECKPOSITION = 1 << 5; -const int SXF_TELEFRAG = 1 << 6; -const int SXF_CLIENTSIDE = 1 << 7; // only used by Skulltag -const int SXF_TRANSFERAMBUSHFLAG = 1 << 8; -const int SXF_TRANSFERPITCH = 1 << 9; -const int SXF_TRANSFERPOINTERS = 1 << 10; -const int SXF_USEBLOODCOLOR = 1 << 11; -const int SXF_CLEARCALLERTID = 1 << 12; -const int SXF_MULTIPLYSPEED = 1 << 13; -const int SXF_TRANSFERSCALE = 1 << 14; -const int SXF_TRANSFERSPECIAL = 1 << 15; -const int SXF_CLEARCALLERSPECIAL = 1 << 16; -const int SXF_TRANSFERSTENCILCOL = 1 << 17; -const int SXF_TRANSFERALPHA = 1 << 18; -const int SXF_TRANSFERRENDERSTYLE = 1 << 19; -const int SXF_SETTARGET = 1 << 20; -const int SXF_SETTRACER = 1 << 21; -const int SXF_NOPOINTERS = 1 << 22; -const int SXF_ORIGINATOR = 1 << 23; -const int SXF_TRANSFERSPRITEFRAME = 1 << 24; -const int SXF_TRANSFERROLL = 1 << 25; -const int SXF_ISTARGET = 1 << 26; -const int SXF_ISMASTER = 1 << 27; -const int SXF_ISTRACER = 1 << 28; +enum ESpawnItemFlags +{ + SXF_TRANSFERTRANSLATION = 1 << 0, + SXF_ABSOLUTEPOSITION = 1 << 1, + SXF_ABSOLUTEANGLE = 1 << 2, + SXF_ABSOLUTEMOMENTUM = 1 << 3, //Since "momentum" is declared to be deprecated in the expressions, for compatibility + SXF_ABSOLUTEVELOCITY = 1 << 3, //purposes, this was made. It does the same thing though. Do not change the value. + SXF_SETMASTER = 1 << 4, + SXF_NOCHECKPOSITION = 1 << 5, + SXF_TELEFRAG = 1 << 6, + SXF_CLIENTSIDE = 1 << 7, // only used by Skulltag + SXF_TRANSFERAMBUSHFLAG = 1 << 8, + SXF_TRANSFERPITCH = 1 << 9, + SXF_TRANSFERPOINTERS = 1 << 10, + SXF_USEBLOODCOLOR = 1 << 11, + SXF_CLEARCALLERTID = 1 << 12, + SXF_MULTIPLYSPEED = 1 << 13, + SXF_TRANSFERSCALE = 1 << 14, + SXF_TRANSFERSPECIAL = 1 << 15, + SXF_CLEARCALLERSPECIAL = 1 << 16, + SXF_TRANSFERSTENCILCOL = 1 << 17, + SXF_TRANSFERALPHA = 1 << 18, + SXF_TRANSFERRENDERSTYLE = 1 << 19, + SXF_SETTARGET = 1 << 20, + SXF_SETTRACER = 1 << 21, + SXF_NOPOINTERS = 1 << 22, + SXF_ORIGINATOR = 1 << 23, + SXF_TRANSFERSPRITEFRAME = 1 << 24, + SXF_TRANSFERROLL = 1 << 25, + SXF_ISTARGET = 1 << 26, + SXF_ISMASTER = 1 << 27, + SXF_ISTRACER = 1 << 28, +}; // Flags for A_Chase -enum +enum EChaseFlags { CHF_FASTCHASE = 1, CHF_NOPLAYACTIVE = 2, @@ -102,20 +142,26 @@ enum }; // Flags for A_LookEx -const int LOF_NOSIGHTCHECK = 1; -const int LOF_NOSOUNDCHECK = 2; -const int LOF_DONTCHASEGOAL = 4; -const int LOF_NOSEESOUND = 8; -const int LOF_FULLVOLSEESOUND = 16; -const int LOF_NOJUMP = 32; +enum ELookFlags +{ + LOF_NOSIGHTCHECK = 1, + LOF_NOSOUNDCHECK = 2, + LOF_DONTCHASEGOAL = 4, + LOF_NOSEESOUND = 8, + LOF_FULLVOLSEESOUND = 16, + LOF_NOJUMP = 32, +}; // Flags for A_Respawn -const int RSF_FOG = 1; -const int RSF_KEEPTARGET = 2; -const int RSF_TELEFRAG = 4; +enum ERespawnFlags +{ + RSF_FOG = 1, + RSF_KEEPTARGET = 2, + RSF_TELEFRAG = 4, +}; // Flags for A_JumpIfTargetInLOS and A_JumpIfInTargetLOS -enum +enum EJumpFlags { JLOSF_PROJECTILE = 1, JLOSF_NOSIGHT = 1 << 1, @@ -133,98 +179,134 @@ enum }; // Flags for A_ChangeVelocity -const int CVF_RELATIVE = 1; -const int CVF_REPLACE = 2; +enum EChangeVelocityFlags +{ + CVF_RELATIVE = 1, + CVF_REPLACE = 2, +}; // Flags for A_WeaponReady -const int WRF_NOBOB = 1; -const int WRF_NOSWITCH = 2; -const int WRF_NOPRIMARY = 4; -const int WRF_NOSECONDARY = 8; -const int WRF_NOFIRE = WRF_NOPRIMARY | WRF_NOSECONDARY; -const int WRF_ALLOWRELOAD = 16; -const int WRF_ALLOWZOOM = 32; -const int WRF_DISABLESWITCH = 64; -const int WRF_ALLOWUSER1 = 128; -const int WRF_ALLOWUSER2 = 256; -const int WRF_ALLOWUSER3 = 512; -const int WRF_ALLOWUSER4 = 1024; +enum EWeaponReadyFlags +{ + WRF_NOBOB = 1, + WRF_NOSWITCH = 2, + WRF_NOPRIMARY = 4, + WRF_NOSECONDARY = 8, + WRF_NOFIRE = WRF_NOPRIMARY | WRF_NOSECONDARY, + WRF_ALLOWRELOAD = 16, + WRF_ALLOWZOOM = 32, + WRF_DISABLESWITCH = 64, + WRF_ALLOWUSER1 = 128, + WRF_ALLOWUSER2 = 256, + WRF_ALLOWUSER3 = 512, + WRF_ALLOWUSER4 = 1024, +}; // Flags for A_SelectWeapon -const int SWF_SELECTPRIORITY = 1; +enum ESelectWeaponFlags +{ + SWF_SELECTPRIORITY = 1, +}; // Morph constants -const int MRF_ADDSTAMINA = 1; -const int MRF_FULLHEALTH = 2; -const int MRF_UNDOBYTOMEOFPOWER = 4; -const int MRF_UNDOBYCHAOSDEVICE = 8; -const int MRF_FAILNOTELEFRAG = 16; -const int MRF_FAILNOLAUGH = 32; -const int MRF_WHENINVULNERABLE = 64; -const int MRF_LOSEACTUALWEAPON = 128; -const int MRF_NEWTIDBEHAVIOUR = 256; -const int MRF_UNDOBYDEATH = 512; -const int MRF_UNDOBYDEATHFORCED = 1024; -const int MRF_UNDOBYDEATHSAVES = 2048; -const int MRF_UNDOALWAYS = 4096; -const int MRF_TRANSFERTRANSLATION = 8192; +enum EMorphFlags +{ + MRF_ADDSTAMINA = 1, + MRF_FULLHEALTH = 2, + MRF_UNDOBYTOMEOFPOWER = 4, + MRF_UNDOBYCHAOSDEVICE = 8, + MRF_FAILNOTELEFRAG = 16, + MRF_FAILNOLAUGH = 32, + MRF_WHENINVULNERABLE = 64, + MRF_LOSEACTUALWEAPON = 128, + MRF_NEWTIDBEHAVIOUR = 256, + MRF_UNDOBYDEATH = 512, + MRF_UNDOBYDEATHFORCED = 1024, + MRF_UNDOBYDEATHSAVES = 2048, + MRF_UNDOALWAYS = 4096, + MRF_TRANSFERTRANSLATION = 8192, +}; // Flags for A_RailAttack and A_CustomRailgun -const int RGF_SILENT = 1; -const int RGF_NOPIERCING = 2; -const int RGF_EXPLICITANGLE = 4; -const int RGF_FULLBRIGHT = 8; -const int RGF_CENTERZ = 16; -const int RGF_NORANDOMPUFFZ = 32; +enum ERailFlags +{ + RGF_SILENT = 1, + RGF_NOPIERCING = 2, + RGF_EXPLICITANGLE = 4, + RGF_FULLBRIGHT = 8, + RGF_CENTERZ = 16, + RGF_NORANDOMPUFFZ = 32, +}; // Flags for A_Mushroom -const int MSF_Standard = 0; -const int MSF_Classic = 1; -const int MSF_DontHurt = 2; +enum EMushroomFlags +{ + MSF_Standard = 0, + MSF_Classic = 1, + MSF_DontHurt = 2, +}; // Flags for A_Explode -const int XF_HURTSOURCE = 1; -const int XF_NOTMISSILE = 4; -const int XF_EXPLICITDAMAGETYPE = 1 << 3; +enum EExplodeFlags +{ + XF_HURTSOURCE = 1, + XF_NOTMISSILE = 4, + XF_EXPLICITDAMAGETYPE = 8, + XF_NOSPLASH = 16, +}; // Flags for A_RadiusThrust -const int RTF_AFFECTSOURCE = 1; -const int RTF_NOIMPACTDAMAGE = 2; -const int RTF_NOTMISSILE = 4; -const int RTF_THRUSTZ = 16; +enum ERadiusThrustFlags +{ + RTF_AFFECTSOURCE = 1, + RTF_NOIMPACTDAMAGE = 2, + RTF_NOTMISSILE = 4, + RTF_THRUSTZ = 16, +}; // Flags for A_RadiusDamageSelf -const int RDSF_BFGDAMAGE = 1; +enum ERadiusDamageSelfFlags +{ + RDSF_BFGDAMAGE = 1, +}; // Flags for A_Blast -const int BF_USEAMMO = 1; -const int BF_DONTWARN = 2; -const int BF_AFFECTBOSSES = 4; -const int BF_NOIMPACTDAMAGE = 8; +enum EBlastFlags +{ + BF_USEAMMO = 1, + BF_DONTWARN = 2, + BF_AFFECTBOSSES = 4, + BF_NOIMPACTDAMAGE = 8, +}; // Flags for A_SeekerMissile -const int SMF_LOOK = 1; -const int SMF_PRECISE = 2; -const int SMF_CURSPEED = 4; +enum ESeekerMissileFlags +{ + SMF_LOOK = 1, + SMF_PRECISE = 2, + SMF_CURSPEED = 4, +}; // Flags for A_CustomPunch -const int CPF_USEAMMO = 1; -const int CPF_DAGGER = 2; -const int CPF_PULLIN = 4; -const int CPF_NORANDOMPUFFZ = 8; -const int CPF_NOTURN = 16; -const int CPF_STEALARMOR = 32; +enum ECustomPunchFlags +{ + CPF_USEAMMO = 1, + CPF_DAGGER = 2, + CPF_PULLIN = 4, + CPF_NORANDOMPUFFZ = 8, + CPF_NOTURN = 16, + CPF_STEALARMOR = 32, +}; -// Flags for A_CustomMissile -const int FPF_AIMATANGLE = 1; -const int FPF_TRANSFERTRANSLATION = 2; -const int FPF_NOAUTOAIM = 4; -const int FBF_PUFFTARGET = 64; -const int FBF_PUFFMASTER = 128; -const int FBF_PUFFTRACER = 256; +enum EFireCustomMissileFlags +{ + FPF_AIMATANGLE = 1, + FPF_TRANSFERTRANSLATION = 2, + FPF_NOAUTOAIM = 4, +}; // Flags for A_Teleport -enum +enum ETeleportFlags { TF_TELEFRAG = 0x00000001, // Allow telefrag in order to teleport. TF_RANDOMDECIDE = 0x00000002, // Randomly fail based on health. (A_Srcr2Decide) @@ -244,11 +326,14 @@ enum }; // Flags for A_WolfAttack -const int WAF_NORANDOM = 1; -const int WAF_USEPUFF = 2; +enum EWolfAttackFlags +{ + WAF_NORANDOM = 1, + WAF_USEPUFF = 2 +}; // Flags for A_RadiusGive -enum +enum ERadiusGiveFlags { RGF_GIVESELF = 1, RGF_PLAYERS = 1 << 1, @@ -271,7 +356,7 @@ enum }; // Activation flags -enum +enum EActivationFlags { THINGSPEC_Default = 0, THINGSPEC_ThingActs = 1, @@ -282,23 +367,28 @@ enum THINGSPEC_ClearSpecial = 32, THINGSPEC_NoDeathSpecial = 64, THINGSPEC_TriggerActs = 128, + + // Shorter aliases for same + AF_Default = 0, + AF_ThingActs = 1, + AF_ThingTargets = 2, + AF_TriggerTargets = 4, + AF_MonsterTrigger = 8, + AF_MissileTrigger = 16, + AF_ClearSpecial = 32, + AF_NoDeathSpecial = 64, + AF_TriggerActs = 128, + }; -// Shorter aliases for same -const int AF_Default = 0; -const int AF_ThingActs = 1; -const int AF_ThingTargets = 2; -const int AF_TriggerTargets = 4; -const int AF_MonsterTrigger = 8; -const int AF_MissileTrigger = 16; -const int AF_ClearSpecial = 32; -const int AF_NoDeathSpecial = 64; -const int AF_TriggerActs = 128; // Flags for A_TakeInventory and A_TakeFromTarget -const int TIF_NOTAKEINFINITE = 1; +enum ETakeFlags +{ + TIF_NOTAKEINFINITE = 1 +}; // constants for A_PlaySound -enum +enum ESoundFlags { CHAN_AUTO = 0, CHAN_WEAPON = 1, @@ -317,96 +407,110 @@ enum }; // sound attenuation values -const float ATTN_NONE = 0; -const float ATTN_NORM = 1; -const float ATTN_IDLE = 1.001; -const float ATTN_STATIC = 3; +const ATTN_NONE = 0; +const ATTN_NORM = 1; +const ATTN_IDLE = 1.001; +const ATTN_STATIC = 3; // For SetPlayerProprty action special -Const Int PROP_FROZEN = 0; -Const Int PROP_NOTARGET = 1; -Const Int PROP_INSTANTWEAPONSWITCH = 2; -Const Int PROP_FLY = 3; -Const Int PROP_TOTALLYFROZEN = 4; -Const Int PROP_INVULNERABILITY = 5; // (Deprecated) -Const Int PROP_STRENGTH = 6; // (Deprecated) -Const Int PROP_INVISIBILITY = 7; // (Deprecated) -Const Int PROP_RADIATIONSUIT = 8; // (Deprecated) -Const Int PROP_ALLMAP = 9; // (Deprecated) -Const Int PROP_INFRARED = 10; // (Deprecated) -Const Int PROP_WEAPONLEVEL2 = 11; // (Deprecated) -Const Int PROP_FLIGHT = 12; // (Deprecated) -Const Int PROP_SPEED = 15; // (Deprecated) -Const Int PROP_BUDDHA = 16; +enum EPlayerProperties +{ + PROP_FROZEN = 0, + PROP_NOTARGET = 1, + PROP_INSTANTWEAPONSWITCH = 2, + PROP_FLY = 3, + PROP_TOTALLYFROZEN = 4, + PROP_INVULNERABILITY = 5, // (Deprecated) + PROP_STRENGTH = 6, // (Deprecated) + PROP_INVISIBILITY = 7, // (Deprecated) + PROP_RADIATIONSUIT = 8, // (Deprecated) + PROP_ALLMAP = 9, // (Deprecated) + PROP_INFRARED = 10, // (Deprecated) + PROP_WEAPONLEVEL2 = 11, // (Deprecated) + PROP_FLIGHT = 12, // (Deprecated) + PROP_SPEED = 15, // (Deprecated) + PROP_BUDDHA = 16, +} // Line_SetBlocking -Const Int BLOCKF_CREATURES = 1; -Const Int BLOCKF_MONSTERS = 2; -Const Int BLOCKF_PLAYERS = 4; -Const Int BLOCKF_FLOATERS = 8; -Const Int BLOCKF_PROJECTILES = 16; -Const Int BLOCKF_EVERYTHING = 32; -Const Int BLOCKF_RAILING = 64; -Const Int BLOCKF_USE = 128; +enum EBlockFlags +{ + BLOCKF_CREATURES = 1, + BLOCKF_MONSTERS = 2, + BLOCKF_PLAYERS = 4, + BLOCKF_FLOATERS = 8, + BLOCKF_PROJECTILES = 16, + BLOCKF_EVERYTHING = 32, + BLOCKF_RAILING = 64, + BLOCKF_USE = 128, +}; // Pointer constants, bitfield-enabled - -Const Int AAPTR_DEFAULT = 0; -Const Int AAPTR_NULL = 0x1; -Const Int AAPTR_TARGET = 0x2; -Const Int AAPTR_MASTER = 0x4; -Const Int AAPTR_TRACER = 0x8; - -Const Int AAPTR_PLAYER_GETTARGET = 0x10; -Const Int AAPTR_PLAYER_GETCONVERSATION = 0x20; - -Const Int AAPTR_PLAYER1 = 0x40; -Const Int AAPTR_PLAYER2 = 0x80; -Const Int AAPTR_PLAYER3 = 0x100; -Const Int AAPTR_PLAYER4 = 0x200; -Const Int AAPTR_PLAYER5 = 0x400; -Const Int AAPTR_PLAYER6 = 0x800; -Const Int AAPTR_PLAYER7 = 0x1000; -Const Int AAPTR_PLAYER8 = 0x2000; - -Const Int AAPTR_FRIENDPLAYER = 0x4000; -Const Int AAPTR_LINETARGET = 0x8000; +enum EPointerFlags +{ + AAPTR_DEFAULT = 0, + AAPTR_NULL = 0x1, + AAPTR_TARGET = 0x2, + AAPTR_MASTER = 0x4, + AAPTR_TRACER = 0x8, + + AAPTR_PLAYER_GETTARGET = 0x10, + AAPTR_PLAYER_GETCONVERSATION = 0x20, + + AAPTR_PLAYER1 = 0x40, + AAPTR_PLAYER2 = 0x80, + AAPTR_PLAYER3 = 0x100, + AAPTR_PLAYER4 = 0x200, + AAPTR_PLAYER5 = 0x400, + AAPTR_PLAYER6 = 0x800, + AAPTR_PLAYER7 = 0x1000, + AAPTR_PLAYER8 = 0x2000, + AAPTR_FRIENDPLAYER = 0x4000, + AAPTR_LINETARGET = 0x8000, +}; // Pointer operation flags -Const Int PTROP_UNSAFETARGET = 1; -Const Int PTROP_UNSAFEMASTER = 2; -Const Int PTROP_NOSAFEGUARDS = PTROP_UNSAFETARGET|PTROP_UNSAFEMASTER; - +enum EPointerOperations +{ + PTROP_UNSAFETARGET = 1, + PTROP_UNSAFEMASTER = 2, + PTROP_NOSAFEGUARDS = PTROP_UNSAFETARGET|PTROP_UNSAFEMASTER, +}; // Flags for A_Warp -Const Int WARPF_ABSOLUTEOFFSET = 0x1; -Const Int WARPF_ABSOLUTEANGLE = 0x2; -Const Int WARPF_USECALLERANGLE = 0x4; -Const Int WARPF_NOCHECKPOSITION = 0x8; -Const Int WARPF_INTERPOLATE = 0x10; -Const Int WARPF_WARPINTERPOLATION = 0x20; -Const Int WARPF_COPYINTERPOLATION = 0x40; -Const Int WARPF_STOP = 0x80; -Const Int WARPF_TOFLOOR = 0x100; -Const Int WARPF_TESTONLY = 0x200; -Const Int WAPRF_ABSOLUTEPOSITION = 0x400; -Const Int WARPF_ABSOLUTEPOSITION = 0x400; -Const Int WARPF_BOB = 0x800; -Const Int WARPF_MOVEPTR = 0x1000; -Const Int WARPF_USETID = 0x2000; -Const Int WARPF_COPYVELOCITY = 0x4000; -Const Int WARPF_COPYPITCH = 0x8000; +enum EWarpFlags +{ + WARPF_ABSOLUTEOFFSET = 0x1, + WARPF_ABSOLUTEANGLE = 0x2, + WARPF_USECALLERANGLE = 0x4, + WARPF_NOCHECKPOSITION = 0x8, + WARPF_INTERPOLATE = 0x10, + WARPF_WARPINTERPOLATION = 0x20, + WARPF_COPYINTERPOLATION = 0x40, + WARPF_STOP = 0x80, + WARPF_TOFLOOR = 0x100, + WARPF_TESTONLY = 0x200, + WAPRF_ABSOLUTEPOSITION = 0x400, + WARPF_ABSOLUTEPOSITION = 0x400, + WARPF_BOB = 0x800, + WARPF_MOVEPTR = 0x1000, + WARPF_USETID = 0x2000, + WARPF_COPYVELOCITY = 0x4000, + WARPF_COPYPITCH = 0x8000, +}; // flags for A_SetPitch/SetAngle/SetRoll -const int SPF_FORCECLAMP = 1; -const int SPF_INTERPOLATE = 2; - +enum EAngleFlags +{ + SPF_FORCECLAMP = 1, + SPF_INTERPOLATE = 2, +}; // flags for A_CheckLOF -enum +enum ELOFFlags { CLOFF_NOAIM_VERT = 0x1, CLOFF_NOAIM_HORZ = 0x2, @@ -449,7 +553,7 @@ enum }; // Flags for A_Kill (Master/Target/Tracer/Children/Siblings) series -enum +enum EKillFlags { KILS_FOILINVUL = 0x00000001, KILS_KILLMISSILES = 0x00000002, @@ -461,7 +565,7 @@ enum }; // Flags for A_Damage (Master/Target/Tracer/Children/Siblings/Self) series -enum +enum EDamageFlags { DMSS_FOILINVUL = 0x00000001, DMSS_AFFECTARMOR = 0x00000002, @@ -476,12 +580,15 @@ enum }; // Flags for A_AlertMonsters -const int AMF_TARGETEMITTER = 1; -const int AMF_TARGETNONPLAYER = 2; -const int AMF_EMITFROMTARGET = 4; +enum EAlertFlags +{ + AMF_TARGETEMITTER = 1, + AMF_TARGETNONPLAYER = 2, + AMF_EMITFROMTARGET = 4, +} // Flags for A_Remove* -enum +enum ERemoveFlags { RMVF_MISSILES = 0x00000001, RMVF_NOMONSTERS = 0x00000002, @@ -493,14 +600,14 @@ enum }; // Flags for A_Fade* -enum +enum EFadeFlags { FTF_REMOVE = 1 << 0, FTF_CLAMP = 1 << 1, }; // Flags for A_Face* -enum +enum EFaceFlags { FAF_BOTTOM = 1, FAF_MIDDLE = 2, @@ -509,7 +616,7 @@ enum }; // Flags for A_QuakeEx -enum +enum EQuakeFlags { QF_RELATIVE = 1, QF_SCALEDOWN = 1 << 1, @@ -520,7 +627,7 @@ enum }; // A_CheckProximity flags -enum +enum EProximityFlags { CPXF_ANCESTOR = 1, CPXF_LESSOREQUAL = 1 << 1, @@ -539,7 +646,7 @@ enum // Flags for A_CheckBlock // These flags only affect the calling actor('s pointer), not the ones being searched. -enum +enum ECheckBlockFlags { CBF_NOLINES = 1 << 0, //Don't check actors. CBF_SETTARGET = 1 << 1, //Sets the caller/pointer's target to the actor blocking it. Actors only. @@ -552,7 +659,7 @@ enum CBF_ABSOLUTEANGLE = 1 << 8, //Absolute angle for offsets. }; -enum +enum EParticleFlags { SPF_FULLBRIGHT = 1, SPF_RELPOS = 1 << 1, @@ -565,7 +672,7 @@ enum }; //Flags for A_FaceMovementDirection -enum +enum EMovementFlags { FMDF_NOPITCH = 1 << 0, FMDF_INTERPOLATE = 1 << 1, @@ -573,7 +680,7 @@ enum }; // Flags for GetZAt -enum +enum EZFlags { GZF_ABSOLUTEPOS = 1, // Use the absolute position instead of an offsetted one. GZF_ABSOLUTEANG = 1 << 1, // Don't add the actor's angle to the parameter. @@ -584,7 +691,7 @@ enum }; // Flags for A_WeaponOffset -enum +enum EWeaponOffsetFlags { WOF_KEEPX = 1, WOF_KEEPY = 1 << 1, @@ -592,7 +699,7 @@ enum }; // Flags for psprite layers -enum +enum EPSpriteFlags { PSPF_ADDWEAPON = 1 << 0, PSPF_ADDBOB = 1 << 1, @@ -602,13 +709,13 @@ enum }; // Default psprite layers -enum +enum EPSPLayers { PSP_WEAPON = 1, PSP_FLASH = 1000, }; -enum +enum EInputFlags { // These are the original inputs sent by the player. INPUT_OLDBUTTONS, @@ -634,7 +741,7 @@ enum MODINPUT_UPMOVE }; -enum +enum EButtons { BT_ATTACK = 1<<0, // Press "Fire". BT_USE = 1<<1, // Use button, to open doors, activate switches. @@ -666,22 +773,23 @@ enum BT_USER3 = 1<<23, BT_USER4 = 1<<24, }; + // Flags for GetAngle -enum +enum EGetAngleFlags { GAF_RELATIVE = 1, GAF_SWITCH = 1 << 1, }; //Flags for A_CopySpriteFrame -enum +enum ECopySpriteFrameFlags { CPSF_NOSPRITE = 1, CPSF_NOFRAME = 1 << 1, }; //Flags for A_SetMaskRotation -enum +enum EMaskRotationFlags { VRF_NOANGLESTART = 1, VRF_NOANGLEEND = 1 << 1, @@ -692,7 +800,7 @@ enum VRF_NOPITCH = VRF_NOPITCHSTART|VRF_NOPITCHEND, }; -enum +enum ERenderStyle { STYLE_None, STYLE_Normal, @@ -709,3 +817,84 @@ enum STYLE_AddStencil, STYLE_AddShaded, }; + +// Type definition for the implicit 'callingstate' parameter that gets passed to action functions. +enum EStateType +{ + STATE_Actor, + STATE_Psprite, + STATE_StateChain, +} + +struct FStateParamInfo +{ + state mCallingState; + EStateType mStateType; + int mPSPIndex; +} + +// returned by AimLineAttack. +struct FTranslatedLineTarget +{ + Actor linetarget; + double angleFromSource; + bool unlinked; // found by a trace that went through an unlinked portal. +} + +enum EAimFlags +{ + ALF_FORCENOSMART = 1, + ALF_CHECK3D = 2, + ALF_CHECKNONSHOOTABLE = 4, + ALF_CHECKCONVERSATION = 8, + ALF_NOFRIENDS = 16, + ALF_PORTALRESTRICT = 32, // only work through portals with a global offset (to be used for stuff that cannot remember the calculated FTranslatedLineTarget info) +} + +enum ELineAttackFlags +{ + LAF_ISMELEEATTACK = 1, + LAF_NORANDOMPUFFZ = 2, + LAF_NOIMPACTDECAL = 4, + LAF_NOINTERACT = 8, +} + +const MELEERANGE = 64; +const SAWRANGE = (64.+(1./65536.)); // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states) +const MISSILERANGE = (32*64); +const PLAYERMISSILERANGE = 8192; // [RH] New MISSILERANGE for players + +enum ESightFlags +{ + SF_IGNOREVISIBILITY=1, + SF_SEEPASTSHOOTABLELINES=2, + SF_SEEPASTBLOCKEVERYTHING=4, + SF_IGNOREWATERBOUNDARY=8 +} + +enum EDmgFlags +{ + DMG_NO_ARMOR = 1, + DMG_INFLICTOR_IS_PUFF = 2, + DMG_THRUSTLESS = 4, + DMG_FORCED = 8, + DMG_NO_FACTOR = 16, + DMG_PLAYERATTACK = 32, + DMG_FOILINVUL = 64, + DMG_FOILBUDDHA = 128, + DMG_NO_PROTECT = 256, + DMG_USEANGLE = 512, +} + +enum EReplace +{ + NO_REPLACE = 0, + ALLOW_REPLACE = 1 +} + +// This translucency value produces the closest match to Heretic's TINTTAB. +// ~40% of the value of the overlaid image shows through. +const HR_SHADOW = (0x6800 / 65536.); +// Hexen's TINTTAB is the same as Heretic's, just reversed. +const HX_SHADOW = (0x9800 / 65536.); +const HX_ALTSHADOW = (0x6800 / 65536.); diff --git a/wadsrc/static/zscript/doom/arachnotron.txt b/wadsrc/static/zscript/doom/arachnotron.txt new file mode 100644 index 000000000..c7e11ab14 --- /dev/null +++ b/wadsrc/static/zscript/doom/arachnotron.txt @@ -0,0 +1,114 @@ +//=========================================================================== +// +// Arachnotron +// +//=========================================================================== +class Arachnotron : Actor +{ + Default + { + Health 500; + Radius 64; + Height 64; + Mass 600; + Speed 12; + PainChance 128; + Monster; + +FLOORCLIP + +BOSSDEATH + SeeSound "baby/sight"; + PainSound "baby/pain"; + DeathSound "baby/death"; + ActiveSound "baby/active"; + Obituary "$OB_BABY"; + } + States + { + Spawn: + BSPI AB 10 A_Look; + Loop; + See: + BSPI A 20; + BSPI A 3 A_BabyMetal; + BSPI ABBCC 3 A_Chase; + BSPI D 3 A_BabyMetal; + BSPI DEEFF 3 A_Chase; + Goto See+1; + Missile: + BSPI A 20 BRIGHT A_FaceTarget; + BSPI G 4 BRIGHT A_BspiAttack; + BSPI H 4 BRIGHT; + BSPI H 1 BRIGHT A_SpidRefire; + Goto Missile+1; + Pain: + BSPI I 3; + BSPI I 3 A_Pain; + Goto See+1; + Death: + BSPI J 20 A_Scream; + BSPI K 7 A_NoBlocking; + BSPI LMNO 7; + BSPI P -1 A_BossDeath; + Stop; + Raise: + BSPI P 5; + BSPI ONMLKJ 5; + Goto See+1; + } +} + +//=========================================================================== +// +// Arachnotron plasma +// +//=========================================================================== +class ArachnotronPlasma : Actor +{ + Default + { + Radius 13; + Height 8; + Speed 25; + Damage 5; + Projectile; + +RANDOMIZE + RenderStyle "Add"; + Alpha 0.75; + SeeSound "baby/attack"; + DeathSound "baby/shotx"; + } + States + { + Spawn: + APLS AB 5 BRIGHT; + Loop; + Death: + APBX ABCDE 5 BRIGHT; + Stop; + } +} + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_BspiAttack() + { + if (target) + { + A_FaceTarget(); + SpawnMissile(target, "ArachnotronPlasma"); + } + } + + void A_BabyMetal() + { + A_PlaySound("baby/walk", CHAN_BODY, 1, false, ATTN_IDLE); + A_Chase(); + } +} + diff --git a/wadsrc/static/zscript/doom/archvile.txt b/wadsrc/static/zscript/doom/archvile.txt new file mode 100644 index 000000000..0e9008570 --- /dev/null +++ b/wadsrc/static/zscript/doom/archvile.txt @@ -0,0 +1,177 @@ +//=========================================================================== +// +// Arch Vile +// +//=========================================================================== + +class Archvile : Actor +{ + Default + { + Health 700; + Radius 20; + Height 56; + Mass 500; + Speed 15; + PainChance 10; + Monster; + MaxTargetRange 896; + +QUICKTORETALIATE + +FLOORCLIP + +NOTARGET + SeeSound "vile/sight"; + PainSound "vile/pain"; + DeathSound "vile/death"; + ActiveSound "vile/active"; + MeleeSound "vile/stop"; + Obituary "$OB_VILE"; + } + States + { + Spawn: + VILE AB 10 A_Look; + Loop; + See: + VILE AABBCCDDEEFF 2 A_VileChase; + Loop; + Missile: + VILE G 0 BRIGHT A_VileStart; + VILE G 10 BRIGHT A_FaceTarget; + VILE H 8 BRIGHT A_VileTarget; + VILE IJKLMN 8 BRIGHT A_FaceTarget; + VILE O 8 BRIGHT A_VileAttack; + VILE P 20 BRIGHT; + Goto See; + Heal: + VILE [\] 10 BRIGHT; + Goto See; + Pain: + VILE Q 5; + VILE Q 5 A_Pain; + Goto See; + Death: + VILE Q 7; + VILE R 7 A_Scream; + VILE S 7 A_NoBlocking; + VILE TUVWXY 7; + VILE Z -1; + Stop; + } +} + + +//=========================================================================== +// +// Arch Vile Fire +// +//=========================================================================== + +class ArchvileFire : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + RenderStyle "Add"; + Alpha 1; + } + States + { + Spawn: + FIRE A 2 BRIGHT A_StartFire; + FIRE BAB 2 BRIGHT A_Fire; + FIRE C 2 BRIGHT A_FireCrackle; + FIRE BCBCDCDCDEDED 2 BRIGHT A_Fire; + FIRE E 2 BRIGHT A_FireCrackle; + FIRE FEFEFGHGHGH 2 BRIGHT A_Fire; + Stop; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +// A_VileAttack flags +//#define VAF_DMGTYPEAPPLYTODIRECT 1 + +extend class Actor +{ + + void A_VileStart() + { + A_PlaySound ("vile/start", CHAN_VOICE); + } + + // + // A_VileTarget + // Spawn the hellfire + // + void A_VileTarget(class fire = "ArchvileFire") + { + if (target) + { + A_FaceTarget (); + + Actor fog = Spawn (fire, target.Pos, ALLOW_REPLACE); + tracer = fog; + fog.target = self; + fog.tracer = self.target; + fog.A_Fire(0); + } + } + + void A_VileAttack(sound snd = "vile/stop", int initialdmg = 20, int blastdmg = 70, int blastradius = 70, float thrust = 1.0, name damagetype = "Fire", int flags = 0) + { + if (target) + { + A_FaceTarget(); + if (!CheckSight(target, 0)) return; + A_PlaySound(snd, CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, initialdmg, (flags & VAF_DMGTYPEAPPLYTODIRECT)? damagetype : 'none'); + + TraceBleed (newdam > 0 ? newdam : initialdmg, target); + + Actor fire = tracer; + if (fire) + { + // move the fire between the vile and the player + fire.SetOrigin(target.Vec3Angle(-24., angle, 0), true); + fire.A_Explode(blastdmg, blastradius, XF_NOSPLASH, false, 0, 0, 0, "BulletPuff", damagetype); + } + if (!target.bDontThrust) + { + target.Vel.z = thrust * 1000 / max(1, target.Mass); + } + } + } + + void A_StartFire() + { + A_PlaySound ("vile/firestrt", CHAN_BODY); + A_Fire(); + } + + // + // A_Fire + // Keep fire in front of player unless out of sight + // + void A_Fire(float spawnheight = 0) + { + Actor dest = tracer; + if (!dest || !target) return; + + // don't move it if the vile lost sight + if (!target.CheckSight (dest, 0) ) return; + + SetOrigin(dest.Vec3Angle(24, dest.angle, height), true); + } + + void A_FireCrackle() + { + A_PlaySound ("vile/firecrkl", CHAN_BODY); + A_Fire(); + } +} diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt new file mode 100644 index 000000000..6a72de2bf --- /dev/null +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -0,0 +1,420 @@ + +//=========================================================================== +// +// Boss Brain +// +//=========================================================================== + +class BossBrain : Actor +{ + Default + { + Health 250; + Mass 10000000; + PainChance 255; + +SOLID +SHOOTABLE + +NOICEDEATH + +OLDRADIUSDMG + PainSound "brain/pain"; + DeathSound "brain/death"; + } + States + { + Spawn: + BBRN A -1; + Stop; + Pain: + BBRN B 36 A_BrainPain; + Goto Spawn; + Death: + BBRN A 100 A_BrainScream; + BBRN AA 10; + BBRN A -1 A_BrainDie; + Stop; + } +} + + +//=========================================================================== +// +// Boss Eye +// +//=========================================================================== + +class BossEye : Actor +{ + Default + { + Height 32; + +NOBLOCKMAP + +NOSECTOR + } + States + { + Spawn: + SSWV A 10 A_Look; + Loop; + See: + SSWV A 181 A_BrainAwake; + SSWV A 150 A_BrainSpit; + Wait; + } +} + +//=========================================================================== +// +// Boss Target +// +//=========================================================================== + +class BossTarget : SpecialSpot +{ + Default + { + Height 32; + +NOBLOCKMAP; + +NOSECTOR; + } +} + +//=========================================================================== +// +// Spawn shot +// +//=========================================================================== + +class SpawnShot : Actor +{ + Default + { + Radius 6; + Height 32; + Speed 10; + Damage 3; + Projectile; + +NOCLIP + -ACTIVATEPCROSS + +RANDOMIZE + SeeSound "brain/spit"; + DeathSound "brain/cubeboom"; + } + States + { + Spawn: + BOSF A 3 BRIGHT A_SpawnSound; + BOSF BCD 3 BRIGHT A_SpawnFly; + Loop; + } +} + +//=========================================================================== +// +// Spawn fire +// +//=========================================================================== + +class SpawnFire : Actor +{ + Default + { + Height 78; + +NOBLOCKMAP + +NOGRAVITY + RenderStyle "Add"; + } + States + { + Spawn: + FIRE ABCDEFGH 4 Bright A_Fire; + Stop; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + + void A_BrainAwake() + { + A_PlaySound("brain/sight", CHAN_VOICE, 1, false, ATTN_NONE); + } + + void A_BrainPain() + { + A_PlaySound("brain/pain", CHAN_VOICE, 1, false, ATTN_NONE); + } + + private static void BrainishExplosion(vector3 pos) + { + Actor boom = Actor.Spawn("Rocket", pos, NO_REPLACE); + if (boom) + { + boom.DeathSound = "misc/brainexplode"; + boom.Vel.z = random[BrainScream](0, 255)/128.; + + boom.SetStateLabel ("Brainexplode"); + boom.bRocketTrail = false; + boom.SetDamage(0); // disables collision detection which is not wanted here + boom.tics -= random[BrainScream](0, 7); + if (boom.tics < 1) boom.tics = 1; + } + } + + void A_BrainScream() + { + for (double x = -196; x < +320; x += 8) + { + // (1 / 512.) is actually what the original value of 128 did, even though it probably meant 128 map units. + BrainishExplosion(Vec2OffsetZ(x, -320, (1 / 512.) + random[BrainExplode](0, 255) * 2)); + } + A_PlaySound("brain/death", CHAN_VOICE, 1, false, ATTN_NONE); + } + + void A_BrainExplode() + { + double x = random2[BrainExplode]() / 32.; + Vector3 pos = Vec2OffsetZ(x, 0, 1 / 512. + random[BrainExplode]() * 2); + BrainishExplosion(pos); + } + + void A_BrainDie() + { + // [RH] If noexit, then don't end the level. + if ((GetCVar("deathmatch") || GetCVar("alwaysapplydmflags")) && GetCVar("sv_noexit")) + return; + + // New dmflag: Kill all boss spawned monsters before ending the level. + if (GetCVar("sv_killbossmonst")) + { + int count; // Repeat until we have no more boss-spawned monsters. + ThinkerIterator it = ThinkerIterator.Create(); + do // (e.g. Pain Elementals can spawn more to kill upon death.) + { + Actor mo; + it.Reinit(); + count = 0; + while (mo = Actor(it.Next())) + { + if (mo.health > 0 && mo.bBossSpawned) + { + mo.DamageMobj(self, self, mo.health, "None", DMG_NO_ARMOR|DMG_FORCED|DMG_THRUSTLESS|DMG_NO_FACTOR); + count++; + } + } + } while (count != 0); + } + Exit_Normal(0); + } + + native + void A_BrainSpit(class spawntype = null) // needs special treatment for default + ;/* + { + SpotState spstate = SpotState.GetSpotState(); + Actor targ; + Actor spit; + bool isdefault = false; + + // shoot a cube at current target + targ = spstate.GetNextInList("BossTarget", G_SkillProperty(SKILLP_EasyBossBrain)); + + if (targ) + { + if (spawntype == null) + { + spawntype = "SpawnShot"; + isdefault = true; + } + + // spawn brain missile + spit = SpawnMissile (targ, spawntype); + + if (spit) + { + // Boss cubes should move freely to their destination so it's + // probably best to disable all collision detection for them. + spit.bNoInteraction = spit.bNoClip; + + spit.target = targ; + spit.master = self; + // [RH] Do this correctly for any trajectory. Doom would divide by 0 + // if the target had the same y coordinate as the spitter. + if (spit.Vel.xy == (0, 0)) + { + spit.special2 = 0; + } + else if (abs(spit.Vel.y) > fabs(spit.Vel.x)) + { + spit.special2 = int((targ.pos.y - pos.y) / spit.Vel.y); + } + else + { + spit.special2 = int((targ.pos.x - pos.x) / spit.Vel.y); + } + // [GZ] Calculates when the projectile will have reached destination + spit.special2 += level.maptime; + spit.bBossCube = true; + } + + if (!isdefault) + { + A_PlaySound(self.AttackSound, CHAN_WEAPON); + } + else + { + // compatibility fallback + A_PlaySound("brain/spit", CHAN_WEAPON); + } + } + } + */ + + private void SpawnFly(class spawntype, sound snd) + { + Actor newmobj; + Actor fog; + Actor eye = master; // The eye is the spawnshot's master, not the target! + Actor targ = target; // Unlike other projectiles, the target is the intended destination. + int r; + + // [GZ] Should be more viable than a countdown... + if (special2 != 0) + { + if (special2 > level.maptime) + return; // still flying + } + else + { + if (reactiontime == 0 || --reactiontime != 0) + return; // still flying + } + + if (spawntype) + { + fog = Spawn (spawntype, targ.pos, ALLOW_REPLACE); + if (fog) A_PlaySound(snd, CHAN_BODY); + } + + class SpawnName = null; + + DropItem di; // di will be our drop item list iterator + DropItem drop; // while drop stays as the reference point. + int n = 0; + + // First see if this cube has its own actor list + drop = GetDropItems(); + + // If not, then default back to its master's list + if (drop == null && eye != null) + drop = eye.GetDropItems(); + + if (drop != null) + { + for (di = drop; di != null; di = di.Next) + { + if (di.Name != 'None') + { + if (di.Amount < 0) + { + di.Amount = 1; // default value is -1, we need a positive value. + } + n += di.Amount; // this is how we can weight the list. + } + } + di = drop; + n = random[pr_spawnfly](0, n); + while (n >= 0) + { + if (di.Name != 'none') + { + n -= di.Amount; // logically, none of the -1 values have survived by now. + } + if ((di.Next != null) && (n >= 0)) + { + di = di.Next; + } + else + { + n = -1; + } + } + SpawnName = di.Name; + } + if (SpawnName == null) + { + // Randomly select monster to spawn. + r = random[pr_spawnfly](0, 255); + + // Probability distribution (kind of :), + // decreasing likelihood. + if (r < 50) SpawnName = "DoomImp"; + else if (r < 90) SpawnName = "Demon"; + else if (r < 120) SpawnName = "Spectre"; + else if (r < 130) SpawnName = "PainElemental"; + else if (r < 160) SpawnName = "Cacodemon"; + else if (r < 162) SpawnName = "Archvile"; + else if (r < 172) SpawnName = "Revenant"; + else if (r < 192) SpawnName = "Arachnotron"; + else if (r < 222) SpawnName = "Fatso"; + else if (r < 246) SpawnName = "HellKnight"; + else SpawnName = "BaronOfHell"; + } + if (spawnname != null) + { + newmobj = Spawn (spawnname, targ.pos, ALLOW_REPLACE); + if (newmobj != null) + { + // Make the new monster hate what the boss eye hates + if (eye != null) + { + newmobj.CopyFriendliness (eye, false); + } + // Make it act as if it was around when the player first made noise + // (if the player has made noise). + newmobj.LastHeard = newmobj.Sector.SoundTarget; + + if (newmobj.SeeState != null && newmobj.LookForPlayers (true)) + { + newmobj.SetState (newmobj.SeeState); + } + if (!newmobj.bDestroyed) + { + // telefrag anything in this spot + newmobj.TeleportMove (newmobj.pos, true); + } + newmobj.bBossSpawned = true; + } + } + + // remove self (i.e., cube). + Destroy (); + } + + void A_SpawnFly(class spawntype = null) + { + sound snd; + if (spawntype != null) + { + snd = GetDefaultByType(spawntype).SeeSound; + } + else + { + spawntype = "SpawnFire"; + snd = "brain/spawn"; + } + SpawnFly(spawntype, snd); + } + + void A_SpawnSound() + { + // travelling cube sound + A_PlaySound("brain/cube", CHAN_BODY); + SpawnFly("SpawnFire", "brain/spawn"); + } +} diff --git a/wadsrc/static/zscript/doom/bruiser.txt b/wadsrc/static/zscript/doom/bruiser.txt new file mode 100644 index 000000000..c1faa23c1 --- /dev/null +++ b/wadsrc/static/zscript/doom/bruiser.txt @@ -0,0 +1,167 @@ +//=========================================================================== +// +// Baron of Hell +// +//=========================================================================== +class BaronOfHell : Actor +{ + Default + { + Health 1000; + Radius 24; + Height 64; + Mass 1000; + Speed 8; + PainChance 50; + Monster; + +FLOORCLIP + +BOSSDEATH + SeeSound "baron/sight"; + PainSound "baron/pain"; + DeathSound "baron/death"; + ActiveSound "baron/active"; + Obituary "$OB_BARON"; + HitObituary "$OB_BARONHIT"; + } + States + { + Spawn: + BOSS AB 10 A_Look ; + Loop; + See: + BOSS AABBCCDD 3 A_Chase; + Loop; + Melee: + Missile: + BOSS EF 8 A_FaceTarget; + BOSS G 8 A_BruisAttack; + Goto See; + Pain: + BOSS H 2; + BOSS H 2 A_Pain; + Goto See; + Death: + BOSS I 8; + BOSS J 8 A_Scream; + BOSS K 8; + BOSS L 8 A_NoBlocking; + BOSS MN 8; + BOSS O -1 A_BossDeath; + Stop; + Raise: + BOSS O 8; + BOSS NMLKJI 8; + Goto See; + } +} + +//=========================================================================== +// +// Hell Knight +// +//=========================================================================== +class HellKnight : BaronOfHell +{ + Default + { + Health 500; + -BOSSDEATH; + SeeSound "knight/sight"; + ActiveSound "knight/active"; + PainSound "knight/pain"; + DeathSound "knight/death"; + HitObituary "$OB_KNIGHTHIT"; + Obituary "$OB_KNIGHT"; + } + States + { + Spawn: + BOS2 AB 10 A_Look; + Loop; + See: + BOS2 AABBCCDD 3 A_Chase; + Loop; + Melee: + Missile: + BOS2 EF 8 A_FaceTarget; + BOS2 G 8 A_BruisAttack; + Goto See; + Pain: + BOS2 H 2; + BOS2 H 2 A_Pain; + Goto See; + Death: + BOS2 I 8; + BOS2 J 8 A_Scream; + BOS2 K 8; + BOS2 L 8 A_NoBlocking; + BOS2 MN 8; + BOS2 O -1; + Stop; + Raise: + BOS2 O 8; + BOS2 NMLKJI 8; + Goto See; + } +} + +//=========================================================================== +// +// Baron slime ball +// +//=========================================================================== +class BaronBall : Actor +{ + Default + { + Radius 6; + Height 16; + Speed 15; + FastSpeed 20; + Damage 8; + Projectile ; + +RANDOMIZE + RenderStyle "Add"; + Alpha 1; + SeeSound "baron/attack"; + DeathSound "baron/shotx"; + Decal "BaronScorch"; + } + States + { + Spawn: + BAL7 AB 4 BRIGHT; + Loop; + Death: + BAL7 CDE 6 BRIGHT; + Stop; + } +} + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_BruisAttack() + { + if (target) + { + if (CheckMeleeRange()) + { + int damage = random[pr_bruisattack](1, 8) * 10; + A_PlaySound ("baron/melee", CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, damage, "Melee"); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + else + { + // launch a missile + SpawnMissile (target, "BaronBall"); + } + } + } +} diff --git a/wadsrc/static/zscript/doom/cacodemon.txt b/wadsrc/static/zscript/doom/cacodemon.txt new file mode 100644 index 000000000..b21acacd2 --- /dev/null +++ b/wadsrc/static/zscript/doom/cacodemon.txt @@ -0,0 +1,117 @@ +//=========================================================================== +// +// Cacodemon +// +//=========================================================================== +class Cacodemon : Actor +{ + Default + { + Health 400; + Radius 31; + Height 56; + Mass 400; + Speed 8; + PainChance 128; + Monster; + +FLOAT +NOGRAVITY + SeeSound "caco/sight"; + PainSound "caco/pain"; + DeathSound "caco/death"; + ActiveSound "caco/active"; + Obituary "$OB_CACO"; + HitObituary "$OB_CACOHIT"; + } + States + { + Spawn: + HEAD A 10 A_Look; + Loop; + See: + HEAD A 3 A_Chase; + Loop; + Missile: + HEAD B 5 A_FaceTarget; + HEAD C 5 A_FaceTarget; + HEAD D 5 BRIGHT A_HeadAttack; + Goto See; + Pain: + HEAD E 3; + HEAD E 3 A_Pain; + HEAD F 6; + Goto See; + Death: + HEAD G 8; + HEAD H 8 A_Scream; + HEAD I 8; + HEAD J 8; + HEAD K 8 A_NoBlocking; + HEAD L -1 A_SetFloorClip; + Stop; + Raise: + HEAD L 8 A_UnSetFloorClip; + HEAD KJIHG 8; + Goto See; + } +} + +//=========================================================================== +// +// Cacodemon plasma ball +// +//=========================================================================== +class CacodemonBall : Actor +{ + Default + { + Radius 6; + Height 8; + Speed 10; + FastSpeed 20; + Damage 5; + Projectile; + +RANDOMIZE + RenderStyle "Add"; + Alpha 1; + SeeSound "caco/attack"; + DeathSound "caco/shotx"; + } + States + { + Spawn: + BAL2 AB 4 BRIGHT; + Loop; + Death: + BAL2 CDE 6 BRIGHT; + Stop; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_HeadAttack() + { + if (target) + { + if (CheckMeleeRange()) + { + int damage = random[pr_headattack](1, 6) * 10; + A_PlaySound (AttackSound, CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, damage, "Melee"); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + else + { + // launch a missile + SpawnMissile (target, "CacodemonBall"); + } + } + } +} diff --git a/wadsrc/static/zscript/doom/cyberdemon.txt b/wadsrc/static/zscript/doom/cyberdemon.txt new file mode 100644 index 000000000..1a2890f9a --- /dev/null +++ b/wadsrc/static/zscript/doom/cyberdemon.txt @@ -0,0 +1,89 @@ + +//=========================================================================== +// +// Cyberdemon +// +//=========================================================================== +class Cyberdemon : Actor +{ + Default + { + Health 4000; + Radius 40; + Height 110; + Mass 1000; + Speed 16; + PainChance 20; + Monster; + MinMissileChance 160; + +BOSS + +MISSILEMORE + +FLOORCLIP + +NORADIUSDMG + +DONTMORPH + +BOSSDEATH + SeeSound "cyber/sight"; + PainSound "cyber/pain"; + DeathSound "cyber/death"; + ActiveSound "cyber/active"; + Obituary "$OB_CYBORG"; + } + States + { + Spawn: + CYBR AB 10 A_Look; + Loop; + See: + CYBR A 3 A_Hoof; + CYBR ABBCC 3 A_Chase; + CYBR D 3 A_Metal; + CYBR D 3 A_Chase; + Loop; + Missile: + CYBR E 6 A_FaceTarget; + CYBR F 12 A_CyberAttack; + CYBR E 12 A_FaceTarget; + CYBR F 12 A_CyberAttack; + CYBR E 12 A_FaceTarget; + CYBR F 12 A_CyberAttack; + Goto See; + Pain: + CYBR G 10 A_Pain; + Goto See; + Death: + CYBR H 10; + CYBR I 10 A_Scream; + CYBR JKL 10; + CYBR M 10 A_NoBlocking; + CYBR NO 10; + CYBR P 30; + CYBR P -1 A_BossDeath; + Stop; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_CyberAttack() + { + if (target) + { + A_FaceTarget(); + SpawnMissile (target, "Rocket"); + } + } + + void A_Hoof() + { + A_PlaySound("cyber/hoof", CHAN_BODY, 1, false, ATTN_IDLE); + A_Chase(); + } + +} diff --git a/wadsrc/static/actors/doom/deadthings.txt b/wadsrc/static/zscript/doom/deadthings.txt similarity index 67% rename from wadsrc/static/actors/doom/deadthings.txt rename to wadsrc/static/zscript/doom/deadthings.txt index f90d35eef..3a7e47610 100644 --- a/wadsrc/static/actors/doom/deadthings.txt +++ b/wadsrc/static/zscript/doom/deadthings.txt @@ -1,30 +1,30 @@ // Gibbed marine ----------------------------------------------------------- -actor GibbedMarine +class GibbedMarine : Actor { States { Spawn: - PLAY W -1 - Stop + PLAY W -1; + Stop; } } // Gibbed marine (extra copy) ---------------------------------------------- -actor GibbedMarineExtra : GibbedMarine +class GibbedMarineExtra : GibbedMarine { } // Dead marine ------------------------------------------------------------- -actor DeadMarine +class DeadMarine : Actor { States { Spawn: - PLAY N -1 - Stop + PLAY N -1; + Stop; } } @@ -35,63 +35,78 @@ actor DeadMarine // Dead zombie man --------------------------------------------------------- -actor DeadZombieMan : ZombieMan +class DeadZombieMan : ZombieMan { - Skip_Super - DropItem None + Default + { + Skip_Super; + DropItem "None"; + } States { Spawn: - Goto Super::Death+4 + Goto Super::Death+4; } } // Dead shotgun guy -------------------------------------------------------- -actor DeadShotgunGuy : ShotgunGuy +class DeadShotgunGuy : ShotgunGuy { - Skip_Super - DropItem None + Default + { + Skip_Super; + DropItem "None"; + } States { Spawn: - Goto Super::Death+4 + Goto Super::Death+4; } } // Dead imp ---------------------------------------------------------------- -actor DeadDoomImp : DoomImp +class DeadDoomImp : DoomImp { - Skip_Super + Default + { + Skip_Super; + } States { Spawn: - Goto Super::Death+4 + Goto Super::Death+4; } } // Dead demon -------------------------------------------------------------- -actor DeadDemon : Demon +class DeadDemon : Demon { - Skip_Super + Default + { + Skip_Super; + } States { Spawn: - Goto Super::Death+5 + Goto Super::Death+5; } } // Dead cacodemon ---------------------------------------------------------- -actor DeadCacodemon : Cacodemon +class DeadCacodemon : Cacodemon { - Skip_Super + Default + { + Skip_Super; + } States { Spawn: - Goto Super::Death+5 + Goto Super::Death+5; } } @@ -103,12 +118,15 @@ actor DeadCacodemon : Cacodemon * a holdover from that.) */ -actor DeadLostSoul : LostSoul +class DeadLostSoul : LostSoul { - Skip_Super + Default + { + Skip_Super; + } States { Spawn: - Goto Super::Death+5 + Goto Super::Death+5; } } diff --git a/wadsrc/static/zscript/doom/demon.txt b/wadsrc/static/zscript/doom/demon.txt new file mode 100644 index 000000000..d4cd9002c --- /dev/null +++ b/wadsrc/static/zscript/doom/demon.txt @@ -0,0 +1,95 @@ +//=========================================================================== +// +// Pink Demon +// +//=========================================================================== +class Demon : Actor +{ + Default + { + Health 150; + PainChance 180; + Speed 10; + Radius 30; + Height 56; + Mass 400; + Monster; + +FLOORCLIP + SeeSound "demon/sight"; + AttackSound "demon/melee"; + PainSound "demon/pain"; + DeathSound "demon/death"; + ActiveSound "demon/active"; + Obituary "$OB_DEMONHIT"; + } + States + { + Spawn: + SARG AB 10 A_Look; + Loop; + See: + SARG AABBCCDD 2 Fast A_Chase; + Loop; + Melee: + SARG EF 8 Fast A_FaceTarget; + SARG G 8 Fast A_SargAttack; + Goto See; + Pain: + SARG H 2 Fast; + SARG H 2 Fast A_Pain; + Goto See; + Death: + SARG I 8; + SARG J 8 A_Scream; + SARG K 4; + SARG L 4 A_NoBlocking; + SARG M 4; + SARG N -1; + Stop; + Raise: + SARG N 5; + SARG MLKJI 5; + Goto See; + } +} + +//=========================================================================== +// +// Spectre +// +//=========================================================================== +class Spectre : Demon +{ + Default + { + +SHADOW + RenderStyle "OptFuzzy"; + Alpha 0.5; + SeeSound "spectre/sight"; + AttackSound "spectre/melee"; + PainSound "spectre/pain"; + DeathSound "spectre/death"; + ActiveSound "spectre/active"; + HitObituary "$OB_SPECTREHIT"; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_SargAttack() + { + if (target && CheckMeleeRange()) + { + int damage = random[pr_sargattack](1, 10) * 4; + int newdam = target.DamageMobj (self, self, damage, "Melee"); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + } +} diff --git a/wadsrc/static/zscript/doom/doomammo.txt b/wadsrc/static/zscript/doom/doomammo.txt new file mode 100644 index 000000000..394f13e94 --- /dev/null +++ b/wadsrc/static/zscript/doom/doomammo.txt @@ -0,0 +1,169 @@ +// Clip -------------------------------------------------------------------- + +class Clip : Ammo +{ + Default + { + Inventory.PickupMessage "$GOTCLIP"; + Inventory.Amount 10; + Inventory.MaxAmount 200; + Ammo.BackpackAmount 10; + Ammo.BackpackMaxAmount 400; + Inventory.Icon "CLIPA0"; + } + States + { + Spawn: + CLIP A -1; + Stop; + } +} + +// Clip box ---------------------------------------------------------------- + +class ClipBox : Clip +{ + Default + { + Inventory.PickupMessage "$GOTCLIPBOX"; + Inventory.Amount 50; + } + States + { + Spawn: + AMMO A -1; + Stop; + } +} + +// Rocket ------------------------------------------------------------------ + +class RocketAmmo : Ammo +{ + Default + { + Inventory.PickupMessage "$GOTROCKET"; + Inventory.Amount 1; + Inventory.MaxAmount 50; + Ammo.BackpackAmount 1; + Ammo.BackpackMaxAmount 100; + Inventory.Icon "ROCKA0"; + } + States + { + Spawn: + ROCK A -1; + Stop; + } +} + +// Rocket box -------------------------------------------------------------- + +class RocketBox : RocketAmmo +{ + Default + { + Inventory.PickupMessage "$GOTROCKBOX"; + Inventory.Amount 5; + } + States + { + Spawn: + BROK A -1; + Stop; + } +} + +// Cell -------------------------------------------------------------------- + +class Cell : Ammo +{ + Default + { + Inventory.PickupMessage "$GOTCELL"; + Inventory.Amount 20; + Inventory.MaxAmount 300; + Ammo.BackpackAmount 20; + Ammo.BackpackMaxAmount 600; + Inventory.Icon "CELLA0"; + } + States + { + Spawn: + CELL A -1; + Stop; + } +} + +// Cell pack --------------------------------------------------------------- + +class CellPack : Cell +{ + Default + { + Inventory.PickupMessage "$GOTCELLBOX"; + Inventory.Amount 100; + } + States + { + Spawn: + CELP A -1; + Stop; + } +} + +// Shells ------------------------------------------------------------------ + +class Shell : Ammo +{ + Default + { + Inventory.PickupMessage "$GOTSHELLS"; + Inventory.Amount 4; + Inventory.MaxAmount 50; + Ammo.BackpackAmount 4; + Ammo.BackpackMaxAmount 100; + Inventory.Icon "SHELA0"; + } + States + { + Spawn: + SHEL A -1; + Stop; + } +} + +// Shell box --------------------------------------------------------------- + +class ShellBox : Shell +{ + Default + { + Inventory.PickupMessage "$GOTSHELLBOX"; + Inventory.Amount 20; + } + States + { + Spawn: + SBOX A -1; + Stop; + } +} + +// Backpack --------------------------------------------------------------- + +class Backpack : BackpackItem +{ + Default + { + Height 26; + Inventory.PickupMessage "$GOTBACKPACK"; + } + States + { + Spawn: + BPAK A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/doom/doomarmor.txt b/wadsrc/static/zscript/doom/doomarmor.txt new file mode 100644 index 000000000..30ff9a140 --- /dev/null +++ b/wadsrc/static/zscript/doom/doomarmor.txt @@ -0,0 +1,69 @@ + +// Armor bonus -------------------------------------------------------------- + +class ArmorBonus : BasicArmorBonus +{ + Default + { + Radius 20; + Height 16; + Inventory.Pickupmessage "$GOTARMBONUS"; + Inventory.Icon "BON2A0"; + Armor.Savepercent 33.335; + Armor.Saveamount 1; + Armor.Maxsaveamount 200; + +COUNTITEM + +INVENTORY.ALWAYSPICKUP + } + States + { + Spawn: + BON2 ABCDCB 6; + loop; + } +} + +// Green armor -------------------------------------------------------------- + +class GreenArmor : BasicArmorPickup +{ + Default + { + Radius 20; + Height 16; + Inventory.Pickupmessage "$GOTARMOR"; + Inventory.Icon "ARM1A0"; + Armor.SavePercent 33.335; + Armor.SaveAmount 100; + } + States + { + Spawn: + ARM1 A 6; + ARM1 B 7 bright; + loop; + } +} + +// Blue armor --------------------------------------------------------------- + +class BlueArmor : BasicArmorPickup +{ + Default + { + Radius 20; + Height 16; + Inventory.Pickupmessage "$GOTMEGA"; + Inventory.Icon "ARM2A0"; + Armor.Savepercent 50; + Armor.Saveamount 200; + } + States + { + Spawn: + ARM2 A 6; + ARM2 B 6 bright; + loop; + } +} + diff --git a/wadsrc/static/zscript/doom/doomartifacts.txt b/wadsrc/static/zscript/doom/doomartifacts.txt new file mode 100644 index 000000000..ad5e304c6 --- /dev/null +++ b/wadsrc/static/zscript/doom/doomartifacts.txt @@ -0,0 +1,201 @@ +// Invulnerability Sphere --------------------------------------------------- + +class InvulnerabilitySphere : PowerupGiver +{ + Default + { + +COUNTITEM + +INVENTORY.AUTOACTIVATE + +INVENTORY.ALWAYSPICKUP + +INVENTORY.BIGPOWERUP + Inventory.MaxAmount 0; + Powerup.Type "PowerInvulnerable"; + Powerup.Color "InverseMap"; + Inventory.PickupMessage "$GOTINVUL"; + } + States + { + Spawn: + PINV ABCD 6 Bright; + Loop; + } +} + +// Soulsphere -------------------------------------------------------------- + +class Soulsphere : Health +{ + Default + { + +COUNTITEM; + +INVENTORY.AUTOACTIVATE; + +INVENTORY.ALWAYSPICKUP; + +INVENTORY.FANCYPICKUPSOUND; + Inventory.Amount 100; + Inventory.MaxAmount 200; + Inventory.PickupMessage "$GOTSUPER"; + Inventory.PickupSound "misc/p_pkup"; + } + States + { + Spawn: + SOUL ABCDCB 6 Bright; + Loop; + } +} + +// Mega sphere -------------------------------------------------------------- + +class MegasphereHealth : Health // for manipulation by Dehacked +{ + Default + { + Inventory.Amount 200; + Inventory.MaxAmount 200; + +INVENTORY.ALWAYSPICKUP + } +} + +// DeHackEd can only modify the blue armor's type, not the megasphere's. +class BlueArmorForMegasphere : BlueArmor +{ + Default + { + Armor.SavePercent 50; + Armor.SaveAmount 200; + } +} + +class Megasphere : CustomInventory +{ + Default + { + +COUNTITEM + +INVENTORY.ALWAYSPICKUP + Inventory.PickupMessage "$GOTMSPHERE"; + Inventory.PickupSound "misc/p_pkup"; + } + States + { + Spawn: + MEGA ABCD 6 BRIGHT; + Loop; + Pickup: + TNT1 A 0 A_GiveInventory("BlueArmorForMegasphere", 1); + TNT1 A 0 A_GiveInventory("MegasphereHealth", 1); + Stop; + } +} + +// Invisibility ------------------------------------------------------------- + +class BlurSphere : PowerupGiver +{ + Default + { + +COUNTITEM + +VISIBILITYPULSE + +INVENTORY.AUTOACTIVATE + +INVENTORY.ALWAYSPICKUP + +INVENTORY.BIGPOWERUP + Inventory.MaxAmount 0; + Powerup.Type "PowerInvisibility"; + RenderStyle "Translucent"; + Inventory.PickupMessage "$GOTINVIS"; + } + States + { + Spawn: + PINS ABCD 6 Bright; + Loop; + } +} + +// Radiation suit (aka iron feet) ------------------------------------------- + +class RadSuit : PowerupGiver +{ + Default + { + Height 46; + +INVENTORY.AUTOACTIVATE + +INVENTORY.ALWAYSPICKUP + Inventory.MaxAmount 0; + Inventory.PickupMessage "$GOTSUIT"; + Powerup.Type "PowerIronFeet"; + } + States + { + Spawn: + SUIT A -1 Bright; + Stop; + } +} + +// infrared ----------------------------------------------------------------- + +class Infrared : PowerupGiver +{ + Default + { + +COUNTITEM + +INVENTORY.AUTOACTIVATE + +INVENTORY.ALWAYSPICKUP + Inventory.MaxAmount 0; + Powerup.Type "PowerLightAmp"; + Inventory.PickupMessage "$GOTVISOR"; + } + States + { + Spawn: + PVIS A 6 Bright; + PVIS B 6; + Loop; + } +} + +// Allmap ------------------------------------------------------------------- + +class Allmap : MapRevealer +{ + Default + { + +COUNTITEM + +INVENTORY.FANCYPICKUPSOUND + +INVENTORY.ALWAYSPICKUP + Inventory.MaxAmount 0; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$GOTMAP"; + } + States + { + Spawn: + PMAP ABCDCB 6 Bright; + Loop; + } +} + +// Berserk ------------------------------------------------------------------ + +class Berserk : CustomInventory +{ + Default + { + +COUNTITEM + +INVENTORY.ALWAYSPICKUP + Inventory.PickupMessage "$GOTBERSERK"; + Inventory.PickupSound "misc/p_pkup"; + } + States + { + Spawn: + PSTR A -1; + Stop; + Pickup: + TNT1 A 0 A_GiveInventory("PowerStrength"); + TNT1 A 0 HealThing(100, 0); + TNT1 A 0 A_SelectWeapon("Fist"); + Stop; + } +} + diff --git a/wadsrc/static/zscript/doom/doomdecorations.txt b/wadsrc/static/zscript/doom/doomdecorations.txt new file mode 100644 index 000000000..8eec812f6 --- /dev/null +++ b/wadsrc/static/zscript/doom/doomdecorations.txt @@ -0,0 +1,900 @@ + +// Tech lamp --------------------------------------------------------------- + +class TechLamp : Actor +{ + Default + { + Radius 16; + Height 80; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + TLMP ABCD 4 BRIGHT; + Loop; + } +} + +// Tech lamp 2 ------------------------------------------------------------- + +class TechLamp2 : Actor +{ + Default + { + Radius 16; + Height 60; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + TLP2 ABCD 4 BRIGHT; + Loop; + } +} + +// Column ------------------------------------------------------------------ + +class Column : Actor +{ + Default + { + Radius 16; + Height 48; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + COLU A -1 BRIGHT; + Stop; + } +} + +// Tall green column ------------------------------------------------------- + +class TallGreenColumn : Actor +{ + Default + { + Radius 16; + Height 52; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + COL1 A -1; + Stop; + } +} + +// Short green column ------------------------------------------------------ + +class ShortGreenColumn : Actor +{ + Default + { + Radius 16; + Height 40;; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + COL2 A -1; + Stop; + } +} + +// Tall red column --------------------------------------------------------- + +class TallRedColumn : Actor +{ + Default + { + Radius 16; + Height 52; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + COL3 A -1; + Stop; + } +} + +// Short red column -------------------------------------------------------- + +class ShortRedColumn : Actor +{ + Default + { + Radius 16; + Height 40; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + COL4 A -1; + Stop; + } +} + +// Skull column ------------------------------------------------------------ + +class SkullColumn : Actor +{ + Default + { + Radius 16; + Height 40; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + COL6 A -1; + Stop; + } +} + +// Heart column ------------------------------------------------------------ + +class HeartColumn : Actor +{ + Default + { + Radius 16; + Height 40; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + COL5 AB 14; + Loop; + } +} + +// Evil eye ---------------------------------------------------------------- + +class EvilEye : Actor +{ + Default + { + Radius 16; + Height 54; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + CEYE ABCB 6 BRIGHT; + Loop; + } +} + +// Floating skull ---------------------------------------------------------- + +class FloatingSkull : Actor +{ + Default + { + Radius 16; + Height 26; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + FSKU ABC 6 BRIGHT; + Loop; + } +} + +// Torch tree -------------------------------------------------------------- + +class TorchTree : Actor +{ + Default + { + Radius 16; + Height 56; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + TRE1 A -1; + Stop; + } +} + +// Blue torch -------------------------------------------------------------- + +class BlueTorch : Actor +{ + Default + { + Radius 16; + Height 68;; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + TBLU ABCD 4 BRIGHT; + Loop; + } +} + +// Green torch ------------------------------------------------------------- + +class GreenTorch : Actor +{ + Default + { + Radius 16; + Height 68; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + TGRN ABCD 4 BRIGHT; + Loop; + } +} + +// Red torch --------------------------------------------------------------- + +class RedTorch : Actor +{ + Default + { + Radius 16; + Height 68; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + TRED ABCD 4 BRIGHT; + Loop; + } +} + +// Short blue torch -------------------------------------------------------- + +class ShortBlueTorch : Actor +{ + Default + { + Radius 16; + Height 37; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + SMBT ABCD 4 BRIGHT; + Loop; + } +} + +// Short green torch ------------------------------------------------------- + +class ShortGreenTorch : Actor +{ + Default + { + Radius 16; + Height 37; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + SMGT ABCD 4 BRIGHT; + Loop; + } +} + +// Short red torch --------------------------------------------------------- + +class ShortRedTorch : Actor +{ + Default + { + Radius 16; + Height 37; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + SMRT ABCD 4 BRIGHT; + Loop; + } +} + +// Stalagtite -------------------------------------------------------------- + +class Stalagtite : Actor +{ + Default + { + Radius 16; + Height 40; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + SMIT A -1; + Stop; + } +} + +// Tech pillar ------------------------------------------------------------- + +class TechPillar : Actor +{ + Default + { + Radius 16; + Height 128; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + ELEC A -1; + Stop; + } +} + +// Candle stick ------------------------------------------------------------ + +class Candlestick : Actor +{ + Default + { + Radius 20; + Height 14; + ProjectilePassHeight -16; + } + States + { + Spawn: + CAND A -1 BRIGHT; + Stop; + } +} + +// Candelabra -------------------------------------------------------------- + +class Candelabra : Actor +{ + Default + { + Radius 16; + Height 60; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + CBRA A -1 BRIGHT; + Stop; + } +} + +// Bloody twitch ----------------------------------------------------------- + +class BloodyTwitch : Actor +{ + Default + { + Radius 16; + Height 68; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + GOR1 A 10; + GOR1 B 15; + GOR1 C 8; + GOR1 B 6; + Loop; + } +} + +// Meat 2 ------------------------------------------------------------------ + +class Meat2 : Actor +{ + Default + { + Radius 16; + Height 84; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + GOR2 A -1; + Stop; + } +} + +// Meat 3 ------------------------------------------------------------------ + +class Meat3 : Actor +{ + Default + { + Radius 16; + Height 84; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + GOR3 A -1; + Stop; + } +} + +// Meat 4 ------------------------------------------------------------------ + +class Meat4 : Actor +{ + Default + { + Radius 16; + Height 68; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + GOR4 A -1; + Stop; + } +} + +// Meat 5 ------------------------------------------------------------------ + +class Meat5 : Actor +{ + Default + { + Radius 16; + Height 52; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + GOR5 A -1; + Stop; + } +} + +// Nonsolid meat ----------------------------------------------------------- + +class NonsolidMeat2 : Meat2 +{ + Default + { + -SOLID + Radius 20; + } +} + +class NonsolidMeat3 : Meat3 +{ + Default + { + -SOLID + Radius 20; + } +} + +class NonsolidMeat4 : Meat4 +{ + Default + { + -SOLID + Radius 20; + } +} + +class NonsolidMeat5 : Meat5 +{ + Default + { + -SOLID + Radius 20; + } +} + +// Nonsolid bloody twitch -------------------------------------------------- + +class NonsolidTwitch : BloodyTwitch +{ + Default + { + -SOLID + Radius 20; + } +} + +// Head on a stick --------------------------------------------------------- + +class HeadOnAStick : Actor +{ + Default + { + Radius 16; + Height 56; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + POL4 A -1; + Stop; + } +} + +// Heads (plural!) on a stick ---------------------------------------------- + +class HeadsOnAStick : Actor +{ + Default + { + Radius 16; + Height 64;; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + POL2 A -1; + Stop; + } +} + +// Head candles ------------------------------------------------------------ + +class HeadCandles : Actor +{ + Default + { + Radius 16; + Height 42; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + POL3 AB 6 BRIGHT; + Loop; + } +} + +// Dead on a stick --------------------------------------------------------- + +class DeadStick : Actor +{ + Default + { + Radius 16; + Height 64; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + POL1 A -1; + Stop; + } +} + +// Still alive on a stick -------------------------------------------------- + +class LiveStick : Actor +{ + Default + { + Radius 16; + Height 64; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + POL6 A 6; + POL6 B 8; + Loop; + } +} + +// Big tree ---------------------------------------------------------------- + +class BigTree : Actor +{ + Default + { + Radius 32; + Height 108; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + TRE2 A -1; + Stop; + } +} + +// Burning barrel ---------------------------------------------------------- + +class BurningBarrel : Actor +{ + Default + { + Radius 16; + Height 32; + ProjectilePassHeight -16; + +SOLID + } + States + { + Spawn: + FCAN ABC 4 BRIGHT; + Loop; + } +} + +// Hanging with no guts ---------------------------------------------------- + +class HangNoGuts : Actor +{ + Default + { + Radius 16; + Height 88; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + HDB1 A -1; + Stop; + } +} + +// Hanging from bottom with no brain --------------------------------------- + +class HangBNoBrain : Actor +{ + Default + { + Radius 16; + Height 88; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + HDB2 A -1; + Stop; + } +} + +// Hanging from top, looking down ------------------------------------------ + +class HangTLookingDown : Actor +{ + Default + { + Radius 16; + Height 64; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + HDB3 A -1; + Stop; + } +} + +// Hanging from top, looking up -------------------------------------------- + +class HangTLookingUp : Actor +{ + Default + { + Radius 16; + Height 64; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + HDB5 A -1; + Stop; + } +} + +// Hanging from top, skully ------------------------------------------------ + +class HangTSkull : Actor +{ + Default + { + Radius 16; + Height 64; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + HDB4 A -1; + Stop; + } +} + +// Hanging from top without a brain ---------------------------------------- + +class HangTNoBrain : Actor +{ + Default + { + Radius 16; + Height 64; + +SOLID + +NOGRAVITY + +SPAWNCEILING + } + States + { + Spawn: + HDB6 A -1; + Stop; + } +} + +// Colon gibs -------------------------------------------------------------- + +class ColonGibs : Actor +{ + Default + { + Radius 20; + Height 4; + +NOBLOCKMAP + +MOVEWITHSECTOR + } + States + { + Spawn: + POB1 A -1; + Stop; + } +} + +// Small pool o' blood ----------------------------------------------------- + +class SmallBloodPool : Actor +{ + Default + { + Radius 20; + Height 1; + +NOBLOCKMAP + +MOVEWITHSECTOR + } + States + { + Spawn: + POB2 A -1; + Stop; + } +} + +// brain stem lying on the ground ------------------------------------------ + +class BrainStem : Actor +{ + Default + { + Radius 20; + Height 4; + +NOBLOCKMAP + +MOVEWITHSECTOR + } + States + { + Spawn: + BRS1 A -1; + Stop; + } +} + + +// Grey stalagmite (unused Doom sprite, definition taken from Skulltag ----- + +class Stalagmite : Actor +{ + Default + { + Radius 16; + Height 48; + +SOLID + } + States + { + Spawn: + SMT2 A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/doom/doomhealth.txt b/wadsrc/static/zscript/doom/doomhealth.txt new file mode 100644 index 000000000..c0ecf2dc0 --- /dev/null +++ b/wadsrc/static/zscript/doom/doomhealth.txt @@ -0,0 +1,54 @@ +// Health bonus ------------------------------------------------------------- + +class HealthBonus : Health +{ + Default + { + +COUNTITEM + +INVENTORY.ALWAYSPICKUP + Inventory.Amount 1; + Inventory.MaxAmount 200; + Inventory.PickupMessage "$GOTHTHBONUS"; + } + States + { + Spawn: + BON1 ABCDCB 6; + Loop; + } +} + +// Stimpack ----------------------------------------------------------------- + +class Stimpack : Health +{ + Default + { + Inventory.Amount 10; + Inventory.PickupMessage "$GOTSTIM"; + } + States + { + Spawn: + STIM A -1; + Stop; + } +} + +// Medikit ----------------------------------------------------------------- + +class Medikit : Health +{ + Default + { + Inventory.Amount 25; + Inventory.PickupMessage "$GOTMEDIKIT"; + Health.LowMessage 25, "$GOTMEDINEED"; + } + States + { + Spawn: + MEDI A -1; + Stop; + } +} diff --git a/wadsrc/static/zscript/doom/doomimp.txt b/wadsrc/static/zscript/doom/doomimp.txt new file mode 100644 index 000000000..d2b93acdd --- /dev/null +++ b/wadsrc/static/zscript/doom/doomimp.txt @@ -0,0 +1,122 @@ +//=========================================================================== +// +// Imp +// +//=========================================================================== +class DoomImp : Actor +{ + Default + { + Health 60; + Radius 20; + Height 56; + Mass 100; + Speed 8; + PainChance 200; + Monster; + +FLOORCLIP + SeeSound "imp/sight"; + PainSound "imp/pain"; + DeathSound "imp/death"; + ActiveSound "imp/active"; + HitObituary "$OB_IMPHIT"; + Obituary "$OB_IMP"; + } + States + { + Spawn: + TROO AB 10 A_Look; + Loop; + See: + TROO AABBCCDD 3 A_Chase; + Loop; + Melee: + Missile: + TROO EF 8 A_FaceTarget; + TROO G 6 A_TroopAttack ; + Goto See; + Pain: + TROO H 2; + TROO H 2 A_Pain; + Goto See; + Death: + TROO I 8; + TROO J 8 A_Scream; + TROO K 6; + TROO L 6 A_NoBlocking; + TROO M -1; + Stop; + XDeath: + TROO N 5; + TROO O 5 A_XScream; + TROO P 5; + TROO Q 5 A_NoBlocking; + TROO RST 5; + TROO U -1; + Stop; + Raise: + TROO ML 8; + TROO KJI 6; + Goto See; + } +} + +//=========================================================================== +// +// Imp fireball +// +//=========================================================================== +class DoomImpBall : Actor +{ + Default + { + Radius 6; + Height 8; + Speed 10; + FastSpeed 20; + Damage 3; + Projectile; + +RANDOMIZE + RenderStyle "Add"; + Alpha 1; + SeeSound "imp/attack"; + DeathSound "imp/shotx"; + } + States + { + Spawn: + BAL1 AB 4 BRIGHT; + Loop; + Death: + BAL1 CDE 6 BRIGHT; + Stop; + } +} + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_TroopAttack() + { + if (target) + { + if (CheckMeleeRange()) + { + int damage = random[pr_troopattack](1, 8) * 3; + A_PlaySound ("imp/melee", CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, damage, "Melee"); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + else + { + // launch a missile + SpawnMissile (target, "DoomImpBall"); + } + } + } +} diff --git a/wadsrc/static/zscript/doom/doomkeys.txt b/wadsrc/static/zscript/doom/doomkeys.txt new file mode 100644 index 000000000..9ae88dade --- /dev/null +++ b/wadsrc/static/zscript/doom/doomkeys.txt @@ -0,0 +1,119 @@ + +class DoomKey : Key +{ + Default + { + Radius 20; + Height 16; + +NOTDMATCH + } +} + +// Blue key card ------------------------------------------------------------ + +class BlueCard : DoomKey +{ + Default + { + Inventory.Pickupmessage "$GOTBLUECARD"; + Inventory.Icon "STKEYS0"; + } + States + { + Spawn: + BKEY A 10; + BKEY B 10 bright; + loop; + } +} + +// Yellow key card ---------------------------------------------------------- + +class YellowCard : DoomKey +{ + Default + { + Inventory.Pickupmessage "$GOTYELWCARD"; + Inventory.Icon "STKEYS1"; + } + States + { + Spawn: + YKEY A 10; + YKEY B 10 bright; + loop; + } +} + +// Red key card ------------------------------------------------------------- + +class RedCard : DoomKey +{ + Default + { + Inventory.Pickupmessage "$GOTREDCARD"; + Inventory.Icon "STKEYS2"; + } + States + { + Spawn: + RKEY A 10; + RKEY B 10 bright; + loop; + } +} + +// Blue skull key ----------------------------------------------------------- + +class BlueSkull : DoomKey +{ + Default + { + Inventory.Pickupmessage "$GOTBLUESKUL"; + Inventory.Icon "STKEYS3"; + } + States + { + Spawn: + BSKU A 10; + BSKU B 10 bright; + loop; + } +} + +// Yellow skull key --------------------------------------------------------- + +class YellowSkull : DoomKey +{ + Default + { + Inventory.Pickupmessage "$GOTYELWSKUL"; + Inventory.Icon "STKEYS4"; + } + States + { + Spawn: + YSKU A 10; + YSKU B 10 bright; + loop; + } +} + +// Red skull key ------------------------------------------------------------ + +class RedSkull : DoomKey +{ + Default + { + Inventory.Pickupmessage "$GOTREDSKUL"; + Inventory.Icon "STKEYS5"; + } + States + { + Spawn: + RSKU A 10; + RSKU B 10 bright; + loop; + } +} + diff --git a/wadsrc/static/zscript/doom/doommisc.txt b/wadsrc/static/zscript/doom/doommisc.txt new file mode 100644 index 000000000..a11c411f8 --- /dev/null +++ b/wadsrc/static/zscript/doom/doommisc.txt @@ -0,0 +1,133 @@ +// The barrel of green goop ------------------------------------------------ + +class ExplosiveBarrel : Actor +{ + Default + { + Health 20; + Radius 10; + Height 42; + +SOLID + +SHOOTABLE + +NOBLOOD + +ACTIVATEMCROSS + +DONTGIB + +NOICEDEATH + +OLDRADIUSDMG + DeathSound "world/barrelx"; + Obituary "$OB_BARREL"; + } + States + { + Spawn: + BAR1 AB 6; + Loop; + Death: + BEXP A 5 BRIGHT; + BEXP B 5 BRIGHT A_Scream; + BEXP C 5 BRIGHT; + BEXP D 5 BRIGHT A_Explode; + BEXP E 10 BRIGHT; + TNT1 A 1050 BRIGHT A_BarrelDestroy; + TNT1 A 5 A_Respawn; + Wait; + } +} + +extend class Actor +{ + void A_BarrelDestroy() + { + if (GetCVar("sv_barrelrespawn")) + { + Height = Default.Height; + bInvisible = true; + bSolid = false; + } + else + { + Destroy(); + } + } +} + +// Bullet puff ------------------------------------------------------------- + +class BulletPuff : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +ALLOWPARTICLES + +RANDOMIZE + RenderStyle "Translucent"; + Alpha 0.5; + VSpeed 1; + Mass 5; + } + States + { + Spawn: + PUFF A 4 Bright; + PUFF B 4; + Melee: + PUFF CD 4; + Stop; + } +} + +// Container for an unused state ------------------------------------------- + +/* Doom defined the states S_STALAG, S_DEADTORSO, and S_DEADBOTTOM but never + * actually used them. For compatibility with DeHackEd patches, they still + * need to be kept around. This class serves that purpose. + */ + +class DoomUnusedStates : Actor +{ + States + { + Label1: + SMT2 A -1; + stop; + Label2: + PLAY N -1; + stop; + PLAY S -1; + stop; + TNT: // MBF compatibility + TNT1 A -1; + Loop; + } +} + +// MBF Beta emulation items + +class EvilSceptre : ScoreItem +{ + Default + { + Inventory.PickupMessage "$BETA_BONUS3"; + } + States + { + Spawn: + BON3 A 6; + Loop; + } +} + +class UnholyBible : ScoreItem +{ + Default + { + Inventory.PickupMessage "$BETA_BONUS4"; + } + States + { + Spawn: + BON4 A 6; + Loop; + } +} diff --git a/wadsrc/static/zscript/doom/doomplayer.txt b/wadsrc/static/zscript/doom/doomplayer.txt new file mode 100644 index 000000000..6ec0d5f90 --- /dev/null +++ b/wadsrc/static/zscript/doom/doomplayer.txt @@ -0,0 +1,93 @@ +//=========================================================================== +// +// Player +// +//=========================================================================== +class DoomPlayer : PlayerPawn +{ + Default + { + Speed 1; + Health 100; + Radius 16; + Height 56; + Mass 100; + PainChance 255; + Player.DisplayName "Marine"; + Player.CrouchSprite "PLYC"; + Player.StartItem "Pistol"; + Player.StartItem "Fist"; + Player.StartItem "Clip", 50; + Player.WeaponSlot 1, "Fist", "Chainsaw"; + Player.WeaponSlot 2, "Pistol"; + Player.WeaponSlot 3, "Shotgun", "SuperShotgun"; + Player.WeaponSlot 4, "Chaingun"; + Player.WeaponSlot 5, "RocketLauncher"; + Player.WeaponSlot 6, "PlasmaRifle"; + Player.WeaponSlot 7, "BFG9000"; + + Player.ColorRange 112, 127; + Player.Colorset 0, "Green", 0x70, 0x7F, 0x72; + Player.Colorset 1, "Gray", 0x60, 0x6F, 0x62; + Player.Colorset 2, "Brown", 0x40, 0x4F, 0x42; + Player.Colorset 3, "Red", 0x20, 0x2F, 0x22; + // Doom Legacy additions + Player.Colorset 4, "Light Gray", 0x58, 0x67, 0x5A; + Player.Colorset 5, "Light Brown", 0x38, 0x47, 0x3A; + Player.Colorset 6, "Light Red", 0xB0, 0xBF, 0xB2; + Player.Colorset 7, "Light Blue", 0xC0, 0xCF, 0xC2; + } + + States + { + Spawn: + PLAY A -1; + Loop; + See: + PLAY ABCD 4; + Loop; + Missile: + PLAY E 12; + Goto Spawn; + Melee: + PLAY F 6 BRIGHT; + Goto Missile; + Pain: + PLAY G 4; + PLAY G 4 A_Pain; + Goto Spawn; + Death: + PLAY H 0 A_PlayerSkinCheck("AltSkinDeath"); + Death1: + PLAY H 10; + PLAY I 10 A_PlayerScream; + PLAY J 10 A_NoBlocking; + PLAY KLM 10; + PLAY N -1; + Stop; + XDeath: + PLAY O 0 A_PlayerSkinCheck("AltSkinXDeath"); + XDeath1: + PLAY O 5; + PLAY P 5 A_XScream; + PLAY Q 5 A_NoBlocking; + PLAY RSTUV 5; + PLAY W -1; + Stop; + AltSkinDeath: + PLAY H 6; + PLAY I 6 A_PlayerScream; + PLAY JK 6; + PLAY L 6 A_NoBlocking; + PLAY MNO 6; + PLAY P -1; + Stop; + AltSkinXDeath: + PLAY Q 5 A_PlayerScream; + PLAY R 0 A_NoBlocking; + PLAY R 5 A_SkullPop; + PLAY STUVWX 5; + PLAY Y -1; + Stop; + } +} diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt new file mode 100644 index 000000000..a6eecd189 --- /dev/null +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -0,0 +1,625 @@ +// -------------------------------------------------------------------------- +// +// Doom weapon base class +// +// -------------------------------------------------------------------------- + +class DoomWeapon : Weapon +{ + Default + { + Weapon.Kickback 100; + } +} + +// -------------------------------------------------------------------------- +// +// Fist +// +// -------------------------------------------------------------------------- + +class Fist : Weapon +{ + Default + { + Weapon.SelectionOrder 3700; + Weapon.Kickback 100; + Obituary "$OB_MPFIST"; + Tag "$TAG_FIST"; + +WEAPON.WIMPY_WEAPON + +WEAPON.MELEEWEAPON + } + States + { + Ready: + PUNG A 1 A_WeaponReady; + Loop; + Deselect: + PUNG A 1 A_Lower; + Loop; + Select: + PUNG A 1 A_Raise; + Loop; + Fire: + PUNG B 4; + PUNG C 4 A_Punch; + PUNG D 5; + PUNG C 4; + PUNG B 5 A_ReFire; + Goto Ready; + } +} + + +// -------------------------------------------------------------------------- +// +// Pistol +// +// -------------------------------------------------------------------------- + +class Pistol : DoomWeapon +{ + Default + { + Weapon.SelectionOrder 1900; + Weapon.AmmoUse 1; + Weapon.AmmoGive 20; + Weapon.AmmoType "Clip"; + Obituary "$OB_MPPISTOL"; + +WEAPON.WIMPY_WEAPON + Inventory.Pickupmessage "$PICKUP_PISTOL_DROPPED"; + Tag "$TAG_PISTOL"; + } + States + { + Ready: + PISG A 1 A_WeaponReady; + Loop; + Deselect: + PISG A 1 A_Lower; + Loop; + Select: + PISG A 1 A_Raise; + Loop; + Fire: + PISG A 4; + PISG B 6 A_FirePistol; + PISG C 4; + PISG B 5 A_ReFire; + Goto Ready; + Flash: + PISF A 7 Bright A_Light1; + Goto LightDone; + PISF A 7 Bright A_Light1; + Goto LightDone; + Spawn: + PIST A -1; + Stop; + } +} + +// -------------------------------------------------------------------------- +// +// Chainsaw +// +// -------------------------------------------------------------------------- + +class Chainsaw : Weapon +{ + Default + { + Weapon.Kickback 0; + Weapon.SelectionOrder 2200; + Weapon.UpSound "weapons/sawup"; + Weapon.ReadySound "weapons/sawidle"; + Inventory.PickupMessage "$GOTCHAINSAW"; + Obituary "$OB_MPCHAINSAW"; + Tag "$TAG_CHAINSAW"; + +WEAPON.MELEEWEAPON + } + States + { + Ready: + SAWG CD 4 A_WeaponReady; + Loop; + Deselect: + SAWG C 1 A_Lower; + Loop; + Select: + SAWG C 1 A_Raise; + Loop; + Fire: + SAWG AB 4 A_Saw; + SAWG B 0 A_ReFire; + Goto Ready; + Spawn: + CSAW A -1; + Stop; + } +} + + +// -------------------------------------------------------------------------- +// +// Shotgun +// +// -------------------------------------------------------------------------- + +class Shotgun : DoomWeapon +{ + Default + { + Weapon.SelectionOrder 1300; + Weapon.AmmoUse 1; + Weapon.AmmoGive 8; + Weapon.AmmoType "Shell"; + Inventory.PickupMessage "$GOTSHOTGUN"; + Obituary "$OB_MPSHOTGUN"; + Tag "$TAG_SHOTGUN"; + } + States + { + Ready: + SHTG A 1 A_WeaponReady; + Loop; + Deselect: + SHTG A 1 A_Lower; + Loop; + Select: + SHTG A 1 A_Raise; + Loop; + Fire: + SHTG A 3; + SHTG A 7 A_FireShotgun; + SHTG BC 5; + SHTG D 4; + SHTG CB 5; + SHTG A 3; + SHTG A 7 A_ReFire; + Goto Ready; + Flash: + SHTF A 4 Bright A_Light1; + SHTF B 3 Bright A_Light2; + Goto LightDone; + Spawn: + SHOT A -1; + Stop; + } +} + +// -------------------------------------------------------------------------- +// +// Shotgun +// +// -------------------------------------------------------------------------- + +class SuperShotgun : DoomWeapon +{ + Default + { + Weapon.SelectionOrder 400; + Weapon.AmmoUse 2; + Weapon.AmmoGive 8; + Weapon.AmmoType "Shell"; + Inventory.PickupMessage "$GOTSHOTGUN2"; + Obituary "$OB_MPSSHOTGUN"; + Tag "$TAG_SUPERSHOTGUN"; + } + States + { + Ready: + SHT2 A 1 A_WeaponReady; + Loop; + Deselect: + SHT2 A 1 A_Lower; + Loop; + Select: + SHT2 A 1 A_Raise; + Loop; + Fire: + SHT2 A 3; + SHT2 A 7 A_FireShotgun2; + SHT2 B 7; + SHT2 C 7 A_CheckReload; + SHT2 D 7 A_OpenShotgun2; + SHT2 E 7; + SHT2 F 7 A_LoadShotgun2; + SHT2 G 6; + SHT2 H 6 A_CloseShotgun2; + SHT2 A 5 A_ReFire; + Goto Ready; + // unused states + SHT2 B 7; + SHT2 A 3; + Goto Deselect; + Flash: + SHT2 I 4 Bright A_Light1; + SHT2 J 3 Bright A_Light2; + Goto LightDone; + Spawn: + SGN2 A -1; + Stop; + } +} + +// -------------------------------------------------------------------------- +// +// Chaingun +// +// -------------------------------------------------------------------------- + +class Chaingun : DoomWeapon +{ + Default + { + Weapon.SelectionOrder 700; + Weapon.AmmoUse 1; + Weapon.AmmoGive 20; + Weapon.AmmoType "Clip"; + Inventory.PickupMessage "$GOTCHAINGUN"; + Obituary "$OB_MPCHAINGUN"; + Tag "$TAG_CHAINGUN"; + } + States + { + Ready: + CHGG A 1 A_WeaponReady; + Loop; + Deselect: + CHGG A 1 A_Lower; + Loop; + Select: + CHGG A 1 A_Raise; + Loop; + Fire: + CHGG AB 4 A_FireCGun; + CHGG B 0 A_ReFire; + Goto Ready; + Flash: + CHGF A 5 Bright A_Light1; + Goto LightDone; + CHGF B 5 Bright A_Light2; + Goto LightDone; + Spawn: + MGUN A -1; + Stop; + } +} + +// -------------------------------------------------------------------------- +// +// Rocket launcher +// +// -------------------------------------------------------------------------- + +class RocketLauncher : DoomWeapon +{ + Default + { + Weapon.SelectionOrder 2500; + Weapon.AmmoUse 1; + Weapon.AmmoGive 2; + Weapon.AmmoType "RocketAmmo"; + +WEAPON.NOAUTOFIRE + Inventory.PickupMessage "$GOTLAUNCHER"; + Tag "$TAG_ROCKETLAUNCHER"; + } + States + { + Ready: + MISG A 1 A_WeaponReady; + Loop; + Deselect: + MISG A 1 A_Lower; + Loop; + Select: + MISG A 1 A_Raise; + Loop; + Fire: + MISG B 8 A_GunFlash; + MISG B 12 A_FireMissile; + MISG B 0 A_ReFire; + Goto Ready; + Flash: + MISF A 3 Bright A_Light1; + MISF B 4 Bright; + MISF CD 4 Bright A_Light2; + Goto LightDone; + Spawn: + LAUN A -1; + Stop; + } +} + +class Rocket : Actor +{ + Default + { + Radius 11; + Height 8; + Speed 20; + Damage 20; + Projectile; + +RANDOMIZE + +DEHEXPLOSION + +ROCKETTRAIL + SeeSound "weapons/rocklf"; + DeathSound "weapons/rocklx"; + Obituary "$OB_MPROCKET"; + } + States + { + Spawn: + MISL A 1 Bright; + Loop; + Death: + MISL B 8 Bright A_Explode; + MISL C 6 Bright; + MISL D 4 Bright; + Stop; + BrainExplode: + MISL BC 10 Bright; + MISL D 10 A_BrainExplode; + Stop; + } +} + +// -------------------------------------------------------------------------- +// +// Grenade -- Taken and adapted from Skulltag, with MBF stuff added to it +// +// -------------------------------------------------------------------------- + +class Grenade : Actor +{ + Default + { + Radius 8; + Height 8; + Speed 25; + Damage 20; + Projectile; + -NOGRAVITY + +RANDOMIZE + +DEHEXPLOSION + +GRENADETRAIL + BounceType "Doom"; + Gravity 0.25; + SeeSound "weapons/grenlf"; + DeathSound "weapons/grenlx"; + BounceSound "weapons/grbnce"; + Obituary "$OB_GRENADE"; + DamageType "Grenade"; + } + States + { + Spawn: + SGRN A 1 Bright; + Loop; + Death: + MISL B 8 Bright A_Explode; + MISL C 6 Bright; + MISL D 4 Bright; + Stop; + Grenade: + MISL A 1000 A_Die; + Wait; + Detonate: + MISL B 4 A_Scream; + MISL C 6 A_Detonate; + MISL D 10; + Stop; + Mushroom: + MISL B 8 A_Mushroom; + Goto Death+1; + } +} + +// -------------------------------------------------------------------------- +// +// Plasma rifle +// +// -------------------------------------------------------------------------- + +class PlasmaRifle : DoomWeapon +{ + Default + { + Weapon.SelectionOrder 100; + Weapon.AmmoUse 1; + Weapon.AmmoGive 40; + Weapon.AmmoType "Cell"; + Inventory.PickupMessage "$GOTPLASMA"; + Tag "$TAG_PLASMARIFLE"; + } + States + { + Ready: + PLSG A 1 A_WeaponReady; + Loop; + Deselect: + PLSG A 1 A_Lower; + Loop; + Select: + PLSG A 1 A_Raise; + Loop; + Fire: + PLSG A 3 A_FirePlasma; + PLSG B 20 A_ReFire; + Goto Ready; + Flash: + PLSF A 4 Bright A_Light1; + Goto LightDone; + PLSF B 4 Bright A_Light1; + Goto LightDone; + Spawn: + PLAS A -1; + Stop; + } +} + +class PlasmaBall : Actor +{ + Default + { + Radius 13; + Height 8; + Speed 25; + Damage 5; + Projectile; + +RANDOMIZE + RenderStyle "Add"; + Alpha 0.75; + SeeSound "weapons/plasmaf"; + DeathSound "weapons/plasmax"; + Obituary "$OB_MPPLASMARIFLE"; + } + States + { + Spawn: + PLSS AB 6 Bright; + Loop; + Death: + PLSE ABCDE 4 Bright; + Stop; + } +} + +// -------------------------------------------------------------------------- +// +// BFG 2704 +// +// -------------------------------------------------------------------------- + +class PlasmaBall1 : PlasmaBall +{ + Default + { + Damage 4; + BounceType "Classic"; + BounceFactor 1.0; + Obituary "$OB_MPBFG_MBF"; + } + States + { + Spawn: + PLS1 AB 6 Bright; + Loop; + Death: + PLS1 CDEFG 4 Bright; + Stop; + } +} + +class PlasmaBall2 : PlasmaBall1 +{ + States + { + Spawn: + PLS2 AB 6 Bright; + Loop; + Death: + PLS2 CDE 4 Bright; + Stop; + } +} + +// -------------------------------------------------------------------------- +// +// BFG 9000 +// +// -------------------------------------------------------------------------- + +class BFG9000 : DoomWeapon +{ + Default + { + Height 20; + Weapon.SelectionOrder 2800; + Weapon.AmmoUse 40; + Weapon.AmmoGive 40; + Weapon.AmmoType "Cell"; + +WEAPON.NOAUTOFIRE; + Inventory.PickupMessage "$GOTBFG9000"; + Tag "$TAG_BFG9000"; + } + States + { + Ready: + BFGG A 1 A_WeaponReady; + Loop; + Deselect: + BFGG A 1 A_Lower; + Loop; + Select: + BFGG A 1 A_Raise; + Loop; + Fire: + BFGG A 20 A_BFGsound; + BFGG B 10 A_GunFlash; + BFGG B 10 A_FireBFG; + BFGG B 20 A_ReFire; + Goto Ready; + Flash: + BFGF A 11 Bright A_Light1; + BFGF B 6 Bright A_Light2; + Goto LightDone; + Spawn: + BFUG A -1; + Stop; + OldFire: + BFGG A 10 A_BFGsound; + BFGG BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 1 A_FireOldBFG; + BFGG B 0 A_Light0; + BFGG B 20 A_ReFire; + Goto Ready; + } +} + + +class BFGBall : Actor +{ + Default + { + Radius 13; + Height 8; + Speed 25; + Damage 100; + Projectile; + +RANDOMIZE + RenderStyle "Add"; + Alpha 0.75; + DeathSound "weapons/bfgx"; + Obituary "$OB_MPBFG_BOOM"; + } + States + { + Spawn: + BFS1 AB 4 Bright; + Loop; + Death: + BFE1 AB 8 Bright; + BFE1 C 8 Bright A_BFGSpray; + BFE1 DEF 8 Bright; + Stop; + } +} + +class BFGExtra : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + RenderStyle "Add"; + Alpha 0.75; + DamageType "BFGSplash"; + } + States + { + Spawn: + BFE2 ABCD 8 Bright; + Stop; + } +} + diff --git a/wadsrc/static/zscript/doom/fatso.txt b/wadsrc/static/zscript/doom/fatso.txt new file mode 100644 index 000000000..d1a456d16 --- /dev/null +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -0,0 +1,222 @@ +//=========================================================================== +// +// Mancubus +// +//=========================================================================== +class Fatso : Actor +{ + Default + { + Health 600; + Radius 48; + Height 64; + Mass 1000; + Speed 8; + PainChance 80; + Monster; + +FLOORCLIP + +BOSSDEATH + SeeSound "fatso/sight"; + PainSound "fatso/pain"; + DeathSound "fatso/death"; + ActiveSound "fatso/active"; + Obituary "$OB_FATSO"; + } + States + { + Spawn: + FATT AB 15 A_Look; + Loop; + See: + FATT AABBCCDDEEFF 4 A_Chase; + Loop; + Missile: + FATT G 20 A_FatRaise; + FATT H 10 BRIGHT A_FatAttack1; + FATT IG 5 A_FaceTarget; + FATT H 10 BRIGHT A_FatAttack2; + FATT IG 5 A_FaceTarget; + FATT H 10 BRIGHT A_FatAttack3; + FATT IG 5 A_FaceTarget; + Goto See; + Pain: + FATT J 3; + FATT J 3 A_Pain; + Goto See; + Death: + FATT K 6; + FATT L 6 A_Scream; + FATT M 6 A_NoBlocking; + FATT NOPQRS 6; + FATT T -1 A_BossDeath; + Stop; + Raise: + FATT R 5; + FATT QPONMLK 5; + Goto See; + } +} + + + +//=========================================================================== +// +// Mancubus fireball +// +//=========================================================================== +class FatShot : Actor +{ + Default + { + Radius 6; + Height 8; + Speed 20; + Damage 8; + Projectile; + +RANDOMIZE + RenderStyle "Add"; + Alpha 1; + SeeSound "fatso/attack"; + DeathSound "fatso/shotx"; + } + States + { + Spawn: + MANF AB 4 BRIGHT; + Loop; + Death: + MISL B 8 BRIGHT; + MISL C 6 BRIGHT; + MISL D 4 BRIGHT; + Stop; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + const FATSPREAD = 90./8; + + + void A_FatRaise() + { + A_FaceTarget(); + A_PlaySound("fatso/raiseguns", CHAN_WEAPON); + } + + // + // Mancubus attack, + // firing three missiles in three different directions? + // Doesn't look like it. + // + + void A_FatAttack1(class spawntype = "FatShot") + { + if (target) + { + A_FaceTarget (); + // Change direction to ... + Angle += FATSPREAD; + SpawnMissile (target, spawntype); + Actor missile = SpawnMissile (target, spawntype); + if (missile) + { + missile.Angle += FATSPREAD; + missile.VelFromAngle(); + } + } + } + + void A_FatAttack2(class spawntype = "FatShot") + { + if (target) + { + A_FaceTarget (); + // Now here choose opposite deviation. + Angle -= FATSPREAD; + SpawnMissile (target, spawntype); + Actor missile = SpawnMissile (target, spawntype); + if (missile) + { + missile.Angle -= FATSPREAD; + missile.VelFromAngle(); + } + } + } + + void A_FatAttack3(class spawntype = "FatShot") + { + if (target) + { + A_FaceTarget (); + Actor missile = SpawnMissile (target, spawntype); + if (missile) + { + missile.Angle -= FATSPREAD/2; + missile.VelFromAngle(); + } + missile = SpawnMissile (target, spawntype); + if (missile) + { + missile.Angle += FATSPREAD/2; + missile.VelFromAngle(); + } + } + } + + // + // killough 9/98: a mushroom explosion effect, sorta :) + // Original idea: Linguica + // + + void A_Mushroom(class spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5) + { + int i, j; + + if (numspawns == 0) + { + numspawns = GetMissileDamage(0, 1); + } + + A_Explode(128, 128, (flags & MSF_DontHurt) ? 0 : XF_HURTSOURCE); + + // Now launch mushroom cloud + Actor aimtarget = Spawn("Mapspot", pos, NO_REPLACE); // We need something to aim at. + Actor owner = (flags & MSF_DontHurt) ? target : self; + aimtarget.Height = Height; + + bool shootmode = ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options + (flags == 0 && isDehState(CurState) && GetCVar("compat_mushroom"))); + + for (i = -numspawns; i <= numspawns; i += 8) + { + for (j = -numspawns; j <= numspawns; j += 8) + { + Actor mo; + aimtarget.SetXYZ(pos + (i, j, (i, j).Length() * vrange)); // Aim up fairly high + if (shootmode) + { // Use old function for MBF compatibility + mo = OldSpawnMissile(aimtarget, spawntype, owner); + } + else // Use normal function + { + mo = SpawnMissile(aimtarget, spawntype, owner); + } + if (mo) + { // Slow it down a bit + mo.Vel *= hrange; + mo.bNoGravity = false; // Make debris fall under gravity + } + } + } + aimtarget.Destroy(); + } + +} + diff --git a/wadsrc/static/zscript/doom/keen.txt b/wadsrc/static/zscript/doom/keen.txt new file mode 100644 index 000000000..6d596c717 --- /dev/null +++ b/wadsrc/static/zscript/doom/keen.txt @@ -0,0 +1,81 @@ +//=========================================================================== +// +// Commander Keen +// +//=========================================================================== +class CommanderKeen : Actor +{ + Default + { + Health 100; + Radius 16; + Height 72; + Mass 10000000; + PainChance 256; + +SOLID + +SPAWNCEILING + +NOGRAVITY + +SHOOTABLE + +COUNTKILL + +NOICEDEATH + +ISMONSTER + PainSound "keen/pain"; + DeathSound "keen/death"; + } + States + { + Spawn: + KEEN A -1; + Loop; + Death: + KEEN AB 6; + KEEN C 6 A_Scream; + KEEN DEFGH 6; + KEEN I 6; + KEEN J 6; + KEEN K 6 A_KeenDie; + KEEN L -1; + Stop; + Pain: + KEEN M 4; + KEEN M 8 A_Pain; + Goto Spawn; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + + // + // A_KeenDie + // DOOM II special, map 32. + // Uses special tag 666 by default. + // + + void A_KeenDie(int doortag = 666) + { + A_NoBlocking(false); + + // scan the remaining thinkers to see if all Keens are dead + ThinkerIterator it = ThinkerIterator.Create(GetClass()); + Actor mo; + while (mo = Actor(it.Next(true))) + { + if (mo.health > 0 && mo != self) + { + // other Keen not dead + return; + } + } + Door_Open(doortag, 16); + } +} + + diff --git a/wadsrc/static/zscript/doom/lostsoul.txt b/wadsrc/static/zscript/doom/lostsoul.txt new file mode 100644 index 000000000..7ef8b4cf0 --- /dev/null +++ b/wadsrc/static/zscript/doom/lostsoul.txt @@ -0,0 +1,121 @@ +//=========================================================================== +// +// Lost Soul +// +//=========================================================================== +class LostSoul : Actor +{ + Default + { + Health 100; + Radius 16; + Height 56; + Mass 50; + Speed 8; + Damage 3; + PainChance 256; + Monster; + +FLOAT +NOGRAVITY +MISSILEMORE +DONTFALL +NOICEDEATH; + AttackSound "skull/melee"; + PainSound "skull/pain"; + DeathSound "skull/death"; + ActiveSound "skull/active"; + RenderStyle "SoulTrans"; + Obituary "$OB_SKULL"; + } + States + { + Spawn: + SKUL AB 10 BRIGHT A_Look; + Loop; + See: + SKUL AB 6 BRIGHT A_Chase; + Loop; + Missile: + SKUL C 10 BRIGHT A_FaceTarget; + SKUL D 4 BRIGHT A_SkullAttack; + SKUL CD 4 BRIGHT; + Goto Missile+2; + Pain: + SKUL E 3 BRIGHT; + SKUL E 3 BRIGHT A_Pain; + Goto See; + Death: + SKUL F 6 BRIGHT; + SKUL G 6 BRIGHT A_Scream; + SKUL H 6 BRIGHT; + SKUL I 6 BRIGHT A_NoBlocking; + SKUL J 6; + SKUL K 6; + Stop; + } +} + +class BetaSkull : LostSoul +{ + States + { + Spawn: + SKUL A 10 A_Look; + Loop; + See: + SKUL BCDA 5 A_Chase; + Loop; + Missile: + SKUL E 4 A_FaceTarget; + SKUL F 5 A_BetaSkullAttack; + SKUL F 4; + Goto See; + Pain: + SKUL G 4; + SKUL H 2 A_Pain; + Goto See; + SKUL I 4; + Goto See; + Death: + SKUL JKLM 5; + SKUL N 5 A_Scream; + SKUL O 5; + SKUL P 5 A_Fall; + SKUL Q 5 A_Stop; + Wait; + } +} + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + const SKULLSPEED = 20; + + void A_SkullAttack(float skullspeed = SKULLSPEED) + { + if (target == null) return; + + if (skullspeed <= 0) skullspeed = SKULLSPEED; + + bSkullfly = true; + A_PlaySound(AttackSound, CHAN_VOICE); + A_FaceTarget(); + VelFromAngle(skullspeed); + Vel.Z = (target.pos.Z + target.Height/2 - pos.Z) / DistanceBySpeed(target, speed); + } + + void A_BetaSkullAttack() + { + if (target == null || target.GetSpecies() == self.GetSpecies()) return; + + A_PlaySound(AttackSound, CHAN_WEAPON); + A_FaceTarget(); + + int damage = GetMissileDamage(7,1); + target.DamageMobj(self, self, damage, 'None'); + } +} + + + diff --git a/wadsrc/static/zscript/doom/painelemental.txt b/wadsrc/static/zscript/doom/painelemental.txt new file mode 100644 index 000000000..fde690b39 --- /dev/null +++ b/wadsrc/static/zscript/doom/painelemental.txt @@ -0,0 +1,95 @@ +//=========================================================================== +// +// Pain Elemental +// +//=========================================================================== +class PainElemental : Actor +{ + Default + { + Health 400; + Radius 31; + Height 56; + Mass 400; + Speed 8; + PainChance 128; + Monster; + +FLOAT + +NOGRAVITY + SeeSound "pain/sight"; + PainSound "pain/pain"; + DeathSound "pain/death"; + ActiveSound "pain/active"; + } + States + { + Spawn: + PAIN A 10 A_Look; + Loop; + See: + PAIN AABBCC 3 A_Chase; + Loop; + Missile: + PAIN D 5 A_FaceTarget; + PAIN E 5 A_FaceTarget; + PAIN F 5 BRIGHT A_FaceTarget; + PAIN F 0 BRIGHT A_PainAttack; + Goto See; + Pain: + PAIN G 6; + PAIN G 6 A_Pain; + Goto See; + Death: + PAIN H 8 BRIGHT; + PAIN I 8 BRIGHT A_Scream; + PAIN JK 8 BRIGHT; + PAIN L 8 BRIGHT A_PainDie; + PAIN M 8 BRIGHT; + Stop; + Raise: + PAIN MLKJIH 8; + Goto See; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + native void A_PainShootSkull(Class spawntype, float angle, int flags = 0, int limit = -1); + + void A_PainAttack(class spawntype = "LostSoul", float addangle = 0, int flags = 0, int limit = -1) + { + if (target) + { + A_FaceTarget(); + A_PainShootSkull(spawntype, angle + addangle, flags, limit); + } + } + void A_DualPainAttack(class spawntype = "LostSoul") + { + if (target) + { + A_FaceTarget(); + A_PainShootSkull(spawntype, angle + 45); + A_PainShootSkull(spawntype, angle - 45); + } + } + + void A_PainDie(class spawntype = "LostSoul") + { + if (target && IsFriend(target)) + { // And I thought you were my friend! + bFriendly = false; + } + A_NoBlocking(); + A_PainShootSkull(spawntype, angle + 90); + A_PainShootSkull(spawntype, angle + 180); + A_PainShootSkull(spawntype, angle + 270); + } +} diff --git a/wadsrc/static/zscript/doom/possessed.txt b/wadsrc/static/zscript/doom/possessed.txt new file mode 100644 index 000000000..8b6612076 --- /dev/null +++ b/wadsrc/static/zscript/doom/possessed.txt @@ -0,0 +1,343 @@ + +//=========================================================================== +// +// Zombie man +// +//=========================================================================== +class ZombieMan : Actor +{ + Default + { + Health 20; + Radius 20; + Height 56; + Speed 8; + PainChance 200; + Monster; + +FLOORCLIP + SeeSound "grunt/sight"; + AttackSound "grunt/attack"; + PainSound "grunt/pain"; + DeathSound "grunt/death"; + ActiveSound "grunt/active"; + Obituary "$OB_ZOMBIE"; + DropItem "Clip"; + } + States + { + Spawn: + POSS AB 10 A_Look; + Loop; + See: + POSS AABBCCDD 4 A_Chase; + Loop; + Missile: + POSS E 10 A_FaceTarget; + POSS F 8 A_PosAttack; + POSS E 8; + Goto See; + Pain: + POSS G 3; + POSS G 3 A_Pain; + Goto See; + Death: + POSS H 5; + POSS I 5 A_Scream; + POSS J 5 A_NoBlocking; + POSS K 5; + POSS L -1; + Stop; + XDeath: + POSS M 5; + POSS N 5 A_XScream; + POSS O 5 A_NoBlocking; + POSS PQRST 5; + POSS U -1; + Stop; + Raise: + POSS K 5; + POSS JIH 5; + Goto See; + } +} + +//=========================================================================== +// +// Sergeant / Shotgun guy +// +//=========================================================================== +class ShotgunGuy : Actor +{ + Default + { + Health 30; + Radius 20; + Height 56; + Mass 100; + Speed 8; + PainChance 170; + Monster; + +FLOORCLIP + SeeSound "shotguy/sight"; + AttackSound "shotguy/attack"; + PainSound "shotguy/pain"; + DeathSound "shotguy/death"; + ActiveSound "shotguy/active"; + Obituary "$OB_SHOTGUY"; + DropItem "Shotgun"; + } + States + { + Spawn: + SPOS AB 10 A_Look; + Loop; + See: + SPOS AABBCCDD 3 A_Chase; + Loop; + Missile: + SPOS E 10 A_FaceTarget; + SPOS F 10 BRIGHT A_SposAttackUseAtkSound; + SPOS E 10; + Goto See; + Pain: + SPOS G 3; + SPOS G 3 A_Pain; + Goto See; + Death: + SPOS H 5; + SPOS I 5 A_Scream; + SPOS J 5 A_NoBlocking; + SPOS K 5; + SPOS L -1; + Stop; + XDeath: + SPOS M 5; + SPOS N 5 A_XScream; + SPOS O 5 A_NoBlocking; + SPOS PQRST 5; + SPOS U -1; + Stop; + Raise: + SPOS L 5; + SPOS KJIH 5; + Goto See; + } +} + +//=========================================================================== +// +// Chaingunner +// +//=========================================================================== +class ChaingunGuy : Actor +{ + Default + { + Health 70; + Radius 20; + Height 56; + Mass 100; + Speed 8; + PainChance 170; + Monster; + +FLOORCLIP + SeeSound "chainguy/sight"; + PainSound "chainguy/pain"; + DeathSound "chainguy/death"; + ActiveSound "chainguy/active"; + AttackSound "chainguy/attack"; + Obituary "$OB_CHAINGUY"; + Dropitem "Chaingun"; + } + States + { + Spawn: + CPOS AB 10 A_Look; + Loop; + See: + CPOS AABBCCDD 3 A_Chase; + Loop; + Missile: + CPOS E 10 A_FaceTarget; + CPOS FE 4 BRIGHT A_CPosAttack; + CPOS F 1 A_CPosRefire; + Goto Missile+1; + Pain: + CPOS G 3; + CPOS G 3 A_Pain; + Goto See; + Death: + CPOS H 5; + CPOS I 5 A_Scream; + CPOS J 5 A_NoBlocking; + CPOS KLM 5; + CPOS N -1; + Stop; + XDeath: + CPOS O 5; + CPOS P 5 A_XScream; + CPOS Q 5 A_NoBlocking; + CPOS RS 5; + CPOS T -1; + Stop; + Raise: + CPOS N 5; + CPOS MLKJIH 5; + Goto See; + } +} + +//=========================================================================== +// +// SS Nazi +// +//=========================================================================== +class WolfensteinSS : Actor +{ + Default + { + Health 50; + Radius 20; + Height 56; + Speed 8; + PainChance 170; + Monster; + +FLOORCLIP + SeeSound "wolfss/sight"; + PainSound "wolfss/pain"; + DeathSound "wolfss/death"; + ActiveSound "wolfss/active"; + AttackSound "wolfss/attack"; + Obituary "$OB_WOLFSS"; + Dropitem "Clip"; + } + States + { + Spawn: + SSWV AB 10 A_Look; + Loop; + See: + SSWV AABBCCDD 3 A_Chase; + Loop; + Missile: + SSWV E 10 A_FaceTarget; + SSWV F 10 A_FaceTarget; + SSWV G 4 BRIGHT A_CPosAttack; + SSWV F 6 A_FaceTarget; + SSWV G 4 BRIGHT A_CPosAttack; + SSWV F 1 A_CPosRefire; + Goto Missile+1; + Pain: + SSWV H 3; + SSWV H 3 A_Pain; + Goto See; + Death: + SSWV I 5; + SSWV J 5 A_Scream; + SSWV K 5 A_NoBlocking; + SSWV L 5; + SSWV M -1; + Stop; + XDeath: + SSWV N 5 ; + SSWV O 5 A_XScream; + SSWV P 5 A_NoBlocking; + SSWV QRSTU 5; + SSWV V -1; + Stop; + Raise: + SSWV M 5; + SSWV LKJI 5; + Goto See ; + } +} + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_PosAttack() + { + if (target) + { + A_FaceTarget(); + double ang = angle; + double slope = AimLineAttack(ang, MISSILERANGE); + A_PlaySound("grunt/attack", CHAN_WEAPON); + ang += Random2[PosAttack]() * (22.5/256); + int damage = Random[PosAttack](1, 5) * 3; + LineAttack(ang, MISSILERANGE, slope, damage, "Hitscan", "Bulletpuff"); + } + } + + + private void A_SPosAttackInternal() + { + if (target) + { + A_FaceTarget(); + double bangle = angle; + double slope = AimLineAttack(bangle, MISSILERANGE); + + for (int i=0 ; i<3 ; i++) + { + double ang = bangle + Random2[SPosAttack]() * (22.5/256); + int damage = Random[SPosAttack](1, 5) * 3; + LineAttack(ang, MISSILERANGE, slope, damage, "Hitscan", "Bulletpuff"); + } + } + } + + void A_SPosAttackUseAtkSound() + { + if (target) + { + A_PlaySound(AttackSound, CHAN_WEAPON); + A_SPosAttackInternal(); + } + } + + // This version of the function, which uses a hard-coded sound, is meant for Dehacked only. + void A_SPosAttack() + { + if (target) + { + A_PlaySound("shotguy/attack", CHAN_WEAPON); + A_SPosAttackInternal(); + } + } + + void A_CPosAttack() + { + if (target) + { + if (bStealth) visdir = 1; + A_PlaySound(AttackSound, CHAN_WEAPON); + A_FaceTarget(); + double slope = AimLineAttack(angle, MISSILERANGE); + double ang = angle + Random2[SPosAttack]() * (22.5/256); + int damage = Random[CPosAttack](1, 5) * 3; + LineAttack(ang, MISSILERANGE, slope, damage, "Hitscan", "Bulletpuff"); + } + } + + void A_CPosRefire() + { + // keep firing unless target got out of sight + A_FaceTarget(); + if (Random[CPosRefire](0, 255) >= 40) + { + if (!target + || HitFriend() + || target.health <= 0 + || !CheckSight(target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES)) + { + SetState(SeeState); + } + } + } +} diff --git a/wadsrc/static/zscript/doom/revenant.txt b/wadsrc/static/zscript/doom/revenant.txt new file mode 100644 index 000000000..2fc35c60f --- /dev/null +++ b/wadsrc/static/zscript/doom/revenant.txt @@ -0,0 +1,242 @@ +//=========================================================================== +// +// Revenant +// +//=========================================================================== +class Revenant : Actor +{ + Default + { + Health 300; + Radius 20; + Height 56; + Mass 500; + Speed 10; + PainChance 100; + Monster; + MeleeThreshold 196; + +MISSILEMORE + +FLOORCLIP + SeeSound "skeleton/sight"; + PainSound "skeleton/pain"; + DeathSound "skeleton/death"; + ActiveSound "skeleton/active"; + MeleeSound "skeleton/melee"; + HitObituary "$OB_UNDEADHIT"; + Obituary "$OB_UNDEAD"; + } + States + { + Spawn: + SKEL AB 10 A_Look; + Loop; + See: + SKEL AABBCCDDEEFF 2 A_Chase; + Loop; + Melee: + SKEL G 0 A_FaceTarget; + SKEL G 6 A_SkelWhoosh; + SKEL H 6 A_FaceTarget; + SKEL I 6 A_SkelFist; + Goto See; + Missile: + SKEL J 0 BRIGHT A_FaceTarget; + SKEL J 10 BRIGHT A_FaceTarget; + SKEL K 10 A_SkelMissile; + SKEL K 10 A_FaceTarget; + Goto See; + Pain: + SKEL L 5; + SKEL L 5 A_Pain; + Goto See; + Death: + SKEL LM 7; + SKEL N 7 A_Scream; + SKEL O 7 A_NoBlocking; + SKEL P 7; + SKEL Q -1; + Stop; + Raise: + SKEL Q 5; + SKEL PONML 5; + Goto See; + } +} + + +//=========================================================================== +// +// Revenant Tracer +// +//=========================================================================== +class RevenantTracer : Actor +{ + Default + { + Radius 11; + Height 8; + Speed 10; + Damage 10; + Projectile; + +SEEKERMISSILE + +RANDOMIZE + SeeSound "skeleton/attack"; + DeathSound "skeleton/tracex"; + RenderStyle "Add"; + } + States + { + Spawn: + FATB AB 2 BRIGHT A_Tracer; + Loop; + Death: + FBXP A 8 BRIGHT; + FBXP B 6 BRIGHT; + FBXP C 4 BRIGHT; + Stop; + } +} + + +//=========================================================================== +// +// Revenant Tracer Smoke +// +//=========================================================================== +class RevenantTracerSmoke : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.5; + } + States + { + Spawn: + PUFF ABABC 4; + Stop; + } +} + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + const TRACEANGLE = (16.875); + + void A_SkelMissile() + { + if (target == null) return; + A_FaceTarget(); + AddZ(16); + Actor missile = SpawnMissile(target, "RevenantTracer"); + AddZ(-16); + if (missile != null) + { + missile.SetOrigin(missile.Vec3Offset(missile.Vel.X, missile.Vel.Y, 0.), false); + missile.tracer = target; + } + } + + void A_SkelWhoosh() + { + if (target == null) return; + A_FaceTarget(); + A_PlaySound("skeleton/swing", CHAN_WEAPON); + } + + void A_SkelFist() + { + if (target == null) return; + A_FaceTarget(); + + if (CheckMeleeRange ()) + { + int damage = random[SkelFist](1, 10) * 6; + A_PlaySound("skeleton/melee", CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + } + + void A_Tracer() + { + double dist; + double slope; + Actor dest; + Actor smoke; + + // killough 1/18/98: this is why some missiles do not have smoke + // and some do. Also, internal demos start at random gametics, thus + // the bug in which revenants cause internal demos to go out of sync. + // + // killough 3/6/98: fix revenant internal demo bug by subtracting + // levelstarttic from gametic: + // + // [RH] level.time is always 0-based, so nothing special to do here. + + if (level.time & 3) return; + + // spawn a puff of smoke behind the rocket + SpawnPuff ("BulletPuff", pos, angle, angle, 3); + smoke = Spawn ("RevenantTracerSmoke", Vec3Offset(-Vel.X, -Vel.Y, 0.), ALLOW_REPLACE); + + smoke.Vel.Z = 1.; + smoke.tics -= random[Tracer](0, 3); + if (smoke.tics < 1) + smoke.tics = 1; + + // adjust direction + dest = tracer; + + if (!dest || dest.health <= 0 || Speed == 0 || !CanSeek(dest)) + return; + + // change angle + double exact = AngleTo(dest); + double diff = deltaangle(angle, exact); + + if (diff < 0) + { + angle -= TRACEANGLE; + if (deltaangle(angle, exact) > 0) + angle = exact; + } + else if (diff > 0) + { + angle += TRACEANGLE; + if (deltaangle(angle, exact) < 0.) + angle = exact; + } + + VelFromAngle(); + + if (!bFloorHugger && !bCeilingHugger) + { + // change slope + dist = DistanceBySpeed(dest, Speed); + + if (dest.Height >= 56.) + { + slope = (dest.pos.z + 40. - pos.z) / dist; + } + else + { + slope = (dest.pos.z + Height*(2./3) - pos.z) / dist; + } + + if (slope < Vel.Z) + Vel.Z -= 1. / 8; + else + Vel.Z += 1. / 8; + } + } +} + diff --git a/wadsrc/static/zscript/doom/scriptedmarine.txt b/wadsrc/static/zscript/doom/scriptedmarine.txt new file mode 100644 index 000000000..7a82513cb --- /dev/null +++ b/wadsrc/static/zscript/doom/scriptedmarine.txt @@ -0,0 +1,309 @@ + +// Scriptable marine ------------------------------------------------------- + +class ScriptedMarine : Actor native +{ + Default + { + Health 100; + Radius 16; + Height 56; + Mass 100; + Speed 8; + Painchance 160; + MONSTER; + -COUNTKILL + Translation 0; + Damage 100; + DeathSound "*death"; + PainSound "*pain50"; + } + + native void A_M_Refire (bool ignoremissile=false); + native void A_M_CheckAttack (); + native void A_MarineChase (); + native void A_MarineLook (); + native void A_MarineNoise (); + native void A_M_Punch (int force); + native void A_M_SawRefire (); + native void A_M_FirePistol (bool accurate); + native void A_M_FireShotgun (); + native void A_M_FireShotgun2 (); + native void A_M_FireCGun(bool accurate); + native void A_M_FireMissile (); + native void A_M_FirePlasma (); + native void A_M_FireRailgun (); + native void A_M_BFGsound (); + native void A_M_FireBFG (); + + States + { + Spawn: + PLAY A 4 A_MarineLook; + PLAY A 4 A_MarineNoise; + Loop; + Idle: + PLAY A 4 A_MarineLook; + PLAY A 4 A_MarineNoise; + PLAY A 4 A_MarineLook; + PLAY B 4 A_MarineNoise; + PLAY B 4 A_MarineLook; + PLAY B 4 A_MarineNoise; + Loop; + See: + PLAY ABCD 4 A_MarineChase; + Loop; + + Melee.Fist: + PLAY E 4 A_FaceTarget; + PLAY E 4 A_M_Punch(1); + PLAY A 9; + PLAY A 0 A_M_Refire(1); + Loop; + PLAY A 5 A_FaceTarget; + Goto See; + Melee.Berserk: + PLAY E 4 A_FaceTarget; + PLAY E 4 A_M_Punch(10); + PLAY A 9; + PLAY A 0 A_M_Refire(1); + Loop; + PLAY A 5 A_FaceTarget; + Goto See; + Melee.Chainsaw: + PLAY E 4 A_MarineNoise; + PLAY E 4 A_M_Saw; + PLAY E 0 A_M_SawRefire; + goto Melee.Chainsaw+1; + PLAY A 0; + Goto See; + + Missile: + Missile.None: + PLAY E 12 A_FaceTarget; + Goto Idle; + PLAY F 6 BRIGHT; + Loop; + Missile.Pistol: + PLAY E 4 A_FaceTarget; + PLAY F 6 BRIGHT A_M_FirePistol(1); + PLAY A 4 A_FaceTarget; + PLAY A 0 A_M_Refire; + PLAY A 5; + Goto See; + Fireloop.Pistol: + PLAY F 6 BRIGHT A_M_FirePistol(0); + PLAY A 4 A_FaceTarget; + PLAY A 0 A_M_Refire; + Goto Fireloop.Pistol; + PLAY A 5; + Goto See; + Missile.Shotgun: + PLAY E 3 A_M_CheckAttack; + PLAY F 7 BRIGHT A_M_FireShotgun; + Goto See; + Missile.SSG: + PLAY E 3 A_M_CheckAttack; + PLAY F 7 BRIGHT A_M_FireShotgun2; + Goto See; + Missile.Chaingun: + PLAY E 4 A_FaceTarget; + PLAY FF 4 BRIGHT A_M_FireCGun(1); + PLAY FF 4 BRIGHT A_M_FireCGun(0); + PLAY A 0 A_M_Refire; + Goto Missile.Chaingun+3; + PLAY A 0; + Goto See; + Missile.Rocket: + PLAY E 8; + PLAY F 6 BRIGHT A_M_FireMissile; + PLAY E 6; + PLAY A 0 A_M_Refire; + Loop; + PLAY A 0; + Goto See; + Missile.Plasma: + PLAY E 2 A_FaceTarget; + PLAY E 0 A_FaceTarget; + PLAY F 3 BRIGHT A_M_FirePlasma; + PLAY A 0 A_M_Refire; + Goto Missile.Plasma+1; + PLAY A 0; + Goto See; + Missile.Railgun: + PLAY E 4 A_M_CheckAttack; + PLAY F 6 BRIGHT A_M_FireRailgun; + Goto See; + Missile.BFG: + PLAY E 5 A_M_BFGSound; + PLAY EEEEE 5 A_FaceTarget; + PLAY F 6 BRIGHT A_M_FireBFG; + PLAY A 4 A_FaceTarget; + PLAY A 0 A_M_Refire; + Loop; + PLAY A 0; + Goto See; + + SkipAttack: + PLAY A 1; + Goto See; + Pain: + PLAY G 4; + PLAY G 4 A_Pain; + Goto Idle; + Death: + PLAY H 10; + PLAY I 10 A_Scream; + PLAY J 10 A_NoBlocking; + PLAY KLM 10; + PLAY N -1; + Stop; + XDeath: + PLAY O 5; + PLAY P 5 A_XScream; + PLAY Q 5 A_NoBlocking; + PLAY RSTUV 5; + PLAY W -1; + Stop; + Raise: + PLAY MLKJIH 5; + Goto See; + } +} + +//--------------------------------------------------------------------------- + +class MarineFist : ScriptedMarine +{ + States + { + Melee: + Goto Super::Melee.Fist; + Missile: + Stop; + } +} + + +//--------------------------------------------------------------------------- + +class MarineBerserk : MarineFist +{ + States + { + Melee: + Goto Super::Melee.Berserk; + Missile: + Stop; + } +} +//--------------------------------------------------------------------------- + +class MarineChainsaw : ScriptedMarine +{ + States + { + Melee: + Goto Super::Melee.Chainsaw; + Missile: + Stop; + } +} + + + +//--------------------------------------------------------------------------- + +class MarinePistol : ScriptedMarine +{ + States + { + Missile: + Goto Super::Missile.Pistol; + } + +} + +//--------------------------------------------------------------------------- + +class MarineShotgun : ScriptedMarine +{ + States + { + Missile: + Goto Super::Missile.Shotgun; + } + +} + + + +//--------------------------------------------------------------------------- + +class MarineSSG : ScriptedMarine +{ + States + { + Missile: + Goto Super::Missile.SSG; + } +} + +//--------------------------------------------------------------------------- + +class MarineChaingun : ScriptedMarine +{ + States + { + Missile: + Goto Super::Missile.Chaingun; + } +} + + +//--------------------------------------------------------------------------- + +class MarineRocket : MarineFist +{ + States + { + Missile: + Goto Super::Missile.Rocket; + } + +} + +//--------------------------------------------------------------------------- + +class MarinePlasma : ScriptedMarine +{ + States + { + Missile: + Goto Super::Missile.Plasma; + } + +} + +//--------------------------------------------------------------------------- + +class MarineRailgun : ScriptedMarine +{ + States + { + Missile: + Goto Super::Missile.Railgun; + } + +} + +//--------------------------------------------------------------------------- + +class MarineBFG : ScriptedMarine +{ + States + { + Missile: + Goto Super::Missile.BFG; + } +} diff --git a/wadsrc/static/zscript/doom/spidermaster.txt b/wadsrc/static/zscript/doom/spidermaster.txt new file mode 100644 index 000000000..9a72a2bbe --- /dev/null +++ b/wadsrc/static/zscript/doom/spidermaster.txt @@ -0,0 +1,93 @@ +//=========================================================================== +// +// Spider boss +// +//=========================================================================== +class SpiderMastermind : Actor +{ + Default + { + Health 3000; + Radius 128; + Height 100; + Mass 1000; + Speed 12; + PainChance 40; + Monster; + MinMissileChance 160; + +BOSS + +MISSILEMORE + +FLOORCLIP + +NORADIUSDMG + +DONTMORPH + +BOSSDEATH + SeeSound "spider/sight"; + AttackSound "spider/attack"; + PainSound "spider/pain"; + DeathSound "spider/death"; + ActiveSound "spider/active"; + Obituary "$OB_SPIDER"; + } + States + { + Spawn: + SPID AB 10 A_Look; + Loop; + See: + SPID A 3 A_Metal; + SPID ABB 3 A_Chase; + SPID C 3 A_Metal; + SPID CDD 3 A_Chase; + SPID E 3 A_Metal; + SPID EFF 3 A_Chase; + Loop; + Missile: + SPID A 20 BRIGHT A_FaceTarget; + SPID G 4 BRIGHT A_SPosAttackUseAtkSound; + SPID H 4 BRIGHT A_SposAttackUseAtkSound; + SPID H 1 BRIGHT A_SpidRefire; + Goto Missile+1; + Pain: + SPID I 3; + SPID I 3 A_Pain; + Goto See; + Death: + SPID J 20 A_Scream; + SPID K 10 A_NoBlocking; + SPID LMNOPQR 10; + SPID S 30; + SPID S -1 A_BossDeath; + Stop; + } +} + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_SpidRefire() + { + // keep firing unless target got out of sight + A_FaceTarget(); + if (Random[CPosRefire](0, 255) >= 10) + { + if (!target + || HitFriend() + || target.health <= 0 + || !CheckSight(target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES)) + { + SetState(SeeState); + } + } + } + + void A_Metal() + { + A_PlaySound("spider/walk", CHAN_BODY, 1, false, ATTN_IDLE); + A_Chase(); + } +} diff --git a/wadsrc/static/zscript/doom/stealthmonsters.txt b/wadsrc/static/zscript/doom/stealthmonsters.txt new file mode 100644 index 000000000..785261fbb --- /dev/null +++ b/wadsrc/static/zscript/doom/stealthmonsters.txt @@ -0,0 +1,139 @@ + +class StealthArachnotron : Arachnotron +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHBABY"; + } +} + +class StealthArchvile : Archvile +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHVILE"; + } +} + +class StealthBaron : BaronOfHell +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHBARON"; + HitObituary "$OB_STEALTHBARON"; + } +} + +class StealthCacodemon : Cacodemon +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHCACO"; + HitObituary "$OB_STEALTHCACO"; + } +} + +class StealthChaingunGuy : ChaingunGuy +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHCHAINGUY"; + } +} + +class StealthDemon : Demon +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHDEMON"; + HitObituary "$OB_STEALTHDEMON"; + } +} + +class StealthHellKnight : HellKnight +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHKNIGHT"; + HitObituary "$OB_STEALTHKNIGHT"; + } +} + +class StealthDoomImp : DoomImp +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHIMP"; + HitObituary "$OB_STEALTHIMP"; + } +} + +class StealthFatso : Fatso +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHFATSO"; + } +} + +class StealthRevenant : Revenant +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHUNDEAD"; + HitObituary "$OB_STEALTHUNDEAD"; + } +} + +class StealthShotgunGuy : ShotgunGuy +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHSHOTGUNGUY"; + } +} + +class StealthZombieMan : ZombieMan +{ + Default + { + +STEALTH + RenderStyle "Translucent"; + Alpha 0; + Obituary "$OB_STEALTHZOMBIE"; + } +} + diff --git a/wadsrc/static/zscript/heretic/beast.txt b/wadsrc/static/zscript/heretic/beast.txt new file mode 100644 index 000000000..209b2da56 --- /dev/null +++ b/wadsrc/static/zscript/heretic/beast.txt @@ -0,0 +1,118 @@ + +// Beast -------------------------------------------------------------------- + +class Beast : Actor +{ + Default + { + Health 220; + Radius 32; + Height 74; + Mass 200; + Speed 14; + Painchance 100; + Monster; + +FLOORCLIP + SeeSound "beast/sight"; + AttackSound "beast/attack"; + PainSound "beast/pain"; + DeathSound "beast/death"; + ActiveSound "beast/active"; + Obituary "$OB_BEAST"; + DropItem "CrossbowAmmo", 84, 10; + } + States + { + Spawn: + BEAS AB 10 A_Look; + Loop; + See: + BEAS ABCDEF 3 A_Chase; + Loop; + Missile: + BEAS H 10 A_FaceTarget; + BEAS I 10 A_CustomComboAttack("BeastBall", 32, random[BeastAttack](1,8)*3, "beast/attack"); + Goto See; + Pain: + BEAS G 3; + BEAS G 3 A_Pain; + Goto See; + Death: + BEAS R 6; + BEAS S 6 A_Scream; + BEAS TUV 6; + BEAS W 6 A_NoBlocking; + BEAS XY 6; + BEAS Z -1; + Stop; + XDeath: + BEAS J 5; + BEAS K 6 A_Scream; + BEAS L 5; + BEAS M 6; + BEAS N 5; + BEAS O 6 A_NoBlocking; + BEAS P 5; + BEAS Q -1; + Stop; + } +} + +// Beast ball --------------------------------------------------------------- + +class BeastBall : Actor +{ + Default + { + Radius 9; + Height 8; + Speed 12; + FastSpeed 20; + Damage 4; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + -NOBLOCKMAP + +WINDTHRUST + +SPAWNSOUNDSOURCE + RenderStyle "Add"; + SeeSound "beast/attack"; + } + States + { + Spawn: + FRB1 AABBCC 2 A_SpawnItemEx("Puffy", random2[BeastPuff]()*0.015625, random2[BeastPuff]()*0.015625, random2[BeastPuff]()*0.015625, + 0,0,0,0,SXF_ABSOLUTEPOSITION, 64); + Loop; + Death: + FRB1 DEFGH 4; + Stop; + } +} + +// Puffy -------------------------------------------------------------------- + +class Puffy : Actor +{ + Default + { + Radius 6; + Height 8; + Speed 10; + +NOBLOCKMAP + +NOGRAVITY + +MISSILE + +NOTELEPORT + +DONTSPLASH + RenderStyle "Add"; + } + States + { + Spawn: + FRB1 DEFGH 4; + Stop; + } +} + + + diff --git a/wadsrc/static/zscript/heretic/chicken.txt b/wadsrc/static/zscript/heretic/chicken.txt new file mode 100644 index 000000000..2e5ada81c --- /dev/null +++ b/wadsrc/static/zscript/heretic/chicken.txt @@ -0,0 +1,201 @@ + +// Beak puff ---------------------------------------------------------------- + +class BeakPuff : StaffPuff +{ + Default + { + Mass 5; + Renderstyle "Translucent"; + Alpha 0.4; + AttackSound "chicken/attack"; + VSpeed 1; + } +} + +// Beak --------------------------------------------------------------------- + +class Beak : Weapon +{ + Default + { + Weapon.SelectionOrder 10000; + +WEAPON.DONTBOB + +WEAPON.MELEEWEAPON + Weapon.YAdjust 15; + Weapon.SisterWeapon "BeakPowered"; + } + + action native void A_BeakRaise (); + action native void A_BeakAttackPL1(); + + States + { + Ready: + BEAK A 1 A_WeaponReady; + Loop; + Deselect: + BEAK A 1 A_Lower; + Loop; + Select: + BEAK A 1 A_BeakRaise; + Loop; + Fire: + BEAK A 18 A_BeakAttackPL1; + Goto Ready; + } +} + + +class BeakPowered : Beak +{ + Default + { + +WEAPON.POWERED_UP + Weapon.SisterWeapon "Beak"; + } + + action native void A_BeakAttackPL2(); + + States + { + Fire: + BEAK A 12 A_BeakAttackPL2; + Goto Ready; + } +} + +// Chicken player ----------------------------------------------------------- + +class ChickenPlayer : PlayerPawn native +{ + Default + { + Health 30; + ReactionTime 0; + PainChance 255; + Radius 16; + Height 24; + Speed 1; + Gravity 0.125; + +NOSKIN + +PLAYERPAWN.CANSUPERMORPH + PainSound "chicken/pain"; + DeathSound "chicken/death"; + Player.JumpZ 1; + Player.Viewheight 21; + Player.ForwardMove 1.22, 1.22; + Player.SideMove 1.22, 1.22; + Player.SpawnClass "Chicken"; + Player.SoundClass "Chicken"; + Player.DisplayName "Chicken"; + Player.MorphWeapon "Beak"; + -PICKUP + } + + States + { + Spawn: + CHKN A -1; + Stop; + See: + CHKN ABAB 3; + Loop; + Melee: + Missile: + CHKN C 12; + Goto Spawn; + Pain: + CHKN D 4 A_Feathers; + CHKN C 4 A_Pain; + Goto Spawn; + Death: + CHKN E 6 A_Scream; + CHKN F 6 A_Feathers; + CHKN G 6; + CHKN H 6 A_NoBlocking; + CHKN IJK 6; + CHKN L -1; + Stop; + } +} + + + +// Chicken (non-player) ----------------------------------------------------- + +class Chicken : MorphedMonster +{ + Default + { + Health 10; + Radius 9; + Height 22; + Mass 40; + Speed 4; + Painchance 200; + Monster; + -COUNTKILL + +WINDTHRUST + +DONTMORPH + +FLOORCLIP + SeeSound "chicken/pain"; + AttackSound "chicken/attack"; + PainSound "chicken/pain"; + DeathSound "chicken/death"; + ActiveSound "chicken/active"; + Obituary "$OB_CHICKEN"; + } + States + { + Spawn: + CHKN AB 10 A_Look; + Loop; + See: + CHKN AB 3 A_Chase; + Loop; + Pain: + CHKN D 5 A_Feathers; + CHKN C 5 A_Pain; + Goto See; + Melee: + CHKN A 8 A_FaceTarget; + CHKN C 10 A_CustomMeleeAttack(random[ChicAttack](1,2)); + Goto See; + Death: + CHKN E 6 A_Scream; + CHKN F 6 A_Feathers; + CHKN G 6; + CHKN H 6 A_NoBlocking; + CHKN IJK 6; + CHKN L -1; + Stop; + } +} + + +// Feather ------------------------------------------------------------------ + +class Feather : Actor +{ + Default + { + Radius 2; + Height 4; + +MISSILE +DROPOFF + +NOTELEPORT +CANNOTPUSH + +WINDTHRUST +DONTSPLASH + Gravity 0.125; + } + + States + { + Spawn: + CHKN MNOPQPON 3; + Loop; + Death: + CHKN N 6; + Stop; + } +} + diff --git a/wadsrc/static/zscript/heretic/clink.txt b/wadsrc/static/zscript/heretic/clink.txt new file mode 100644 index 000000000..7549ff097 --- /dev/null +++ b/wadsrc/static/zscript/heretic/clink.txt @@ -0,0 +1,48 @@ +class Clink : Actor +{ + Default + { + Health 150; + Radius 20; + Height 64; + Mass 75; + Speed 14; + Painchance 32; + Monster; + +NOBLOOD + +FLOORCLIP + SeeSound "clink/sight"; + AttackSound "clink/attack"; + PainSound "clink/pain"; + DeathSound "clink/death"; + ActiveSound "clink/active"; + Obituary "$OB_CLINK"; + DropItem "SkullRodAmmo", 84, 20; + } + States + { + Spawn: + CLNK AB 10 A_Look; + Loop; + See: + CLNK ABCD 3 A_Chase; + Loop; + Melee: + CLNK E 5 A_FaceTarget; + CLNK F 4 A_FaceTarget; + CLNK G 7 A_CustomMeleeAttack(random[ClinkAttack](3,9), "clink/attack", "clink/attack"); + Goto See; + Pain: + CLNK H 3; + CLNK H 3 A_Pain; + Goto See; + Death: + CLNK IJ 6; + CLNK K 5 A_Scream; + CLNK L 5 A_NoBlocking; + CLNK MN 5; + CLNK O -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/heretic/dsparil.txt b/wadsrc/static/zscript/heretic/dsparil.txt new file mode 100644 index 000000000..8cd60c8bb --- /dev/null +++ b/wadsrc/static/zscript/heretic/dsparil.txt @@ -0,0 +1,297 @@ + +// Boss spot ---------------------------------------------------------------- + +class BossSpot : SpecialSpot +{ + Default + { + +INVISIBLE + } +} + +// Sorcerer (D'Sparil on his serpent) --------------------------------------- + +class Sorcerer1 : Actor +{ + Default + { + Health 2000; + Radius 28; + Height 100; + Mass 800; + Speed 16; + PainChance 56; + Monster; + +BOSS + +DONTMORPH + +NORADIUSDMG + +NOTARGET + +NOICEDEATH + +FLOORCLIP + +DONTGIB + SeeSound "dsparilserpent/sight"; + AttackSound "dsparilserpent/attack"; + PainSound "dsparilserpent/pain"; + DeathSound "dsparilserpent/death"; + ActiveSound "dsparilserpent/active"; + Obituary "$OB_DSPARIL1"; + HitObituary "$OB_DSPARIL1HIT"; + } + + native void A_Sor1Pain (); + native void A_Sor1Chase (); + native void A_Srcr1Attack (); + native void A_SorcererRise (); + + States + { + Spawn: + SRCR AB 10 A_Look; + Loop; + See: + SRCR ABCD 5 A_Sor1Chase; + Loop; + Pain: + SRCR Q 6 A_Sor1Pain; + Goto See; + Missile: + SRCR Q 7 A_FaceTarget; + SRCR R 6 A_FaceTarget; + SRCR S 10 A_Srcr1Attack; + Goto See; + Missile2: + SRCR S 10 A_FaceTarget; + SRCR Q 7 A_FaceTarget; + SRCR R 6 A_FaceTarget; + SRCR S 10 A_Srcr1Attack; + Goto See; + Death: + SRCR E 7; + SRCR F 7 A_Scream; + SRCR G 7; + SRCR HIJK 6; + SRCR L 25 A_PlaySound("dsparil/zap", CHAN_BODY, 1, false, ATTN_NONE); + SRCR MN 5; + SRCR O 4; + SRCR L 20 A_PlaySound("dsparil/zap", CHAN_BODY, 1, false, ATTN_NONE); + SRCR MN 5; + SRCR O 4; + SRCR L 12; + SRCR P -1 A_SorcererRise; + } +} + + +// Sorcerer FX 1 ------------------------------------------------------------ + +class SorcererFX1 : Actor +{ + Default + { + Radius 10; + Height 10; + Speed 20; + FastSpeed 28; + Damage 10; + DamageType "Fire"; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + RenderStyle "Add"; + } + + States + { + Spawn: + FX14 ABC 6 BRIGHT; + Loop; + Death: + FX14 DEFGH 5 BRIGHT; + Stop; + } +} + + +// Sorcerer 2 (D'Sparil without his serpent) -------------------------------- + +class Sorcerer2 : Actor +{ + Default + { + Health 3500; + Radius 16; + Height 70; + Mass 300; + Speed 14; + Painchance 32; + Monster; + +DROPOFF + +BOSS + +DONTMORPH + +FULLVOLACTIVE + +NORADIUSDMG + +NOTARGET + +NOICEDEATH + +FLOORCLIP + +BOSSDEATH + SeeSound "dsparil/sight"; + AttackSound "dsparil/attack"; + PainSound "dsparil/pain"; + ActiveSound "dsparil/active"; + Obituary "$OB_DSPARIL2"; + HitObituary "$OB_DSPARIL2HIT"; + } + + native void A_Srcr2Decide (); + native void A_Srcr2Attack (); + native void A_Sor2DthInit (); + native void A_Sor2DthLoop (); + + States + { + Spawn: + SOR2 MN 10 A_Look; + Loop; + See: + SOR2 MNOP 4 A_Chase; + Loop; + Rise: + SOR2 AB 4; + SOR2 C 4 A_PlaySound("dsparil/rise", CHAN_BODY, 1, false, ATTN_NONE); + SOR2 DEF 4; + SOR2 G 12 A_PlaySound("dsparil/sight", CHAN_BODY, 1, false, ATTN_NONE); + Goto See; + Pain: + SOR2 Q 3; + SOR2 Q 6 A_Pain; + Goto See; + Missile: + SOR2 R 9 A_Srcr2Decide; + SOR2 S 9 A_FaceTarget; + SOR2 T 20 A_Srcr2Attack; + Goto See; + Teleport: + SOR2 LKJIHG 6; + Goto See; + Death: + SDTH A 8 A_Sor2DthInit; + SDTH B 8; + SDTH C 8 A_PlaySound("dsparil/scream", CHAN_BODY, 1, false, ATTN_NONE); + DeathLoop: + SDTH DE 7; + SDTH F 7 A_Sor2DthLoop; + SDTH G 6 A_PlaySound("dsparil/explode", CHAN_BODY, 1, false, ATTN_NONE); + SDTH H 6; + SDTH I 18; + SDTH J 6 A_NoBlocking; + SDTH K 6 A_PlaySound("dsparil/bones", CHAN_BODY, 1, false, ATTN_NONE); + SDTH LMN 6; + SDTH O -1 A_BossDeath; + Stop; + } +} + + + +// Sorcerer 2 FX 1 ---------------------------------------------------------- + +class Sorcerer2FX1 : Actor +{ + Default + { + Radius 10; + Height 6; + Speed 20; + FastSpeed 28; + Damage 1; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + RenderStyle "Add"; + } + + native void A_BlueSpark (); + + States + { + Spawn: + FX16 ABC 3 BRIGHT A_BlueSpark; + Loop; + Death: + FX16 G 5 BRIGHT A_Explode(random[S2FX1](80,111)); + FX16 HIJKL 5 BRIGHT; + Stop; + } +} + +// Sorcerer 2 FX Spark ------------------------------------------------------ + +class Sorcerer2FXSpark : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + +NOGRAVITY + +NOTELEPORT + +CANNOTPUSH + RenderStyle "Add"; + } + + States + { + Spawn: + FX16 DEF 12 BRIGHT; + Stop; + } +} + +// Sorcerer 2 FX 2 ---------------------------------------------------------- + +class Sorcerer2FX2 : Actor +{ + Default + { + Radius 10; + Height 6; + Speed 6; + Damage 10; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + RenderStyle "Add"; + } + + native void A_GenWizard (); + + States + { + Spawn: + FX11 A 35 BRIGHT; + FX11 A 5 BRIGHT A_GenWizard; + FX11 B 5 BRIGHT; + Goto Spawn+1; + Death: + FX11 CDEFG 5 BRIGHT; + Stop; + + } +} +// Sorcerer 2 Telefade ------------------------------------------------------ + +class Sorcerer2Telefade : Actor +{ + Default + { + +NOBLOCKMAP + } + + States + { + Spawn: + SOR2 GHIJKL 6; + Stop; + } +} + diff --git a/wadsrc/static/zscript/heretic/hereticammo.txt b/wadsrc/static/zscript/heretic/hereticammo.txt new file mode 100644 index 000000000..cf1e50a3d --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticammo.txt @@ -0,0 +1,243 @@ + +// Wimpy ammo --------------------------------------------------------------- + +Class GoldWandAmmo : Ammo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOGOLDWAND1"; + Inventory.Amount 10; + Inventory.MaxAmount 100; + Ammo.BackpackAmount 10; + Ammo.BackpackMaxAmount 200; + Inventory.Icon "INAMGLD"; + } + States + { + Spawn: + AMG1 A -1; + Stop; + } +} + +// Hefty ammo --------------------------------------------------------------- + +Class GoldWandHefty : GoldWandAmmo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOGOLDWAND2"; + Inventory.Amount 50; + } + States + { + Spawn: + AMG2 ABC 4; + Loop; + } +} +// Wimpy ammo --------------------------------------------------------------- + +Class CrossbowAmmo : Ammo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOCROSSBOW1"; + Inventory.Amount 5; + Inventory.MaxAmount 50; + Ammo.BackpackAmount 5; + Ammo.BackpackMaxAmount 100; + Inventory.Icon "INAMBOW"; + } + States + { + Spawn: + AMC1 A -1; + Stop; + } +} + +// Hefty ammo --------------------------------------------------------------- + +Class CrossbowHefty : CrossbowAmmo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOCROSSBOW2"; + Inventory.Amount 20; + } + States + { + Spawn: + AMC2 ABC 5; + Loop; + } +} +// Wimpy ammo --------------------------------------------------------------- + +Class MaceAmmo : Ammo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOMACE1"; + Inventory.Amount 20; + Inventory.MaxAmount 150; + Ammo.BackpackAmount 20; + Ammo.BackpackMaxAmount 300; + Inventory.Icon "INAMLOB"; + } + States + { + Spawn: + AMM1 A -1; + Stop; + } +} + +// Hefty ammo --------------------------------------------------------------- + +Class MaceHefty : MaceAmmo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOMACE2"; + Inventory.Amount 100; + } + States + { + Spawn: + AMM2 A -1; + Stop; + } +} + +// Wimpy ammo --------------------------------------------------------------- + +Class BlasterAmmo : Ammo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOBLASTER1"; + Inventory.Amount 10; + Inventory.MaxAmount 200; + Ammo.BackpackAmount 10; + Ammo.BackpackMaxAmount 400; + Inventory.Icon "INAMBST"; + } + States + { + Spawn: + AMB1 ABC 4; + Loop; + } +} + +// Hefty ammo --------------------------------------------------------------- + +Class BlasterHefty : BlasterAmmo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOBLASTER2"; + Inventory.Amount 25; + } + States + { + Spawn: + AMB2 ABC 4; + Loop; + } +} + +// Wimpy ammo --------------------------------------------------------------- + +Class SkullRodAmmo : Ammo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOSKULLROD1"; + Inventory.Amount 20; + Inventory.MaxAmount 200; + Ammo.BackpackAmount 20; + Ammo.BackpackMaxAmount 400; + Inventory.Icon "INAMRAM"; + } + States + { + Spawn: + AMS1 AB 5; + Loop; + } +} + +// Hefty ammo --------------------------------------------------------------- + +Class SkullRodHefty : SkullRodAmmo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOSKULLROD2"; + Inventory.Amount 100; + } + States + { + Spawn: + AMS2 AB 5; + Loop; + } +} + +// Wimpy ammo --------------------------------------------------------------- + +Class PhoenixRodAmmo : Ammo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOPHOENIXROD1"; + Inventory.Amount 1; + Inventory.MaxAmount 20; + Ammo.BackpackAmount 1; + Ammo.BackpackMaxAmount 40; + Inventory.Icon "INAMPNX"; + } + States + { + Spawn: + AMP1 ABC 4; + Loop; + } +} +// Hefty ammo --------------------------------------------------------------- + +Class PhoenixRodHefty : PhoenixRodAmmo +{ + Default + { + Inventory.PickupMessage "$TXT_AMMOPHOENIXROD2"; + Inventory.Amount 10; + } + States + { + Spawn: + AMP2 ABC 4; + Loop; + } +} + +// --- Bag of holding ------------------------------------------------------- + +Class BagOfHolding : BackpackItem +{ + Default + { + Inventory.PickupMessage "$TXT_ITEMBAGOFHOLDING"; + +COUNTITEM + +FLOATBOB + } + States + { + Spawn: + BAGH A -1; + Stop; + } +} diff --git a/wadsrc/static/zscript/heretic/hereticarmor.txt b/wadsrc/static/zscript/heretic/hereticarmor.txt new file mode 100644 index 000000000..8cbcb9fbc --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticarmor.txt @@ -0,0 +1,41 @@ + +// Silver Shield (Shield1) -------------------------------------------------- + +Class SilverShield : BasicArmorPickup +{ + Default + { + +FLOATBOB + Inventory.Pickupmessage "$TXT_ITEMSHIELD1"; + Inventory.Icon "SHLDA0"; + Armor.Savepercent 50; + Armor.Saveamount 100; + } + States + { + Spawn: + SHLD A -1; + stop; + } +} + +// Enchanted shield (Shield2) ----------------------------------------------- + +Class EnchantedShield : BasicArmorPickup +{ + Default + { + +FLOATBOB + Inventory.Pickupmessage "$TXT_ITEMSHIELD2"; + Inventory.Icon "SHD2A0"; + Armor.Savepercent 75; + Armor.Saveamount 200; + } + States + { + Spawn: + SHD2 A -1; + stop; + } +} + diff --git a/wadsrc/static/zscript/heretic/hereticartifacts.txt b/wadsrc/static/zscript/heretic/hereticartifacts.txt new file mode 100644 index 000000000..e239748ff --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticartifacts.txt @@ -0,0 +1,118 @@ +// Super map ---------------------------------------------------------------- + +Class SuperMap : MapRevealer +{ + Default + { + +COUNTITEM + +INVENTORY.ALWAYSPICKUP + +FLOATBOB + Inventory.MaxAmount 0; + Inventory.PickupMessage "$TXT_ITEMSUPERMAP"; + } + States + { + Spawn: + SPMP A -1; + Stop; + } +} + + +// Invisibility ------------------------------------------------------------- + +Class ArtiInvisibility : PowerupGiver +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + RenderStyle "Translucent"; + Alpha 0.4; + Inventory.RespawnTics 4230; + Inventory.Icon "ARTIINVS"; + Powerup.Type "PowerGhost"; + Inventory.PickupMessage "$TXT_ARTIINVISIBILITY"; + Tag "$TAG_ARTIINVISIBILITY"; + } + States + { + Spawn: + INVS A 350 Bright; + Loop; + } +} + + +// Tome of power ------------------------------------------------------------ + +Class ArtiTomeOfPower : PowerupGiver native +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + Inventory.Icon "ARTIPWBK"; + Powerup.Type "PowerWeaponlevel2"; + Inventory.PickupMessage "$TXT_ARTITOMEOFPOWER"; + Tag "$TAG_ARTITOMEOFPOWER"; + } + States + { + Spawn: + PWBK A 350; + Loop; + } +} + + +// Time bomb ---------------------------------------------------------------- + +Class ActivatedTimeBomb : Actor +{ + Default + { + +NOGRAVITY + RenderStyle "Translucent"; + Alpha 0.4; + DeathSound "misc/timebomb"; + } + + native void A_Timebomb(); + + States + { + Spawn: + FBMB ABCD 10; + FBMB E 6 A_Scream; + XPL1 A 4 BRIGHT A_Timebomb; + XPL1 BCDEF 4 BRIGHT; + Stop; + } +} + + +Class ArtiTimeBomb : Inventory native +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.INVBAR + +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTIFBMB"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIFIREBOMB"; + Tag "$TAG_ARTIFIREBOMB"; + Inventory.DefMaxAmount; + } + States + { + Spawn: + FBMB E 350; + Loop; + } +} diff --git a/wadsrc/static/zscript/heretic/hereticdecorations.txt b/wadsrc/static/zscript/heretic/hereticdecorations.txt new file mode 100644 index 000000000..d38f47a39 --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticdecorations.txt @@ -0,0 +1,302 @@ +Class SkullHang70 : Actor +{ + Default + { + Radius 20; + Height 70; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + SKH1 A -1; + Stop; + } +} + +Class SkullHang60 : Actor +{ + Default + { + Radius 20; + Height 60; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + SKH2 A -1; + Stop; + } +} + +Class SkullHang45 : Actor +{ + Default + { + Radius 20; + Height 45; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + SKH3 A -1; + Stop; + } +} + +Class SkullHang35 : Actor +{ + Default + { + Radius 20; + Height 35; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + SKH4 A -1; + Stop; + } +} + +Class Chandelier : Actor +{ + Default + { + Radius 20; + Height 60; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + CHDL ABC 4; + Loop; + } +} + +Class SerpentTorch : Actor +{ + Default + { + Radius 12; + Height 54; + +SOLID + } + States + { + Spawn: + SRTC ABC 4; + Loop; + } +} + +Class SmallPillar : Actor +{ + Default + { + Radius 16; + Height 34; + +SOLID + } + States + { + Spawn: + SMPL A -1; + Stop; + } +} + +Class StalagmiteSmall : Actor +{ + Default + { + Radius 8; + Height 32; + +SOLID + } + States + { + Spawn: + STGS A -1; + Stop; + } +} + +Class StalagmiteLarge : Actor +{ + Default + { + Radius 12; + Height 64; + +SOLID + } + States + { + Spawn: + STGL A -1; + Stop; + } +} + +Class StalactiteSmall : Actor +{ + Default + { + Radius 8; + Height 36; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + STCS A -1; + Stop; + } +} + +Class StalactiteLarge : Actor +{ + Default + { + Radius 12; + Height 68; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + STCL A -1; + Stop; + } +} + +Class FireBrazier : Actor +{ + Default + { + Radius 16; + Height 44; + +SOLID + } + States + { + Spawn: + KFR1 ABCDEFGH 3 Bright; + Loop; + } +} + +Class Barrel : Actor +{ + Default + { + Radius 12; + Height 32; + +SOLID + } + States + { + Spawn: + BARL A -1; + Stop; + } +} + +Class BrownPillar : Actor +{ + Default + { + Radius 14; + Height 128; + +SOLID + } + States + { + Spawn: + BRPL A -1; + Stop; + } +} + +Class Moss1 : Actor +{ + Default + { + Radius 20; + Height 23; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + MOS1 A -1; + Stop; + } +} + +Class Moss2 : Actor +{ + Default + { + Radius 20; + Height 27; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + MOS2 A -1; + Stop; + } +} + +Class WallTorch : Actor +{ + Default + { + Radius 6; + Height 16; + +NOGRAVITY + +FIXMAPTHINGPOS + } + States + { + Spawn: + WTRH ABC 6 Bright; + Loop; + } +} + +Class HangingCorpse : Actor +{ + Default + { + Radius 8; + Height 104; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + HCOR A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/heretic/hereticimp.txt b/wadsrc/static/zscript/heretic/hereticimp.txt new file mode 100644 index 000000000..c1443de03 --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticimp.txt @@ -0,0 +1,238 @@ + +// Heretic imp (as opposed to the Doom variety) ----------------------------- + +class HereticImp : Actor +{ + bool extremecrash; + + Default + { + Health 40; + Radius 16; + Height 36; + Mass 50; + Speed 10; + Painchance 200; + Monster; + +FLOAT + +NOGRAVITY + +SPAWNFLOAT + +DONTOVERLAP + +MISSILEMORE + SeeSound "himp/sight"; + AttackSound "himp/attack"; + PainSound "himp/pain"; + DeathSound "himp/death"; + ActiveSound "himp/active"; + Obituary "$OB_HERETICIMP"; + HitObituary "$OB_HERETICIMPHIT"; + } + + States + { + Spawn: + IMPX ABCB 10 A_Look; + Loop; + See: + IMPX AABBCCBB 3 A_Chase; + Loop; + Melee: + IMPX DE 6 A_FaceTarget; + IMPX F 6 A_CustomMeleeAttack(random[ImpMeAttack](5,12), "himp/attack", "himp/attack"); + Goto See; + Missile: + IMPX A 10 A_FaceTarget; + IMPX B 6 A_ImpMsAttack; + IMPX CBAB 6; + Goto Missile+2; + Pain: + IMPX G 3; + IMPX G 3 A_Pain; + Goto See; + Death: + IMPX G 4 A_ImpDeath; + IMPX H 5; + Wait; + XDeath: + IMPX S 5 A_ImpXDeath1; + IMPX TU 5; + IMPX V 5 A_Gravity; + IMPX W 5; + Wait; + Crash: + IMPX I 7 A_ImpExplode; + IMPX J 7 A_Scream; + IMPX K 7; + IMPX L -1; + Stop; + XCrash: + IMPX X 7; + IMPX Y 7; + IMPX Z -1; + Stop; + } + + + //---------------------------------------------------------------------------- + // + // PROC A_ImpMsAttack + // + //---------------------------------------------------------------------------- + + void A_ImpMsAttack() + { + if (!target || random[ImpMSAtk]() > 64) + { + SetState (SeeState); + return; + } + A_SkullAttack(12); +} + + //---------------------------------------------------------------------------- + // + // PROC A_ImpExplode + // + //---------------------------------------------------------------------------- + + void A_ImpExplode() + { + Actor chunk; + + bNoGravity = false; + + chunk = Spawn("HereticImpChunk1", pos, ALLOW_REPLACE); + chunk.vel.x = random2[ImpExplode]() / 64.; + chunk.vel.y = random2[ImpExplode]() / 64.; + chunk.vel.z = 9; + + chunk = Spawn("HereticImpChunk2", pos, ALLOW_REPLACE); + chunk.vel.x = random2[ImpExplode]() / 64.; + chunk.vel.y = random2[ImpExplode]() / 64.; + chunk.vel.z = 9; + + if (extremecrash) + { + SetStateLabel ("XCrash"); + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_ImpDeath + // + //---------------------------------------------------------------------------- + + void A_ImpDeath() + { + bSolid = false; + bFloorClip = true; + } + + //---------------------------------------------------------------------------- + // + // PROC A_ImpXDeath1 + // + //---------------------------------------------------------------------------- + + void A_ImpXDeath1() + { + bSolid = false; + bFloorClip = true; + bNoGravity = true; + extremecrash = true; + } +} + +// Heretic imp leader ------------------------------------------------------- + +class HereticImpLeader : HereticImp +{ + Default + { + Species "HereticImpLeader"; + Health 80; + -MISSILEMORE + AttackSound "himp/leaderattack"; + } + States + { + Melee: + Stop; + Missile: + IMPX DE 6 A_FaceTarget; + IMPX F 6 A_CustomComboAttack("HereticImpBall", 32, random[ImpMsAttack2](5,12), "himp/leaderattack"); + Goto See; + } +} + +// Heretic imp chunk 1 ------------------------------------------------------ + +class HereticImpChunk1 : Actor +{ + Default + { + Mass 5; + Radius 4; + +NOBLOCKMAP + +MOVEWITHSECTOR + } + States + { + Spawn: + IMPX M 5; + IMPX NO 700; + Stop; + } +} + +// Heretic imp chunk 2 ------------------------------------------------------ + +class HereticImpChunk2 : Actor +{ + Default + { + Mass 5; + Radius 4; + +NOBLOCKMAP + +MOVEWITHSECTOR + } + States + { + Spawn: + IMPX P 5; + IMPX QR 700; + Stop; + } +} + +// Heretic imp ball --------------------------------------------------------- + +class HereticImpBall : Actor +{ + Default + { + Radius 8; + Height 8; + Speed 10; + FastSpeed 20; + Damage 1; + Projectile; + SeeSound "himp/leaderattack"; + +SPAWNSOUNDSOURCE + -ACTIVATEPCROSS + -ACTIVATEIMPACT + RenderStyle "Add"; + } + States + { + Spawn: + FX10 ABC 6 Bright; + Loop; + Death: + FX10 DEFG 5 Bright; + Stop; + } +} + + diff --git a/wadsrc/static/zscript/heretic/heretickeys.txt b/wadsrc/static/zscript/heretic/heretickeys.txt new file mode 100644 index 000000000..d5532ce01 --- /dev/null +++ b/wadsrc/static/zscript/heretic/heretickeys.txt @@ -0,0 +1,174 @@ + +Class HereticKey : Key +{ + Default + { + +NOTDMATCH + Radius 20; + Height 16; + } +} + +// Green key ------------------------------------------------------------ + +Class KeyGreen : HereticKey +{ + Default + { + Inventory.PickupMessage "$TXT_GOTGREENKEY"; + Inventory.Icon "GKEYICON"; + } + States + { + Spawn: + AKYY ABCDEFGHIJ 3 Bright; + Loop; + } +} + +// Blue key ----------------------------------------------------------------- + +Class KeyBlue : HereticKey +{ + Default + { + Inventory.PickupMessage "$TXT_GOTBLUEKEY"; + Inventory.Icon "BKEYICON"; + } + States + { + Spawn: + BKYY ABCDEFGHIJ 3 Bright; + Loop; + } +} + +// Yellow key --------------------------------------------------------------- + +Class KeyYellow : HereticKey +{ + Default + { + Inventory.PickupMessage "$TXT_GOTYELLOWKEY"; + Inventory.Icon "YKEYICON"; + } + States + { + Spawn: + CKYY ABCDEFGHI 3 Bright; + Loop; + } +} + + +// --- Blue Key gizmo ----------------------------------------------------------- + +Class KeyGizmoBlue : Actor +{ + Default + { + Radius 16; + Height 50; + +SOLID + } + States + { + Spawn: + KGZ1 A 1; + KGZ1 A 1 A_SpawnItemEx("KeyGizmoFloatBlue", 0, 0, 60); + KGZ1 A -1; + Stop; + } +} + +Class KeyGizmoFloatBlue : Actor +{ + Default + { + Radius 16; + Height 16; + +SOLID + +NOGRAVITY + } + States + { + Spawn: + KGZB A -1 Bright; + Stop; + } +} + +// --- Green Key gizmo ----------------------------------------------------------- + +Class KeyGizmoGreen : Actor +{ + Default + { + Radius 16; + Height 50; + +SOLID + } + States + { + Spawn: + KGZ1 A 1; + KGZ1 A 1 A_SpawnItemEx("KeyGizmoFloatGreen", 0, 0, 60); + KGZ1 A -1; + Stop; + } +} + +Class KeyGizmoFloatGreen : Actor +{ + Default + { + Radius 16; + Height 16; + +SOLID + +NOGRAVITY + } + States + { + Spawn: + KGZG A -1 Bright; + Stop; + } +} + +// --- Yellow Key gizmo ----------------------------------------------------------- + +Class KeyGizmoYellow : Actor +{ + Default + { + Radius 16; + Height 50; + +SOLID + } + States + { + Spawn: + KGZ1 A 1; + KGZ1 A 1 A_SpawnItemEx("KeyGizmoFloatYellow", 0, 0, 60); + KGZ1 A -1; + Stop; + } +} + +Class KeyGizmoFloatYellow : Actor +{ + Default + { + Radius 16; + Height 16; + +SOLID + +NOGRAVITY + } + States + { + Spawn: + KGZY A -1 Bright; + Stop; + } +} + diff --git a/wadsrc/static/zscript/heretic/hereticmisc.txt b/wadsrc/static/zscript/heretic/hereticmisc.txt new file mode 100644 index 000000000..f858a6fa2 --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticmisc.txt @@ -0,0 +1,255 @@ + +// Pod ---------------------------------------------------------------------- + +class Pod : Actor +{ + Default + { + Health 45; + Radius 16; + Height 54; + Painchance 255; + +SOLID +NOBLOOD +SHOOTABLE +DROPOFF + +WINDTHRUST +PUSHABLE +SLIDESONWALLS + +CANPASS +TELESTOMP +DONTMORPH + +NOBLOCKMONST +DONTGIB +OLDRADIUSDMG + DeathSound "world/podexplode"; + PushFactor 0.5; + } + native void A_PodPain (class podtype = "PodGoo"); + native void A_RemovePod (); + + States + { + Spawn: + PPOD A 10; + Loop; + Pain: + PPOD B 14 A_PodPain; + Goto Spawn; + Death: + PPOD C 5 BRIGHT A_RemovePod; + PPOD D 5 BRIGHT A_Scream; + PPOD E 5 BRIGHT A_Explode; + PPOD F 10 BRIGHT; + Stop; + Grow: + PPOD IJKLMNOP 3; + Goto Spawn; + } +} + + +// Pod goo (falls from pod when damaged) ------------------------------------ + +class PodGoo : Actor +{ + Default + { + Radius 2; + Height 4; + Gravity 0.125; + +NOBLOCKMAP +MISSILE +DROPOFF + +NOTELEPORT +CANNOTPUSH + } + States + { + Spawn: + PPOD GH 8; + Loop; + Death: + PPOD G 10; + Stop; + } +} + +// Pod generator ------------------------------------------------------------ + +class PodGenerator : Actor +{ + Default + { + +NOBLOCKMAP + +NOSECTOR + +DONTSPLASH + AttackSound "world/podgrow"; + } + + native void A_MakePod (class podtype = "Pod"); + + States + { + Spawn: + TNT1 A 35 A_MakePod; + Loop; + } +} + + +// Teleglitter generator 1 -------------------------------------------------- + +class TeleGlitterGenerator1 : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + +MOVEWITHSECTOR + } + States + { + Spawn: + TNT1 A 8 A_SpawnItemEx("TeleGlitter1", random[TeleGlitter](0,31)-16, random[TeleGlitter](0,31)-16, 0, 0,0,0.25); + Loop; + } +} + +// Teleglitter generator 2 -------------------------------------------------- + +class TeleGlitterGenerator2 : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + +MOVEWITHSECTOR + } + States + { + Spawn: + TNT1 A 8 A_SpawnItemEx("TeleGlitter2", random[TeleGlitter2](0,31)-16, random[TeleGlitter2](0,31)-16, 0, 0,0,0.25); + Loop; + } +} + + +// Teleglitter 1 ------------------------------------------------------------ + +class TeleGlitter1 : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY +MISSILE + RenderStyle "Add"; + Damage 0; + } + + native void A_AccTeleGlitter (); + + States + { + Spawn: + TGLT A 2 BRIGHT; + TGLT B 2 BRIGHT A_AccTeleGlitter; + TGLT C 2 BRIGHT; + TGLT D 2 BRIGHT A_AccTeleGlitter; + TGLT E 2 BRIGHT; + Loop; + } +} + +// Teleglitter 2 ------------------------------------------------------------ + +class TeleGlitter2 : TeleGlitter1 +{ + States + { + Spawn: + TGLT F 2 BRIGHT; + TGLT G 2 BRIGHT A_AccTeleGlitter; + TGLT H 2 BRIGHT; + TGLT I 2 BRIGHT A_AccTeleGlitter; + TGLT J 2 BRIGHT; + Loop; + } +} + + +// --- Volcano -------------------------------------------------------------- + +class Volcano : Actor +{ + Default + { + Radius 12; + Height 20; + +SOLID + } + + native void A_VolcanoSet (); + native void A_VolcanoBlast (); + + States + { + Spawn: + VLCO A 350; + VLCO A 35 A_VolcanoSet; + VLCO BCDBCD 3; + VLCO E 10 A_VolcanoBlast; + Goto Spawn+1; + } + +} + +// Volcano blast ------------------------------------------------------------ + +class VolcanoBlast : Actor +{ + Default + { + Radius 8; + Height 8; + Speed 2; + Damage 2; + DamageType "Fire"; + Gravity 0.125; + +NOBLOCKMAP +MISSILE +DROPOFF + +NOTELEPORT + DeathSound "world/volcano/blast"; + } + + native void A_VolcBallImpact (); + + States + { + Spawn: + VFBL AB 4 BRIGHT A_SpawnItemEx("Puffy", random2[BeastPuff]()*0.015625, random2[BeastPuff]()*0.015625, random2[BeastPuff]()*0.015625, + 0,0,0,0,SXF_ABSOLUTEPOSITION, 64); + Loop; + + Death: + XPL1 A 4 BRIGHT A_VolcBallImpact; + XPL1 BCDEF 4 BRIGHT; + Stop; + } +} + +// Volcano T Blast ---------------------------------------------------------- + +class VolcanoTBlast : Actor +{ + Default + { + Radius 8; + Height 6; + Speed 2; + Damage 1; + DamageType "Fire"; + Gravity 0.125; + +NOBLOCKMAP +MISSILE +DROPOFF + +NOTELEPORT + } + States + { + Spawn: + VTFB AB 4 BRIGHT; + Loop; + Death: + SFFI CBABCDE 4 BRIGHT; + Stop; + } +} + + diff --git a/wadsrc/static/zscript/heretic/hereticplayer.txt b/wadsrc/static/zscript/heretic/hereticplayer.txt new file mode 100644 index 000000000..26ff684f3 --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticplayer.txt @@ -0,0 +1,135 @@ +class HereticPlayer : PlayerPawn +{ + Default + { + Health 100; + Radius 16; + Height 56; + Mass 100; + Painchance 255; + Speed 1; + Player.DisplayName "Corvus"; + Player.StartItem "GoldWand"; + Player.StartItem "Staff"; + Player.StartItem "GoldWandAmmo", 50; + Player.WeaponSlot 1, "Staff", "Gauntlets"; + Player.WeaponSlot 2, "GoldWand"; + Player.WeaponSlot 3, "Crossbow"; + Player.WeaponSlot 4, "Blaster"; + Player.WeaponSlot 5, "SkullRod"; + Player.WeaponSlot 6, "PhoenixRod"; + Player.WeaponSlot 7, "Mace"; + + Player.ColorRange 225, 240; + Player.Colorset 0, "Green", 225, 240, 238; + Player.Colorset 1, "Yellow", 114, 129, 127; + Player.Colorset 2, "Red", 145, 160, 158; + Player.Colorset 3, "Blue", 190, 205, 203; + // Doom Legacy additions + Player.Colorset 4, "Brown", 67, 82, 80; + Player.Colorset 5, "Light Gray", 9, 24, 22; + Player.Colorset 6, "Light Brown", 74, 89, 87; + Player.Colorset 7, "Light Red", 150, 165, 163; + Player.Colorset 8, "Light Blue", 192, 207, 205; + Player.Colorset 9, "Beige", 95, 110, 108; + } + + States + { + Spawn: + PLAY A -1; + Stop; + See: + PLAY ABCD 4; + Loop; + Melee: + Missile: + PLAY F 6 BRIGHT; + PLAY E 12; + Goto Spawn; + Pain: + PLAY G 4; + PLAY G 4 A_Pain; + Goto Spawn; + Death: + PLAY H 6 A_PlayerSkinCheck("AltSkinDeath"); + PLAY I 6 A_PlayerScream; + PLAY JK 6; + PLAY L 6 A_NoBlocking; + PLAY MNO 6; + PLAY P -1; + Stop; + XDeath: + PLAY Q 0 A_PlayerSkinCheck("AltSkinXDeath"); + PLAY Q 5 A_PlayerScream; + PLAY R 0 A_NoBlocking; + PLAY R 5 A_SkullPop; + PLAY STUVWX 5; + PLAY Y -1; + Stop; + Burn: + FDTH A 5 BRIGHT A_PlaySound("*burndeath"); + FDTH B 4 BRIGHT; + FDTH C 5 BRIGHT; + FDTH D 4 BRIGHT A_PlayerScream; + FDTH E 5 BRIGHT; + FDTH F 4 BRIGHT; + FDTH G 5 BRIGHT A_PlaySound("*burndeath"); + FDTH H 4 BRIGHT; + FDTH I 5 BRIGHT; + FDTH J 4 BRIGHT; + FDTH K 5 BRIGHT; + FDTH L 4 BRIGHT; + FDTH M 5 BRIGHT; + FDTH N 4 BRIGHT; + FDTH O 5 BRIGHT A_NoBlocking; + FDTH P 4 BRIGHT; + FDTH Q 5 BRIGHT; + FDTH R 4 BRIGHT; + ACLO E 35 A_CheckPlayerDone; + Wait; + AltSkinDeath: + PLAY H 10; + PLAY I 10 A_PlayerScream; + PLAY J 10 A_NoBlocking; + PLAY KLM 10; + PLAY N -1; + Stop; + AltSkinXDeath: + PLAY O 5; + PLAY P 5 A_XScream; + PLAY Q 5 A_NoBlocking; + PLAY RSTUV 5; + PLAY W -1; + Stop; + } +} + +// The player's skull ------------------------------------------------------- + +class BloodySkull : PlayerChunk +{ + Default + { + Radius 4; + Height 4; + Gravity 0.125; + +NOBLOCKMAP + +DROPOFF + +CANNOTPUSH + +SKYEXPLODE + +NOBLOCKMONST + +NOSKIN + } + States + { + Spawn: + BSKL A 0; + BSKL ABCDE 5 A_CheckFloor("Hit"); + Goto Spawn+1; + Hit: + BSKL F 16 A_CheckPlayerDone; + Wait; + } +} + diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt new file mode 100644 index 000000000..4c254500b --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -0,0 +1,1286 @@ + +class HereticWeapon : Weapon +{ + Default + { + Weapon.Kickback 150; + } +} + + +// Staff -------------------------------------------------------------------- + +class Staff : HereticWeapon +{ + Default + { + Weapon.SelectionOrder 3800; + +THRUGHOST + +WEAPON.WIMPY_WEAPON + +WEAPON.MELEEWEAPON + Weapon.sisterweapon "StaffPowered"; + Obituary "$OB_MPSTAFF"; + Tag "$TAG_STAFF"; + } + + action native void A_StaffAttack (int damage, class puff); + + States + { + Ready: + STFF A 1 A_WeaponReady; + Loop; + Deselect: + STFF A 1 A_Lower; + Loop; + Select: + STFF A 1 A_Raise; + Loop; + Fire: + STFF B 6; + STFF C 8 A_StaffAttack(random[StaffAttack](5, 20), "StaffPuff"); + STFF B 8 A_ReFire; + Goto Ready; + } +} + +class StaffPowered : Staff +{ + Default + { + Weapon.sisterweapon "Staff"; + Weapon.ReadySound "weapons/staffcrackle"; + +WEAPON.POWERED_UP + +WEAPON.READYSNDHALF + +WEAPON.STAFF2_KICKBACK + Obituary "$OB_MPPSTAFF"; + Tag "$TAG_STAFFP"; + } + + States + { + Ready: + STFF DEF 4 A_WeaponReady; + Loop; + Deselect: + STFF D 1 A_Lower; + Loop; + Select: + STFF D 1 A_Raise; + Loop; + Fire: + STFF G 6; + STFF H 8 A_StaffAttack(random[StaffAttack](18, 81), "StaffPuff2"); + STFF G 8 A_ReFire; + Goto Ready; + } +} + + +// Staff puff --------------------------------------------------------------- + +class StaffPuff : Actor +{ + Default + { + RenderStyle "Translucent"; + Alpha 0.4; + VSpeed 1; + +NOBLOCKMAP + +NOGRAVITY + +PUFFONACTORS + AttackSound "weapons/staffhit"; + } + + States + { + Spawn: + PUF3 A 4 BRIGHT; + PUF3 BCD 4; + Stop; + } +} + +// Staff puff 2 ------------------------------------------------------------- + +class StaffPuff2 : Actor +{ + Default + { + RenderStyle "Add"; + +NOBLOCKMAP + +NOGRAVITY + +PUFFONACTORS + AttackSound "weapons/staffpowerhit"; + } + + States + { + Spawn: + PUF4 ABCDEF 4 BRIGHT; + Stop; + } +} + + + +// Gold wand ---------------------------------------------------------------- + +class GoldWand : HereticWeapon +{ + Default + { + +BLOODSPLATTER + Weapon.SelectionOrder 2000; + Weapon.AmmoGive 25; + Weapon.AmmoUse 1; + Weapon.AmmoType "GoldWandAmmo"; + Weapon.SisterWeapon "GoldWandPowered"; + Weapon.YAdjust 5; + Inventory.PickupMessage "$TXT_WPNGOLDWAND"; + Obituary "$OB_MPGOLDWAND"; + Tag "$TAG_GOLDWAND"; + } + + action native void A_FireGoldWandPL1 (); + + States + { + Spawn: + GWAN A -1; + Stop; + Ready: + GWND A 1 A_WeaponReady; + Loop; + Deselect: + GWND A 1 A_Lower; + Loop; + Select: + GWND A 1 A_Raise; + Loop; + Fire: + GWND B 3; + GWND C 5 A_FireGoldWandPL1; + GWND D 3; + GWND D 0 A_ReFire; + Goto Ready; + } +} + +class GoldWandPowered : GoldWand +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoGive 0; + Weapon.SisterWeapon "GoldWand"; + Obituary "$OB_MPPGOLDWAND"; + Tag "$TAG_GOLDWANDP"; + } + + action native void A_FireGoldWandPL2 (); + + States + { + Fire: + GWND B 3; + GWND C 4 A_FireGoldWandPL2; + GWND D 3; + GWND D 0 A_ReFire; + Goto Ready; + } +} + + +// Gold wand FX1 ------------------------------------------------------------ + +class GoldWandFX1 : Actor +{ + Default + { + Radius 10; + Height 6; + Speed 22; + Damage 2; + Projectile; + RenderStyle "Add"; + DeathSound "weapons/wandhit"; + Obituary "$OB_MPPGOLDWAND"; + } + + States + { + Spawn: + FX01 AB 6 BRIGHT; + Loop; + Death: + FX01 EFGH 3 BRIGHT; + Stop; + } +} + +// Gold wand FX2 ------------------------------------------------------------ + +class GoldWandFX2 : GoldWandFX1 +{ + Default + { + Speed 18; + Damage 1; + DeathSound ""; + } + + States + { + Spawn: + FX01 CD 6 BRIGHT; + Loop; + } +} + +// Gold wand puff 1 --------------------------------------------------------- + +class GoldWandPuff1 : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +PUFFONACTORS + RenderStyle "Add"; + } + + States + { + Spawn: + PUF2 ABCDE 3 BRIGHT; + Stop; + } +} + +// Gold wand puff 2 --------------------------------------------------------- + +class GoldWandPuff2 : GoldWandFX1 +{ + Default + { + Skip_Super; + +NOBLOCKMAP + +NOGRAVITY + +PUFFONACTORS + } + + States + { + Spawn: + Goto Super::Death; + } +} + + +// Crossbow ----------------------------------------------------------------- + +class Crossbow : HereticWeapon +{ + Default + { + Weapon.SelectionOrder 800; + Weapon.AmmoUse 1; + Weapon.AmmoGive 10; + Weapon.AmmoType "CrossbowAmmo"; + Weapon.SisterWeapon "CrossbowPowered"; + Weapon.YAdjust 15; + Inventory.PickupMessage "$TXT_WPNCROSSBOW"; + Tag "$TAG_CROSSBOW"; + } + + action native void A_FireCrossbowPL1 (); + + States + { + Spawn: + WBOW A -1; + Stop; + Ready: + CRBW AAAAAABBBBBBCCCCCC 1 A_WeaponReady; + Loop; + Deselect: + CRBW A 1 A_Lower; + Loop; + Select: + CRBW A 1 A_Raise; + Loop; + Fire: + CRBW D 6 A_FireCrossbowPL1; + CRBW EFGH 3; + CRBW AB 4; + CRBW C 5 A_ReFire; + Goto Ready; + } +} + + +class CrossbowPowered : Crossbow +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoGive 0; + Weapon.SisterWeapon "Crossbow"; + Tag "$TAG_CROSSBOWP"; + } + + action native void A_FireCrossbowPL2(); + + States + { + Fire: + CRBW D 5 A_FireCrossbowPL2; + CRBW E 3; + CRBW F 2; + CRBW G 3; + CRBW H 2; + CRBW A 3; + CRBW B 3; + CRBW C 4 A_ReFire; + Goto Ready; + } +} + + +// Crossbow FX1 ------------------------------------------------------------- + +class CrossbowFX1 : Actor +{ + Default + { + Radius 11; + Height 8; + Speed 30; + Damage 10; + Projectile; + RenderStyle "Add"; + SeeSound "weapons/bowshoot"; + DeathSound "weapons/bowhit"; + Obituary "$OB_MPCROSSBOW"; + } + + States + { + Spawn: + FX03 B 1 BRIGHT; + Loop; + Death: + FX03 HIJ 8 BRIGHT; + Stop; + } +} + + +// Crossbow FX2 ------------------------------------------------------------- + +class CrossbowFX2 : CrossbowFX1 +{ + Default + { + Speed 32; + Damage 6; + Obituary "$OB_MPPCROSSBOW"; + } + + States + { + Spawn: + FX03 B 1 BRIGHT A_SpawnItemEx("CrossbowFX4", random2[BoltSpark]()*0.015625, random2[BoltSpark]()*0.015625, 0, 0,0,0,0,SXF_ABSOLUTEPOSITION, 50); + Loop; + } +} + +// Crossbow FX3 ------------------------------------------------------------- + +class CrossbowFX3 : CrossbowFX1 +{ + Default + { + Speed 20; + Damage 2; + SeeSound ""; + -NOBLOCKMAP + +WINDTHRUST + +THRUGHOST + } + + States + { + Spawn: + FX03 A 1 BRIGHT; + Loop; + Death: + FX03 CDE 8 BRIGHT; + Stop; + } +} + +// Crossbow FX4 ------------------------------------------------------------- + +class CrossbowFX4 : Actor +{ + Default + { + +NOBLOCKMAP + Gravity 0.125; + RenderStyle "Add"; + } + + States + { + Spawn: + FX03 FG 8 BRIGHT; + Stop; + } +} + + + + +// Gauntlets ---------------------------------------------------------------- + +class Gauntlets : Weapon +{ + Default + { + +BLOODSPLATTER + Weapon.SelectionOrder 2300; + +WEAPON.WIMPY_WEAPON + +WEAPON.MELEEWEAPON + Weapon.Kickback 0; + Weapon.YAdjust 15; + Weapon.UpSound "weapons/gauntletsactivate"; + Weapon.SisterWeapon "GauntletsPowered"; + Inventory.PickupMessage "$TXT_WPNGAUNTLETS"; + Tag "$TAG_GAUNTLETS"; + Obituary "$OB_MPGAUNTLETS"; + } + + action native void A_GauntletAttack (int power); + + States + { + Spawn: + WGNT A -1; + Stop; + Ready: + GAUN A 1 A_WeaponReady; + Loop; + Deselect: + GAUN A 1 A_Lower; + Loop; + Select: + GAUN A 1 A_Raise; + Loop; + Fire: + GAUN B 4 A_PlaySound("weapons/gauntletsuse", CHAN_WEAPON); + GAUN C 4; + Hold: + GAUN DEF 4 BRIGHT A_GauntletAttack(0); + GAUN C 4 A_ReFire; + GAUN B 4 A_Light0; + Goto Ready; + } +} + + +class GauntletsPowered : Gauntlets +{ + Default + { + +WEAPON.POWERED_UP + Tag "$TAG_GAUNTLETSP"; + Obituary "$OB_MPPGAUNTLETS"; + Weapon.SisterWeapon "Gauntlets"; + } + + States + { + Ready: + GAUN GHI 4 A_WeaponReady; + Loop; + Deselect: + GAUN G 1 A_Lower; + Loop; + Select: + GAUN G 1 A_Raise; + Loop; + Fire: + GAUN J 4 A_PlaySound("weapons/gauntletsuse", CHAN_WEAPON); + GAUN K 4; + Hold: + GAUN LMN 4 BRIGHT A_GauntletAttack(1); + GAUN K 4 A_ReFire; + GAUN J 4 A_Light0; + Goto Ready; + } +} + + +// Gauntlet puff 1 ---------------------------------------------------------- + +class GauntletPuff1 : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +PUFFONACTORS + RenderStyle "Translucent"; + Alpha 0.4; + VSpeed 0.8; + } + + States + { + Spawn: + PUF1 ABCD 4 BRIGHT; + Stop; + } +} + +// Gauntlet puff 2 --------------------------------------------------------- + +class GauntletPuff2 : GauntletPuff1 +{ + States + { + Spawn: + PUF1 EFGH 4 BRIGHT; + Stop; + } +} + + +// The mace itself ---------------------------------------------------------- + +class Mace : HereticWeapon +{ + Default + { + Weapon.SelectionOrder 1400; + Weapon.AmmoUse 1; + Weapon.AmmoGive1 50; + Weapon.YAdjust 15; + Weapon.AmmoType "MaceAmmo"; + Weapon.SisterWeapon "MacePowered"; + Inventory.PickupMessage "$TXT_WPNMACE"; + Tag "$TAG_MACE"; + } + + action native void A_FireMacePL1(); + + States + { + Spawn: + WMCE A -1; + Stop; + Ready: + MACE A 1 A_WeaponReady; + Loop; + Deselect: + MACE A 1 A_Lower; + Loop; + Select: + MACE A 1 A_Raise; + Loop; + Fire: + MACE B 4; + Hold: + MACE CDEF 3 A_FireMacePL1; + MACE C 4 A_ReFire; + MACE DEFB 4; + Goto Ready; + } +} + +class MacePowered : Mace +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoUse 5; + Weapon.AmmoGive 0; + Weapon.SisterWeapon "Mace"; + Tag "$TAG_MACEP"; + } + + action native void A_FireMacePL2(); + + States + { + Fire: + Hold: + MACE B 4; + MACE D 4 A_FireMacePL2; + MACE B 4; + MACE A 8 A_ReFire; + Goto Ready; + } +} + +// Mace FX1 ----------------------------------------------------------------- + +class MaceFX1 : Actor +{ + Default + { + Radius 8; + Height 6; + Speed 20; + Damage 2; + Projectile; + +THRUGHOST + BounceType "HereticCompat"; + SeeSound "weapons/maceshoot"; + Obituary "$OB_MPMACE"; + } + + native void A_MacePL1Check(); + native void A_MaceBallImpact(); + + States + { + Spawn: + FX02 AB 4 A_MacePL1Check; + Loop; + Death: + FX02 F 4 BRIGHT A_MaceBallImpact; + FX02 GHIJ 4 BRIGHT; + Stop; + } +} + +// Mace FX2 ----------------------------------------------------------------- + +class MaceFX2 : MaceFX1 +{ + Default + { + Speed 10; + Damage 6; + Gravity 0.125; + -NOGRAVITY + SeeSound ""; + } + + native void A_MaceBallImpact2(); + + States + { + Spawn: + FX02 CD 4; + Loop; + Death: + FX02 F 4 A_MaceBallImpact2; + goto Super::Death+1; + } +} + +// Mace FX3 ----------------------------------------------------------------- + +class MaceFX3 : MaceFX1 +{ + Default + { + Speed 7; + Damage 4; + -NOGRAVITY; + Gravity 0.125; + } + + States + { + Spawn: + FX02 AB 4; + Loop; + } +} + + +// Mace FX4 ----------------------------------------------------------------- + +class MaceFX4 : Actor native +{ + Default + { + Radius 8; + Height 6; + Speed 7; + Damage 18; + Gravity 0.125; + Projectile; + -NOGRAVITY + +TELESTOMP + +THRUGHOST + -NOTELEPORT + BounceType "HereticCompat"; + SeeSound ""; + Obituary "$OB_MPPMACE"; + } + + native void A_DeathBallImpact(); + + States + { + Spawn: + FX02 E 99; + Loop; + Death: + FX02 C 4 A_DeathBallImpact; + FX02 GHIJ 4 BRIGHT; + Stop; + } +} + + +// Mace spawn spot ---------------------------------------------------------- + +class MaceSpawner : SpecialSpot +{ + Default + { + +NOSECTOR + +NOBLOCKMAP + } + + States + { + Spawn: + TNT1 A 1; + TNT1 A -1 A_SpawnSingleItem("Mace", 64, 64, 0); + Stop; + } +} + + +// Blaster ------------------------------------------------------------------ + +class Blaster : HereticWeapon +{ + Default + { + +BLOODSPLATTER + Weapon.SelectionOrder 500; + Weapon.AmmoUse 1; + Weapon.AmmoGive 30; + Weapon.YAdjust 15; + Weapon.AmmoType "BlasterAmmo"; + Weapon.SisterWeapon "BlasterPowered"; + Inventory.PickupMessage "$TXT_WPNBLASTER"; + Tag "$TAG_BLASTER"; + Obituary "$OB_MPBLASTER"; + } + + action native void A_FireBlasterPL1(); + + States + { + Spawn: + WBLS A -1; + Stop; + Ready: + BLSR A 1 A_WeaponReady; + Loop; + Deselect: + BLSR A 1 A_Lower; + Loop; + Select: + BLSR A 1 A_Raise; + Loop; + Fire: + BLSR BC 3; + Hold: + BLSR D 2 A_FireBlasterPL1; + BLSR CB 2; + BLSR A 0 A_ReFire; + Goto Ready; + } +} + +class BlasterPowered : Blaster +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoUse 5; + Weapon.AmmoGive 0; + Weapon.SisterWeapon "Blaster"; + Tag "$TAG_BLASTERP"; + } + + States + { + Fire: + BLSR BC 0; + Hold: + BLSR D 3 A_FireCustomMissile("BlasterFX1"); + BLSR CB 4; + BLSR A 0 A_ReFire; + Goto Ready; + } +} + +// Blaster FX 1 ------------------------------------------------------------- + +class BlasterFX1 : FastProjectile native +{ + Default + { + Radius 12; + Height 8; + Speed 184; + Damage 2; + SeeSound "weapons/blastershoot"; + DeathSound "weapons/blasterhit"; + +SPAWNSOUNDSOURCE + Obituary "$OB_MPPBLASTER"; + } + + native void A_SpawnRippers(); + + States + { + Spawn: + ACLO E 200; + Loop; + Death: + FX18 A 3 BRIGHT A_SpawnRippers; + FX18 B 3 BRIGHT; + FX18 CDEFG 4 BRIGHT; + Stop; + } +} + +// Blaster smoke ------------------------------------------------------------ + +class BlasterSmoke : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +NOTELEPORT + +CANNOTPUSH + RenderStyle "Translucent"; + Alpha 0.4; + } + + States + { + Spawn: + FX18 HIJKL 4; + Stop; + } +} + +// Ripper ------------------------------------------------------------------- + +class Ripper : Actor native +{ + Default + { + Radius 8; + Height 6; + Speed 14; + Damage 1; + Projectile; + +RIPPER + DeathSound "weapons/blasterpowhit"; + Obituary "$OB_MPPBLASTER"; + } + + States + { + Spawn: + FX18 M 4; + FX18 N 5; + Loop; + Death: + FX18 OPQRS 4 BRIGHT; + Stop; + } +} + +// Blaster Puff ------------------------------------------------------------- + +class BlasterPuff : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +PUFFONACTORS + RenderStyle "Add"; + SeeSound "weapons/blasterhit"; + } + + States + { + Crash: + FX17 ABCDE 4 BRIGHT; + Stop; + Spawn: + FX17 FG 3 BRIGHT; + FX17 HIJKL 4 BRIGHT; + Stop; + } +} + + +// Skull (Horn) Rod --------------------------------------------------------- + +class SkullRod : HereticWeapon +{ + Default + { + Weapon.SelectionOrder 200; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 50; + Weapon.YAdjust 15; + Weapon.AmmoType1 "SkullRodAmmo"; + Weapon.SisterWeapon "SkullRodPowered"; + Inventory.PickupMessage "$TXT_WPNSKULLROD"; + Tag "$TAG_SKULLROD"; + } + + action native void A_FireSkullRodPL1(); + + States + { + Spawn: + WSKL A -1; + Stop; + Ready: + HROD A 1 A_WeaponReady; + Loop; + Deselect: + HROD A 1 A_Lower; + Loop; + Select: + HROD A 1 A_Raise; + Loop; + Fire: + HROD AB 4 A_FireSkullRodPL1; + HROD B 0 A_ReFire; + Goto Ready; + } +} + +class SkullRodPowered : SkullRod +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoUse1 5; + Weapon.AmmoGive1 0; + Weapon.SisterWeapon "SkullRod"; + Tag "$TAG_SKULLRODP"; + } + + action native void A_FireSkullRodPL2(); + + States + { + Fire: + HROD C 2; + HROD D 3; + HROD E 2; + HROD F 3; + HROD G 4 A_FireSkullRodPL2; + HROD F 2; + HROD E 3; + HROD D 2; + HROD C 2 A_ReFire; + Goto Ready; + } +} + +// Horn Rod FX 1 ------------------------------------------------------------ + +class HornRodFX1 : Actor +{ + Default + { + Radius 12; + Height 8; + Speed 22; + Damage 3; + Projectile; + +WINDTHRUST + -NOBLOCKMAP + RenderStyle "Add"; + SeeSound "weapons/hornrodshoot"; + DeathSound "weapons/hornrodhit"; + Obituary "$OB_MPSKULLROD"; + } + + States + { + Spawn: + FX00 AB 6 BRIGHT; + Loop; + Death: + FX00 HI 5 BRIGHT; + FX00 JK 4 BRIGHT; + FX00 LM 3 BRIGHT; + Stop; + } +} + + +// Horn Rod FX 2 ------------------------------------------------------------ + +class HornRodFX2 : Actor native +{ + Default + { + Radius 12; + Height 8; + Speed 22; + Damage 10; + Health 140; + Projectile; + RenderStyle "Add"; + SeeSound "weapons/hornrodpowshoot"; + DeathSound "weapons/hornrodpowhit"; + Obituary "$OB_MPPSKULLROD"; + } + + native void A_AddPlayerRain(); + native void A_HideInCeiling(); + native void A_SkullRodStorm(); + + States + { + Spawn: + FX00 C 3 BRIGHT; + FX00 D 3 BRIGHT A_SeekerMissile(10, 30); + FX00 E 3 BRIGHT; + FX00 F 3 BRIGHT A_SeekerMissile(10, 30); + Loop; + Death: + FX00 H 5 BRIGHT A_AddPlayerRain; + FX00 I 5 BRIGHT; + FX00 J 4 BRIGHT; + FX00 KLM 3 BRIGHT; + FX00 G 1 A_HideInCeiling; + FX00 G 1 A_SkullRodStorm; + Wait; + } +} + +// Rain pillar 1 ------------------------------------------------------------ + +class RainPillar : Actor native +{ + Default + { + Radius 5; + Height 12; + Speed 12; + Damage 5; + Mass 5; + Projectile; + -ACTIVATEPCROSS + -ACTIVATEIMPACT + RenderStyle "Add"; + Obituary "$OB_MPPSKULLROD"; + } + + native void A_RainImpact(); + + States + { + Spawn: + FX22 A -1 BRIGHT; + Stop; + Death: + FX22 B 4 BRIGHT A_RainImpact; + FX22 CDEF 4 BRIGHT; + Stop; + NotFloor: + FX22 GHI 4 BRIGHT; + Stop; + } +} + +// Rain tracker "inventory" item -------------------------------------------- + +class RainTracker : Inventory native +{ + Default + { + +INVENTORY.UNDROPPABLE + } +} + + +// Phoenix Rod -------------------------------------------------------------- + +class PhoenixRod : Weapon native +{ + Default + { + +WEAPON.NOAUTOFIRE + Weapon.SelectionOrder 2600; + Weapon.Kickback 150; + Weapon.YAdjust 15; + Weapon.AmmoUse 1; + Weapon.AmmoGive 2; + Weapon.AmmoType "PhoenixRodAmmo"; + Weapon.Sisterweapon "PhoenixRodPowered"; + Inventory.PickupMessage "$TXT_WPNPHOENIXROD"; + Tag "$TAG_PHOENIXROD"; + } + + action native void A_FirePhoenixPL1(); + + States + { + Spawn: + WPHX A -1; + Stop; + Ready: + PHNX A 1 A_WeaponReady; + Loop; + Deselect: + PHNX A 1 A_Lower; + Loop; + Select: + PHNX A 1 A_Raise; + Loop; + Fire: + PHNX B 5; + PHNX C 7 A_FirePhoenixPL1; + PHNX DB 4; + PHNX B 0 A_ReFire; + Goto Ready; + } +} + +class PhoenixRodPowered : PhoenixRod native +{ + Default + { + +WEAPON.POWERED_UP + +WEAPON.MELEEWEAPON + Weapon.SisterWeapon "PhoenixRod"; + Weapon.AmmoGive 0; + Tag "$TAG_PHOENIXRODP"; + } + + action native void A_InitPhoenixPL2(); + action native void A_FirePhoenixPL2(); + action native void A_ShutdownPhoenixPL2(); + + States + { + Fire: + PHNX B 3 A_InitPhoenixPL2; + Hold: + PHNX C 1 A_FirePhoenixPL2; + PHNX B 4 A_ReFire; + Powerdown: + PHNX B 4 A_ShutdownPhoenixPL2; + Goto Ready; + } +} + +// Phoenix FX 1 ------------------------------------------------------------- + +class PhoenixFX1 : Actor native +{ + Default + { + Radius 11; + Height 8; + Speed 20; + Damage 20; + DamageType "Fire"; + Projectile; + +THRUGHOST + +SPECIALFIREDAMAGE + SeeSound "weapons/phoenixshoot"; + DeathSound "weapons/phoenixhit"; + Obituary "$OB_MPPHOENIXROD"; + } + + native void A_PhoenixPuff(); + + States + { + Spawn: + FX04 A 4 BRIGHT A_PhoenixPuff; + Loop; + Death: + FX08 A 6 BRIGHT A_Explode; + FX08 BC 5 BRIGHT; + FX08 DEFGH 4 BRIGHT; + Stop; + } +} + +// Phoenix puff ------------------------------------------------------------- + +class PhoenixPuff : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +NOTELEPORT + +CANNOTPUSH + RenderStyle "Translucent"; + Alpha 0.4; + } + + States + { + Spawn: + FX04 BCDEF 4; + Stop; + } +} + +// Phoenix FX 2 ------------------------------------------------------------- + +class PhoenixFX2 : Actor native +{ + Default + { + Radius 6; + Height 8; + Speed 10; + Damage 2; + DamageType "Fire"; + Projectile; + RenderStyle "Add"; + Obituary "$OB_MPPPHOENIXROD"; + } + + native void A_FlameEnd(); + native void A_FloatPuff(); + + States + { + Spawn: + FX09 ABABA 2 BRIGHT; + FX09 B 2 BRIGHT A_FlameEnd; + FX09 CDEF 2 BRIGHT; + Stop; + Death: + FX09 G 3 BRIGHT; + FX09 H 3 BRIGHT A_FloatPuff; + FX09 I 4 BRIGHT; + FX09 JK 5 BRIGHT; + Stop; + } +} + diff --git a/wadsrc/static/zscript/heretic/ironlich.txt b/wadsrc/static/zscript/heretic/ironlich.txt new file mode 100644 index 000000000..e6ba05e05 --- /dev/null +++ b/wadsrc/static/zscript/heretic/ironlich.txt @@ -0,0 +1,191 @@ + +// Ironlich ----------------------------------------------------------------- + +class Ironlich : Actor +{ + Default + { + Health 700; + Radius 40; + Height 72; + Mass 325; + Speed 6; + Painchance 32; + Monster; + +NOBLOOD + +DONTMORPH + +DONTSQUASH + +BOSSDEATH + SeeSound "ironlich/sight"; + AttackSound "ironlich/attack"; + PainSound "ironlich/pain"; + DeathSound "ironlich/death"; + ActiveSound "ironlich/active"; + Obituary "$OB_IRONLICH"; + HitObituary "$OB_IRONLICHHIT"; + DropItem "BlasterAmmo", 84, 10; + DropItem "ArtiEgg", 51, 0; + } + + native void A_LichAttack (); + + States + { + Spawn: + LICH A 10 A_Look; + Loop; + See: + LICH A 4 A_Chase; + Loop; + Missile: + LICH A 5 A_FaceTarget; + LICH B 20 A_LichAttack; + Goto See; + Pain: + LICH A 4; + LICH A 4 A_Pain; + Goto See; + Death: + LICH C 7; + LICH D 7 A_Scream; + LICH EF 7; + LICH G 7 A_NoBlocking; + LICH H 7; + LICH I -1 A_BossDeath; + Stop; + } +} + +// Head FX 1 ---------------------------------------------------------------- + +class HeadFX1 : Actor +{ + Default + { + Radius 12; + Height 6; + Speed 13; + FastSpeed 20; + Damage 1; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + +THRUGHOST + RenderStyle "Add"; + } + + native void A_LichIceImpact(); + + States + { + Spawn: + FX05 ABC 6 BRIGHT; + Loop; + Death: + FX05 D 5 BRIGHT A_LichIceImpact; + FX05 EFG 5 BRIGHT; + Stop; + } +} + +// Head FX 2 ---------------------------------------------------------------- + +class HeadFX2 : Actor +{ + Default + { + Radius 12; + Height 6; + Speed 8; + Damage 3; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + RenderStyle "Add"; + } + + States + { + Spawn: + FX05 HIJ 6 BRIGHT; + Loop; + Death: + FX05 DEFG 5 BRIGHT; + Stop; + } +} + + +// Head FX 3 ---------------------------------------------------------------- + +class HeadFX3 : Actor +{ + Default + { + Radius 14; + Height 12; + Speed 10; + FastSpeed 18; + Damage 5; + Projectile; + +WINDTHRUST + -ACTIVATEIMPACT + -ACTIVATEPCROSS + -NOBLOCKMAP + RenderStyle "Add"; + } + + native void A_LichFireGrow (); + + States + { + Spawn: + FX06 ABC 4 BRIGHT A_LichFireGrow; + Loop; + NoGrow: + FX06 ABC 5 BRIGHT; + Loop; + Death: + FX06 DEFG 5 BRIGHT; + Stop; + } +} + + +// Whirlwind ---------------------------------------------------------------- + +class Whirlwind : Actor native +{ + Default + { + Radius 16; + Height 74; + Speed 10; + Damage 1; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEMCROSS + +SEEKERMISSILE + +EXPLOCOUNT + +StepMissile + RenderStyle "Translucent"; + DefThreshold 60; + Threshold 50; + Alpha 0.4; + } + + native void A_WhirlwindSeek(); + + States + { + Spawn: + FX07 DEFG 3; + FX07 ABC 3 A_WhirlwindSeek; + Goto Spawn+4; + Death: + FX07 GFED 4; + Stop; + } +} + + diff --git a/wadsrc/static/zscript/heretic/knight.txt b/wadsrc/static/zscript/heretic/knight.txt new file mode 100644 index 000000000..01b7252c6 --- /dev/null +++ b/wadsrc/static/zscript/heretic/knight.txt @@ -0,0 +1,170 @@ + +// Knight ------------------------------------------------------------------- + +class Knight : Actor +{ + Default + { + Health 200; + Radius 24; + Height 78; + Mass 150; + Speed 12; + Painchance 100; + Monster; + +FLOORCLIP + SeeSound "hknight/sight"; + AttackSound "hknight/attack"; + PainSound "hknight/pain"; + DeathSound "hknight/death"; + ActiveSound "hknight/active"; + Obituary "$OB_BONEKNIGHT"; + HitObituary "$OB_BONEKNIGHTHIT"; + DropItem "CrossbowAmmo", 84, 5; + } + + States + { + Spawn: + KNIG AB 10 A_Look; + Loop; + See: + KNIG ABCD 4 A_Chase; + Loop; + Melee: + Missile: + KNIG E 10 A_FaceTarget; + KNIG F 8 A_FaceTarget; + KNIG G 8 A_KnightAttack; + KNIG E 10 A_FaceTarget; + KNIG F 8 A_FaceTarget; + KNIG G 8 A_KnightAttack; + Goto See; + Pain: + KNIG H 3; + KNIG H 3 A_Pain; + Goto See; + Death: + KNIG I 6; + KNIG J 6 A_Scream; + KNIG K 6; + KNIG L 6 A_NoBlocking; + KNIG MN 6; + KNIG O -1; + Stop; + } + + //---------------------------------------------------------------------------- + // + // PROC A_KnightAttack + // + //---------------------------------------------------------------------------- + + void A_KnightAttack () + { + if (!target) return; + if (CheckMeleeRange ()) + { + int damage = random[KnightAttack](1, 8) * 3; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + A_PlaySound ("hknight/melee", CHAN_BODY); + return; + } + // Throw axe + A_PlaySound (AttackSound, CHAN_BODY); + if (self.bShadow || random[KnightAttack]() < 40) + { // Red axe + SpawnMissileZ (pos.Z + 36, target, "RedAxe"); + } + else + { // Green axe + SpawnMissileZ (pos.Z + 36, target, "KnightAxe"); + } + } +} + + +// Knight ghost ------------------------------------------------------------- + +class KnightGhost : Knight +{ + Default + { + +SHADOW + +GHOST + RenderStyle "Translucent"; + Alpha 0.4; + } +} + +// Knight axe --------------------------------------------------------------- + +class KnightAxe : Actor +{ + Default + { + Radius 10; + Height 8; + Speed 9; + FastSpeed 18; + Damage 2; + Projectile; + -NOBLOCKMAP + -ACTIVATEIMPACT + -ACTIVATEPCROSS + +WINDTHRUST + +THRUGHOST + DeathSound "hknight/hit"; + } + + States + { + Spawn: + SPAX A 3 BRIGHT A_PlaySound("hknight/axewhoosh"); + SPAX BC 3 BRIGHT; + Loop; + Death: + SPAX DEF 6 BRIGHT; + Stop; + } +} + + +// Red axe ------------------------------------------------------------------ + +class RedAxe : KnightAxe +{ + Default + { + +NOBLOCKMAP + -WINDTHRUST + Damage 7; + } + + States + { + Spawn: + RAXE AB 5 BRIGHT A_DripBlood; + Loop; + Death: + RAXE CDE 6 BRIGHT; + Stop; + } + + //---------------------------------------------------------------------------- + // + // PROC A_DripBlood + // + //---------------------------------------------------------------------------- + + void A_DripBlood () + { + double xo = random2[DripBlood]() / 32.0; + double yo = random2[DripBlood]() / 32.0; + Actor mo = Spawn ("Blood", Vec3Offset(xo, yo, 0.), ALLOW_REPLACE); + mo.Vel.X = random2[DripBlood]() / 64.0; + mo.Vel.Y = random2[DripBlood]() / 64.0; + mo.Gravity = 1./8; + } +} diff --git a/wadsrc/static/zscript/heretic/mummy.txt b/wadsrc/static/zscript/heretic/mummy.txt new file mode 100644 index 000000000..6d01fcea4 --- /dev/null +++ b/wadsrc/static/zscript/heretic/mummy.txt @@ -0,0 +1,151 @@ + +// Mummy -------------------------------------------------------------------- + +class Mummy : Actor +{ + Default + { + Health 80; + Radius 22; + Height 62; + Mass 75; + Speed 12; + Painchance 128; + Monster; + +FLOORCLIP + SeeSound "mummy/sight"; + AttackSound "mummy/attack1"; + PainSound "mummy/pain"; + DeathSound "mummy/death"; + ActiveSound "mummy/active"; + HitObituary "$OB_MUMMY"; + DropItem "GoldWandAmmo", 84, 3; + } + States + { + Spawn: + MUMM AB 10 A_Look; + Loop; + See: + MUMM ABCD 4 A_Chase; + Loop; + Melee: + MUMM E 6 A_FaceTarget; + MUMM F 6 A_CustomMeleeAttack(random[MummyAttack](1,8)*2, "mummy/attack2", "mummy/attack"); + MUMM G 6; + Goto See; + Pain: + MUMM H 4; + MUMM H 4 A_Pain; + Goto See; + Death: + MUMM I 5; + MUMM J 5 A_Scream; + MUMM K 5 A_SpawnItemEx("MummySoul", 0,0,10, 0,0,1); + MUMM L 5; + MUMM M 5 A_NoBlocking; + MUMM NO 5; + MUMM P -1; + Stop; + } +} + +// Mummy leader ------------------------------------------------------------- + +class MummyLeader : Mummy +{ + Default + { + Species "MummyLeader"; + Health 100; + Painchance 64; + Obituary "$OB_MUMMYLEADER"; + } + States + { + Missile: + MUMM X 5 A_FaceTarget; + MUMM Y 5 Bright A_FaceTarget; + MUMM X 5 A_FaceTarget; + MUMM Y 5 Bright A_FaceTarget; + MUMM X 5 A_FaceTarget; + MUMM Y 5 Bright A_CustomComboAttack("MummyFX1", 32, random[MummyAttack2](1,8)*2, "mummy/attack2"); + Goto See; + } +} + +// Mummy ghost -------------------------------------------------------------- + +class MummyGhost : Mummy +{ + Default + { + +SHADOW + +GHOST + RenderStyle "Translucent"; + Alpha 0.4; + } +} + +// Mummy leader ghost ------------------------------------------------------- + +class MummyLeaderGhost : MummyLeader +{ + Default + { + Species "MummyLeaderGhost"; + +SHADOW + +GHOST + RenderStyle "Translucent"; + Alpha 0.4; + } +} + +// Mummy soul --------------------------------------------------------------- + +class MummySoul : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + } + States + { + Spawn: + MUMM QRS 5; + MUMM TUVW 9; + Stop; + } +} + +// Mummy FX 1 (flying head) ------------------------------------------------- + +class MummyFX1 : Actor +{ + Default + { + Radius 8; + Height 14; + Speed 9; + FastSpeed 18; + Damage 4; + RenderStyle "Add"; + Projectile; + -ACTIVATEPCROSS + -ACTIVATEIMPACT + +SEEKERMISSILE + } + States + { + Spawn: + FX15 A 5 Bright A_PlaySound("mummy/head"); + FX15 B 5 Bright A_SeekerMissile(10,20); + FX15 C 5 Bright; + FX15 B 5 Bright A_SeekerMissile(10,20); + Loop; + Death: + FX15 DEFG 5 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/heretic/snake.txt b/wadsrc/static/zscript/heretic/snake.txt new file mode 100644 index 000000000..613559a86 --- /dev/null +++ b/wadsrc/static/zscript/heretic/snake.txt @@ -0,0 +1,104 @@ + +class Snake : Actor +{ + Default + { + Health 280; + Radius 22; + Height 70; + Speed 10; + Painchance 48; + Monster; + +FLOORCLIP + AttackSound "snake/attack"; + SeeSound "snake/sight"; + PainSound "snake/pain"; + DeathSound "snake/death"; + ActiveSound "snake/active"; + Obituary "$OB_SNAKE"; + DropItem "PhoenixRodAmmo", 84, 5; + } + States + { + Spawn: + SNKE AB 10 A_Look; + Loop; + See: + SNKE ABCD 4 A_Chase; + Loop; + Missile: + SNKE FF 5 A_FaceTarget; + SNKE FFF 4 A_CustomMissile("SnakeProjA", 32, 0, 0, CMF_CHECKTARGETDEAD); + SNKE FFF 5 A_FaceTarget; + SNKE F 4 A_CustomMissile("SnakeProjB", 32, 0, 0, CMF_CHECKTARGETDEAD); + Goto See; + Pain: + SNKE E 3; + SNKE E 3 A_Pain; + Goto See; + Death: + SNKE G 5; + SNKE H 5 A_Scream; + SNKE IJKL 5; + SNKE M 5 A_NoBlocking; + SNKE NO 5; + SNKE P -1; + Stop; + } +} + +// Snake projectile A ------------------------------------------------------- + +class SnakeProjA : Actor +{ + Default + { + Radius 12; + Height 8; + Speed 14; + FastSpeed 20; + Damage 1; + Projectile; + -NOBLOCKMAP + -ACTIVATEIMPACT + -ACTIVATEPCROSS + +WINDTHRUST + +SPAWNSOUNDSOURCE + RenderStyle "Add"; + SeeSound "snake/attack"; + } + States + { + Spawn: + SNFX ABCD 5 Bright; + Loop; + Death: + SNFX EF 5 Bright; + SNFX G 4 Bright; + SNFX HI 3 Bright; + Stop; + } +} + +// Snake projectile B ------------------------------------------------------- + +class SnakeProjB : SnakeProjA +{ + Default + { + Damage 3; + +NOBLOCKMAP + -WINDTHRUST + } + States + { + Spawn: + SNFX JK 6 Bright; + Loop; + Death: + SNFX LM 5 Bright; + SNFX N 4 Bright; + SNFX O 3 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/heretic/wizard.txt b/wadsrc/static/zscript/heretic/wizard.txt new file mode 100644 index 000000000..d146ae220 --- /dev/null +++ b/wadsrc/static/zscript/heretic/wizard.txt @@ -0,0 +1,162 @@ + +// Wizard -------------------------------------------------------- + +class Wizard : Actor +{ + Default + { + Health 180; + Radius 16; + Height 68; + Mass 100; + Speed 12; + Painchance 64; + Monster; + +FLOAT + +NOGRAVITY + +DONTOVERLAP + SeeSound "wizard/sight"; + AttackSound "wizard/attack"; + PainSound "wizard/pain"; + DeathSound "wizard/death"; + ActiveSound "wizard/active"; + Obituary "$OB_WIZARD"; + HitObituary "$OB_WIZARDHIT"; + DropItem "BlasterAmmo", 84, 10; + DropItem "ArtiTomeOfPower", 4, 0; + } + + States + { + Spawn: + WZRD AB 10 A_Look; + Loop; + See: + WZRD A 3 A_Chase; + WZRD A 4 A_Chase; + WZRD A 3 A_Chase; + WZRD A 4 A_Chase; + WZRD B 3 A_Chase; + WZRD B 4 A_Chase; + WZRD B 3 A_Chase; + WZRD B 4 A_Chase; + Loop; + Missile: + WZRD C 4 A_WizAtk1; + WZRD C 4 A_WizAtk2; + WZRD C 4 A_WizAtk1; + WZRD C 4 A_WizAtk2; + WZRD C 4 A_WizAtk1; + WZRD C 4 A_WizAtk2; + WZRD C 4 A_WizAtk1; + WZRD C 4 A_WizAtk2; + WZRD D 12 A_WizAtk3; + Goto See; + Pain: + WZRD E 3 A_GhostOff; + WZRD E 3 A_Pain; + Goto See; + Death: + WZRD F 6 A_GhostOff; + WZRD G 6 A_Scream; + WZRD HI 6; + WZRD J 6 A_NoBlocking; + WZRD KL 6; + WZRD M -1 A_SetFloorClip; + Stop; + } + + //---------------------------------------------------------------------------- + // + // PROC A_GhostOff + // + //---------------------------------------------------------------------------- + + void A_GhostOff () + { + A_SetRenderStyle(1.0, STYLE_Normal); + bGhost = false; + } + + //---------------------------------------------------------------------------- + // + // PROC A_WizAtk1 + // + //---------------------------------------------------------------------------- + + void A_WizAtk1 () + { + A_FaceTarget (); + A_GhostOff(); + } + + //---------------------------------------------------------------------------- + // + // PROC A_WizAtk2 + // + //---------------------------------------------------------------------------- + + void A_WizAtk2 () + { + A_FaceTarget (); + A_SetRenderStyle(HR_SHADOW, STYLE_Translucent); + bGhost = true; + } + + //---------------------------------------------------------------------------- + // + // PROC A_WizAtk3 + // + //---------------------------------------------------------------------------- + + void A_WizAtk3 () + { + A_GhostOff(); + if (!target) return; + A_PlaySound (AttackSound, CHAN_WEAPON); + if (CheckMeleeRange()) + { + int damage = random[WizAtk3](1, 8) * 4; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + return; + } + Actor mo = SpawnMissile (target, "WizardFX1"); + if (mo != null) + { + SpawnMissileAngle("WizardFX1", mo.Angle - 45. / 8, mo.Vel.Z); + SpawnMissileAngle("WizardFX1", mo.Angle + 45. / 8, mo.Vel.Z); + } + } + +} + +// Projectile -------------------------------------------------------- + +class WizardFX1 : Actor +{ + Default + { + Radius 10; + Height 6; + Speed 18; + FastSpeed 24; + Damage 3; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + RenderStyle "Add"; + } + + States + { + Spawn: + FX11 AB 6 BRIGHT; + Loop; + Death: + FX11 CDEFG 5 BRIGHT; + Stop; + } +} + + diff --git a/wadsrc/static/zscript/hexen/baseweapons.txt b/wadsrc/static/zscript/hexen/baseweapons.txt new file mode 100644 index 000000000..eb685a873 --- /dev/null +++ b/wadsrc/static/zscript/hexen/baseweapons.txt @@ -0,0 +1,29 @@ +// The Doom and Heretic players are not excluded from pickup in case +// somebody wants to use these weapons with either of those games. + +class FighterWeapon : Weapon native +{ + Default + { + Weapon.Kickback 150; + Inventory.ForbiddenTo "ClericPlayer", "MagePlayer"; + } +} + +class ClericWeapon : Weapon native +{ + Default + { + Weapon.Kickback 150; + Inventory.ForbiddenTo "FighterPlayer", "MagePlayer"; + } +} + +class MageWeapon : Weapon native +{ + Default + { + Weapon.Kickback 150; + Inventory.ForbiddenTo "FighterPlayer", "ClericPlayer"; + } +} diff --git a/wadsrc/static/zscript/hexen/bats.txt b/wadsrc/static/zscript/hexen/bats.txt new file mode 100644 index 000000000..aaefaaeb7 --- /dev/null +++ b/wadsrc/static/zscript/hexen/bats.txt @@ -0,0 +1,125 @@ + +// Bat Spawner -------------------------------------------------------------- + +class BatSpawner : SwitchableDecoration +{ + Default + { + +NOBLOCKMAP +NOSECTOR +NOGRAVITY + RenderStyle "None"; + } + + States + { + Spawn: + Active: + TNT1 A 2; + TNT1 A 2 A_BatSpawnInit; + TNT1 A 2 A_BatSpawn; + Wait; + Inactive: + TNT1 A -1; + Stop; + } + + //=========================================================================== + // Bat Spawner Variables + // special1 frequency counter + // special2 + // args[0] frequency of spawn (1=fastest, 10=slowest) + // args[1] spread angle (0..255) + // args[2] + // args[3] duration of bats (in octics) + // args[4] turn amount per move (in degrees) + // + // Bat Variables + // special2 lifetime counter + // args[4] turn amount per move (in degrees) + //=========================================================================== + + void A_BatSpawnInit() + { + special1 = 0; // Frequency count + } + + void A_BatSpawn() + { + // Countdown until next spawn + if (special1-- > 0) return; + special1 = args[0]; // Reset frequency count + + int delta = args[1]; + if (delta == 0) delta = 1; + + double ang = Angle + (((random[BatSpawn]() % delta) - (delta >> 1)) * (360 / 256.)); + + Actor mo = SpawnMissileAngle ("Bat", ang, 0); + if (mo) + { + mo.args[0] = random[BatSpawn]() & 63; // floatbob index + mo.args[4] = args[4]; // turn degrees + mo.special2 = args[3] << 3; // Set lifetime + mo.target = self; + } + } + +} + +// Bat ---------------------------------------------------------------------- + +class Bat : Actor +{ + Default + { + Speed 5; + Radius 3; + Height 3; + +NOBLOCKMAP +NOGRAVITY +MISSILE + +NOTELEPORT +CANPASS + } + + States + { + Spawn: + ABAT ABC 2 A_BatMove; + Loop; + Death: + ABAT A 2; + Stop; + } + + void A_BatMove() + { + if (special2 < 0) + { + SetStateLabel ("Death"); + } + special2 -= 2; // Called every 2 tics + + double newangle; + if (random[BatMove]() < 128) + { + newangle = Angle + args[4]; + } + else + { + newangle = Angle - args[4]; + } + + // Adjust velocity vector to new direction + VelFromAngle(Speed, newangle); + + if (random[BatMove]() < 15) + { + A_PlaySound ("BatScream", CHAN_VOICE, 1, false, ATTN_IDLE); + } + + // Handle Z movement + SetZ(target.pos.Z + 2 * BobSin(args[0])); + args[0] = (args[0] + 3) & 63; + } +} + + + + diff --git a/wadsrc/static/zscript/hexen/bishop.txt b/wadsrc/static/zscript/hexen/bishop.txt new file mode 100644 index 000000000..32f0f3e63 --- /dev/null +++ b/wadsrc/static/zscript/hexen/bishop.txt @@ -0,0 +1,328 @@ + +// Bishop ------------------------------------------------------------------- + +class Bishop : Actor +{ + int missilecount; + int bobstate; + + Default + { + Health 130; + Radius 22; + Height 65; + Speed 10; + PainChance 110; + Monster; + +FLOAT +NOGRAVITY +NOBLOOD + +TELESTOMP + +DONTOVERLAP + +NOTARGETSWITCH + SeeSound "BishopSight"; + AttackSound "BishopAttack"; + PainSound "BishopPain"; + DeathSound "BishopDeath"; + ActiveSound "BishopActiveSounds"; + Obituary"$OB_BISHOP"; + } + + States + { + Spawn: + BISH A 10 A_Look; + Loop; + See: + BISH A 2 A_Chase; + BISH A 2 A_BishopChase; + BISH A 2; + BISH B 2 A_BishopChase; + BISH B 2 A_Chase; + BISH B 2 A_BishopChase; + BISH A 1 A_BishopDecide; + Loop; + Blur: + BISH A 2 A_BishopDoBlur; + BISH A 4 A_BishopSpawnBlur; + Wait; + Pain: + BISH C 6 A_Pain; + BISH CCC 6 A_BishopPainBlur; + BISH C 0; + Goto See; + Missile: + BISH A 3 A_FaceTarget; + BISH DE 3 A_FaceTarget; + BISH F 3 A_BishopAttack; + BISH F 5 A_BishopAttack2; + Wait; + Death: + BISH G 6; + BISH H 6 Bright A_Scream; + BISH I 5 Bright A_NoBlocking; + BISH J 5 BRIGHT A_Explode(random[BishopBoom](25,40)); + BISH K 5 Bright; + BISH LM 4 Bright; + BISH N 4 A_SpawnItemEx("BishopPuff", 0,0,40, 0,0,-0.5); + BISH O 4 A_QueueCorpse; + BISH P -1; + Stop; + Ice: + BISH X 5 A_FreezeDeath; + BISH X 1 A_FreezeDeathChunks; + Wait; + } + + + + //============================================================================ + // + // A_BishopAttack + // + //============================================================================ + + void A_BishopAttack() + { + if (!target) + { + return; + } + A_PlaySound (AttackSound, CHAN_BODY); + if (CheckMeleeRange()) + { + int damage = random[BishopAttack](1, 8) * 4; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + return; + } + missilecount = (random[BishopAttack]() & 3) + 5; + } + + //============================================================================ + // + // A_BishopAttack2 + // + // Spawns one of a string of bishop missiles + //============================================================================ + + void A_BishopAttack2() + { + if (!target || !missilecount) + { + missilecount = 0; + SetState (SeeState); + return; + } + Actor mo = SpawnMissile (target, "BishopFX"); + if (mo != null) + { + mo.tracer = target; + } + missilecount--; + return; + } + + //============================================================================ + // + // A_BishopDecide + // + //============================================================================ + + void A_BishopDecide() + { + if (random[BishopDecide]() >= 220) + { + SetStateLabel ("Blur"); + } + } + + //============================================================================ + // + // A_BishopDoBlur + // + //============================================================================ + + void A_BishopDoBlur() + { + missilecount = (random[BishopDoBlur]() & 3) + 3; // Random number of blurs + if (random[BishopDoBlur]() < 120) + { + Thrust(11, Angle + 90); + } + else if (random[BishopDoBlur]() > 125) + { + Thrust(11, Angle - 90); + } + else + { // Thrust forward + Thrust(11); + } + A_PlaySound ("BishopBlur", CHAN_BODY); + } + + //============================================================================ + // + // A_BishopSpawnBlur + // + //============================================================================ + + void A_BishopSpawnBlur() + { + if (!--missilecount) + { + Vel.XY = (0,0);// = Vel.Y = 0; + if (random[BishopSpawnBlur]() > 96) + { + SetState (SeeState); + } + else + { + SetState (MissileState); + } + } + Actor mo = Spawn ("BishopBlur", Pos, ALLOW_REPLACE); + if (mo) + { + mo.angle = angle; + } + } + + //============================================================================ + // + // A_BishopChase + // + //============================================================================ + + void A_BishopChase() + { + double newz = pos.z - BobSin(bobstate) / 2.; + bobstate = (bobstate + 4) & 63; + newz += BobSin(bobstate) / 2.; + SetZ(newz); + } + + //============================================================================ + // + // A_BishopPainBlur + // + //============================================================================ + + void A_BishopPainBlur() + { + if (random[BishopPainBlur]() < 64) + { + SetStateLabel ("Blur"); + return; + } + double xo = random2[BishopPainBlur]() / 16.; + double yo = random2[BishopPainBlue]() / 16.; + double zo = random2[BishopPainBlue]() / 32.; + Actor mo = Spawn ("BishopPainBlur", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + if (mo) + { + mo.angle = angle; + } + } + +} + +extend class Actor +{ + //============================================================================ + // + // A_BishopMissileWeave (this function must be in Actor) + // + //============================================================================ + + void A_BishopMissileWeave() + { + A_Weave(2, 2, 2., 1.); + } +} + +// Bishop puff -------------------------------------------------------------- + +class BishopPuff : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + RenderStyle "Translucent"; + Alpha 0.6; + } + States + { + Spawn: + BISH QRST 5; + BISH UV 6; + BISH W 5; + Stop; + } +} + +// Bishop pain blur --------------------------------------------------------- + +class BishopPainBlur : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + RenderStyle "Translucent"; + Alpha 0.6; + } + States + { + Spawn: + BISH C 8; + Stop; + } +} + +// Bishop FX ---------------------------------------------------------------- + +class BishopFX : Actor +{ + Default + { + Radius 10; + Height 6; + Speed 10; + Damage 1; + Projectile; + +SEEKERMISSILE + -ACTIVATEIMPACT -ACTIVATEPCROSS + +STRIFEDAMAGE + RenderStyle "Add"; + DeathSound "BishopMissileExplode"; + } + States + { + Spawn: + BPFX ABAB 1 Bright A_BishopMissileWeave; + BPFX B 0 Bright A_SeekerMissile(2,3); + Loop; + Death: + BPFX CDEF 4 Bright; + BPFX GH 3 Bright; + Stop; + } +} + +// Bishop blur -------------------------------------------------------------- + +class BishopBlur : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + RenderStyle "Translucent"; + Alpha 0.6; + } + States + { + Spawn: + BISH A 16; + BISH A 8 A_SetTranslucent(0.4); + Stop; + } +} + diff --git a/wadsrc/static/zscript/hexen/blastradius.txt b/wadsrc/static/zscript/hexen/blastradius.txt new file mode 100644 index 000000000..17ac75dc3 --- /dev/null +++ b/wadsrc/static/zscript/hexen/blastradius.txt @@ -0,0 +1,42 @@ + +class ArtiBlastRadius : CustomInventory +{ + Default + { + +FLOATBOB + Inventory.DefMaxAmount; + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.INVBAR +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTIBLST"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIBLASTRADIUS"; + Tag "$TAG_ARTIBLASTRADIUS"; + } + States + { + Spawn: + BLST ABCDEFGH 4 Bright; + Loop; + Use: + TNT1 A 0 A_Blast; + } +} + +// Blast Effect ------------------------------------------------------------- + +class BlastEffect : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY +NOCLIP + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.666; + } + States + { + Spawn: + RADE ABCDEFGHI 4; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/boostarmor.txt b/wadsrc/static/zscript/hexen/boostarmor.txt new file mode 100644 index 000000000..4c14b69bc --- /dev/null +++ b/wadsrc/static/zscript/hexen/boostarmor.txt @@ -0,0 +1,24 @@ + +// Boost Armor Artifact (Dragonskin Bracers) -------------------------------- + +class ArtiBoostArmor : Inventory native +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.DefMaxAmount; + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.INVBAR +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTIBRAC"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIBOOSTARMOR"; + Tag "$TAG_ARTIBOOSTARMOR"; + } + States + { + Spawn: + BRAC ABCDEFGH 4 Bright; + Loop; + } +} diff --git a/wadsrc/static/zscript/hexen/centaur.txt b/wadsrc/static/zscript/hexen/centaur.txt new file mode 100644 index 000000000..f8c8e2c3d --- /dev/null +++ b/wadsrc/static/zscript/hexen/centaur.txt @@ -0,0 +1,223 @@ +// Centaur ------------------------------------------------------------------ + +class Centaur : Actor +{ + Default + { + Health 200; + Painchance 135; + Speed 13; + Height 64; + Mass 120; + Monster; + +FLOORCLIP + +TELESTOMP + +SHIELDREFLECT + SeeSound "CentaurSight"; + AttackSound "CentaurAttack"; + PainSound "CentaurPain"; + DeathSound "CentaurDeath"; + ActiveSound "CentaurActive"; + HowlSound "PuppyBeat"; + Obituary "$OB_CENTAUR"; + DamageFactor "Electric", 3; + } + States + { + Spawn: + CENT AB 10 A_Look; + Loop; + See: + CENT ABCD 4 A_Chase; + Loop; + Pain: + CENT G 6 A_Pain; + CENT G 6 A_SetReflectiveInvulnerable; + CENT EEE 15 A_CentaurDefend; + CENT E 1 A_UnsetReflectiveInvulnerable; + Goto See; + Melee: + CENT H 5 A_FaceTarget; + CENT I 4 A_FaceTarget; + CENT J 7 A_CustomMeleeAttack(random[CentaurAttack](3,9)); + Goto See; + Death: + CENT K 4; + CENT L 4 A_Scream; + CENT MN 4; + CENT O 4 A_NoBlocking; + CENT PQ 4; + CENT R 4 A_QueueCorpse; + CENT S 4; + CENT T -1; + Stop; + XDeath: + CTXD A 4; + CTXD B 4 A_NoBlocking; + CTXD C 4 + { + A_SpawnItemEx("CentaurSword", 0, 0, 45, + 1 + random[CentaurDrop](-128,127)*0.03125, + 1 + random[CentaurDrop](-128,127)*0.03125, + 8 + random[CentaurDrop](0,255)*0.015625, 270); + A_SpawnItemEx("CentaurShield", 0, 0, 45, + 1 + random[CentaurDrop](-128,127)*0.03125, + 1 + random[CentaurDrop](-128,127)*0.03125, + 8 + random[CentaurDrop](0,255)*0.015625, 90); + } + CTXD D 3 A_Scream; + CTXD E 4 A_QueueCorpse; + CTXD F 3; + CTXD G 4; + CTXD H 3; + CTXD I 4; + CTXD J 3; + CTXD K -1; + Ice: + CENT U 5 A_FreezeDeath; + CENT U 1 A_FreezeDeathChunks; + Wait; + } +} + +extend class Actor +{ + void A_CentaurDefend() + { + A_FaceTarget (); + if (CheckMeleeRange() && random[CentaurDefend]() < 32) + { + // This should unset REFLECTIVE as well + // (unless you want the Centaur to reflect projectiles forever!) + bReflective = false; + bInvulnerable = false; + SetState(MeleeState); + } + } +} + +// Centaur Leader ----------------------------------------------------------- + +class CentaurLeader : Centaur +{ + Default + { + Health 250; + PainChance 96; + Speed 10; + Obituary "$OB_SLAUGHTAUR"; + HitObituary "$OB_SLAUGHTAURHIT"; + } + States + { + Missile: + CENT E 10 A_FaceTarget; + CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET); + CENT E 10 A_FaceTarget; + CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET); + Goto See; + } +} + +// Mashed centaur ----------------------------------------------------------- +// +// The mashed centaur is only placed through ACS. Nowhere in the game source +// is it ever referenced. + +class CentaurMash : Centaur +{ + Default + { + +NOBLOOD + +BLASTED + -TELESTOMP + +NOICEDEATH + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Death: + XDeath: + Ice: + Stop; + } +} + +// Centaur projectile ------------------------------------------------------- + +class CentaurFX : Actor +{ + Default + { + Speed 20; + Damage 4; + Projectile; + +SPAWNSOUNDSOURCE + RenderStyle "Add"; + SeeSound "CentaurLeaderAttack"; + DeathSound "CentaurMissileExplode"; + } + States + { + Spawn: + CTFX A -1 Bright; + Stop; + Death: + CTFX B 4 Bright; + CTFX C 3 Bright; + CTFX D 4 Bright; + CTFX E 3 Bright; + CTFX F 2 Bright; + Stop; + } +} + +// Centaur shield (debris) -------------------------------------------------- + +class CentaurShield : Actor +{ + Default + { + +DROPOFF + +CORPSE + +NOTELEPORT + } + States + { + Spawn: + CTDP ABCDEF 3; + Goto Spawn+2; + Crash: + CTDP G 4; + CTDP H 4 A_QueueCorpse; + CTDP I 4; + CTDP J -1; + Stop; + } +} + +// Centaur sword (debris) --------------------------------------------------- + +class CentaurSword : Actor +{ + Default + { + +DROPOFF + +CORPSE + +NOTELEPORT + } + States + { + Spawn: + CTDP KLMNOPQ 3; + Goto Spawn+2; + Crash: + CTDP R 4; + CTDP S 4 A_QueueCorpse; + CTDP T -1; + Stop; + } +} + + diff --git a/wadsrc/static/zscript/hexen/clericboss.txt b/wadsrc/static/zscript/hexen/clericboss.txt new file mode 100644 index 000000000..a2019bae5 --- /dev/null +++ b/wadsrc/static/zscript/hexen/clericboss.txt @@ -0,0 +1,82 @@ + +// Cleric Boss (Traductus) -------------------------------------------------- + +class ClericBoss : Actor +{ + Default + { + Health 800; + PainChance 50; + Speed 25; + Radius 16; + Height 64; + Monster; + +FLOORCLIP +TELESTOMP + +DONTMORPH + PainSound "PlayerClericPain"; + DeathSound "PlayerClericCrazyDeath"; + Obituary "$OBCBOSS"; + } + + native void A_ClericAttack(); + + States + { + Spawn: + CLER A 2; + CLER A 3 A_ClassBossHealth; + CLER A 5 A_Look; + Wait; + See: + CLER ABCD 4 A_FastChase; + Loop; + Pain: + CLER H 4; + CLER H 4 A_Pain; + Goto See; + Melee: + Missile: + CLER EF 8 A_FaceTarget; + CLER G 10 A_ClericAttack; + Goto See; + Death: + CLER I 6; + CLER K 6 A_Scream; + CLER LL 6; + CLER M 6 A_NoBlocking; + CLER NOP 6; + CLER Q -1; + Stop; + XDeath: + CLER R 5 A_Scream; + CLER S 5; + CLER T 5 A_NoBlocking; + CLER UVWXYZ 5; + CLER [ -1; + Stop; + Ice: + CLER \ 5 A_FreezeDeath; + CLER \ 1 A_FreezeDeathChunks; + Wait; + Burn: + CLER C 5 Bright A_PlaySound("PlayerClericBurnDeath"); + FDTH D 4 Bright ; + FDTH G 5 Bright ; + FDTH H 4 Bright A_Scream; + FDTH I 5 Bright ; + FDTH J 4 Bright ; + FDTH K 5 Bright ; + FDTH L 4 Bright ; + FDTH M 5 Bright ; + FDTH N 4 Bright ; + FDTH O 5 Bright ; + FDTH P 4 Bright ; + FDTH Q 5 Bright ; + FDTH R 4 Bright ; + FDTH S 5 Bright A_NoBlocking; + FDTH T 4 Bright ; + FDTH U 5 Bright ; + FDTH V 4 Bright ; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/clericflame.txt b/wadsrc/static/zscript/hexen/clericflame.txt new file mode 100644 index 000000000..13fca8ad1 --- /dev/null +++ b/wadsrc/static/zscript/hexen/clericflame.txt @@ -0,0 +1,211 @@ + +// The Cleric's Flame Strike ------------------------------------------------ + +class CWeapFlame : ClericWeapon +{ + Default + { + +NOGRAVITY + Weapon.SelectionOrder 1000; + Weapon.AmmoUse 4; + Weapon.AmmoGive 25; + Weapon.KickBack 150; + Weapon.YAdjust 10; + Weapon.AmmoType1 "Mana2"; + Inventory.PickupMessage "$TXT_WEAPON_C3"; + Tag "$TAG_CWEAPFLAME"; + } + + action native void A_CFlameAttack(); + + States + { + Spawn: + WCFM ABCDEFGH 4 Bright; + Loop; + Select: + CFLM A 1 A_Raise; + Loop; + Deselect: + CFLM A 1 A_Lower; + Loop; + Ready: + CFLM AAAABBBBCCCC 1 A_WeaponReady; + Loop; + Fire: + CFLM A 2 Offset (0, 40); + CFLM D 2 Offset (0, 50); + CFLM D 2 Offset (0, 36); + CFLM E 4 Bright; + CFLM F 4 Bright A_CFlameAttack; + CFLM E 4 Bright; + CFLM G 2 Offset (0, 40); + CFLM G 2; + Goto Ready; + } +} + +// Floor Flame -------------------------------------------------------------- + +class CFlameFloor : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + RenderStyle "Add"; + } + States + { + Spawn: + CFFX N 5 Bright; + CFFX O 4 Bright; + CFFX P 3 Bright; + Stop; + } +} + +// Flame Puff --------------------------------------------------------------- + +class FlamePuff : Actor +{ + Default + { + Radius 1; + Height 1; + +NOBLOCKMAP +NOGRAVITY + RenderStyle "Add";; + SeeSound "ClericFlameExplode"; + AttackSound "ClericFlameExplode"; + } + States + { + Spawn: + CFFX ABC 3 Bright; + CFFX D 4 Bright; + CFFX E 3 Bright; + CFFX F 4 Bright; + CFFX G 3 Bright; + CFFX H 4 Bright; + CFFX I 3 Bright; + CFFX J 4 Bright; + CFFX K 3 Bright; + CFFX L 4 Bright; + CFFX M 3 Bright; + Stop; + } +} + +// Flame Puff 2 ------------------------------------------------------------- + +class FlamePuff2 : FlamePuff +{ + States + { + Spawn: + CFFX ABC 3 Bright; + CFFX D 4 Bright; + CFFX E 3 Bright; + CFFX F 4 Bright; + CFFX G 3 Bright; + CFFX H 4 Bright; + CFFX IC 3 Bright; + CFFX D 4 Bright; + CFFX E 3 Bright; + CFFX F 4 Bright; + CFFX G 3 Bright; + CFFX H 4 Bright; + CFFX I 3 Bright; + CFFX J 4 Bright; + CFFX K 3 Bright; + CFFX L 4 Bright; + CFFX M 3 Bright; + Stop; + } +} + +// Circle Flame ------------------------------------------------------------- + +class CircleFlame : Actor +{ + Default + { + Radius 6; + Damage 2; + DamageType "Fire"; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + RenderStyle "Add"; + DeathSound "ClericFlameCircle"; + Obituary "$OB_MPCWEAPFLAME"; + } + + native void A_CFlameRotate(); + + States + { + Spawn: + CFCF A 4 Bright; + CFCF B 2 Bright A_CFlameRotate; + CFCF C 2 Bright; + CFCF D 1 Bright; + CFCF E 2 Bright; + CFCF F 2 Bright A_CFlameRotate; + CFCF G 1 Bright; + CFCF HI 2 Bright; + CFCF J 1 Bright A_CFlameRotate; + CFCF K 2 Bright; + CFCF LM 3 Bright; + CFCF N 2 Bright A_CFlameRotate; + CFCF O 3 Bright; + CFCF P 2 Bright; + Stop; + Death: + CFCF QR 3 Bright; + CFCF S 3 Bright A_Explode(20, 20, 0); + CFCF TUVWXYZ 3 Bright; + Stop; + } +} + +// Flame Missile ------------------------------------------------------------ + +class CFlameMissile : FastProjectile native +{ + Default + { + Speed 200; + Radius 14; + Height 8; + Damage 8; + DamageType "Fire"; + +INVISIBLE + RenderStyle "Add"; + Obituary "$OB_MPCWEAPFLAME"; + } + + native void A_CFlamePuff(); + native void A_CFlameMissile(); + + States + { + Spawn: + CFFX A 4 Bright; + CFFX A 1 A_CFlamePuff; + Goto Death + 1; + Death: + CFFX A 1 Bright A_CFlameMissile; + CFFX ABC 3 Bright; + CFFX D 4 Bright; + CFFX E 3 Bright; + CFFX F 4 Bright; + CFFX G 3 Bright; + CFFX H 4 Bright; + CFFX I 3 Bright; + CFFX J 4 Bright; + CFFX K 3 Bright; + CFFX L 4 Bright; + CFFX M 3 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/clericholy.txt b/wadsrc/static/zscript/hexen/clericholy.txt new file mode 100644 index 000000000..1a4372f4d --- /dev/null +++ b/wadsrc/static/zscript/hexen/clericholy.txt @@ -0,0 +1,267 @@ + +// Cleric Weapon Piece ------------------------------------------------------ + +class ClericWeaponPiece : WeaponPiece +{ + Default + { + Inventory.PickupSound "misc/w_pkup"; + Inventory.PickupMessage "$TXT_WRAITHVERGE_PIECE"; + Inventory.ForbiddenTo "FighterPlayer", "MagePlayer"; + WeaponPiece.Weapon "CWeapWraithverge"; + +FLOATBOB + } +} + +// Cleric Weapon Piece 1 ---------------------------------------------------- + +class CWeaponPiece1 : ClericWeaponPiece +{ + Default + { + WeaponPiece.Number 1; + } + States + { + Spawn: + WCH1 A -1; + Stop; + } +} + +// Cleric Weapon Piece 2 ---------------------------------------------------- + +class CWeaponPiece2 : ClericWeaponPiece +{ + Default + { + WeaponPiece.Number 2; + } + States + { + Spawn: + WCH2 A -1; + Stop; + } +} + +// Cleric Weapon Piece 3 ---------------------------------------------------- + +class CWeaponPiece3 : ClericWeaponPiece +{ + Default + { + WeaponPiece.Number 3; + } + States + { + Spawn: + WCH3 A -1; + Stop; + } +} + +// Wraithverge Drop --------------------------------------------------------- + +class WraithvergeDrop : Actor +{ + States + { + Spawn: + TNT1 A 1; + TNT1 A 1 A_DropWeaponPieces("CWeaponPiece1", "CWeaponPiece2", "CWeaponPiece3"); + Stop; + } +} + +// Cleric's Wraithverge (Holy Symbol?) -------------------------------------- + +class CWeapWraithverge : ClericWeapon native +{ + Default + { + Health 3; + Weapon.SelectionOrder 3000; + +WEAPON.PRIMARY_USES_BOTH; + +Inventory.NoAttenPickupSound + Weapon.AmmoUse1 18; + Weapon.AmmoUse2 18; + Weapon.AmmoGive1 20; + Weapon.AmmoGive2 20; + Weapon.KickBack 150; + Weapon.AmmoType1 "Mana1"; + Weapon.AmmoType2 "Mana2"; + Inventory.PickupMessage "$TXT_WEAPON_C4"; + Tag "$TAG_CWEAPWRAITHVERGE"; + Inventory.PickupSound "WeaponBuild"; + } + + action native void A_CHolyAttack(); + action native void A_CHolyPalette(); + + States + { + Spawn: + TNT1 A -1; + Stop; + Ready: + CHLY A 1 A_WeaponReady; + Loop; + Select: + CHLY A 1 A_Raise; + Loop; + Deselect: + CHLY A 1 A_Lower; + Loop; + Fire: + CHLY AB 1 Bright Offset (0, 40); + CHLY CD 2 Bright Offset (0, 43); + CHLY E 2 Bright Offset (0, 45); + CHLY F 6 Bright Offset (0, 48) A_CHolyAttack; + CHLY GG 2 Bright Offset (0, 40) A_CHolyPalette; + CHLY G 2 Offset (0, 36) A_CHolyPalette; + Goto Ready; + } +} + +// Holy Missile ------------------------------------------------------------- + +class HolyMissile : Actor +{ + Default + { + Speed 30; + Radius 15; + Height 8; + Damage 4; + Projectile; + -ACTIVATEIMPACT -ACTIVATEPCROSS + +EXTREMEDEATH + } + + native void A_CHolyAttack2(); + + States + { + Spawn: + SPIR PPPP 3 Bright A_SpawnItemEx("HolyMissilePuff"); + Death: + SPIR P 1 Bright A_CHolyAttack2; + Stop; + } +} + +// Holy Missile Puff -------------------------------------------------------- + +class HolyMissilePuff : Actor +{ + Default + { + Radius 4; + Height 8; + +NOBLOCKMAP +NOGRAVITY +DROPOFF + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Spawn: + SPIR QRSTU 3; + Stop; + } +} + +// Holy Puff ---------------------------------------------------------------- + +class HolyPuff : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + RenderStyle "Translucent"; + Alpha 0.6; + } + States + { + Spawn: + SPIR KLMNO 3; + Stop; + } +} + +// Holy Spirit -------------------------------------------------------------- + +class HolySpirit : Actor native +{ + Default + { + Health 105; + Speed 12; + Radius 10; + Height 6; + Damage 3; + Projectile; + +RIPPER +SEEKERMISSILE + +FOILINVUL +SKYEXPLODE +NOEXPLODEFLOOR +CANBLAST + +EXTREMEDEATH + RenderStyle "Translucent"; + Alpha 0.4; + DeathSound "SpiritDie"; + Obituary "$OB_MPCWEAPWRAITHVERGE"; + } + + native void A_CHolySeek(); + native void A_CHolyCheckScream(); + + States + { + Spawn: + SPIR AAB 2 A_CHolySeek; + SPIR B 2 A_CHolyCheckScream; + Loop; + Death: + SPIR D 4; + SPIR E 4 A_Scream; + SPIR FGHI 4; + Stop; + } +} + +// Holy Tail ---------------------------------------------------------------- + +class HolyTail : Actor +{ + Default + { + Radius 1; + Height 1; + +NOBLOCKMAP +NOGRAVITY +DROPOFF +NOCLIP + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.6; + } + + native void A_CHolyTail(); + + States + { + Spawn: + SPIR C 1 A_CHolyTail; + Loop; + TailTrail: + SPIR D -1; + Stop; + } +} + +// Holy Tail Trail --------------------------------------------------------- + +class HolyTailTrail : HolyTail +{ + States + { + Spawn: + Goto TailTrail; + } +} diff --git a/wadsrc/static/zscript/hexen/clericmace.txt b/wadsrc/static/zscript/hexen/clericmace.txt new file mode 100644 index 000000000..5e00b9c3b --- /dev/null +++ b/wadsrc/static/zscript/hexen/clericmace.txt @@ -0,0 +1,49 @@ + +// The Cleric's Mace -------------------------------------------------------- + +class CWeapMace : ClericWeapon +{ + Default + { + Weapon.SelectionOrder 3500; + Weapon.KickBack 150; + Weapon.YAdjust -8; + +BLOODSPLATTER + Obituary "$OB_MPCWEAPMACE"; + Tag "$TAG_CWEAPMACE"; + } + + action native void A_CMaceAttack(); + + States + { + Select: + CMCE A 1 A_Raise; + Loop; + Deselect: + CMCE A 1 A_Lower; + Loop; + Ready: + CMCE A 1 A_WeaponReady; + Loop; + Fire: + CMCE B 2 Offset (60, 20); + CMCE B 1 Offset (30, 33); + CMCE B 2 Offset (8, 45); + CMCE C 1 Offset (8, 45); + CMCE D 1 Offset (8, 45); + CMCE E 1 Offset (8, 45); + CMCE E 1 Offset (-11, 58) A_CMaceAttack; + CMCE F 1 Offset (8, 45); + CMCE F 2 Offset (-8, 74); + CMCE F 1 Offset (-20, 96); + CMCE F 8 Offset (-33, 160); + CMCE A 2 Offset (8, 75) A_ReFire; + CMCE A 1 Offset (8, 65); + CMCE A 2 Offset (8, 60); + CMCE A 1 Offset (8, 55); + CMCE A 2 Offset (8, 50); + CMCE A 1 Offset (8, 45); + Goto Ready; + } +} diff --git a/wadsrc/static/zscript/hexen/clericplayer.txt b/wadsrc/static/zscript/hexen/clericplayer.txt new file mode 100644 index 000000000..1b47ad3f5 --- /dev/null +++ b/wadsrc/static/zscript/hexen/clericplayer.txt @@ -0,0 +1,106 @@ +// The cleric --------------------------------------------------------------- + +class ClericPlayer : PlayerPawn +{ + Default + { + Health 100; + ReactionTime 0; + PainChance 255; + Radius 16; + Height 64; + Speed 1; + +NOSKIN + +NODAMAGETHRUST + +PLAYERPAWN.NOTHRUSTWHENINVUL + PainSound "PlayerClericPain"; + RadiusDamageFactor 0.25; + Player.JumpZ 9; + Player.Viewheight 48; + Player.SpawnClass "Cleric"; + Player.DisplayName "Cleric"; + Player.SoundClass "cleric"; + Player.ScoreIcon "CLERFACE"; + Player.InvulnerabilityMode "Ghost"; + Player.HealRadiusType "Health"; + Player.Hexenarmor 10, 10, 25, 5, 20; + Player.StartItem "CWeapMace"; + Player.Portrait "P_CWALK1"; + Player.WeaponSlot 1, "CWeapMace"; + Player.WeaponSlot 2, "CWeapStaff"; + Player.WeaponSlot 3, "CWeapFlame"; + Player.WeaponSlot 4, "CWeapWraithverge"; + Player.FlechetteType "ArtiPoisonBag1"; + + Player.ColorRange 146, 163; + Player.Colorset 0, "Blue", 146, 163, 161; + Player.ColorsetFile 1, "Red", "TRANTBL7", 0xB3; + Player.ColorsetFile 2, "Gold", "TRANTBL8", 0x8C; + Player.ColorsetFile 3, "Dull Green", "TRANTBL9", 0x41; + Player.ColorsetFile 4, "Green", "TRANTBLA", 0xC9; + Player.ColorsetFile 5, "Gray", "TRANTBLB", 0x30; + Player.ColorsetFile 6, "Brown", "TRANTBLC", 0x72; + Player.ColorsetFile 7, "Purple", "TRANTBLD", 0xEE; + } + + States + { + Spawn: + CLER A -1; + Stop; + See: + CLER ABCD 4; + Loop; + Pain: + CLER H 4; + CLER H 4 A_Pain; + Goto Spawn; + Missile: + Melee: + CLER EFG 6; + Goto Spawn; + Death: + CLER I 6; + CLER J 6 A_PlayerScream; + CLER KL 6; + CLER M 6 A_NoBlocking; + CLER NOP 6; + CLER Q -1; + Stop; + XDeath: + CLER R 5 A_PlayerScream; + CLER S 5; + CLER T 5 A_NoBlocking; + CLER UVWXYZ 5; + CLER [ -1; + Stop; + Ice: + CLER \ 5 A_FreezeDeath; + CLER \ 1 A_FreezeDeathChunks; + Wait; + Burn: + FDTH C 5 BRIGHT A_PlaySound("*burndeath"); + FDTH D 4 BRIGHT; + FDTH G 5 BRIGHT; + FDTH H 4 BRIGHT A_PlayerScream; + FDTH I 5 BRIGHT; + FDTH J 4 BRIGHT; + FDTH K 5 BRIGHT; + FDTH L 4 BRIGHT; + FDTH M 5 BRIGHT; + FDTH N 4 BRIGHT; + FDTH O 5 BRIGHT; + FDTH P 4 BRIGHT; + FDTH Q 5 BRIGHT; + FDTH R 4 BRIGHT; + FDTH S 5 BRIGHT A_NoBlocking; + FDTH T 4 BRIGHT; + FDTH U 5 BRIGHT; + FDTH V 4 BRIGHT; + ACLO E 35 A_CheckPlayerDone; + Wait; + ACLO E 8; + Stop; + } +} + diff --git a/wadsrc/static/zscript/hexen/clericstaff.txt b/wadsrc/static/zscript/hexen/clericstaff.txt new file mode 100644 index 000000000..7ae0e9da3 --- /dev/null +++ b/wadsrc/static/zscript/hexen/clericstaff.txt @@ -0,0 +1,105 @@ + +// The Cleric's Serpent Staff ----------------------------------------------- + +class CWeapStaff : ClericWeapon +{ + Default + { + Weapon.SelectionOrder 1600; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 25; + Weapon.KickBack 150; + Weapon.YAdjust 10; + Weapon.AmmoType1 "Mana1"; + Inventory.PickupMessage "$TXT_WEAPON_C2"; + Obituary "$OB_MPCWEAPSTAFFM"; + Tag "$TAG_CWEAPSTAFF"; + } + + action native void A_CStaffInitBlink(); + action native void A_CStaffCheckBlink(); + action native void A_CStaffCheck(); + action native void A_CStaffAttack(); + + States + { + Spawn: + WCSS A -1; + Stop; + Select: + CSSF C 1 A_Raise; + Loop; + Deselect: + CSSF B 3; + CSSF C 4; + CSSF C 1 A_Lower; + Wait; + Ready: + CSSF C 4; + CSSF B 3 A_CStaffInitBlink; + CSSF AAAAAAA 1 A_WeaponReady; + CSSF A 1 A_CStaffCheckBlink; + Goto Ready + 2; + Fire: + CSSF A 1 Offset (0, 45) A_CStaffCheck; + CSSF J 1 Offset (0, 50) A_CStaffAttack; + CSSF J 2 Offset (0, 50); + CSSF J 2 Offset (0, 45); + CSSF A 2 Offset (0, 40); + CSSF A 2 Offset (0, 36); + Goto Ready + 2; + Blink: + CSSF BBBCCCCCBBB 1 A_WeaponReady; + Goto Ready + 2; + Drain: + CSSF K 10 Offset (0, 36); + Goto Ready + 2; + } +} + +// Serpent Staff Missile ---------------------------------------------------- + +class CStaffMissile : Actor native +{ + Default + { + Speed 22; + Radius 12; + Height 10; + Damage 5; + RenderStyle "Add"; + Projectile; + DeathSound "ClericCStaffExplode"; + Obituary "$OB_MPCWEAPSTAFFR"; + } + States + { + Spawn: + CSSF DDEE 1 Bright A_CStaffMissileSlither; + Loop; + Death: + CSSF FG 4 Bright; + CSSF HI 3 Bright; + Stop; + } +} + +// Serpent Staff Puff ------------------------------------------------------- + +class CStaffPuff : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + +PUFFONACTORS + RenderStyle "Translucent"; + Alpha 0.6; + SeeSound "ClericCStaffHitThing"; + } + States + { + Spawn: + FHFX STUVW 4; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/demons.txt b/wadsrc/static/zscript/hexen/demons.txt new file mode 100644 index 000000000..8aa65629d --- /dev/null +++ b/wadsrc/static/zscript/hexen/demons.txt @@ -0,0 +1,414 @@ + +// Demon, type 1 (green, like D'Sparil's) ----------------------------------- + +class Demon1 : Actor +{ + Default + { + Health 250; + Painchance 50; + Speed 13; + Radius 32; + Height 64; + Mass 220; + Monster; + +TELESTOMP + +FLOORCLIP + SeeSound "DemonSight"; + AttackSound "DemonAttack"; + PainSound "DemonPain"; + DeathSound "DemonDeath"; + ActiveSound "DemonActive"; + Obituary "$OB_DEMON1"; + } + + const ChunkFlags = SXF_TRANSFERTRANSLATION | SXF_ABSOLUTEVELOCITY; + + States + { + Spawn: + DEMN AA 10 A_Look; + Loop; + See: + DEMN ABCD 4 A_Chase; + Loop; + Pain: + DEMN E 4; + DEMN E 4 A_Pain; + Goto See; + Melee: + DEMN E 6 A_FaceTarget; + DEMN F 8 A_FaceTarget; + DEMN G 6 A_CustomMeleeAttack(random[DemonAttack1](1,8)*2); + Goto See; + Missile: + DEMN E 5 A_FaceTarget; + DEMN F 6 A_FaceTarget; + DEMN G 5 A_CustomMissile("Demon1FX1", 62, 0); + Goto See; + Death: + DEMN HI 6; + DEMN J 6 A_Scream; + DEMN K 6 A_NoBlocking; + DEMN L 6 A_QueueCorpse; + DEMN MNO 6; + DEMN P -1; + Stop; + XDeath: + DEMN H 6; + DEMN I 6 + { + A_SpawnItemEx("Demon1Chunk1", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle+90), frandom[DemonChunks](1,4.984375)*sin(Angle+90), 8, 90, ChunkFlags); + A_SpawnItemEx("Demon1Chunk2", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags); + A_SpawnItemEx("Demon1Chunk3", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags); + A_SpawnItemEx("Demon1Chunk4", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags); + A_SpawnItemEx("Demon1Chunk5", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags); + } + Goto Death+2; + Ice: + DEMN Q 5 A_FreezeDeath; + DEMN Q 1 A_FreezeDeathChunks; + Wait; + } +} + +// Demon, type 1, mashed ---------------------------------------------------- + +class Demon1Mash : Demon1 +{ + Default + { + +NOBLOOD + +BLASTED + -TELESTOMP + +NOICEDEATH + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Death: + XDeath: + Ice: + Stop; + } +} + +// Demon chunk, base class -------------------------------------------------- + +class DemonChunk : Actor +{ + Default + { + Radius 5; + Height 5; + +NOBLOCKMAP + +DROPOFF + +MISSILE + +CORPSE + +FLOORCLIP + +NOTELEPORT + } +} + +// Demon, type 1, chunk 1 --------------------------------------------------- + +class Demon1Chunk1 : DemonChunk +{ + States + { + Spawn: + DEMA A 4; + DEMA A 10 A_QueueCorpse; + DEMA A 20; + Wait; + Death: + DEMA A -1; + Stop; + } +} + +// Demon, type 1, chunk 2 --------------------------------------------------- + +class Demon1Chunk2 : DemonChunk +{ + States + { + Spawn: + DEMB A 4; + DEMB A 10 A_QueueCorpse; + DEMB A 20; + Wait; + Death: + DEMB A -1; + Stop; + } +} + +class Demon1Chunk3 : DemonChunk +{ + States + { + Spawn: + DEMC A 4; + DEMC A 10 A_QueueCorpse; + DEMC A 20; + Wait; + Death: + DEMC A -1; + Stop; + } +} + +// Demon, type 1, chunk 4 --------------------------------------------------- + +class Demon1Chunk4 : DemonChunk +{ + States + { + Spawn: + DEMD A 4; + DEMD A 10 A_QueueCorpse; + DEMD A 20; + Wait; + Death: + DEMD A -1; + Stop; + } +} + +// Demon, type 1, chunk 5 --------------------------------------------------- + +class Demon1Chunk5 : DemonChunk +{ + States + { + Spawn: + DEME A 4; + DEME A 10 A_QueueCorpse; + DEME A 20; + Wait; + Death: + DEME A -1; + Stop; + } +} + +// Demon, type 1, projectile ------------------------------------------------ + +class Demon1FX1 : Actor +{ + Default + { + Speed 15; + Radius 10; + Height 6; + Damage 5; + DamageType "Fire"; + Projectile; + +SPAWNSOUNDSOURCE + RenderStyle "Add"; + SeeSound "DemonMissileFire"; + DeathSound "DemonMissileExplode"; + } + States + { + Spawn: + DMFX ABC 4 Bright; + Loop; + Death: + DMFX DE 4 Bright; + DMFX FGH 3 Bright; + Stop; + } +} + +// Demon, type 2 (brown) ---------------------------------------------------- + +class Demon2 : Demon1 +{ + Default + { + Obituary "$OB_DEMON2"; + Species "Demon2"; + } + States + { + Spawn: + DEM2 AA 10 A_Look; + Loop; + See: + DEM2 ABCD 4 A_Chase; + Loop; + Pain: + DEM2 E 4; + DEM2 E 4 A_Pain; + Goto See; + Melee: + DEM2 E 6 A_FaceTarget; + DEM2 F 8 A_FaceTarget; + DEM2 G 6 A_CustomMeleeAttack(random[DemonAttack1](1,8)*2); + Goto See; + Missile: + DEM2 E 5 A_FaceTarget; + DEM2 F 6 A_FaceTarget; + DEM2 G 5 A_CustomMissile("Demon2FX1", 62, 0); + Goto See; + Death: + DEM2 HI 6; + DEM2 J 6 A_Scream; + DEM2 K 6 A_NoBlocking; + DEM2 L 6 A_QueueCorpse; + DEM2 MNO 6; + DEM2 P -1; + Stop; + XDeath: + DEM2 H 6; + DEM2 I 6 + { + A_SpawnItemEx("Demon2Chunk1", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle+90), frandom[DemonChunks](1,4.984375)*sin(Angle+90), 8, 90, ChunkFlags); + A_SpawnItemEx("Demon2Chunk2", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags); + A_SpawnItemEx("Demon2Chunk3", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags); + A_SpawnItemEx("Demon2Chunk4", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags); + A_SpawnItemEx("Demon2Chunk5", 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle-90), frandom[DemonChunks](1,4.984375)*sin(Angle-90), 8, 270, ChunkFlags); + } + Goto Death+2; + } +} + +// Demon, type 2, mashed ---------------------------------------------------- + +class Demon2Mash : Demon2 +{ + Default + { + +NOBLOOD + +BLASTED + -TELESTOMP + +NOICEDEATH + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Death: + XDeath: + Ice: + Stop; + } +} + +// Demon, type 2, chunk 1 --------------------------------------------------- + +class Demon2Chunk1 : DemonChunk +{ + States + { + Spawn: + DMBA A 4; + DMBA A 10 A_QueueCorpse; + DMBA A 20; + Wait; + Death: + DMBA A -1; + Stop; + } +} + +// Demon, type 2, chunk 2 --------------------------------------------------- + +class Demon2Chunk2 : DemonChunk +{ + States + { + Spawn: + DMBB A 4; + DMBB A 10 A_QueueCorpse; + DMBB A 20; + Wait; + Death: + DMBB A -1; + Stop; + } +} + +// Demon, type 2, chunk 3 --------------------------------------------------- + +class Demon2Chunk3 : DemonChunk +{ + States + { + Spawn: + DMBC A 4; + DMBC A 10 A_QueueCorpse; + DMBC A 20; + Wait; + Death: + DMBC A -1; + Stop; + } +} + +// Demon, type 2, chunk 4 --------------------------------------------------- + +class Demon2Chunk4 : DemonChunk +{ + States + { + Spawn: + DMBD A 4; + DMBD A 10 A_QueueCorpse; + DMBD A 20; + Wait; + Death: + DMBD A -1; + Stop; + } +} + +// Demon, type 2, chunk 5 --------------------------------------------------- + +class Demon2Chunk5 : DemonChunk +{ + States + { + Spawn: + DMBE A 4; + DMBE A 10 A_QueueCorpse; + DMBE A 20; + Wait; + Death: + DMBE A -1; + Stop; + } +} + +// Demon, type 2, projectile ------------------------------------------------ + +class Demon2FX1 : Actor +{ + Default + { + Speed 15; + Radius 10; + Height 6; + Damage 5; + DamageType "Fire"; + Projectile; + +SPAWNSOUNDSOURCE + RenderStyle "Add"; + SeeSound "DemonMissileFire"; + DeathSound "DemonMissileExplode"; + } + States + { + Spawn: + D2FX ABCDEF 4 Bright; + Loop; + Death: + D2FX GHIJ 4 Bright; + D2FX KL 3 Bright; + Stop; + } +} + diff --git a/wadsrc/static/zscript/hexen/dragon.txt b/wadsrc/static/zscript/hexen/dragon.txt new file mode 100644 index 000000000..6df3da943 --- /dev/null +++ b/wadsrc/static/zscript/hexen/dragon.txt @@ -0,0 +1,126 @@ + +// Dragon ------------------------------------------------------------------- + +class Dragon : Actor +{ + Default + { + Health 640; + PainChance 128; + Speed 10; + Height 65; + Mass 0x7fffffff; + Monster; + +NOGRAVITY +FLOAT +NOBLOOD + +BOSS + +DONTMORPH +NOTARGET + +NOICEDEATH + SeeSound "DragonSight"; + AttackSound "DragonAttack"; + PainSound "DragonPain"; + DeathSound "DragonDeath"; + ActiveSound "DragonActive"; + Obituary "$OB_DRAGON"; + } + + native void A_DragonInitFlight(); + native void A_DragonFlap(); + native void A_DragonFlight(); + native void A_DragonPain(); + native void A_DragonAttack(); + native void A_DragonCheckCrash(); + + States + { + Spawn: + DRAG D 10 A_Look; + Loop; + See: + DRAG CB 5; + DRAG A 5 A_DragonInitFlight; + DRAG B 3 A_DragonFlap; + DRAG BCCDDCCBBAA 3 A_DragonFlight; + Goto See + 3; + Pain: + DRAG F 10 A_DragonPain; + Goto See + 3; + Missile: + DRAG E 8 A_DragonAttack; + Goto See + 3; + Death: + DRAG G 5 A_Scream; + DRAG H 4 A_NoBlocking; + DRAG I 4; + DRAG J 4 A_DragonCheckCrash; + Wait; + Crash: + DRAG KL 5; + DRAG M -1; + Stop; + } +} + +// Dragon Fireball ---------------------------------------------------------- + +class DragonFireball : Actor +{ + Default + { + Speed 24; + Radius 12; + Height 10; + Damage 6; + DamageType "Fire"; + Projectile; + -ACTIVATEIMPACT -ACTIVATEPCROSS + RenderStyle "Add"; + DeathSound "DragonFireballExplode"; + } + + native void A_DragonFX2(); + + States + { + Spawn: + DRFX ABCDEF 4 Bright; + Loop; + Death: + DRFX GHI 4 Bright; + DRFX J 4 Bright A_DragonFX2; + DRFX KL 3 Bright; + Stop; + } +} + +// Dragon Fireball Secondary Explosion -------------------------------------- + +class DragonExplosion : Actor +{ + Default + { + Radius 8; + Height 8; + DamageType "Fire"; + +NOBLOCKMAP + +NOTELEPORT + +INVISIBLE + RenderStyle "Add"; + DeathSound "DragonFireballExplode"; + } + States + { + Spawn: + CFCF Q 1 Bright; + CFCF Q 4 Bright A_UnHideThing; + CFCF R 3 Bright A_Scream; + CFCF S 4 Bright; + CFCF T 3 Bright A_Explode (80, 128, 0); + CFCF U 4 Bright; + CFCF V 3 Bright; + CFCF W 4 Bright; + CFCF X 3 Bright; + CFCF Y 4 Bright; + CFCF Z 3 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/ettin.txt b/wadsrc/static/zscript/hexen/ettin.txt new file mode 100644 index 000000000..8ddf9e7d2 --- /dev/null +++ b/wadsrc/static/zscript/hexen/ettin.txt @@ -0,0 +1,115 @@ + +// Ettin -------------------------------------------------------------------- + +class Ettin : Actor +{ + Default + { + Health 175; + Radius 25; + Height 68; + Mass 175; + Speed 13; + Damage 3; + Painchance 60; + Monster; + +FLOORCLIP + +TELESTOMP + SeeSound "EttinSight"; + AttackSound "EttinAttack"; + PainSound "EttinPain"; + DeathSound "EttinDeath"; + ActiveSound "EttinActive"; + HowlSound "PuppyBeat"; + Obituary "$OB_ETTIN"; + } + States + { + Spawn: + ETTN AA 10 A_Look; + Loop; + See: + ETTN ABCD 5 A_Chase; + Loop; + Pain: + ETTN H 7 A_Pain; + Goto See; + Melee: + ETTN EF 6 A_FaceTarget; + ETTN G 8 A_CustomMeleeAttack(random[EttinAttack](1,8)*2); + Goto See; + Death: + ETTN IJ 4; + ETTN K 4 A_Scream; + ETTN L 4 A_NoBlocking; + ETTN M 4 A_QueueCorpse; + ETTN NOP 4; + ETTN Q -1; + Stop; + XDeath: + ETTB A 4; + ETTB B 4 A_NoBlocking; + ETTB C 4 A_SpawnItemEx("EttinMace", 0,0,8.5, + random[DropMace](-128,127) * 0.03125, + random[DropMace](-128,127) * 0.03125, + 10 + random[DropMace](0,255) * 0.015625, 0, SXF_ABSOLUTEVELOCITY); + ETTB D 4 A_Scream; + ETTB E 4 A_QueueCorpse; + ETTB FGHIJK 4; + ETTB L -1; + Stop; + Ice: + ETTN R 5 A_FreezeDeath; + ETTN R 1 A_FreezeDeathChunks; + Wait; + } +} + +// Ettin mace --------------------------------------------------------------- + +class EttinMace : Actor +{ + Default + { + Radius 5; + Height 5; + +DROPOFF + +CORPSE + +NOTELEPORT + +FLOORCLIP + } + States + { + Spawn: + ETTB MNOP 5; + Loop; + Crash: + ETTB Q 5; + ETTB R 5 A_QueueCorpse; + ETTB S -1; + Stop; + } +} + +// Ettin mash --------------------------------------------------------------- + +class EttinMash : Ettin +{ + Default + { + +NOBLOOD + +NOICEDEATH + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Death: + XDeath: + Ice: + Stop; + } +} + + + diff --git a/wadsrc/static/zscript/hexen/fighteraxe.txt b/wadsrc/static/zscript/hexen/fighteraxe.txt new file mode 100644 index 000000000..30b235192 --- /dev/null +++ b/wadsrc/static/zscript/hexen/fighteraxe.txt @@ -0,0 +1,122 @@ + +// The Fighter's Axe -------------------------------------------------------- + +class FWeapAxe : FighterWeapon native +{ + Default + { + Weapon.SelectionOrder 1500; + +WEAPON.AXEBLOOD +WEAPON.AMMO_OPTIONAL +WEAPON.MELEEWEAPON + Weapon.AmmoUse1 2; + Weapon.AmmoGive1 25; + Weapon.KickBack 150; + Weapon.YAdjust -12; + Weapon.AmmoType1 "Mana1"; + Inventory.PickupMessage "$TXT_WEAPON_F2"; + Obituary "$OB_MPFWEAPAXE"; + Tag "$TAG_FWEAPAXE"; + } + + action native void A_FAxeCheckUp(); + action native void A_FAxeCheckReady(); + action native void A_FAxeCheckAtk(); + action native void A_FAxeAttack(); + action native void A_FAxeCheckUpG(); + action native void A_FAxeCheckReadyG(); + + States + { + Spawn: + WFAX A -1; + Stop; + Select: + FAXE A 1 A_FAxeCheckUp; + Loop; + Deselect: + FAXE A 1 A_Lower; + Loop; + Ready: + FAXE A 1 A_FAxeCheckReady; + Loop; + Fire: + FAXE B 4 Offset (15, 32) A_FAxeCheckAtk; + FAXE C 3 Offset (15, 32); + FAXE D 2 Offset (15, 32); + FAXE D 1 Offset (-5, 70) A_FAxeAttack; + FAXE D 2 Offset (-25, 90); + FAXE E 1 Offset (15, 32); + FAXE E 2 Offset (10, 54); + FAXE E 7 Offset (10, 150); + FAXE A 1 Offset (0, 60) A_ReFire; + FAXE A 1 Offset (0, 52); + FAXE A 1 Offset (0, 44); + FAXE A 1 Offset (0, 36); + FAXE A 1; + Goto Ready; + SelectGlow: + FAXE L 1 A_FAxeCheckUpG; + Loop; + DeselectGlow: + FAXE L 1 A_Lower; + Loop; + ReadyGlow: + FAXE LLL 1 A_FAxeCheckReadyG; + FAXE MMM 1 A_FAxeCheckReadyG; + Loop; + FireGlow: + FAXE N 4 Offset (15, 32); + FAXE O 3 Offset (15, 32); + FAXE P 2 Offset (15, 32); + FAXE P 1 Offset (-5, 70) A_FAxeAttack; + FAXE P 2 Offset (-25, 90); + FAXE Q 1 Offset (15, 32); + FAXE Q 2 Offset (10, 54); + FAXE Q 7 Offset (10, 150); + FAXE A 1 Offset (0, 60) A_ReFire; + FAXE A 1 Offset (0, 52); + FAXE A 1 Offset (0, 44); + FAXE A 1 Offset (0, 36); + FAXE A 1; + Goto ReadyGlow; + } +} + +// Axe Puff ----------------------------------------------------------------- + +class AxePuff : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + +PUFFONACTORS + RenderStyle "Translucent"; + Alpha 0.6; + SeeSound "FighterAxeHitThing"; + AttackSound "FighterHammerHitWall"; + ActiveSound "FighterHammerMiss"; + } + States + { + Spawn: + FHFX STUVW 4; + Stop; + } +} + +// Glowing Axe Puff --------------------------------------------------------- + +class AxePuffGlow : AxePuff +{ + Default + { + +PUFFONACTORS + RenderStyle "Add"; + Alpha 1; + } + States + { + Spawn: + FAXE RSTUVWX 4 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/fighterboss.txt b/wadsrc/static/zscript/hexen/fighterboss.txt new file mode 100644 index 000000000..8e862de30 --- /dev/null +++ b/wadsrc/static/zscript/hexen/fighterboss.txt @@ -0,0 +1,83 @@ + +// Fighter Boss (Zedek) ----------------------------------------------------- + +class FighterBoss : Actor +{ + Default + { + health 800; + PainChance 50; + Speed 25; + Radius 16; + Height 64; + Monster; + +FLOORCLIP + +TELESTOMP + +DONTMORPH + PainSound "PlayerFighterPain"; + DeathSound "PlayerFighterCrazyDeath"; + Obituary "$OB_FBOSS"; + } + + native void A_FighterAttack(); + + States + { + Spawn: + PLAY A 2; + PLAY A 3 A_ClassBossHealth; + PLAY A 5 A_Look; + Wait; + See: + PLAY ABCD 4 A_FastChase; + Loop; + Pain: + PLAY G 4; + PLAY G 4 A_Pain; + Goto See; + Melee: + Missile: + PLAY E 8 A_FaceTarget; + PLAY F 8 A_FighterAttack; + Goto See; + Death: + PLAY H 6; + PLAY I 6 A_Scream; + PLAY JK 6; + PLAY L 6 A_NoBlocking; + PLAY M 6; + PLAY N -1; + Stop; + XDeath: + PLAY O 5 A_Scream; + PLAY P 5 A_SkullPop; + PLAY R 5 A_NoBlocking; + PLAY STUV 5; + PLAY W -1; + Stop; + Ice: + PLAY X 5 A_FreezeDeath; + PLAY X 1 A_FreezeDeathChunks; + Wait; + Burn: + FDTH A 5 Bright A_PlaySound("PlayerFighterBurnDeath"); + FDTH B 4 Bright; + FDTH G 5 Bright; + FDTH H 4 Bright A_Scream; + FDTH I 5 Bright; + FDTH J 4 Bright; + FDTH K 5 Bright; + FDTH L 4 Bright; + FDTH M 5 Bright; + FDTH N 4 Bright; + FDTH O 5 Bright; + FDTH P 4 Bright; + FDTH Q 5 Bright; + FDTH R 4 Bright; + FDTH S 5 Bright A_NoBlocking; + FDTH T 4 Bright; + FDTH U 5 Bright; + FDTH V 4 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/fighterfist.txt b/wadsrc/static/zscript/hexen/fighterfist.txt new file mode 100644 index 000000000..8428ebe7d --- /dev/null +++ b/wadsrc/static/zscript/hexen/fighterfist.txt @@ -0,0 +1,70 @@ + +// Fist (first weapon) ------------------------------------------------------ + +class FWeapFist : FighterWeapon +{ + Default + { + +BLOODSPLATTER + Weapon.SelectionOrder 3400; + +WEAPON.MELEEWEAPON + Weapon.KickBack 150; + Obituary "$OB_MPFWEAPFIST"; + Tag "$TAG_FWEAPFIST"; + } + + action native void A_FPunchAttack(); + + States + { + Select: + FPCH A 1 A_Raise; + Loop; + Deselect: + FPCH A 1 A_Lower; + Loop; + Ready: + FPCH A 1 A_WeaponReady; + Loop; + Fire: + FPCH B 5 Offset (5, 40); + FPCH C 4 Offset (5, 40); + FPCH D 4 Offset (5, 40) A_FPunchAttack; + FPCH C 4 Offset (5, 40); + FPCH B 5 Offset (5, 40) A_ReFire; + Goto Ready; + Fire2: + FPCH DE 4 Offset (5, 40); + FPCH E 1 Offset (15, 50); + FPCH E 1 Offset (25, 60); + FPCH E 1 Offset (35, 70); + FPCH E 1 Offset (45, 80); + FPCH E 1 Offset (55, 90); + FPCH E 1 Offset (65, 90); + FPCH E 10 Offset (0, 150); + Goto Ready; + } +} + +// Punch puff --------------------------------------------------------------- + +class PunchPuff : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + +PUFFONACTORS + RenderStyle "Translucent"; + Alpha 0.6; + SeeSound "FighterPunchHitThing"; + AttackSound "FighterPunchHitWall"; + ActiveSound "FighterPunchMiss"; + VSpeed 1; + } + States + { + Spawn: + FHFX STUVW 4; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/fighterhammer.txt b/wadsrc/static/zscript/hexen/fighterhammer.txt new file mode 100644 index 000000000..f415cbb72 --- /dev/null +++ b/wadsrc/static/zscript/hexen/fighterhammer.txt @@ -0,0 +1,110 @@ + +// The Fighter's Hammer ----------------------------------------------------- + +class FWeapHammer : FighterWeapon +{ + Default + { + +BLOODSPLATTER + Weapon.SelectionOrder 900; + +WEAPON.AMMO_OPTIONAL +WEAPON.MELEEWEAPON + Weapon.AmmoUse1 3; + Weapon.AmmoGive1 25; + Weapon.KickBack 150; + Weapon.YAdjust -10; + Weapon.AmmoType1 "Mana2"; + Inventory.PickupMessage "$TXT_WEAPON_F3"; + Obituary "$OB_MPFWEAPHAMMERM"; + Tag "$TAG_FWEAPHAMMER"; + } + + action native void A_FHammerAttack(); + action native void A_FHammerThrow(); + + States + { + Spawn: + WFHM A -1; + Stop; + Select: + FHMR A 1 A_Raise; + Loop; + Deselect: + FHMR A 1 A_Lower; + Loop; + Ready: + FHMR A 1 A_WeaponReady; + Loop; + Fire: + FHMR B 6 Offset (5, 0); + FHMR C 3 Offset (5, 0) A_FHammerAttack; + FHMR D 3 Offset (5, 0); + FHMR E 2 Offset (5, 0); + FHMR E 10 Offset (5, 150) A_FHammerThrow; + FHMR A 1 Offset (0, 60); + FHMR A 1 Offset (0, 55); + FHMR A 1 Offset (0, 50); + FHMR A 1 Offset (0, 45); + FHMR A 1 Offset (0, 40); + FHMR A 1 Offset (0, 35); + FHMR A 1; + Goto Ready; + } +} + +// Hammer Missile ----------------------------------------------------------- + +class HammerMissile : Actor +{ + Default + { + Speed 25; + Radius 14; + Height 20; + Damage 10; + DamageType "Fire"; + Projectile; + DeathSound "FighterHammerExplode"; + Obituary "$OB_MPFWEAPHAMMERR"; + } + + States + { + Spawn: + FHFX A 2 Bright; + FHFX B 2 Bright A_PlaySound ("FighterHammerContinuous"); + FHFX CDEFGH 2 Bright; + Loop; + Death: + FHFX I 3 Bright A_SetTranslucent(1,1); + FHFX J 3 Bright; + FHFX K 3 Bright A_Explode (128, 128, 0); + FHFX LM 3 Bright; + FHFX N 3; + FHFX OPQR 3 Bright; + Stop; + } +} + +// Hammer Puff (also used by fist) ------------------------------------------ + +class HammerPuff : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + +PUFFONACTORS + RenderStyle "Translucent"; + Alpha 0.6; + VSpeed 0.8; + SeeSound "FighterHammerHitThing"; + AttackSound "FighterHammerHitWall"; + ActiveSound "FighterHammerMiss"; + } + States + { + Spawn: + FHFX STUVW 4; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/fighterplayer.txt b/wadsrc/static/zscript/hexen/fighterplayer.txt new file mode 100644 index 000000000..3aa5607d3 --- /dev/null +++ b/wadsrc/static/zscript/hexen/fighterplayer.txt @@ -0,0 +1,133 @@ +// The fighter -------------------------------------------------------------- + +class FighterPlayer : PlayerPawn +{ + Default + { + Health 100; + PainChance 255; + Radius 16; + Height 64; + Speed 1; + +NOSKIN + +NODAMAGETHRUST + +PLAYERPAWN.NOTHRUSTWHENINVUL + PainSound "PlayerFighterPain"; + RadiusDamageFactor 0.25; + Player.JumpZ 9; + Player.Viewheight 48; + Player.SpawnClass "Fighter"; + Player.DisplayName "Fighter"; + Player.SoundClass "fighter"; + Player.ScoreIcon "FITEFACE"; + Player.HealRadiusType "Armor"; + Player.Hexenarmor 15, 25, 20, 15, 5; + Player.StartItem "FWeapFist"; + Player.ForwardMove 1.08, 1.2; + Player.SideMove 1.125, 1.475; + Player.Portrait "P_FWALK1"; + Player.WeaponSlot 1, "FWeapFist"; + Player.WeaponSlot 2, "FWeapAxe"; + Player.WeaponSlot 3, "FWeapHammer"; + Player.WeaponSlot 4, "FWeapQuietus"; + + Player.ColorRange 246, 254; + Player.Colorset 0, "Gold", 246, 254, 253; + Player.ColorsetFile 1, "Red", "TRANTBL0", 0xAC; + Player.ColorsetFile 2, "Blue", "TRANTBL1", 0x9D; + Player.ColorsetFile 3, "Dull Green", "TRANTBL2", 0x3E; + Player.ColorsetFile 4, "Green", "TRANTBL3", 0xC8; + Player.ColorsetFile 5, "Gray", "TRANTBL4", 0x2D; + Player.ColorsetFile 6, "Brown", "TRANTBL5", 0x6F; + Player.ColorsetFile 7, "Purple", "TRANTBL6", 0xEE; + } + + States + { + Spawn: + PLAY A -1; + Stop; + See: + PLAY ABCD 4; + Loop; + Missile: + Melee: + PLAY EF 8; + Goto Spawn; + Pain: + PLAY G 4; + PLAY G 4 A_Pain; + Goto Spawn; + Death: + PLAY H 6; + PLAY I 6 A_PlayerScream; + PLAY JK 6; + PLAY L 6 A_NoBlocking; + PLAY M 6; + PLAY N -1; + Stop; + XDeath: + PLAY O 5 A_PlayerScream; + PLAY P 5 A_SkullPop("BloodyFighterSkull"); + PLAY R 5 A_NoBlocking; + PLAY STUV 5; + PLAY W -1; + Stop; + Ice: + PLAY X 5 A_FreezeDeath; + PLAY X 1 A_FreezeDeathChunks; + Wait; + Burn: + FDTH A 5 BRIGHT A_PlaySound("*burndeath"); + FDTH B 4 BRIGHT; + FDTH G 5 BRIGHT; + FDTH H 4 BRIGHT A_PlayerScream; + FDTH I 5 BRIGHT; + FDTH J 4 BRIGHT; + FDTH K 5 BRIGHT; + FDTH L 4 BRIGHT; + FDTH M 5 BRIGHT; + FDTH N 4 BRIGHT; + FDTH O 5 BRIGHT; + FDTH P 4 BRIGHT; + FDTH Q 5 BRIGHT; + FDTH R 4 BRIGHT; + FDTH S 5 BRIGHT A_NoBlocking; + FDTH T 4 BRIGHT; + FDTH U 5 BRIGHT; + FDTH V 4 BRIGHT; + ACLO E 35 A_CheckPlayerDone; + Wait; + ACLO E 8; + Stop; + } +} + +// The fighter's bloody skull -------------------------------------------------------------- + +class BloodyFighterSkull : PlayerChunk +{ + Default + { + Radius 4; + Height 4; + Gravity 0.125; + +NOBLOCKMAP + +DROPOFF + +CANNOTPUSH + +SKYEXPLODE + +NOBLOCKMONST + +NOSKIN + } + + States + { + Spawn: + BSKL A 0; + BSKL ABCDFGH 5 A_CheckFloor("Hit"); + Goto Spawn+1; + Hit: + BSKL I 16 A_CheckPlayerDone; + Wait; + } +} diff --git a/wadsrc/static/zscript/hexen/fighterquietus.txt b/wadsrc/static/zscript/hexen/fighterquietus.txt new file mode 100644 index 000000000..7c94f7901 --- /dev/null +++ b/wadsrc/static/zscript/hexen/fighterquietus.txt @@ -0,0 +1,185 @@ + +// Fighter Weapon Piece ----------------------------------------------------- + +class FighterWeaponPiece : WeaponPiece +{ + Default + { + Inventory.PickupSound "misc/w_pkup"; + Inventory.PickupMessage "$TXT_QUIETUS_PIECE"; + Inventory.ForbiddenTo "ClericPlayer", "MagePlayer"; + WeaponPiece.Weapon "FWeapQuietus"; + +FLOATBOB + } +} + +// Fighter Weapon Piece 1 --------------------------------------------------- + +class FWeaponPiece1 : FighterWeaponPiece +{ + Default + { + WeaponPiece.Number 1; + } + States + { + Spawn: + WFR1 A -1 Bright; + Stop; + } +} + +// Fighter Weapon Piece 2 --------------------------------------------------- + +class FWeaponPiece2 : FighterWeaponPiece +{ + Default + { + WeaponPiece.Number 2; + } + States + { + Spawn: + WFR2 A -1 Bright; + Stop; + } +} + +// Fighter Weapon Piece 3 --------------------------------------------------- + +class FWeaponPiece3 : FighterWeaponPiece +{ + Default + { + WeaponPiece.Number 3; + } + States + { + Spawn: + WFR3 A -1 Bright; + Stop; + } +} + +// Quietus Drop ------------------------------------------------------------- + +class QuietusDrop : Actor +{ + States + { + Spawn: + TNT1 A 1; + TNT1 A 1 A_DropWeaponPieces("FWeaponPiece1", "FWeaponPiece2", "FWeaponPiece3"); + Stop; + } +} + +// The Fighter's Sword (Quietus) -------------------------------------------- + +class FWeapQuietus : FighterWeapon +{ + Default + { + Health 3; + Weapon.SelectionOrder 2900; + +WEAPON.PRIMARY_USES_BOTH; + +Inventory.NoAttenPickupSound + Weapon.AmmoUse1 14; + Weapon.AmmoUse2 14; + Weapon.AmmoGive1 20; + Weapon.AmmoGive2 20; + Weapon.KickBack 150; + Weapon.YAdjust 10; + Weapon.AmmoType1 "Mana1"; + Weapon.AmmoType2 "Mana2"; + Inventory.PickupMessage "$TXT_WEAPON_F4"; + Inventory.PickupSound "WeaponBuild"; + Tag "$TAG_FWEAPQUIETUS"; + } + + action native void A_FSwordAttack(); + + States + { + Spawn: + TNT1 A -1; + Stop; + Select: + FSRD A 1 Bright A_Raise; + Loop; + Deselect: + FSRD A 1 Bright A_Lower; + Loop; + Ready: + FSRD AAAABBBBCCCC 1 Bright A_WeaponReady; + Loop; + Fire: + FSRD DE 3 Bright Offset (5, 36); + FSRD F 2 Bright Offset (5, 36); + FSRD G 3 Bright Offset (5, 36) A_FSwordAttack; + FSRD H 2 Bright Offset (5, 36); + FSRD I 2 Bright Offset (5, 36); + FSRD I 10 Bright Offset (5, 150); + FSRD A 1 Bright Offset (5, 60); + FSRD B 1 Bright Offset (5, 55); + FSRD C 1 Bright Offset (5, 50); + FSRD A 1 Bright Offset (5, 45); + FSRD B 1 Bright Offset (5, 40); + Goto Ready; + } +} + +// Fighter Sword Missile ---------------------------------------------------- + +class FSwordMissile : Actor native +{ + Default + { + Speed 30; + Radius 16; + Height 8; + Damage 8; + Projectile; + +EXTREMEDEATH + RenderStyle "Add"; + DeathSound "FighterSwordExplode"; + Obituary "$OB_MPFWEAPQUIETUS"; + } + + native void A_FSwordFlames(); + + States + { + Spawn: + FSFX ABC 3 Bright; + Loop; + Death: + FSFX D 4 Bright; + FSFX E 3 Bright A_FSwordFlames; + FSFX F 4 Bright A_Explode (64, 128, 0); + FSFX G 3 Bright; + FSFX H 4 Bright; + FSFX I 3 Bright; + FSFX J 4 Bright; + FSFX KLM 3 Bright; + Stop; + } +} + +// Fighter Sword Flame ------------------------------------------------------ + +class FSwordFlame : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + RenderStyle "Translucent"; + Alpha 0.6; + } + States + { + Spawn: + FSFX NOPQRSTUVW 3 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/firedemon.txt b/wadsrc/static/zscript/hexen/firedemon.txt new file mode 100644 index 000000000..b425ecb11 --- /dev/null +++ b/wadsrc/static/zscript/hexen/firedemon.txt @@ -0,0 +1,449 @@ + +// FireDemon ---------------------------------------------------------------- + +class FireDemon : Actor +{ + const FIREDEMON_ATTACK_RANGE = 64*8.; + int strafecount; + + Default + { + Health 80; + ReactionTime 8; + PainChance 1; + Speed 13; + Radius 20; + Height 68; + Mass 75; + Damage 1; + Monster; + +DROPOFF +NOGRAVITY +FLOAT + +FLOORCLIP +INVULNERABLE +TELESTOMP + SeeSound "FireDemonSpawn"; + PainSound "FireDemonPain"; + DeathSound "FireDemonDeath"; + ActiveSound "FireDemonActive"; + Obituary "$OB_FIREDEMON"; + } + + States + { + Spawn: + FDMN X 5 Bright; + FDMN EFG 10 Bright A_Look; + Goto Spawn + 1; + See: + FDMN E 8 Bright; + FDMN F 6 Bright; + FDMN G 5 Bright; + FDMN F 8 Bright; + FDMN E 6 Bright; + FDMN G 7 Bright A_FiredRocks; + FDMN HI 5 Bright; + FDMN J 5 Bright A_UnSetInvulnerable; + Chase: + FDMN ABC 5 Bright A_FiredChase; + Loop; + Pain: + FDMN D 0 Bright A_UnSetInvulnerable; + FDMN D 6 Bright A_Pain; + Goto Chase; + Missile: + FDMN K 3 Bright A_FaceTarget; + FDMN KKK 5 Bright A_FiredAttack; + Goto Chase; + Crash: + XDeath: + FDMN M 5 A_FaceTarget; + FDMN N 5 A_NoBlocking; + FDMN O 5 A_FiredSplotch; + Stop; + Death: + FDMN D 4 Bright A_FaceTarget; + FDMN L 4 Bright A_Scream; + FDMN L 4 Bright A_NoBlocking; + FDMN L 200 Bright; + Stop; + Ice: + FDMN R 5 A_FreezeDeath; + FDMN R 1 A_FreezeDeathChunks; + Wait; + } + + + + + //============================================================================ + // Fire Demon AI + // + // special1 index into floatbob + // strafecount whether strafing or not + //============================================================================ + + //============================================================================ + // + // A_FiredSpawnRock + // + //============================================================================ + + private void A_FiredSpawnRock () + { + Actor mo; + class rtype; + + switch (random[FireDemonRock](0, 4)) + { + case 0: + rtype = "FireDemonRock1"; + break; + case 1: + rtype = "FireDemonRock2"; + break; + case 2: + rtype = "FireDemonRock3"; + break; + case 3: + rtype = "FireDemonRock4"; + break; + case 4: + default: + rtype = "FireDemonRock5"; + break; + } + + double xo = (random[FireDemonRock]() - 128) / 16.; + double yo = (random[FireDemonRock]() - 128) / 16.; + double zo = random[FireDemonRock]() / 32.; + mo = Spawn (rtype, Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + if (mo) + { + mo.target = self; + mo.Vel.X = (random[FireDemonRock]() - 128) / 64.; + mo.Vel.Y = (random[FireDemonRock]() - 128) / 64.; + mo.Vel.Z = (random[FireDemonRock]() / 64.); + mo.special1 = 2; // Number bounces + } + + // Initialize fire demon + strafecount = 0; + bJustAttacked = false; + } + + //============================================================================ + // + // A_FiredRocks + // + //============================================================================ + void A_FiredRocks() + { + A_FiredSpawnRock (); + A_FiredSpawnRock (); + A_FiredSpawnRock (); + A_FiredSpawnRock (); + A_FiredSpawnRock (); + } + + //============================================================================ + // + // A_FiredAttack + // + //============================================================================ + + void A_FiredAttack() + { + if (target == null) return; + Actor mo = SpawnMissile (target, "FireDemonMissile"); + if (mo) A_PlaySound ("FireDemonAttack", CHAN_BODY); + } + + //============================================================================ + // + // A_FiredChase + // + //============================================================================ + + void A_FiredChase() + { + int weaveindex = special1; + double ang; + double dist; + + if (reactiontime) reactiontime--; + if (threshold) threshold--; + + // Float up and down + AddZ(BobSin(weaveindex)); + special1 = (weaveindex + 2) & 63; + + // Ensure it stays above certain height + if (pos.Z < floorz + 64) + { + AddZ(2); + } + + if(!target || !target.bShootable) + { // Invalid target + LookForPlayers (true); + return; + } + + // Strafe + if (strafecount > 0) + { + strafecount--; + } + else + { + strafecount = 0; + Vel.X = Vel.Y = 0; + dist = Distance2D(target); + if (dist < FIREDEMON_ATTACK_RANGE) + { + if (random[FiredChase]() < 30) + { + ang = AngleTo(target); + if (random[FiredChase]() < 128) + ang += 90; + else + ang -= 90; + Thrust(8, ang); + strafecount = 3; // strafe time + } + } + } + + FaceMovementDirection (); + + // Normal movement + if (!strafecount) + { + if (--movecount<0 || !MonsterMove ()) + { + NewChaseDir (); + } + } + + // Do missile attack + if (!bJustAttacked) + { + if (CheckMissileRange () && (random[FiredChase]() < 20)) + { + SetState (MissileState); + bJustAttacked = true; + return; + } + } + else + { + bJustAttacked = false; + } + + // make active sound + if (random[FiredChase]() < 3) + { + PlayActiveSound (); + } + } + + //============================================================================ + // + // A_FiredSplotch + // + //============================================================================ + + void A_FiredSplotch() + { + Actor mo; + + mo = Spawn ("FireDemonSplotch1", Pos, ALLOW_REPLACE); + if (mo) + { + mo.Vel.X = (random[FireDemonSplotch]() - 128) / 32.; + mo.Vel.Y = (random[FireDemonSplotch]() - 128) / 32.; + mo.Vel.Z = (random[FireDemonSplotch]() / 64.) + 3; + } + mo = Spawn ("FireDemonSplotch2", Pos, ALLOW_REPLACE); + if (mo) + { + mo.Vel.X = (random[FireDemonSplotch]() - 128) / 32.; + mo.Vel.Y = (random[FireDemonSplotch]() - 128) / 32.; + mo.Vel.Z = (random[FireDemonSplotch]() / 64.) + 3; + } + } + +} + +// FireDemonSplotch1 ------------------------------------------------------- + +class FireDemonSplotch1 : Actor +{ + Default + { + ReactionTime 8; + Radius 3; + Height 16; + Mass 100; + +DROPOFF +CORPSE + +NOTELEPORT +FLOORCLIP + } + States + { + Spawn: + FDMN P 3; + FDMN P 6 A_QueueCorpse; + FDMN Y -1; + Stop; + } +} + +// FireDemonSplotch2 ------------------------------------------------------- + +class FireDemonSplotch2 : FireDemonSplotch1 +{ + States + { + Spawn: + FDMN Q 3; + FDMN Q 6 A_QueueCorpse; + FDMN Z -1; + Stop; + } +} + +// FireDemonRock1 ------------------------------------------------------------ + +class FireDemonRock1 : Actor +{ + Default + { + ReactionTime 8; + Radius 3; + Height 5; + Mass 16; + +NOBLOCKMAP +DROPOFF +MISSILE + +NOTELEPORT + } + + States + { + Spawn: + FDMN S 4; + Loop; + Death: + FDMN S 5 A_SmBounce; + XDeath: + FDMN S 200; + Stop; + } + + //============================================================================ + // + // A_SmBounce + // + //============================================================================ + + void A_SmBounce() + { + // give some more velocity (x,y,&z) + SetZ(floorz + 1); + Vel.Z = 2. + random[SMBounce]() / 64.; + Vel.X = random[SMBounce](0, 2); + Vel.Y = random[SMBounce](0, 2); + } +} + +// FireDemonRock2 ------------------------------------------------------------ + +class FireDemonRock2 : FireDemonRock1 +{ + States + { + Spawn: + FDMN T 4; + Loop; + Death: + FDMN T 5 A_SmBounce; + XDeath: + FDMN T 200; + Stop; + } +} + +// FireDemonRock3 ------------------------------------------------------------ + +class FireDemonRock3 : FireDemonRock1 +{ + States + { + Spawn: + FDMN U 4; + Loop; + Death: + FDMN U 5 A_SmBounce; + XDeath: + FDMN U 200; + Stop; + } +} + +// FireDemonRock4 ------------------------------------------------------------ + +class FireDemonRock4 : FireDemonRock1 +{ + States + { + Spawn: + FDMN V 4; + Loop; + Death: + FDMN V 5 A_SmBounce; + XDeath: + FDMN V 200; + Stop; + } +} + +// FireDemonRock5 ------------------------------------------------------------ + +class FireDemonRock5 : FireDemonRock1 +{ + States + { + Spawn: + FDMN W 4; + Loop; + Death: + FDMN W 5 A_SmBounce; + XDeath: + FDMN W 200; + Stop; + } +} + +// FireDemonMissile ----------------------------------------------------------- + +class FireDemonMissile : Actor +{ + Default + { + ReactionTime 8; + Speed 10; + Radius 10; + Height 6; + Mass 5; + Damage 1; + DamageType "Fire"; + Projectile; + RenderStyle "Add"; + DeathSound "FireDemonMissileHit"; + } + States + { + Spawn: + FDMB A 5 Bright; + Loop; + Death: + FDMB BCDE 5 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/flame.txt b/wadsrc/static/zscript/hexen/flame.txt new file mode 100644 index 000000000..4eab6c6d3 --- /dev/null +++ b/wadsrc/static/zscript/hexen/flame.txt @@ -0,0 +1,122 @@ +// Temp Small Flame -------------------------------------------------------- + +class FlameSmallTemp : Actor +{ + Default + { + +NOTELEPORT + RenderStyle "Add"; + } + + States + { + Spawn: + FFSM AB 3 Bright; + FFSM C 2 Bright A_CountdownArg(0); + FFSM C 2 Bright; + FFSM D 3 Bright; + FFSM E 3 Bright A_CountdownArg(0); + Loop; + } +} + + +// Temp Large Flame --------------------------------------------------------- + +class FlameLargeTemp : Actor +{ + Default + { + +NOTELEPORT + RenderStyle "Add"; + } + + States + { + Spawn: + FFLG A 4 Bright; + FFLG B 4 Bright A_CountdownArg(0); + FFLG C 4 Bright; + FFLG D 4 Bright A_CountdownArg(0); + FFLG E 4 Bright; + FFLG F 4 Bright A_CountdownArg(0); + FFLG G 4 Bright; + FFLG H 4 Bright A_CountdownArg(0); + FFLG I 4 Bright; + FFLG J 4 Bright A_CountdownArg(0); + FFLG K 4 Bright; + FFLG L 4 Bright A_CountdownArg(0); + FFLG M 4 Bright; + FFLG N 4 Bright A_CountdownArg(0); + FFLG O 4 Bright; + FFLG P 4 Bright A_CountdownArg(0); + Goto Spawn+4; + } +} + +// Small Flame -------------------------------------------------------------- + +class FlameSmall : SwitchableDecoration +{ + Default + { + +NOTELEPORT + +INVISIBLE + Radius 15; + RenderStyle "Add"; + } + + States + { + Active: + FFSM A 0 Bright A_PlaySound("Ignite"); + Spawn: + FFSM A 3 Bright; + FFSM A 3 Bright A_UnHideThing; + FFSM ABCDE 3 Bright; + Goto Spawn+2; + Inactive: + FFSM A 2; + FFSM B 2 A_HideThing; + FFSM C 200; + Wait; + } +} + +class FlameSmall2 : FlameSmall +{ +} + +// Large Flame -------------------------------------------------------------- + +class FlameLarge : SwitchableDecoration +{ + Default + { + +NOTELEPORT + +INVISIBLE + Radius 15; + RenderStyle "Add"; + } + + States + { + Active: + FFLG A 0 Bright A_PlaySound("Ignite"); + Spawn: + FFLG A 2 Bright; + FFLG A 2 Bright A_UnHideThing; + FFLG ABCDEFGHIJKLMNOP 4 Bright; + Goto Spawn+6; + Inactive: + FFLG DCB 2; + FFLG A 2 A_HideThing; + FFLG A 200; + Wait; + } +} + +class FlameLarge2 : FlameLarge +{ +} + diff --git a/wadsrc/static/zscript/hexen/flechette.txt b/wadsrc/static/zscript/hexen/flechette.txt new file mode 100644 index 000000000..6f7b3a818 --- /dev/null +++ b/wadsrc/static/zscript/hexen/flechette.txt @@ -0,0 +1,254 @@ + +// Poison Bag (Flechette used by Cleric) ------------------------------------ + +class PoisonBag : Actor +{ + Default + { + Radius 5; + Height 5; + +NOBLOCKMAP +NOGRAVITY + } + + native void A_PoisonBagInit(); + + States + { + Spawn: + PSBG A 18 Bright; + PSBG B 4 Bright; + PSBG C 3; + PSBG C 1 A_PoisonBagInit; + Stop; + } +} + +// Fire Bomb (Flechette used by Mage) --------------------------------------- + +class FireBomb : Actor +{ + Default + { + DamageType "Fire"; + +NOGRAVITY + +FOILINVUL + RenderStyle "Translucent"; + Alpha 0.6; + DeathSound "FlechetteExplode"; + } + + native void A_TimeBomb(); + + States + { + Spawn: + PSBG A 20; + PSBG AA 10; + PSBG B 4; + PSBG C 4 A_Scream; + XPL1 A 4 Bright A_TimeBomb; + XPL1 BCDEF 4 Bright; + Stop; + } +} + +// Throwing Bomb (Flechette used by Fighter) -------------------------------- + +class ThrowingBomb : Actor +{ + Default + { + Health 48; + Speed 12; + Radius 8; + Height 10; + DamageType "Fire"; + +NOBLOCKMAP +DROPOFF +MISSILE + BounceType "HexenCompat"; + SeeSound "FlechetteBounce"; + DeathSound "FlechetteExplode"; + } + + native void A_CheckThrowBomb(); + native void A_CheckThrowBomb2(); + + States + { + Spawn: + THRW A 4 A_CheckThrowBomb; + THRW BCDE 3 A_CheckThrowBomb; + THRW F 3 A_CheckThrowBomb2; + Loop; + THRW G 6 A_CheckThrowBomb; + THRW F 4 A_CheckThrowBomb; + THRW H 6 A_CheckThrowBomb; + THRW F 4 A_CheckThrowBomb; + THRW G 6 A_CheckThrowBomb; + THRW F 3 A_CheckThrowBomb; + Wait; + Death: + CFCF Q 4 Bright A_NoGravity; + CFCF R 3 Bright A_Scream; + CFCF S 4 Bright A_Explode; + CFCF T 3 Bright; + CFCF U 4 Bright; + CFCF W 3 Bright; + CFCF X 4 Bright; + CFCF Z 3 Bright; + Stop; + } +} + +// Poison Bag Artifact (Flechette) ------------------------------------------ + +class ArtiPoisonBag : Inventory native +{ + Default + { + +FLOATBOB + Inventory.DefMaxAmount; + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.INVBAR +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTIPSBG"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIPOISONBAG"; + Tag "$TAG_ARTIPOISONBAG"; + } + States + { + Spawn: + PSBG A -1; + Stop; + } +} + +// Poison Bag 1 (The Cleric's) ---------------------------------------------- + +class ArtiPoisonBag1 : ArtiPoisonBag native +{ + Default + { + Inventory.Icon "ARTIPSB1"; + Tag "$TAG_ARTIPOISONBAG1"; + } +} + +// Poison Bag 2 (The Mage's) ------------------------------------------------ + +class ArtiPoisonBag2 : ArtiPoisonBag native +{ + Default + { + Inventory.Icon "ARTIPSB2"; + Tag "$TAG_ARTIPOISONBAG2"; + } +} + +// Poison Bag 3 (The Fighter's) --------------------------------------------- + +class ArtiPoisonBag3 : ArtiPoisonBag native +{ + Default + { + Inventory.Icon "ARTIPSB3"; + Tag "$TAG_ARTIPOISONBAG3"; + } +} + +// Poison Bag 4 (Custom Giver) ---------------------------------------------- + +class ArtiPoisonBagGiver : ArtiPoisonBag native +{ + Default + { + Inventory.Icon "ARTIPSB4"; + } +} + +// Poison Bag 5 (Custom Thrower) -------------------------------------------- + +class ArtiPoisonBagShooter : ArtiPoisonBag native +{ + Default + { + Inventory.Icon "ARTIPSB5"; + } +} + +// Poison Cloud ------------------------------------------------------------- + +class PoisonCloud : Actor native +{ + Default + { + Radius 20; + Height 30; + Mass 0x7fffffff; + +NOBLOCKMAP +NOGRAVITY +DROPOFF + +NODAMAGETHRUST + +DONTSPLASH +FOILINVUL +CANBLAST +BLOODLESSIMPACT +BLOCKEDBYSOLIDACTORS + RenderStyle "Translucent"; + Alpha 0.6; + DeathSound "PoisonShroomDeath"; + DamageType "PoisonCloud"; + } + + native void A_PoisonBagDamage(); + native void A_PoisonBagCheck(); + + States + { + Spawn: + PSBG D 1; + PSBG D 1 A_Scream; + PSBG DEEEFFFGGGHHHII 2 A_PoisonBagDamage; + PSBG I 2 A_PoisonBagCheck; + PSBG I 1 A_PoisonBagCheck; + Goto Spawn + 3; + Death: + PSBG HG 7; + PSBG FD 6; + Stop; + } +} + +// Poison Shroom ------------------------------------------------------------ + +class ZPoisonShroom : PoisonBag +{ + Default + { + Radius 6; + Height 20; + PainChance 255; + Health 30; + Mass 0x7fffffff; + +SHOOTABLE + +SOLID + +NOBLOOD + +NOICEDEATH + -NOBLOCKMAP + -NOGRAVITY + PainSound "PoisonShroomPain"; + DeathSound "PoisonShroomDeath"; + } + + native void A_PoisonShroom(); + + States + { + Spawn: + SHRM A 5 A_PoisonShroom; + Goto Pain+1; + Pain: + SHRM A 6; + SHRM B 8 A_Pain; + Goto Spawn; + Death: + SHRM CD 5; + SHRM E 5 A_PoisonBagInit; + SHRM F -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/hexen/flies.txt b/wadsrc/static/zscript/hexen/flies.txt new file mode 100644 index 000000000..464e6e9d9 --- /dev/null +++ b/wadsrc/static/zscript/hexen/flies.txt @@ -0,0 +1,30 @@ + +// Buzzy fly ---------------------------------------------------------------- + +class LittleFly : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + +CANPASS + + Speed 6; + Radius 5; + Height 5; + Mass 2; + ActiveSound "FlyBuzz"; + } + + native void A_FlySearch(); + native void A_FlyBuzz(); + + States + { + Spawn: + TNT1 A 20 A_FlySearch; // [RH] Invisible when not flying + Loop; + Buzz: + AFLY ABCD 3 A_FlyBuzz; + Loop; + } +} diff --git a/wadsrc/static/zscript/hexen/fog.txt b/wadsrc/static/zscript/hexen/fog.txt new file mode 100644 index 000000000..93b5e9593 --- /dev/null +++ b/wadsrc/static/zscript/hexen/fog.txt @@ -0,0 +1,78 @@ + +// Fog Spawner -------------------------------------------------------------- + +class FogSpawner : Actor +{ + Default + { + +NOSECTOR +NOBLOCKMAP + +FLOATBOB + +NOGRAVITY + +INVISIBLE + } + + native void A_FogSpawn(); + + States + { + Spawn: + TNT1 A 20 A_FogSpawn; + Loop; + } +} + +// Small Fog Patch ---------------------------------------------------------- + +class FogPatchSmall : Actor +{ + Default + { + Speed 1; + +NOBLOCKMAP +NOGRAVITY +NOCLIP +FLOAT + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.6; + } + + native void A_FogMove(); + + States + { + Spawn: + FOGS ABCDE 7 A_FogMove; + Loop; + Death: + FOGS E 5; + Stop; + } +} + +// Medium Fog Patch --------------------------------------------------------- + +class FogPatchMedium : FogPatchSmall +{ + States + { + Spawn: + FOGM ABCDE 7 A_FogMove; + Loop; + Death: + FOGS ABCDE 5; + Goto Super::Death; + } +} + +// Large Fog Patch ---------------------------------------------------------- + +class FogPatchLarge : FogPatchMedium +{ + States + { + Spawn: + FOGL ABCDE 7 A_FogMove; + Loop; + Death: + FOGM ABCDEF 4; + Goto Super::Death; + } +} diff --git a/wadsrc/static/zscript/hexen/healingradius.txt b/wadsrc/static/zscript/hexen/healingradius.txt new file mode 100644 index 000000000..94d8e2dd5 --- /dev/null +++ b/wadsrc/static/zscript/hexen/healingradius.txt @@ -0,0 +1,26 @@ + +// Healing Radius Artifact -------------------------------------------------- + +class ArtiHealingRadius : Inventory native +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.DefMaxAmount; + +INVENTORY.INVBAR + +INVENTORY.FANCYPICKUPSOUND + Inventory.PickupFlash "PickupFlash"; + Inventory.Icon "ARTIHRAD"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIHEALINGRADIUS"; + Tag "$TAG_ARTIHEALINGRADIUS"; + } + States + { + Spawn: + HRAD ABCDEFGHIJKLMNOP 4 Bright; + Loop; + } +} + diff --git a/wadsrc/static/zscript/hexen/heresiarch.txt b/wadsrc/static/zscript/hexen/heresiarch.txt new file mode 100644 index 000000000..7d3ba63a5 --- /dev/null +++ b/wadsrc/static/zscript/hexen/heresiarch.txt @@ -0,0 +1,365 @@ + +// The Heresiarch him/itself ------------------------------------------------ + +class Heresiarch native +{ + Default + { + Health 5000; + Painchance 10; + Speed 16; + Radius 40; + Height 110; + Mass 500; + Damage 9; + Monster; + +FLOORCLIP + +BOSS + +DONTMORPH + +NOTARGET + +NOICEDEATH + +DEFLECT + +NOBLOOD + SeeSound "SorcererSight"; + PainSound "SorcererPain"; + DeathSound "SorcererDeathScream"; + ActiveSound "SorcererActive"; + Obituary "$OB_HERESIARCH"; + } + + native void A_SorcSpinBalls(); + native void A_SpeedBalls(); + native void A_SorcBossAttack(); + native void A_SpawnFizzle(); + + States + { + Spawn: + SORC A 3; + SORC A 2 A_SorcSpinBalls; + Idle: + SORC A 10 A_Look; + Wait; + See: + SORC ABCD 5 A_Chase; + Loop; + Pain: + SORC G 8; + SORC G 8 A_Pain; + Goto See; + Missile: + SORC F 6 Bright A_FaceTarget; + SORC F 6 Bright A_SpeedBalls; + SORC F 6 Bright A_FaceTarget; + Wait; + Attack1: + SORC E 6 Bright; + SORC E 6 Bright A_SpawnFizzle; + SORC E 5 Bright A_FaceTarget; + Goto Attack1+1; + Attack2: + SORC E 2 Bright; + SORC E 2 Bright A_SorcBossAttack; + Goto See; + Death: + SORC H 5 Bright; + SORC I 5 Bright A_FaceTarget; + SORC J 5 Bright A_Scream; + SORC KLMNOPQRST 5 Bright; + SORC U 5 Bright A_NoBlocking; + SORC VWXY 5 Bright; + SORC Z -1 Bright; + Stop; + } +} + +// Base class for the balls flying around the Heresiarch's head ------------- + +class SorcBall native +{ + Default + { + Speed 10; + Radius 5; + Height 5; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + +FULLVOLDEATH + +CANBOUNCEWATER + +NOWALLBOUNCESND + BounceType "HexenCompat"; + SeeSound "SorcererBallBounce"; + DeathSound "SorcererBigBallExplode"; + } + + native void A_SorcBallOrbit(); + native void A_SorcBallPop(); + native void A_BounceCheck (); + + void A_SorcBallExplode() + { + bNOBOUNCESOUND = true; + A_Explode(255, 255); + } +} + +// First ball (purple) - fires projectiles ---------------------------------- + +class SorcBall1 : SorcBall native +{ + States + { + Spawn: + SBMP ABCDEFGHIJKLMNOP 2 A_SorcBallOrbit; + Loop; + Pain: + SBMP A 5 A_SorcBallPop; + SBMP B 2 A_BounceCheck; + Wait; + Death: + SBS4 D 5 A_SorcBallExplode; + SBS4 E 5; + SBS4 FGH 6; + Stop; + } +} + + +// Second ball (blue) - generates the shield -------------------------------- + +class SorcBall2 : SorcBall native +{ + States + { + Spawn: + SBMB ABCDEFGHIJKLMNOP 2 A_SorcBallOrbit; + Loop; + Pain: + SBMB A 5 A_SorcBallPop; + SBMB B 2 A_BounceCheck; + Wait; + Death: + SBS3 D 5 A_SorcBallExplode; + SBS3 E 5; + SBS3 FGH 6; + Stop; + } +} + +// Third ball (green) - summons Bishops ------------------------------------- + +class SorcBall3 : SorcBall native +{ + States + { + Spawn: + SBMG ABCDEFGHIJKLMNOP 2 A_SorcBallOrbit; + Loop; + Pain: + SBMG A 5 A_SorcBallPop; + SBMG B 2 A_BounceCheck; + Wait; + Death: + SBS3 D 5 A_SorcBallExplode; + SBS3 E 5; + SBS3 FGH 6; + Stop; + } +} + + +// Sorcerer spell 1 (The burning, bouncing head thing) ---------------------- + +class SorcFX1 : Actor +{ + Default + { + Speed 7; + Radius 5; + Height 5; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + -NOGRAVITY + +FULLVOLDEATH + +CANBOUNCEWATER + +NOWALLBOUNCESND + BounceFactor 1.0; + BounceType "HexenCompat"; + SeeSound "SorcererBallBounce"; + DeathSound "SorcererHeadScream"; + } + + native void A_SorcFX1Seek(); + + States + { + Spawn: + SBS1 A 2 Bright; + SBS1 BCD 3 Bright A_SorcFX1Seek; + Loop; + Death: + FHFX S 2 Bright A_Explode(30, 128); + FHFX SS 6 Bright; + Stop; + } +} + + +// Sorcerer spell 2 (The visible part of the shield) ------------------------ + +class SorcFX2 : Actor +{ + Default + { + Speed 15; + Radius 5; + Height 5; + +NOBLOCKMAP + +NOGRAVITY + +NOTELEPORT + } + + native void A_SorcFX2Split(); + native void A_SorcFX2Orbit (); + + states + { + Spawn: + SBS2 A 3 Bright A_SorcFX2Split; + Loop; + Orbit: + SBS2 A 2 Bright; + SBS2 BCDEFGHIJKLMNOPA 2 Bright A_SorcFX2Orbit; + Goto Orbit+1; + Death: + SBS2 A 10; + Stop; + } +} + +// The translucent trail behind SorcFX2 ------------------------------------- + +class SorcFX2T1 : SorcFX2 +{ + Default + { + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Spawn: + Goto Death; + } +} + + +// Sorcerer spell 3 (The Bishop spawner) ------------------------------------ + +class SorcFX3 : Actor +{ + Default + { + Speed 15; + Radius 22; + Height 65; + +NOBLOCKMAP + +MISSILE + +NOTELEPORT + SeeSound "SorcererBishopSpawn"; + } + + native void A_SpawnBishop(); + native void A_SorcererBishopEntry(); + + States + { + Spawn: + SBS3 ABC 2 Bright; + Loop; + Death: + SBS3 A 4 Bright; + BISH P 4 A_SorcererBishopEntry; + BISH ON 4; + BISH MLKJIH 3; + BISH G 3 A_SpawnBishop; + Stop; + } +} + + +// The Bishop spawner's explosion animation --------------------------------- + +class SorcFX3Explosion : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Spawn: + SBS3 DEFGH 3; + Stop; + } +} + + +// Sorcerer spell 4 (The purple projectile) --------------------------------- + +class SorcFX4 : Actor +{ + Default + { + Speed 12; + Radius 10; + Height 10; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + DeathSound "SorcererBallExplode"; + } + + native void A_SorcFX4Check(); + + States + { + Spawn: + SBS4 ABC 2 Bright A_SorcFX4Check; + Loop; + Death: + SBS4 D 2 Bright; + SBS4 E 2 Bright A_Explode(20, 128); + SBS4 FGH 2 Bright; + Stop; + } +} + + +// Spark that appears when shooting SorcFX4 --------------------------------- + +class SorcSpark1 : Actor +{ + Default + { + Radius 5; + Height 5; + Gravity 0.125; + +NOBLOCKMAP + +DROPOFF + +NOTELEPORT + RenderStyle "Add"; + } + States + { + Spawn: + SBFX ABCDEFG 4 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/hexenarmor.txt b/wadsrc/static/zscript/hexen/hexenarmor.txt new file mode 100644 index 000000000..13b674fbf --- /dev/null +++ b/wadsrc/static/zscript/hexen/hexenarmor.txt @@ -0,0 +1,77 @@ + +// Mesh Armor (1) ----------------------------------------------------------- + +class MeshArmor : HexenArmor +{ + Default + { + +NOGRAVITY + Health 0; // Armor class + Inventory.Amount 0; + Inventory.PickupMessage "$TXT_ARMOR1"; + } + States + { + Spawn: + AR_1 A -1; + Stop; + } +} + +// Falcon Shield (2) -------------------------------------------------------- + +class FalconShield : HexenArmor +{ + Default + { + +NOGRAVITY + Health 1; // Armor class + Inventory.Amount 0; + Inventory.PickupMessage "$TXT_ARMOR2"; + } + States + { + Spawn: + AR_2 A -1; + Stop; + } +} + +// Platinum Helm (3) -------------------------------------------------------- + +class PlatinumHelm : HexenArmor +{ + Default + { + +NOGRAVITY + Health 2; // Armor class + Inventory.Amount 0; + Inventory.PickupMessage "$TXT_ARMOR3"; + } + States + { + Spawn: + AR_3 A -1; + Stop; + } +} + +// Amulet of Warding (4) ---------------------------------------------------- + +class AmuletOfWarding : HexenArmor +{ + Default + { + +NOGRAVITY + Health 3; // Armor class + Inventory.Amount 0; + Inventory.PickupMessage "$TXT_ARMOR4"; + } + States + { + Spawn: + AR_4 A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/hexen/hexendecorations.txt b/wadsrc/static/zscript/hexen/hexendecorations.txt new file mode 100644 index 000000000..937034bd8 --- /dev/null +++ b/wadsrc/static/zscript/hexen/hexendecorations.txt @@ -0,0 +1,1705 @@ +class ZWingedStatue : Actor +{ + Default + { + Radius 10; + Height 62; + +SOLID + } + States + { + Spawn: + STTW A -1; + Stop; + } +} + +class ZRock1 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + RCK1 A -1; + Stop; + } +} + +class ZRock2 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + RCK2 A -1; + Stop; + } +} + +class ZRock3 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + RCK3 A -1; + Stop; + } +} + +class ZRock4 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + RCK4 A -1; + Stop; + } +} + +class ZChandelier : Actor +{ + Default + { + Radius 20; + Height 60; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + CDLR ABC 4; + Loop; + } +} + +class ZChandelierUnlit : Actor +{ + Default + { + Radius 20; + Height 60; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + CDLR D -1; + Stop; + } +} + +class ZTreeDead : Actor +{ + Default + { + Radius 10; + Height 96; + +SOLID + } + States + { + Spawn: + ZTRE A -1; + Stop; + } +} + +class ZTree : Actor +{ + Default + { + Radius 15; + Height 128; + +SOLID + } + States + { + Spawn: + ZTRE A -1; + Stop; + } +} + +class ZTreeSwamp150 : Actor +{ + Default + { + Radius 10; + Height 150; + +SOLID + } + States + { + Spawn: + TRES A -1; + Stop; + } +} + +class ZTreeSwamp120 : Actor +{ + Default + { + Radius 10; + Height 120; + +SOLID + } + States + { + Spawn: + TRE3 A -1; + Stop; + } +} + +class ZStumpBurned : Actor +{ + Default + { + Radius 12; + Height 20; + +SOLID + } + States + { + Spawn: + STM1 A -1; + Stop; + } +} + +class ZStumpBare : Actor +{ + Default + { + Radius 12; + Height 20; + +SOLID + } + States + { + Spawn: + STM2 A -1; + Stop; + } +} + +class ZStumpSwamp1 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + STM3 A -1; + Stop; + } +} + +class ZStumpSwamp2 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + STM4 A -1; + Stop; + } +} + +class ZShroomLarge1 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + MSH1 A -1; + Stop; + } +} + +class ZShroomLarge2 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + MSH2 A -1; + Stop; + } +} + +class ZShroomLarge3 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + MSH3 A -1; + Stop; + } +} + +class ZShroomSmall1 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + MSH4 A -1; + Stop; + } +} + +class ZShroomSmall2 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + MSH5 A -1; + Stop; + } +} + +class ZShroomSmall3 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + MSH6 A -1; + Stop; + } +} + +class ZShroomSmall4 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + MSH7 A -1; + Stop; + } +} + +class ZShroomSmall5 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + MSH8 A -1; + Stop; + } +} + +class ZStalagmitePillar : Actor +{ + Default + { + Radius 8; + Height 138; + +SOLID + } + States + { + Spawn: + SGMP A -1; + Stop; + } +} + +class ZStalagmiteLarge : Actor +{ + Default + { + Radius 8; + Height 48; + +SOLID + } + States + { + Spawn: + SGM1 A -1; + Stop; + } +} + +class ZStalagmiteMedium : Actor +{ + Default + { + Radius 6; + Height 40; + +SOLID + } + States + { + Spawn: + SGM2 A -1; + Stop; + } +} + +class ZStalagmiteSmall : Actor +{ + Default + { + Radius 8; + Height 36; + +SOLID + } + States + { + Spawn: + SGM3 A -1; + Stop; + } +} + +class ZStalactiteLarge : Actor +{ + Default + { + Radius 8; + Height 66; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + SLC1 A -1; + Stop; + } +} + +class ZStalactiteMedium : Actor +{ + Default + { + Radius 6; + Height 50; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + SLC2 A -1; + Stop; + } +} + +class ZStalactiteSmall : Actor +{ + Default + { + Radius 8; + Height 40; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + SLC3 A -1; + Stop; + } +} + +class ZMossCeiling1 : Actor +{ + Default + { + Radius 20; + Height 20; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + MSS1 A -1; + Stop; + } +} + +class ZMossCeiling2 : Actor +{ + Default + { + Radius 20; + Height 24; + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + MSS2 A -1; + Stop; + } +} + +class ZSwampVine : Actor +{ + Default + { + Radius 8; + Height 52; + +SOLID + } + States + { + Spawn: + SWMV A -1; + Stop; + } +} + +class ZCorpseKabob : Actor +{ + Default + { + Radius 10; + Height 92; + +SOLID + } + States + { + Spawn: + CPS1 A -1; + Stop; + } +} + +class ZCorpseSleeping : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + CPS2 A -1; + Stop; + } +} + +class ZTombstoneRIP : Actor +{ + Default + { + Radius 10; + Height 46; + +SOLID + } + States + { + Spawn: + TMS1 A -1; + Stop; + } +} + +class ZTombstoneShane : Actor +{ + Default + { + Radius 10; + Height 46; + +SOLID + } + States + { + Spawn: + TMS2 A -1; + Stop; + } +} + +class ZTombstoneBigCross : Actor +{ + Default + { + Radius 10; + Height 46; + +SOLID + } + States + { + Spawn: + TMS3 A -1; + Stop; + } +} + +class ZTombstoneBrianR : Actor +{ + Default + { + Radius 10; + Height 52; + +SOLID + } + States + { + Spawn: + TMS4 A -1; + Stop; + } +} + +class ZTombstoneCrossCircle : Actor +{ + Default + { + Radius 10; + Height 52; + +SOLID + } + States + { + Spawn: + TMS5 A -1; + Stop; + } +} + +class ZTombstoneSmallCross : Actor +{ + Default + { + Radius 8; + Height 46; + +SOLID + } + States + { + Spawn: + TMS6 A -1; + Stop; + } +} + +class ZTombstoneBrianP : Actor +{ + Default + { + Radius 8; + Height 46; + +SOLID + } + States + { + Spawn: + TMS7 A -1; + Stop; + } +} + +class ZCorpseHanging : Actor +{ + Default + { + Radius 6; + Height 75; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + CPS3 A -1; + Stop; + } +} + +class ZStatueGargoyleGreenTall : Actor +{ + Default + { + Radius 14; + Height 108; + +SOLID + } + States + { + Spawn: + STT2 A -1; + Stop; + } +} + +class ZStatueGargoyleBlueTall : Actor +{ + Default + { + Radius 14; + Height 108; + +SOLID + } + States + { + Spawn: + STT3 A -1; + Stop; + } +} + +class ZStatueGargoyleGreenShort : Actor +{ + Default + { + Radius 14; + Height 62; + +SOLID + } + States + { + Spawn: + STT4 A -1; + Stop; + } +} + +class ZStatueGargoyleBlueShort : Actor +{ + Default + { + Radius 14; + Height 62; + +SOLID + } + States + { + Spawn: + STT5 A -1; + Stop; + } +} + +class ZStatueGargoyleStripeTall : Actor +{ + Default + { + Radius 14; + Height 108; + +SOLID + } + States + { + Spawn: + GAR1 A -1; + Stop; + } +} + +class ZStatueGargoyleDarkRedTall : Actor +{ + Default + { + Radius 14; + Height 108; + +SOLID + } + States + { + Spawn: + GAR2 A -1; + Stop; + } +} + +class ZStatueGargoyleRedTall : Actor +{ + Default + { + Radius 14; + Height 108; + +SOLID + } + States + { + Spawn: + GAR3 A -1; + Stop; + } +} + +class ZStatueGargoyleTanTall : Actor +{ + Default + { + Radius 14; + Height 108; + +SOLID + } + States + { + Spawn: + GAR4 A -1; + Stop; + } +} + +class ZStatueGargoyleRustTall : Actor +{ + Default + { + Radius 14; + Height 108; + +SOLID + } + States + { + Spawn: + GAR5 A -1; + Stop; + } +} + +class ZStatueGargoyleDarkRedShort : Actor +{ + Default + { + Radius 14; + Height 62; + +SOLID + } + States + { + Spawn: + GAR6 A -1; + Stop; + } +} + +class ZStatueGargoyleRedShort : Actor +{ + Default + { + Radius 14; + Height 62; + +SOLID + } + States + { + Spawn: + GAR7 A -1; + Stop; + } +} + +class ZStatueGargoyleTanShort : Actor +{ + Default + { + Radius 14; + Height 62; + +SOLID + } + States + { + Spawn: + GAR8 A -1; + Stop; + } +} + +class ZStatueGargoyleRustShort : Actor +{ + Default + { + Radius 14; + Height 62; + +SOLID + } + States + { + Spawn: + GAR9 A -1; + Stop; + } +} + +class ZBannerTattered : Actor +{ + Default + { + Radius 8; + Height 120; + +SOLID + } + States + { + Spawn: + BNR1 A -1; + Stop; + } +} + +class ZTreeLarge1 : Actor +{ + Default + { + Radius 15; + Height 180; + +SOLID + } + States + { + Spawn: + TRE4 A -1; + Stop; + } +} + +class ZTreeLarge2 : Actor +{ + Default + { + Radius 15; + Height 180; + +SOLID + } + States + { + Spawn: + TRE5 A -1; + Stop; + } +} + +class ZTreeGnarled1 : Actor +{ + Default + { + Radius 22; + Height 100; + +SOLID + } + States + { + Spawn: + TRE6 A -1; + Stop; + } +} + +class ZTreeGnarled2 : Actor +{ + Default + { + Radius 22; + Height 100; + +SOLID + } + States + { + Spawn: + TRE7 A -1; + Stop; + } +} + +class ZLog : Actor +{ + Default + { + Radius 20; + Height 25; + +SOLID + } + States + { + Spawn: + LOGG A -1; + Stop; + } +} + +class ZStalactiteIceLarge : Actor +{ + Default + { + Radius 8; + Height 66; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + ICT1 A -1; + Stop; + } +} + +class ZStalactiteIceMedium : Actor +{ + Default + { + Radius 5; + Height 50; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + ICT2 A -1; + Stop; + } +} + +class ZStalactiteIceSmall : Actor +{ + Default + { + Radius 4; + Height 32; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + ICT3 A -1; + Stop; + } +} + +class ZStalactiteIceTiny : Actor +{ + Default + { + Radius 4; + Height 8; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + ICT4 A -1; + Stop; + } +} + +class ZStalagmiteIceLarge : Actor +{ + Default + { + Radius 8; + Height 66; + +SOLID + } + States + { + Spawn: + ICM1 A -1; + Stop; + } +} + +class ZStalagmiteIceMedium : Actor +{ + Default + { + Radius 5; + Height 50; + +SOLID + } + States + { + Spawn: + ICM2 A -1; + Stop; + } +} + +class ZStalagmiteIceSmall : Actor +{ + Default + { + Radius 4; + Height 32; + +SOLID + } + States + { + Spawn: + ICM3 A -1; + Stop; + } +} + +class ZStalagmiteIceTiny : Actor +{ + Default + { + Radius 4; + Height 8; + +SOLID + } + States + { + Spawn: + ICM4 A -1; + Stop; + } +} + +class ZRockBrown1 : Actor +{ + Default + { + Radius 17; + Height 72; + +SOLID + } + States + { + Spawn: + RKBL A -1; + Stop; + } +} + +class ZRockBrown2 : Actor +{ + Default + { + Radius 15; + Height 50; + +SOLID + } + States + { + Spawn: + RKBS A -1; + Stop; + } +} + +class ZRockBlack : Actor +{ + Default + { + Radius 20; + Height 40; + +SOLID + } + States + { + Spawn: + RKBK A -1; + Stop; + } +} + +class ZRubble1 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + RBL1 A -1; + Stop; + } +} + +class ZRubble2 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + RBL2 A -1; + Stop; + } +} + +class ZRubble3 : Actor +{ + Default + { + Radius 20; + Height 16; + } + States + { + Spawn: + RBL3 A -1; + Stop; + } +} + +class ZVasePillar : Actor +{ + Default + { + Radius 12; + Height 54; + +SOLID + } + States + { + Spawn: + VASE A -1; + Stop; + } +} + +class ZCorpseLynched : Actor +{ + Default + { + Radius 11; + Height 95; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + CPS4 A -1; + Stop; + } +} + +class ZCandle : Actor +{ + Default + { + Radius 20; + Height 16; + +NOGRAVITY + +NOBLOCKMAP + } + States + { + Spawn: + CNDL ABC 4 Bright; + Loop; + } +} + +class ZBarrel : Actor +{ + Default + { + Radius 15; + Height 32; + +SOLID + } + States + { + Spawn: + ZBAR A -1; + Stop; + } +} + +class ZBucket : Actor +{ + Default + { + Radius 8; + Height 72; + +SOLID + +SPAWNCEILING + +NOGRAVITY + } + States + { + Spawn: + BCKT A -1; + Stop; + } +} + +class FireThing : Actor +{ + Default + { + Radius 5; + Height 10; + +SOLID + } + States + { + Spawn: + FSKL A 4 Bright; + FSKL B 3 Bright; + FSKL C 4 Bright; + FSKL D 3 Bright; + FSKL E 4 Bright; + FSKL F 3 Bright; + FSKL G 4 Bright; + FSKL H 3 Bright; + FSKL I 4 Bright; + Loop; + } +} + +class BrassTorch : Actor +{ + Default + { + Radius 6; + Height 35; + +SOLID + } + States + { + Spawn: + BRTR ABCDEFGHIJKLM 4 Bright; + Loop; + } +} + +class ZBlueCandle : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + BCAN ABCDE 5 Bright; + Loop; + } +} + +class ZIronMaiden : Actor +{ + Default + { + Radius 12; + Height 60; + +SOLID + } + States + { + Spawn: + IRON A -1; + Stop; + } +} + +class ZChainBit32 : Actor +{ + Default + { + Radius 4; + Height 32; + +SPAWNCEILING + +NOGRAVITY + +NOBLOCKMAP + } + States + { + Spawn: + CHNS A -1; + Stop; + } +} + +class ZChainBit64 : Actor +{ + Default + { + Radius 4; + Height 64; + +SPAWNCEILING + +NOGRAVITY + +NOBLOCKMAP + } + States + { + Spawn: + CHNS B -1; + Stop; + } +} + +class ZChainEndHeart : Actor +{ + Default + { + Radius 4; + Height 32; + +SPAWNCEILING + +NOGRAVITY + +NOBLOCKMAP + } + States + { + Spawn: + CHNS C -1; + Stop; + } +} + +class ZChainEndHook1 : Actor +{ + Default + { + Radius 4; + Height 32; + +SPAWNCEILING + +NOGRAVITY + +NOBLOCKMAP + } + States + { + Spawn: + CHNS D -1; + Stop; + } +} + +class ZChainEndHook2 : Actor +{ + Default + { + Radius 4; + Height 32; + +SPAWNCEILING + +NOGRAVITY + +NOBLOCKMAP + } + States + { + Spawn: + CHNS E -1; + Stop; + } +} + +class ZChainEndSpike : Actor +{ + Default + { + Radius 4; + Height 32; + +SPAWNCEILING + +NOGRAVITY + +NOBLOCKMAP + } + States + { + Spawn: + CHNS F -1; + Stop; + } +} + +class ZChainEndSkull : Actor +{ + Default + { + Radius 4; + Height 32; + +SPAWNCEILING + +NOGRAVITY + +NOBLOCKMAP + } + States + { + Spawn: + CHNS G -1; + Stop; + } +} + +class TableShit1 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST1 A -1; + Stop; + } +} + +class TableShit2 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST2 A -1; + Stop; + } +} + +class TableShit3 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST3 A -1; + Stop; + } +} + +class TableShit4 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST4 A -1; + Stop; + } +} + +class TableShit5 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST5 A -1; + Stop; + } +} + +class TableShit6 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST6 A -1; + Stop; + } +} + +class TableShit7 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST7 A -1; + Stop; + } +} + +class TableShit8 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST8 A -1; + Stop; + } +} + +class TableShit9 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST9 A -1; + Stop; + } +} + +class TableShit10 : Actor +{ + Default + { + Radius 20; + Height 16; + +NOBLOCKMAP + } + States + { + Spawn: + TST0 A -1; + Stop; + } +} + +class TeleSmoke : Actor +{ + Default + { + Radius 20; + Height 16; + +NOGRAVITY + +NOBLOCKMAP + RenderStyle "Translucent"; + Alpha 0.6; + } + States + { + Spawn: + TSMK A 4; + TSMK B 3; + TSMK C 4; + TSMK D 3; + TSMK E 4; + TSMK F 3; + TSMK G 4; + TSMK H 3; + TSMK I 4; + TSMK J 3; + TSMK K 4; + TSMK L 3; + TSMK M 4; + TSMK N 3; + TSMK O 4; + TSMK P 3; + TSMK Q 4; + TSMK R 3; + TSMK S 4; + TSMK T 3; + TSMK U 4; + TSMK V 3; + TSMK W 4; + TSMK X 3; + TSMK Y 4; + TSMK Z 3; + Loop; + } +} + diff --git a/wadsrc/static/zscript/hexen/hexenkeys.txt b/wadsrc/static/zscript/hexen/hexenkeys.txt new file mode 100644 index 000000000..9bf9f426c --- /dev/null +++ b/wadsrc/static/zscript/hexen/hexenkeys.txt @@ -0,0 +1,175 @@ + +class HexenKey : Key +{ + Default + { + Radius 8; + Height 20; + } +} + +class KeySteel : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT1"; + Inventory.PickupMessage "$TXT_KEY_STEEL"; + } + States + { + Spawn: + KEY1 A -1; + Stop; + } +} + +class KeyCave : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT2"; + Inventory.PickupMessage "$TXT_KEY_CAVE"; + } + States + { + Spawn: + KEY2 A -1; + Stop; + } +} + +class KeyAxe : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT3"; + Inventory.PickupMessage "$TXT_KEY_AXE"; + } + States + { + Spawn: + KEY3 A -1; + Stop; + } +} + +class KeyFire : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT4"; + Inventory.PickupMessage "$TXT_KEY_FIRE"; + } + States + { + Spawn: + KEY4 A -1; + Stop; + } +} + +class KeyEmerald : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT5"; + Inventory.PickupMessage "$TXT_KEY_EMERALD"; + } + States + { + Spawn: + KEY5 A -1; + Stop; + } +} + +class KeyDungeon : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT6"; + Inventory.PickupMessage "$TXT_KEY_DUNGEON"; + } + States + { + Spawn: + KEY6 A -1; + Stop; + } +} + +class KeySilver : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT7"; + Inventory.PickupMessage "$TXT_KEY_SILVER"; + } + States + { + Spawn: + KEY7 A -1; + Stop; + } +} + +class KeyRusted : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT8"; + Inventory.PickupMessage "$TXT_KEY_RUSTED"; + } + States + { + Spawn: + KEY8 A -1; + Stop; + } +} + +class KeyHorn : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOT9"; + Inventory.PickupMessage "$TXT_KEY_HORN"; + } + States + { + Spawn: + KEY9 A -1; + Stop; + } +} + +class KeySwamp : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOTA"; + Inventory.PickupMessage "$TXT_KEY_SWAMP"; + } + States + { + Spawn: + KEYA A -1; + Stop; + } +} + +class KeyCastle : HexenKey +{ + Default + { + Inventory.Icon "KEYSLOTB"; + Inventory.PickupMessage "$TXT_KEY_CASTLE"; + } + States + { + Spawn: + KEYB A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/hexen/hexenspecialdecs.txt b/wadsrc/static/zscript/hexen/hexenspecialdecs.txt new file mode 100644 index 000000000..30ae0fff1 --- /dev/null +++ b/wadsrc/static/zscript/hexen/hexenspecialdecs.txt @@ -0,0 +1,756 @@ + +// Winged Statue (no skull) ------------------------------------------------- + +class ZWingedStatueNoSkull : SwitchingDecoration +{ + Default + { + Radius 10; + Height 62; + +SOLID + } + States + { + Spawn: + STWN A -1; + Stop; + Active: + STWN B -1; + Stop; + } +} + + +// Gem pedestal ------------------------------------------------------------- + +class ZGemPedestal : SwitchingDecoration +{ + Default + { + Radius 10; + Height 40; + +SOLID + } + States + { + Spawn: + GMPD A -1; + Stop; + Active: + GMPD B -1; + Stop; + } +} + + +// Tree (destructible) ------------------------------------------------------ + +class TreeDestructible : Actor +{ + Default + { + Health 70; + Radius 15; + Height 180; + DeathHeight 24; + Mass 0x7fffffff; + PainSound "TreeExplode"; + DeathSound "TreeBreak"; + +SOLID +SHOOTABLE +NOBLOOD +NOICEDEATH + } + States + { + Spawn: + TRDT A -1; + Stop; + Death: + TRDT B 5; + TRDT C 5 A_Scream; + TRDT DEF 5; + TRDT G -1; + Stop; + Burn: + TRDT H 5 Bright A_Pain; + TRDT IJKL 5 Bright; + TRDT M 5 Bright A_Explode(10, 128); + TRDT N 5 Bright; + TRDT OP 5; + TRDT Q -1; + Stop; + } +} + + +// Pottery1 ------------------------------------------------------------------ + +class Pottery1 : Actor native +{ + Default + { + Health 15; + Speed 10; + Height 32; + +SOLID +SHOOTABLE +NOBLOOD +DROPOFF + +SLIDESONWALLS +PUSHABLE +TELESTOMP +CANPASS + +NOICEDEATH + } + + native void A_PotteryExplode(); + + States + { + Spawn: + POT1 A -1; + Loop; + Death: + POT1 A 0 A_PotteryExplode; + Stop; + } +} + +// Pottery2 ----------------------------------------------------------------- + +class Pottery2 : Pottery1 +{ + Default + { + Height 25; + } + States + { + Spawn: + POT2 A -1; + Stop; + } +} + +// Pottery3 ----------------------------------------------------------------- + +class Pottery3 : Pottery1 +{ + Default + { + Height 25; + } + States + { + Spawn: + POT3 A -1; + Stop; + } +} + +// Pottery Bit -------------------------------------------------------------- + +class PotteryBit : Actor +{ + Default + { + Radius 5; + Height 5; + +MISSILE + +NOTELEPORT + +NOICEDEATH + } + + native void A_PotteryChooseBit(); + native void A_PotteryCheck(); + + States + { + Spawn: + PBIT ABCDE -1; + Stop; + Death: + PBIT F 0 A_PotteryChooseBit; + Stop; + Pottery1: + PBIT F 140; + PBIT F 1 A_PotteryCheck; + Stop; + Pottery2: + PBIT G 140; + PBIT G 1 A_PotteryCheck; + Stop; + Pottery3: + PBIT H 140; + PBIT H 1 A_PotteryCheck; + Stop; + Pottery4: + PBIT I 140; + PBIT I 1 A_PotteryCheck; + Stop; + Pottery5: + PBIT J 140; + PBIT J 1 A_PotteryCheck; + Stop; + } +} + + +// Blood pool --------------------------------------------------------------- + +class BloodPool : Actor +{ + States + { + Spawn: + BDPL A -1; + Stop; + } +} + + +// Lynched corpse (no heart) ------------------------------------------------ + +class ZCorpseLynchedNoHeart : Actor native +{ + Default + { + Radius 10; + Height 100; + +SOLID +SPAWNCEILING +NOGRAVITY + } + + native void A_CorpseBloodDrip(); + + States + { + Spawn: + CPS5 A 140 A_CorpseBloodDrip; + Loop; + } +} + + +// CorpseBloodDrip ---------------------------------------------------------- + +class CorpseBloodDrip : Actor +{ + Default + { + Radius 1; + Height 4; + Gravity 0.125; + +MISSILE + +NOICEDEATH + DeathSound "Drip"; + } + States + { + Spawn: + BDRP A -1; + Stop; + Death: + BDSH AB 3; + BDSH CD 2; + Stop; + } +} + + +// Corpse bit --------------------------------------------------------------- + +class CorpseBit : Actor +{ + Default + { + Radius 5; + Height 5; + +NOBLOCKMAP + +TELESTOMP + } + States + { + Spawn: + CPB1 A -1; + Stop; + CPB2 A -1; + Stop; + CPB3 A -1; + Stop; + CPB4 A -1; + Stop; + } +} + + +// Corpse (sitting, splatterable) ------------------------------------------- + +class ZCorpseSitting : Actor +{ + Default + { + Health 30; + Radius 15; + Height 35; + +SOLID +SHOOTABLE +NOBLOOD + +NOICEDEATH + DeathSound "FireDemonDeath"; + } + + native void A_CorpseExplode(); + + States + { + Spawn: + CPS6 A -1; + Stop; + Death: + CPS6 A 1 A_CorpseExplode; + Stop; + } +} + + +// Leaf Spawner ------------------------------------------------------------- + +class LeafSpawner : Actor +{ + Default + { + +NOBLOCKMAP +NOSECTOR + +INVISIBLE + } + + native void A_LeafSpawn(); + + States + { + Spawn: + TNT1 A 20 A_LeafSpawn; + Loop; + } +} + + +// Leaf 1 ------------------------------------------------------------------- + +class Leaf1 : Actor +{ + Default + { + Radius 2; + Height 4; + Gravity 0.125; + +NOBLOCKMAP +MISSILE + +NOTELEPORT +DONTSPLASH + +NOICEDEATH + } + + native void A_LeafThrust(); + native void A_LeafCheck(); + + States + { + Spawn: + LEF1 ABC 4; + LEF1 D 4 A_LeafThrust; + LEF1 EFG 4; + LEF1 H 4 A_LeafThrust; + LEF1 I 4; + LEF1 AB 4; + LEF1 C 4 A_LeafThrust; + LEF1 DEF 4; + LEF1 G 4 A_LeafThrust; + LEF1 HI 4; + Stop; + Death: + LEF3 D 10 A_LeafCheck; + Wait; + } +} + + +// Leaf 2 ------------------------------------------------------------------- + +class Leaf2 : Leaf1 +{ + States + { + Spawn: + LEF2 ABC 4; + LEF2 D 4 A_LeafThrust; + LEF2 EFG 4; + LEF2 H 4 A_LeafThrust; + LEF2 I 4; + LEF2 AB 4; + LEF2 C 4 A_LeafThrust; + LEF2 DEF 4; + LEF2 G 4 A_LeafThrust; + LEF2 HI 4; + Stop; + } +} + + +// Twined torch ------------------------------------------------------------- + +class ZTwinedTorch : SwitchableDecoration +{ + Default + { + Radius 10; + Height 64; + +SOLID + } + States + { + Active: + TWTR A 0 Bright A_PlaySound("Ignite"); + Spawn: + TWTR ABCDEFGH 4 Bright; + Loop; + Inactive: + TWTR I -1; + Stop; + } +} + +class ZTwinedTorchUnlit : ZTwinedTorch +{ + States + { + Spawn: + Goto Super::Inactive; + } +} + + +// Wall torch --------------------------------------------------------------- + +class ZWallTorch : SwitchableDecoration +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +FIXMAPTHINGPOS + Radius 6.5; + } + States + { + Active: + WLTR A 0 Bright A_PlaySound("Ignite"); + Spawn: + WLTR ABCDEFGH 5 Bright; + Loop; + Inactive: + WLTR I -1; + Stop; + } +} + +class ZWallTorchUnlit : ZWallTorch +{ + States + { + Spawn: + Goto Super::Inactive; + } +} + + +// Shrub1 ------------------------------------------------------------------- + +class ZShrub1 : Actor +{ + Default + { + Radius 8; + Height 24; + Health 20; + Mass 0x7fffffff; + +SOLID +SHOOTABLE +NOBLOOD +NOICEDEATH + DeathSound "TreeExplode"; + } + States + { + Spawn: + SHB1 A -1; + Stop; + Burn: + SHB1 B 7 Bright; + SHB1 C 6 Bright A_Scream; + SHB1 D 5 Bright; + Stop; + } +} + + +// Shrub2 ------------------------------------------------------------------- + +class ZShrub2 : Actor +{ + Default + { + Radius 16; + Height 40; + Health 20; + Mass 0x7fffffff; + +SOLID +SHOOTABLE +NOBLOOD +NOICEDEATH + DeathSound "TreeExplode"; + } + States + { + Spawn: + SHB2 A -1; + Stop; + Burn: + SHB2 B 7 Bright; + SHB2 C 6 Bright A_Scream; + SHB2 D 5 Bright A_Explode(30, 64); + SHB2 E 5 Bright; + Stop; + } +} + + +// Fire Bull ---------------------------------------------------------------- + +class ZFireBull : SwitchableDecoration +{ + Default + { + Radius 20; + Height 80; + +SOLID + } + States + { + Active: + FBUL I 4 Bright A_PlaySound("Ignite"); + FBUL J 4 Bright; + Spawn: + FBUL ABCDEFG 4 Bright; + Loop; + Inactive: + FBUL JI 4 Bright; + FBUL H -1; + Stop; + } +} + +class ZFireBullUnlit : ZFireBull +{ + States + { + Spawn: + Goto Super::Inactive+2; + } +} + + +// Suit of armor ------------------------------------------------------------ + +class ZSuitOfArmor : Actor +{ + Default + { + Health 60; + Radius 16; + Height 72; + Mass 0x7fffffff; + +SOLID +SHOOTABLE +NOBLOOD + +NOICEDEATH + DeathSound "SuitofArmorBreak"; + } + + native void A_SoAExplode(); + + States + { + Spawn: + ZSUI A -1; + Stop; + Death: + ZSUI A 1 A_SoAExplode; + Stop; + } +} + + +// Armor chunk -------------------------------------------------------------- + +class ZArmorChunk : Actor +{ + Default + { + Radius 4; + Height 8; + } + States + { + Spawn: + ZSUI B -1; + Stop; + ZSUI C -1; + Stop; + ZSUI D -1; + Stop; + ZSUI E -1; + Stop; + ZSUI F -1; + Stop; + ZSUI G -1; + Stop; + ZSUI H -1; + Stop; + ZSUI I -1; + Stop; + ZSUI J -1; + Stop; + ZSUI K -1; + Stop; + } +} + + +// Bell --------------------------------------------------------------------- + +class ZBell : Actor native +{ + Default + { + Health 5; + Radius 56; + Height 120; + Mass 0x7fffffff; + +SOLID +SHOOTABLE +NOBLOOD +NOGRAVITY +SPAWNCEILING + +NOICEDEATH + DeathSound "BellRing"; + } + + native void A_BellReset1(); + native void A_BellReset2(); + + States + { + Spawn: + BBLL F -1; + Stop; + Death: + BBLL A 4 A_BellReset1; + BBLL BC 4; + BBLL D 5 A_Scream; + BBLL CB 4; + BBLL A 3; + BBLL E 4; + BBLL F 5; + BBLL G 6 A_Scream; + BBLL F 5; + BBLL EA 4; + BBLL BC 5; + BBLL D 6 A_Scream; + BBLL CB 5; + BBLL A 4; + BBLL EF 5; + BBLL G 7 A_Scream; + BBLL FEA 5; + BBLL B 6; + BBLL C 6; + BBLL D 7 A_Scream; + BBLL CB 6; + BBLL A 5; + BBLL EF 6; + BBLL G 7 A_Scream; + BBLL FEABC 6; + BBLL B 7; + BBLL A 8; + BBLL E 12; + BBLL A 10; + BBLL B 12; + BBLL A 12; + BBLL E 14; + BBLL A 1 A_BellReset2; + Goto Spawn; + } +} + + +// "Christmas" Tree --------------------------------------------------------- + +class ZXmasTree : Actor +{ + Default + { + Radius 11; + Height 130; + Health 20; + Mass 0x7fffffff; + +SOLID +SHOOTABLE +NOBLOOD +NOICEDEATH + DeathSound "TreeExplode"; + } + States + { + Spawn: + XMAS A -1; + Stop; + Burn: + XMAS B 6 Bright; + XMAS C 6 Bright A_Scream; + XMAS D 5 Bright; + XMAS E 5 Bright A_Explode(30, 64); + XMAS F 5 Bright; + XMAS G 4 Bright; + XMAS H 5; + XMAS I 4 A_NoBlocking; + XMAS J 4; + XMAS K -1; + Stop; + } +} + +// Cauldron ----------------------------------------------------------------- + +class ZCauldron : SwitchableDecoration +{ + Default + { + Radius 12; + Height 26; + +SOLID + } + States + { + Active: + CDRN B 0 Bright A_PlaySound("Ignite"); + Spawn: + CDRN BCDEFGH 4 Bright; + Loop; + Inactive: + CDRN A -1; + Stop; + } +} + +class ZCauldronUnlit : ZCauldron +{ + States + { + Spawn: + Goto Super::Inactive; + } +} + + +// Water Drip --------------------------------------------------------------- + +class HWaterDrip : Actor +{ + Default + { + +MISSILE + +NOTELEPORT + Gravity 0.125; + Mass 1; + DeathSound "Drip"; + } + States + { + Spawn: + HWAT A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/hexen/iceguy.txt b/wadsrc/static/zscript/hexen/iceguy.txt new file mode 100644 index 000000000..8081d5a61 --- /dev/null +++ b/wadsrc/static/zscript/hexen/iceguy.txt @@ -0,0 +1,185 @@ + +// Ice Guy ------------------------------------------------------------------ + +class IceGuy : Actor +{ + Default + { + Health 120; + PainChance 144; + Speed 14; + Radius 22; + Height 75; + Mass 150; + DamageType "Ice"; + Monster; + +NOBLOOD + +TELESTOMP + +NOICEDEATH + SeeSound "IceGuySight"; + AttackSound "IceGuyAttack"; + ActiveSound "IceGuyActive"; + Obituary "$OB_ICEGUY"; + } + + native void A_IceGuyLook(); + native void A_IceGuyChase(); + native void A_IceGuyAttack(); + + States + { + Spawn: + ICEY A 10 A_IceGuyLook; + Loop; + See: + ICEY A 4 A_Chase; + ICEY B 4 A_IceGuyChase; + ICEY CD 4 A_Chase; + Loop; + Pain: + ICEY A 1 A_Pain; + Goto See; + Missile: + ICEY EF 3 A_FaceTarget; + ICEY G 8 Bright A_IceGuyAttack; + ICEY F 4 A_FaceTarget; + Goto See; + Death: + ICEY A 1 A_IceGuyDie; + Stop; + Inactive: + ICEY A -1; + Goto See; + } +} + +// Ice Guy Projectile ------------------------------------------------------- + +class IceGuyFX : Actor +{ + Default + { + Speed 14; + Radius 8; + Height 10; + Damage 1; + DamageType "Ice"; + Projectile; + -ACTIVATEIMPACT -ACTIVATEPCROSS + DeathSound "IceGuyMissileExplode"; + } + + native void A_IceGuyMissileExplode(); + + States + { + Spawn: + ICPR ABC 3 Bright A_SpawnItemEx("IceFXPuff", 0,0,2); + Loop; + Death: + ICPR D 4 Bright; + ICPR E 4 Bright A_IceGuyMissileExplode; + ICPR FG 4 Bright; + ICPR H 3 Bright; + Stop; + } +} + +// Ice Guy Projectile's Puff ------------------------------------------------ + +class IceFXPuff : Actor +{ + Default + { + Radius 1; + Height 1; + +NOBLOCKMAP +NOGRAVITY +DROPOFF +SHADOW + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Spawn: + ICPR IJK 3; + ICPR LM 2; + Stop; + } +} + +// Secondary Ice Guy Projectile (ejected by the primary projectile) --------- + +class IceGuyFX2 : Actor +{ + Default + { + Speed 10; + Radius 4; + Height 4; + Damage 1; + DamageType "Ice"; + Gravity 0.125; + +NOBLOCKMAP +DROPOFF +MISSILE + +NOTELEPORT + +STRIFEDAMAGE + } + States + { + Spawn: + ICPR NOP 3 Bright; + Loop; + } +} + +// Ice Guy Bit -------------------------------------------------------------- + +class IceGuyBit : Actor +{ + Default + { + Radius 1; + Height 1; + Gravity 0.125; + +NOBLOCKMAP +DROPOFF + +NOTELEPORT + } + States + { + Spawn: + ICPR Q 50 Bright; + Stop; + ICPR R 50 Bright; + Stop; + } +} + +// Ice Guy Wisp 1 ----------------------------------------------------------- + +class IceGuyWisp1 : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Spawn: + ICWS ABCDEFGHI 2; + Stop; + } +} + +// Ice Guy Wisp 2 ----------------------------------------------------------- + +class IceGuyWisp2 : IceGuyWisp1 +{ + States + { + Spawn: + ICWS JKLMNOPQR 2; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/korax.txt b/wadsrc/static/zscript/hexen/korax.txt new file mode 100644 index 000000000..16bf172a4 --- /dev/null +++ b/wadsrc/static/zscript/hexen/korax.txt @@ -0,0 +1,133 @@ +class Korax : Actor +{ + Default + { + Health 5000; + Painchance 20; + Speed 10; + Radius 65; + Height 115; + Mass 2000; + Damage 15; + Monster; + +BOSS + +FLOORCLIP + +TELESTOMP + +DONTMORPH + +NOTARGET + +NOICEDEATH + SeeSound "KoraxSight"; + AttackSound "KoraxAttack"; + PainSound "KoraxPain"; + DeathSound "KoraxDeath"; + ActiveSound "KoraxActive"; + Obituary "$OB_KORAX"; + } + + native void A_KoraxChase(); + native void A_KoraxDecide(); + native void A_KoraxBonePop(); + native void A_KoraxMissile(); + native void A_KoraxCommand(); + + States + { + Spawn: + KORX A 5 A_Look; + Loop; + See: + KORX AAA 3 A_KoraxChase; + KORX B 3 A_Chase; + KORX BBB 3 A_KoraxChase; + KORX C 0 A_PlaySound("KoraxStep"); + KORX C 3 A_Chase; + KORX CCC 3 A_KoraxChase; + KORX D 3 A_Chase; + KORX DDD 3 A_KoraxChase; + KORX A 0 A_PlaySound("KoraxStep"); + KORX A 3 A_Chase; + Loop; + Pain: + KORX H 5 A_Pain; + KORX H 5; + Goto See; + Missile: + KORX E 2 Bright A_FaceTarget; + KORX E 5 Bright A_KoraxDecide; + Wait; + Death: + KORX I 5; + KORX J 5 A_FaceTarget; + KORX K 5 A_Scream; + KORX LMNOP 5; + KORX Q 10; + KORX R 5 A_KoraxBonePop; + KORX S 5 A_NoBlocking; + KORX TU 5; + KORX V -1; + Stop; + Attack: + KORX E 4 Bright A_FaceTarget; + KORX F 8 Bright A_KoraxMissile; + KORX E 8 Bright; + Goto See; + Command: + KORX E 5 Bright A_FaceTarget; + KORX W 10 Bright A_FaceTarget; + KORX G 15 Bright A_KoraxCommand; + KORX W 10 Bright; + KORX E 5 Bright; + Goto See; + } +} + +class KoraxSpirit : Actor +{ + Default + { + Speed 8; + Projectile; + +NOCLIP + -ACTIVATEPCROSS + -ACTIVATEIMPACT + RenderStyle "Translucent"; + Alpha 0.4; + } + + native void A_KSpiritRoam(); + + States + { + Spawn: + SPIR AB 5 A_KSpiritRoam; + Loop; + Death: + SPIR DEFGHI 5; + Stop; + } +} + +class KoraxBolt : Actor +{ + Default + { + Radius 15; + Height 35; + Projectile; + -ACTIVATEPCROSS + -ACTIVATEIMPACT + RenderStyle "Add"; + } + + native void A_KBolt(); + native void A_KBoltRaise(); + + States + { + Spawn: + MLFX I 2 Bright; + MLFX J 2 Bright A_KBoltRaise; + MLFX IJKLM 2 Bright A_KBolt; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/mageboss.txt b/wadsrc/static/zscript/hexen/mageboss.txt new file mode 100644 index 000000000..f9637f8d1 --- /dev/null +++ b/wadsrc/static/zscript/hexen/mageboss.txt @@ -0,0 +1,86 @@ + +// Mage Boss (Menelkir) ----------------------------------------------------- + +class MageBoss : Actor +{ + Default + { + Health 800; + PainChance 50; + Speed 25; + Radius 16; + Height 64; + Monster; + +FLOORCLIP +TELESTOMP + +DONTMORPH + PainSound "PlayerMagePain"; + DeathSound "PlayerMageCrazyDeath"; + Obituary "$OB_MBOSS"; + } + + native void A_MageAttack(); + + States + { + Spawn: + MAGE A 2; + MAGE A 3 A_ClassBossHealth; + MAGE A 5 A_Look; + Wait; + See: + MAGE ABCD 4 A_FastChase; + Loop; + Pain: + MAGE G 4; + MAGE G 4 A_Pain; + Goto See; + Melee: + Missile: + MAGE E 8 A_FaceTarget; + MAGE F 8 Bright A_MageAttack; + Goto See; + Death: + MAGE H 6; + MAGE I 6 A_Scream; + MAGE JK 6; + MAGE L 6 A_NoBlocking; + MAGE M 6; + MAGE N -1; + Stop; + XDeath: + MAGE O 5 A_Scream; + MAGE P 5; + MAGE R 5 A_NoBlocking; + MAGE S 5; + MAGE T 5; + MAGE U 5; + MAGE V 5; + MAGE W 5; + MAGE X -1; + Stop; + Ice: + MAGE Y 5 A_FreezeDeath; + MAGE Y 1 A_FreezeDeathChunks; + Wait; + Burn: + FDTH E 5 Bright A_PlaySound("PlayerMageBurnDeath"); + FDTH F 4 Bright; + FDTH G 5 Bright; + FDTH H 4 Bright A_Scream; + FDTH I 5 Bright; + FDTH J 4 Bright; + FDTH K 5 Bright; + FDTH L 4 Bright; + FDTH M 5 Bright; + FDTH N 4 Bright; + FDTH O 5 Bright; + FDTH P 4 Bright; + FDTH Q 5 Bright; + FDTH R 4 Bright; + FDTH S 5 Bright A_NoBlocking; + FDTH T 4 Bright; + FDTH U 5 Bright; + FDTH V 4 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/magecone.txt b/wadsrc/static/zscript/hexen/magecone.txt new file mode 100644 index 000000000..a9f2d29dc --- /dev/null +++ b/wadsrc/static/zscript/hexen/magecone.txt @@ -0,0 +1,98 @@ + +// The Mage's Frost Cone ---------------------------------------------------- + +class MWeapFrost : MageWeapon +{ + Default + { + +BLOODSPLATTER + Weapon.SelectionOrder 1700; + Weapon.AmmoUse1 3; + Weapon.AmmoGive1 25; + Weapon.KickBack 150; + Weapon.YAdjust 20; + Weapon.AmmoType1 "Mana1"; + Inventory.PickupMessage "$TXT_WEAPON_M2"; + Obituary "$OB_MPMWEAPFROST"; + Tag "$TAG_MWEAPFROST"; + } + + action native void A_FireConePL1(); + + States + { + Spawn: + WMCS ABC 8 Bright; + Loop; + Select: + CONE A 1 A_Raise; + Loop; + Deselect: + CONE A 1 A_Lower; + Loop; + Ready: + CONE A 1 A_WeaponReady; + Loop; + Fire: + CONE B 3; + CONE C 4; + Hold: + CONE D 3; + CONE E 5; + CONE F 3 A_FireConePL1; + CONE G 3; + CONE A 9; + CONE A 10 A_ReFire; + Goto Ready; + } +} + +// Frost Missile ------------------------------------------------------------ + +class FrostMissile : Actor native +{ + Default + { + Speed 25; + Radius 13; + Height 8; + Damage 1; + DamageType "Ice"; + Projectile; + DeathSound "MageShardsExplode"; + Obituary "$OB_MPMWEAPFROST"; + } + + native void A_ShedShard(); + + States + { + Spawn: + SHRD A 2 Bright; + SHRD A 3 Bright A_ShedShard; + SHRD B 3 Bright; + SHRD C 3 Bright; + Loop; + Death: + SHEX ABCDE 5 Bright; + Stop; + } +} + +// Ice Shard ---------------------------------------------------------------- + +class IceShard : FrostMissile +{ + Default + { + DamageType "Ice"; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + } + States + { + Spawn: + SHRD ABC 3 Bright; + Loop; + } +} diff --git a/wadsrc/static/zscript/hexen/magelightning.txt b/wadsrc/static/zscript/hexen/magelightning.txt new file mode 100644 index 000000000..154776d15 --- /dev/null +++ b/wadsrc/static/zscript/hexen/magelightning.txt @@ -0,0 +1,169 @@ + +// The Mage's Lightning Arc of Death ---------------------------------------- + +class MWeapLightning : MageWeapon +{ + Default + { + +NOGRAVITY + Weapon.SelectionOrder 1100; + Weapon.AmmoUse1 5; + Weapon.AmmoGive1 25; + Weapon.KickBack 0; + Weapon.YAdjust 20; + Weapon.AmmoType1 "Mana2"; + Inventory.PickupMessage "$TXT_WEAPON_M3"; + Tag "$TAG_MWEAPLIGHTNING"; + } + + action native void A_LightningReady(); + action native void A_MLightningAttack(class floor = "LightningFloor", class ceiling = "LightningCeiling"); + + States + { + Spawn: + WMLG ABCDEFGH 4 Bright; + Loop; + Select: + MLNG A 1 Bright A_Raise; + Loop; + Deselect: + MLNG A 1 Bright A_Lower; + Loop; + Ready: + MLNG AAAAA 1 Bright A_WeaponReady; + MLNG A 1 Bright A_LightningReady; + MLNG BBBBBB 1 Bright A_WeaponReady; + MLNG CCCCC 1 Bright A_WeaponReady; + MLNG C 1 Bright A_LightningReady; + MLNG BBBBBB 1 Bright A_WeaponReady; + Loop; + Fire: + MLNG DE 3 Bright; + MLNG F 4 Bright A_MLightningAttack; + MLNG G 4 Bright; + MLNG HI 3 Bright; + MLNG I 6 Bright Offset (0, 199); + MLNG C 2 Bright Offset (0, 55); + MLNG B 2 Bright Offset (0, 50); + MLNG B 2 Bright Offset (0, 45); + MLNG B 2 Bright Offset (0, 40); + Goto Ready; + } +} + +// Ceiling Lightning -------------------------------------------------------- + +class Lightning : Actor native +{ + Default + { + MissileType "LightningZap"; + AttackSound "MageLightningZap"; + ActiveSound "MageLightningContinuous"; + Obituary "$OB_MPMWEAPLIGHTNING"; + } +} + +class LightningCeiling : Lightning +{ + Default + { + Health 144; + Speed 25; + Radius 16; + Height 40; + Damage 8; + Projectile; + +CEILINGHUGGER + RenderStyle "Add"; + } + + native void A_LightningZap(); + native void A_LightningClip(); + native void A_LightningRemove(); + + States + { + Spawn: + MLFX A 2 Bright A_LightningZap; + MLFX BCD 2 Bright A_LightningClip; + Loop; + Death: + MLF2 A 2 Bright A_LightningRemove; + MLF2 BCDEKLM 3 Bright; + ACLO E 35; + MLF2 NO 3 Bright; + MLF2 P 4 Bright; + MLF2 QP 3 Bright; + MLF2 Q 4 Bright; + MLF2 P 3 Bright; + MLF2 O 3 Bright; + MLF2 P 3 Bright; + MLF2 P 1 Bright A_HideThing; + ACLO E 1050; + Stop; + } +} + +// Floor Lightning ---------------------------------------------------------- + +class LightningFloor : LightningCeiling +{ + Default + { + -CEILINGHUGGER + +FLOORHUGGER + RenderStyle "Add"; + } + + native void A_LastZap(); + + States + { + Spawn: + MLFX E 2 Bright A_LightningZap; + MLFX FGH 2 Bright A_LightningClip; + Loop; + Death: + MLF2 F 2 Bright A_LightningRemove; + MLF2 GHIJKLM 3 Bright; + ACLO E 20; + MLF2 NO 3 Bright; + MLF2 P 4 Bright; + MLF2 QP 3 Bright; + MLF2 Q 4 Bright A_LastZap; + MLF2 POP 3 Bright; + MLF2 P 1 Bright A_HideThing; + Goto Super::Death + 19; + } +} + +// Lightning Zap ------------------------------------------------------------ + +class LightningZap : Actor native +{ + Default + { + Radius 15; + Height 35; + Damage 2; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + RenderStyle "Add"; + Obituary "$OB_MPMWEAPLIGHTNING"; + } + + native void A_ZapMimic(); + + States + { + Spawn: + MLFX IJKLM 2 Bright A_ZapMimic; + Loop; + Death: + MLFX NOPQRSTU 2 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/mageplayer.txt b/wadsrc/static/zscript/hexen/mageplayer.txt new file mode 100644 index 000000000..33b34633e --- /dev/null +++ b/wadsrc/static/zscript/hexen/mageplayer.txt @@ -0,0 +1,107 @@ +// The mage ----------------------------------------------------------------- + +class MagePlayer : PlayerPawn +{ + Default + { + Health 100; + ReactionTime 0; + PainChance 255; + Radius 16; + Height 64; + Speed 1; + +NOSKIN + +NODAMAGETHRUST + +PLAYERPAWN.NOTHRUSTWHENINVUL + PainSound "PlayerMagePain"; + RadiusDamageFactor 0.25; + Player.JumpZ 9; + Player.Viewheight 48; + Player.SpawnClass "Mage"; + Player.DisplayName "Mage"; + Player.SoundClass "mage"; + Player.ScoreIcon "MAGEFACE"; + Player.InvulnerabilityMode "Reflective"; + Player.HealRadiusType "Mana"; + Player.Hexenarmor 5, 5, 15, 10, 25; + Player.StartItem "MWeapWand"; + Player.ForwardMove 0.88, 0.92; + Player.SideMove 0.875, 0.925; + Player.Portrait "P_MWALK1"; + Player.WeaponSlot 1, "MWeapWand"; + Player.WeaponSlot 2, "MWeapFrost"; + Player.WeaponSlot 3, "MWeapLightning"; + Player.WeaponSlot 4, "MWeapBloodscourge"; + Player.FlechetteType "ArtiPoisonBag2"; + + Player.ColorRange 146, 163; + Player.Colorset 0, "Blue", 146, 163, 161; + Player.ColorsetFile 1, "Red", "TRANTBL7", 0xB3; + Player.ColorsetFile 2, "Gold", "TRANTBL8", 0x8C; + Player.ColorsetFile 3, "Dull Green", "TRANTBL9", 0x41; + Player.ColorsetFile 4, "Green", "TRANTBLA", 0xC9; + Player.ColorsetFile 5, "Gray", "TRANTBLB", 0x30; + Player.ColorsetFile 6, "Brown", "TRANTBLC", 0x72; + Player.ColorsetFile 7, "Purple", "TRANTBLD", 0xEE; + } + + States + { + Spawn: + MAGE A -1; + Stop; + See: + MAGE ABCD 4; + Loop; + Missile: + Melee: + MAGE EF 8; + Goto Spawn; + Pain: + MAGE G 4; + MAGE G 4 A_Pain; + Goto Spawn; + Death: + MAGE H 6; + MAGE I 6 A_PlayerScream; + MAGE JK 6; + MAGE L 6 A_NoBlocking; + MAGE M 6; + MAGE N -1; + Stop; + XDeath: + MAGE O 5 A_PlayerScream; + MAGE P 5; + MAGE R 5 A_NoBlocking; + MAGE STUVW 5; + MAGE X -1; + Stop; + Ice: + MAGE Y 5 A_FreezeDeath; + MAGE Y 1 A_FreezeDeathChunks; + Wait; + Burn: + FDTH E 5 BRIGHT A_PlaySound("*burndeath"); + FDTH F 4 BRIGHT; + FDTH G 5 BRIGHT; + FDTH H 4 BRIGHT A_PlayerScream; + FDTH I 5 BRIGHT; + FDTH J 4 BRIGHT; + FDTH K 5 BRIGHT; + FDTH L 4 BRIGHT; + FDTH M 5 BRIGHT; + FDTH N 4 BRIGHT; + FDTH O 5 BRIGHT; + FDTH P 4 BRIGHT; + FDTH Q 5 BRIGHT; + FDTH R 4 BRIGHT; + FDTH S 5 BRIGHT A_NoBlocking; + FDTH T 4 BRIGHT; + FDTH U 5 BRIGHT; + FDTH V 4 BRIGHT; + ACLO E 35 A_CheckPlayerDone; + Wait; + ACLO E 8; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/magestaff.txt b/wadsrc/static/zscript/hexen/magestaff.txt new file mode 100644 index 000000000..c11542834 --- /dev/null +++ b/wadsrc/static/zscript/hexen/magestaff.txt @@ -0,0 +1,160 @@ + +// Mage Weapon Piece -------------------------------------------------------- + +class MageWeaponPiece : WeaponPiece +{ + Default + { + Inventory.PickupSound "misc/w_pkup"; + Inventory.PickupMessage "$TXT_BLOODSCOURGE_PIECE"; + Inventory.ForbiddenTo "FighterPlayer", "ClericPlayer"; + WeaponPiece.Weapon "MWeapBloodscourge"; + +FLOATBOB + } +} + +// Mage Weapon Piece 1 ------------------------------------------------------ + +class MWeaponPiece1 : MageWeaponPiece +{ + Default + { + WeaponPiece.Number 1; + } + States + { + Spawn: + WMS1 A -1 Bright; + Stop; + } +} + +// Mage Weapon Piece 2 ------------------------------------------------------ + +class MWeaponPiece2 : MageWeaponPiece +{ + Default + { + WeaponPiece.Number 2; + } + States + { + Spawn: + WMS2 A -1 Bright; + Stop; + } +} + +// Mage Weapon Piece 3 ------------------------------------------------------ + +class MWeaponPiece3 : MageWeaponPiece +{ + Default + { + WeaponPiece.Number 3; + } + States + { + Spawn: + WMS3 A -1 Bright; + Stop; + } +} + +// Bloodscourge Drop -------------------------------------------------------- + +class BloodscourgeDrop : Actor +{ + States + { + Spawn: + TNT1 A 1; + TNT1 A 1 A_DropWeaponPieces("MWeaponPiece1", "MWeaponPiece2", "MWeaponPiece3"); + Stop; + } +} + +// The Mages's Staff (Bloodscourge) ----------------------------------------- + +class MWeapBloodscourge : MageWeapon native +{ + Default + { + Health 3; + Weapon.SelectionOrder 3100; + Weapon.AmmoUse1 15; + Weapon.AmmoUse2 15; + Weapon.AmmoGive1 20; + Weapon.AmmoGive2 20; + Weapon.KickBack 150; + Weapon.YAdjust 20; + Weapon.AmmoType1 "Mana1"; + Weapon.AmmoType2 "Mana2"; + +WEAPON.PRIMARY_USES_BOTH; + +Inventory.NoAttenPickupSound + Inventory.PickupMessage "$TXT_WEAPON_M4"; + Inventory.PickupSound "WeaponBuild"; + Tag "$TAG_MWEAPBLOODSCOURGE"; + } + + action native void A_MStaffAttack(); + action native void A_MStaffPalette(); + + States + { + Spawn: + TNT1 A -1; + Stop; + Select: + MSTF A 1 A_Raise; + Loop; + Deselect: + MSTF A 1 A_Lower; + Loop; + Ready: + MSTF AAAAAABBBBBBCCCCCCDDDDDDEEEEEEFFFFF 1 A_WeaponReady; + Loop; + Fire: + MSTF G 4 Offset (0, 40); + MSTF H 4 Bright Offset (0, 48) A_MStaffAttack; + MSTF H 2 Bright Offset (0, 48) A_MStaffPalette; + MSTF II 2 Offset (0, 48) A_MStaffPalette; + MSTF I 1 Offset (0, 40); + MSTF J 5 Offset (0, 36); + Goto Ready; + } +} + +// Mage Staff FX2 (Bloodscourge) -------------------------------------------- + +class MageStaffFX2 : Actor native +{ + Default + { + Speed 17; + Height 8; + Damage 4; + DamageType "Fire"; + Projectile; + +SEEKERMISSILE + +SCREENSEEKER + +EXTREMEDEATH + DeathSound "MageStaffExplode"; + Obituary "$OB_MPMWEAPBLOODSCOURGE"; + } + + native void A_MStaffTrack(); + + States + { + Spawn: + MSP2 ABCD 2 Bright A_MStaffTrack; + Loop; + Death: + MSP2 E 4 Bright A_SetTranslucent(1,1); + MSP2 F 5 Bright A_Explode (80, 192, 0); + MSP2 GH 5 Bright; + MSP2 I 4 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/magewand.txt b/wadsrc/static/zscript/hexen/magewand.txt new file mode 100644 index 000000000..3feb96ae1 --- /dev/null +++ b/wadsrc/static/zscript/hexen/magewand.txt @@ -0,0 +1,81 @@ + +// The Mage's Wand ---------------------------------------------------------- + +class MWeapWand : MageWeapon +{ + Default + { + Weapon.SelectionOrder 3600; + Weapon.KickBack 0; + Weapon.YAdjust 9; + Tag "$TAG_MWEAPWAND"; + } + States + { + Select: + MWND A 1 A_Raise; + Loop; + Deselect: + MWND A 1 A_Lower; + Loop; + Ready: + MWND A 1 A_WeaponReady; + Loop; + Fire: + MWND A 6; + MWND B 6 Bright Offset (0, 48) A_FireCustomMissile ("MageWandMissile"); + MWND A 3 Offset (0, 40); + MWND A 3 Offset (0, 36) A_ReFire; + Goto Ready; + } +} + +// Wand Smoke --------------------------------------------------------------- + +class MageWandSmoke : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY +SHADOW + +NOTELEPORT +CANNOTPUSH +NODAMAGETHRUST + RenderStyle "Translucent"; + Alpha 0.6; + } + States + { + Spawn: + MWND CDCD 4; + Stop; + } +} + +// Wand Missile ------------------------------------------------------------- + +class MageWandMissile : FastProjectile +{ + Default + { + Speed 184; + Radius 12; + Height 8; + Damage 2; + +RIPPER +CANNOTPUSH +NODAMAGETHRUST + +SPAWNSOUNDSOURCE + MissileType "MageWandSmoke"; + SeeSound "MageWandFire"; + Obituary "$OB_MPMWEAPWAND"; + } + States + { + Spawn: + MWND CD 4 Bright; + Loop; + Death: + MWND E 4 Bright; + MWND F 3 Bright; + MWND G 4 Bright; + MWND H 3 Bright; + MWND I 4 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/mana.txt b/wadsrc/static/zscript/hexen/mana.txt new file mode 100644 index 000000000..0a43a21dd --- /dev/null +++ b/wadsrc/static/zscript/hexen/mana.txt @@ -0,0 +1,99 @@ +// Blue mana ---------------------------------------------------------------- + +class Mana1 : Ammo +{ + Default + { + Inventory.Amount 15; + Inventory.MaxAmount 200; + Ammo.BackpackAmount 15; + Ammo.BackpackMaxAmount 200; + Radius 8; + Height 8; + +FLOATBOB + Inventory.Icon "MAN1I0"; + Inventory.PickupMessage "$TXT_MANA_1"; + } + States + { + Spawn: + MAN1 ABCDEFGHI 4 Bright; + Loop; + } +} + +// Green mana --------------------------------------------------------------- + +class Mana2 : Ammo +{ + Default + { + Inventory.Amount 15; + Inventory.MaxAmount 200; + Ammo.BackpackAmount 15; + Ammo.BackpackMaxAmount 200; + Radius 8; + Height 8; + +FLOATBOB + Inventory.Icon "MAN2G0"; + Inventory.PickupMessage "$TXT_MANA_2"; + } + States + { + Spawn: + MAN2 ABCDEFGHIJKLMNOP 4 Bright; + Loop; + } +} + +// Combined mana ------------------------------------------------------------ + +class Mana3 : CustomInventory +{ + Default + { + Radius 8; + Height 8; + +FLOATBOB + Inventory.PickupMessage "$TXT_MANA_BOTH"; + } + States + { + Spawn: + MAN3 ABCDEFGHIJKLMNOP 4 Bright; + Loop; + Pickup: + TNT1 A 0 A_GiveInventory("Mana1", 20); + TNT1 A 0 A_GiveInventory("Mana2", 20); + Stop; + } +} + +// Boost Mana Artifact Krater of Might ------------------------------------ + +class ArtiBoostMana : CustomInventory +{ + Default + { + +FLOATBOB + +COUNTITEM + +INVENTORY.INVBAR + +INVENTORY.FANCYPICKUPSOUND + Inventory.PickupFlash "PickupFlash"; + Inventory.DefMaxAmount; + Inventory.Icon "ARTIBMAN"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIBOOSTMANA"; + Tag "$TAG_ARTIBOOSTMANA"; + } + States + { + Spawn: + BMAN A -1; + Stop; + Use: + TNT1 A 0 A_GiveInventory("Mana1", 200); + TNT1 A 0 A_GiveInventory("Mana2", 200); + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/pig.txt b/wadsrc/static/zscript/hexen/pig.txt new file mode 100644 index 000000000..8fa446882 --- /dev/null +++ b/wadsrc/static/zscript/hexen/pig.txt @@ -0,0 +1,170 @@ + + +// Snout puff --------------------------------------------------------------- + +class SnoutPuff : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + Renderstyle "Translucent"; + Alpha 0.6; + } + + States + { + Spawn: + FHFX STUVW 4; + Stop; + } +} + + +// Snout -------------------------------------------------------------------- + +class Snout : Weapon +{ + Default + { + Weapon.SelectionOrder 10000; + +WEAPON.DONTBOB + +WEAPON.MELEEWEAPON + Weapon.Kickback 150; + Weapon.YAdjust 10; + } + + action native void A_SnoutAttack (); + + States + { + Ready: + WPIG A 1 A_WeaponReady; + Loop; + Deselect: + WPIG A 1 A_Lower; + Loop; + Select: + WPIG A 1 A_Raise; + Fire: + WPIG A 4 A_SnoutAttack; + WPIG B 8 A_SnoutAttack; + Goto Ready; + Grunt: + WPIG B 8; + Goto Ready; + } +} + + +// Pig player --------------------------------------------------------------- + +class PigPlayer : PlayerPawn native +{ + Default + { + Health 30; + ReactionTime 0; + PainChance 255; + Radius 16; + Height 24; + Speed 1; + +WINDTHRUST + +NOSKIN + -PICKUP + PainSound "PigPain"; + DeathSound "PigDeath"; + Player.JumpZ 6; + Player.Viewheight 28; + Player.ForwardMove 0.96, 0.98; + Player.SideMove 0.95833333, 0.975; + Player.SpawnClass "Pig"; + Player.SoundClass "Pig"; + Player.DisplayName "Pig"; + Player.MorphWeapon "Snout"; + } + + States + { + Spawn: + PIGY A -1; + Stop; + See: + PIGY ABCD 3; + Loop; + Pain: + PIGY D 4 A_PigPain; + Goto Spawn; + Melee: + Missile: + PIGY A 12; + Goto Spawn; + Death: + PIGY E 4 A_Scream; + PIGY F 3 A_NoBlocking; + PIGY G 4; + PIGY H 3; + PIGY IJK 4; + PIGY L -1; + Stop; + Ice: + PIGY M 5 A_FreezeDeath; + PIGY M 1 A_FreezeDeathChunks; + Wait; + } +} + + + +// Pig (non-player) --------------------------------------------------------- + +class Pig : MorphedMonster +{ + Default + { + Health 25; + Painchance 128; + Speed 10; + Radius 12; + Height 22; + Mass 60; + Monster; + -COUNTKILL + +WINDTHRUST + +DONTMORPH + SeeSound "PigActive1"; + PainSound "PigPain"; + DeathSound "PigDeath"; + ActiveSound "PigActive1"; + } + + States + { + Spawn: + PIGY B 10 A_Look; + Loop; + See: + PIGY ABCD 3 A_Chase; + Loop; + Pain: + PIGY D 4 A_PigPain; + Goto See; + Melee: + PIGY A 5 A_FaceTarget; + PIGY A 10 A_CustomMeleeAttack(random[PigAttack](2,3), "PigAttack"); + Goto See; + Death: + PIGY E 4 A_Scream; + PIGY F 3 A_NoBlocking; + PIGY G 4 A_QueueCorpse; + PIGY H 3; + PIGY IJK 4; + PIGY L -1; + Stop; + Ice: + PIGY M 5 A_FreezeDeath; + PIGY M 1 A_FreezeDeathChunks; + Wait; + } +} + diff --git a/wadsrc/static/zscript/hexen/puzzleitems.txt b/wadsrc/static/zscript/hexen/puzzleitems.txt new file mode 100644 index 000000000..f502664d7 --- /dev/null +++ b/wadsrc/static/zscript/hexen/puzzleitems.txt @@ -0,0 +1,338 @@ + +// Yorick's Skull ----------------------------------------------------------- + +class PuzzSkull : PuzzleItem +{ + Default + { + PuzzleItem.Number 0; + Inventory.Icon "ARTISKLL"; + Inventory.PickupMessage "$TXT_ARTIPUZZSKULL"; + Tag "$TAG_ARTIPUZZSKULL"; + } + States + { + Spawn: + ASKU A -1; + Stop; + } +} + + +// Heart of D'Sparil -------------------------------------------------------- + +class PuzzGemBig : PuzzleItem +{ + Default + { + PuzzleItem.Number 1; + Inventory.Icon "ARTIBGEM"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEMBIG"; + Tag "$TAG_ARTIPUZZGEMBIG"; + } + States + { + Spawn: + ABGM A -1; + Stop; + } +} + +// Red Gem (Ruby Planet) ---------------------------------------------------- + +class PuzzGemRed : PuzzleItem +{ + Default + { + PuzzleItem.Number 2; + Inventory.Icon "ARTIGEMR"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEMRED"; + Tag "$TAG_ARTIPUZZGEMRED"; + } + States + { + Spawn: + AGMR A -1; + Stop; + } +} + + +// Green Gem 1 (Emerald Planet) --------------------------------------------- + +class PuzzGemGreen1 : PuzzleItem +{ + Default + { + PuzzleItem.Number 3; + Inventory.Icon "ARTIGEMG"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEMGREEN1"; + Tag "$TAG_ARTIPUZZGEMGREEN1"; + } + States + { + Spawn: + AGMG A -1; + Stop; + } +} + + +// Green Gem 2 (Emerald Planet) --------------------------------------------- + +class PuzzGemGreen2 : PuzzleItem +{ + Default + { + PuzzleItem.Number 4; + Inventory.Icon "ARTIGMG2"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEMGREEN2"; + Tag "$TAG_ARTIPUZZGEMGREEN2"; + } + States + { + Spawn: + AGG2 A -1; + Stop; + } +} + + +// Blue Gem 1 (Sapphire Planet) --------------------------------------------- + +class PuzzGemBlue1 : PuzzleItem +{ + Default + { + PuzzleItem.Number 5; + Inventory.Icon "ARTIGEMB"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEMBLUE1"; + Tag "$TAG_ARTIPUZZGEMBLUE1"; + } + States + { + Spawn: + AGMB A -1; + Stop; + } +} + + +// Blue Gem 2 (Sapphire Planet) --------------------------------------------- + +class PuzzGemBlue2 : PuzzleItem +{ + Default + { + PuzzleItem.Number 6; + Inventory.Icon "ARTIGMB2"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEMBLUE2"; + Tag "$TAG_ARTIPUZZGEMBLUE2"; + } + States + { + Spawn: + AGB2 A -1; + Stop; + } +} + + +// Book 1 (Daemon Codex) ---------------------------------------------------- + +class PuzzBook1 : PuzzleItem +{ + Default + { + PuzzleItem.Number 7; + Inventory.Icon "ARTIBOK1"; + Inventory.PickupMessage "$TXT_ARTIPUZZBOOK1"; + Tag "$TAG_ARTIPUZZBOOK1"; + } + States + { + Spawn: + ABK1 A -1; + Stop; + } +} + + +// Book 2 (Liber Oscura) ---------------------------------------------------- + +class PuzzBook2 : PuzzleItem +{ + Default + { + PuzzleItem.Number 8; + Inventory.Icon "ARTIBOK2"; + Inventory.PickupMessage "$TXT_ARTIPUZZBOOK2"; + Tag "$TAG_ARTIPUZZBOOK2"; + } + States + { + Spawn: + ABK2 A -1; + Stop; + } +} + + +// Flame Mask --------------------------------------------------------------- + + +class PuzzFlameMask : PuzzleItem +{ + Default + { + PuzzleItem.Number 9; + Inventory.Icon "ARTISKL2"; + Inventory.PickupMessage "$TXT_ARTIPUZZSKULL2"; + Tag "$TAG_ARTIPUZZSKULL2"; + } + States + { + Spawn: + ASK2 A -1; + Stop; + } +} + +// Fighter Weapon (Glaive Seal) --------------------------------------------- + +class PuzzFWeapon : PuzzleItem +{ + Default + { + PuzzleItem.Number 10; + Inventory.Icon "ARTIFWEP"; + Inventory.PickupMessage "$TXT_ARTIPUZZFWEAPON"; + Tag "$TAG_ARTIPUZZFWEAPON"; + } + States + { + Spawn: + AFWP A -1; + Stop; + } +} + + +// Cleric Weapon (Holy Relic) ----------------------------------------------- + +class PuzzCWeapon : PuzzleItem +{ + Default + { + PuzzleItem.Number 11; + Inventory.Icon "ARTICWEP"; + Inventory.PickupMessage "$TXT_ARTIPUZZCWEAPON"; + Tag "$TAG_ARTIPUZZCWEAPON"; + } + States + { + Spawn: + ACWP A -1; + Stop; + } +} + + +// Mage Weapon (Sigil of the Magus) ----------------------------------------- + +class PuzzMWeapon : PuzzleItem +{ + Default + { + PuzzleItem.Number 12; + Inventory.Icon "ARTIMWEP"; + Inventory.PickupMessage "$TXT_ARTIPUZZMWEAPON"; + Tag "$TAG_ARTIPUZZMWEAPON"; + } + States + { + Spawn: + AMWP A -1; + Stop; + } +} + +// Clock Gear 1 ------------------------------------------------------------- + +class PuzzGear1 : PuzzleItem +{ + Default + { + PuzzleItem.Number 13; + Inventory.Icon "ARTIGEAR"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEAR"; + Tag "$TAG_ARTIPUZZGEAR1"; + } + States + { + Spawn: + AGER ABCDEFGH 4 Bright; + Loop; + } +} + + +// Clock Gear 2 ------------------------------------------------------------- + +class PuzzGear2 : PuzzleItem +{ + Default + { + PuzzleItem.Number 14; + Inventory.Icon "ARTIGER2"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEAR"; + Tag "$TAG_ARTIPUZZGEAR2"; + } + States + { + Spawn: + AGR2 ABCDEFGH 4 Bright; + Loop; + } +} + + +// Clock Gear 3 ------------------------------------------------------------- + +class PuzzGear3 : PuzzleItem +{ + Default + { + PuzzleItem.Number 15; + Inventory.Icon "ARTIGER3"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEAR"; + Tag "$TAG_ARTIPUZZGEAR3"; + } + States + { + Spawn: + AGR3 ABCDEFGH 4 Bright; + Loop; + } +} + + +// Clock Gear 4 ------------------------------------------------------------- + +class PuzzGear4 : PuzzleItem +{ + Default + { + PuzzleItem.Number 16; + Inventory.Icon "ARTIGER4"; + Inventory.PickupMessage "$TXT_ARTIPUZZGEAR"; + Tag "$TAG_ARTIPUZZGEAR4"; + } + States + { + Spawn: + AGR4 ABCDEFGH 4 Bright; + Loop; + } +} + diff --git a/wadsrc/static/zscript/hexen/scriptprojectiles.txt b/wadsrc/static/zscript/hexen/scriptprojectiles.txt new file mode 100644 index 000000000..5bf3f254f --- /dev/null +++ b/wadsrc/static/zscript/hexen/scriptprojectiles.txt @@ -0,0 +1,141 @@ +// Fire Ball ---------------------------------------------------------------- + +class FireBall : Actor +{ + Default + { + Speed 2; + Radius 8; + Height 8; + Damage 4; + DamageType "Fire"; + +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE + +NOTELEPORT + RenderStyle "Add"; + DeathSound "Fireball"; + } + States + { + Spawn: + FBL1 AB 4 Bright; + Loop; + Death: + XPL1 ABCDEF 4 Bright; + Stop; + } +} + +// Arrow -------------------------------------------------------------------- + +class Arrow : Actor +{ + Default + { + Speed 6; + Radius 8; + Height 4; + Damage 4; + +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ARRW A -1; + Stop; + Death: + ARRW A 1; + Stop; + } +} + +// Dart --------------------------------------------------------------------- + +class Dart : Actor +{ + Default + { + Speed 6; + Radius 8; + Height 4; + Damage 2; + +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE + +NOTELEPORT + } + States + { + Spawn: + DART A -1; + Stop; + Death: + DART A 1; + Stop; + } +} + +// Poison Dart -------------------------------------------------------------- + +class PoisonDart : Dart +{ + Default + { + PoisonDamage 20; + } +} + +// Ripper Ball -------------------------------------------------------------- + +class RipperBall : Actor +{ + Default + { + Speed 6; + Radius 8; + Damage 2; + +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE + +NOTELEPORT +RIPPER + } + States + { + Spawn: + RIPP ABC 3; + Loop; + Death: + CFCF Q 4 Bright; + CFCF R 3 Bright; + CFCF S 4 Bright; + CFCF T 3 Bright; + CFCF U 4 Bright; + CFCF V 3 Bright; + CFCF W 4 Bright; + CFCF X 3 Bright; + CFCF Y 4 Bright; + CFCF Z 3 Bright; + Stop; + } +} + +// Projectile Blade --------------------------------------------------------- + +class ProjectileBlade : Actor +{ + Default + { + Speed 6; + Radius 6; + Height 6; + Damage 3; + +NOBLOCKMAP +NOGRAVITY +DROPOFF +MISSILE + +NOTELEPORT + } + States + { + Spawn: + BLAD A -1; + Stop; + Death: + BLAD A 1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/hexen/serpent.txt b/wadsrc/static/zscript/hexen/serpent.txt new file mode 100644 index 000000000..70fb2195a --- /dev/null +++ b/wadsrc/static/zscript/hexen/serpent.txt @@ -0,0 +1,238 @@ + +// Serpent ------------------------------------------------------------------ + +class Serpent : Actor +{ + Default + { + Health 90; + PainChance 96; + Speed 12; + Radius 32; + Height 70; + Mass 0x7fffffff; + Monster; + -SHOOTABLE + +NOBLOOD + +CANTLEAVEFLOORPIC +NONSHOOTABLE + +STAYMORPHED +DONTBLAST +NOTELEOTHER + +INVISIBLE + SeeSound "SerpentSight"; + AttackSound "SerpentAttack"; + PainSound "SerpentPain"; + DeathSound "SerpentDeath"; + HitObituary "$OB_SERPENTHIT"; + } + + native void A_SerpentHumpDecide(); + native void A_SerpentHide(); + native void A_SerpentCheckForAttack(); + native void A_SerpentSpawnGibs(); + native void A_SerpentUnHide(); + native void A_SerpentRaiseHump(); + native void A_SerpentLowerHump(); + native void A_SerpentChooseAttack(); + native void A_SerpentMeleeAttack(); + + States + { + Spawn: + SSPT H 10 A_Look; + Loop; + See: + SSPT HH 1 A_Chase("Melee", null, CHF_NIGHTMAREFAST|CHF_NOPLAYACTIVE); + SSPT H 2 A_SerpentHumpDecide; + Loop; + Pain: + SSPT L 5; + SSPT L 5 A_Pain; + Dive: + SSDV ABC 4; + SSDV D 4 A_UnSetShootable; + SSDV E 3 A_PlaySound("SerpentActive", CHAN_BODY); + SSDV F 3; + SSDV GH 4; + SSDV I 3; + SSDV J 3 A_SerpentHide; + Goto See; + Melee: + SSPT A 1 A_UnHideThing; + SSPT A 1 A_PlaySound("SerpentBirth", CHAN_BODY); + SSPT B 3 A_SetShootable; + SSPT C 3; + SSPT D 4 A_SerpentCheckForAttack; + Goto Dive; + Death: + SSPT O 4; + SSPT P 4 A_Scream; + SSPT Q 4 A_NoBlocking; + SSPT RSTUVWXYZ 4; + Stop; + XDeath: + SSXD A 4; + SSXD B 4 A_SpawnItemEx("SerpentHead", 0, 0, 45); + SSXD C 4 A_NoBlocking; + SSXD DE 4; + SSXD FG 3; + SSXD H 3 A_SerpentSpawnGibs; + Stop; + Ice: + SSPT [ 5 A_FreezeDeath; + SSPT [ 1 A_FreezeDeathChunks; + Wait; + Walk: + SSPT IJI 5 A_Chase("Attack", null, CHF_NIGHTMAREFAST); + SSPT J 5 A_SerpentCheckForAttack; + Goto Dive; + Hump: + SSPT H 3 A_SerpentUnHide; + SSPT EFGEF 3 A_SerpentRaiseHump; + SSPT GEF 3; + SSPT GEFGE 3 A_SerpentLowerHump; + SSPT F 3 A_SerpentHide; + Goto See; + Attack: + SSPT K 6 A_FaceTarget; + SSPT L 5 A_SerpentChooseAttack; + Goto MeleeAttack; + MeleeAttack: + SSPT N 5 A_SerpentMeleeAttack; + Goto Dive; + } +} + +// Serpent Leader ----------------------------------------------------------- + +class SerpentLeader : Serpent +{ + Default + { + Mass 200; + Obituary "$OB_SERPENT"; + } + States + { + Missile: + SSPT N 5 A_CustomMissile("SerpentFX", 32, 0); + Goto Dive; + } +} + +// Serpent Missile Ball ----------------------------------------------------- + +class SerpentFX : Actor +{ + Default + { + Speed 15; + Radius 8; + Height 10; + Damage 4; + Projectile; + -ACTIVATEIMPACT -ACTIVATEPCROSS + RenderStyle "Add"; + DeathSound "SerpentFXHit"; + } + States + { + Spawn: + SSFX A 0; + SSFX A 3 Bright A_PlaySound("SerpentFXContinuous", CHAN_BODY, 1.0, 1); + SSFX BAB 3 Bright; + Goto Spawn+1; + Death: + SSFX C 4 Bright A_StopSound(CHAN_BODY); + SSFX DEFGH 4 Bright; + Stop; + } +} + +// Serpent Head ------------------------------------------------------------- + +class SerpentHead : Actor +{ + Default + { + Radius 5; + Height 10; + Gravity 0.125; + +NOBLOCKMAP + } + + native void A_SerpentHeadCheck(); + + States + { + Spawn: + SSXD IJKLMNOP 4 A_SerpentHeadCheck; + Loop; + Death: + SSXD S -1; + Loop; + } +} + +// Serpent Gib 1 ------------------------------------------------------------ + +class SerpentGib1 : Actor +{ + Default + { + Radius 3; + Height 3; + +NOBLOCKMAP +NOGRAVITY + } + + native void A_FloatGib(); + native void A_DelayGib(); + native void A_SinkGib(); + + States + { + Spawn: + SSXD Q 6; + SSXD Q 6 A_FloatGib; + SSXD QQ 8 A_FloatGib; + SSXD QQ 12 A_FloatGib; + SSXD Q 232 A_DelayGib; + SSXD QQ 12 A_SinkGib; + SSXD QQQ 8 A_SinkGib; + Stop; + } +} + +// Serpent Gib 2 ------------------------------------------------------------ + +class SerpentGib2 : SerpentGib1 +{ + States + { + Spawn: + SSXD R 6; + SSXD R 6 A_FloatGib; + SSXD RR 8 A_FloatGib; + SSXD RR 12 A_FloatGib; + SSXD R 232 A_DelayGib; + SSXD RR 12 A_SinkGib; + SSXD RRR 8 A_SinkGib; + Stop; + } +} + +// Serpent Gib 3 ------------------------------------------------------------ + +class SerpentGib3 : SerpentGib1 +{ + States + { + Spawn: + SSXD T 6; + SSXD T 6 A_FloatGib; + SSXD TT 8 A_FloatGib; + SSXD TT 12 A_FloatGib; + SSXD T 232 A_DelayGib; + SSXD TT 12 A_SinkGib; + SSXD TTT 8 A_SinkGib; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/speedboots.txt b/wadsrc/static/zscript/hexen/speedboots.txt new file mode 100644 index 000000000..e5a0364ec --- /dev/null +++ b/wadsrc/static/zscript/hexen/speedboots.txt @@ -0,0 +1,21 @@ + + +class ArtiSpeedBoots : PowerupGiver +{ + Default + { + +FLOATBOB + +COUNTITEM + Inventory.PickupFlash "PickupFlash"; + Inventory.Icon "ARTISPED"; + Inventory.PickupMessage "$TXT_ARTISPEED"; + Tag "$TAG_ARTISPEED"; + Powerup.Type "PowerSpeed"; + } + States + { + Spawn: + SPED ABCDEFGH 3 Bright; + Loop; + } +} diff --git a/wadsrc/static/zscript/hexen/spike.txt b/wadsrc/static/zscript/hexen/spike.txt new file mode 100644 index 000000000..58f763ccc --- /dev/null +++ b/wadsrc/static/zscript/hexen/spike.txt @@ -0,0 +1,116 @@ + +// Dirt clump (spawned by spike) -------------------------------------------- + +class DirtClump : Actor +{ + Default + { + +NOBLOCKMAP + +NOTELEPORT + } + States + { + Spawn: + TSPK C 20; + Loop; + } +} + +// Spike (thrust floor) ----------------------------------------------------- + +class ThrustFloor : Actor native +{ + Default + { + Radius 20; + Height 128; + } + + native void A_ThrustRaise(); + native void A_ThrustImpale(); + native void A_ThrustLower(); + native void A_ThrustInitDn(); + native void A_ThrustInitUp(); + + States + { + ThrustRaising: + TSPK A 2 A_ThrustRaise; + Loop; + BloodThrustRaising: + TSPK B 2 A_ThrustRaise; + Loop; + ThrustLower: + TSPK A 2 A_ThrustLower; + Loop; + BloodThrustLower: + TSPK B 2 A_ThrustLower; + Loop; + ThrustInit1: + TSPK A 3; + TSPK A 4 A_ThrustInitDn; + TSPK A -1; + Loop; + BloodThrustInit1: + TSPK B 3; + TSPK B 4 A_ThrustInitDn; + TSPK B -1; + Loop; + ThrustInit2: + TSPK A 3; + TSPK A 4 A_ThrustInitUp; + TSPK A 10; + Loop; + BloodThrustInit2: + TSPK B 3; + TSPK B 4 A_ThrustInitUp; + TSPK B 10; + Loop; + ThrustRaise: + TSPK A 8 A_ThrustRaise; + TSPK A 6 A_ThrustRaise; + TSPK A 4 A_ThrustRaise; + TSPK A 3 A_SetSolid; + TSPK A 2 A_ThrustImpale; + Loop; + BloodThrustRaise: + TSPK B 8 A_ThrustRaise; + TSPK B 6 A_ThrustRaise; + TSPK B 4 A_ThrustRaise; + TSPK B 3 A_SetSolid; + TSPK B 2 A_ThrustImpale; + Loop; + } +} + +// Spike up ----------------------------------------------------------------- + +class ThrustFloorUp : ThrustFloor +{ + Default + { + +SOLID + +NOTELEPORT +FLOORCLIP + } + States + { + Spawn: + Goto ThrustInit2; + } +} + +// Spike down --------------------------------------------------------------- + +class ThrustFloorDown : ThrustFloor +{ + Default + { + +NOTELEPORT +FLOORCLIP + +INVISIBLE + } + States + { + Spawn: + Goto ThrustInit1; + } +} diff --git a/wadsrc/static/zscript/hexen/summon.txt b/wadsrc/static/zscript/hexen/summon.txt new file mode 100644 index 000000000..06ceb7e17 --- /dev/null +++ b/wadsrc/static/zscript/hexen/summon.txt @@ -0,0 +1,71 @@ + +// Dark Servant Artifact ---------------------------------------------------- + +class ArtiDarkServant : Inventory native +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.RespawnTics 4230; + Inventory.DefMaxAmount; + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.INVBAR + +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTISUMN"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTISUMMON"; + Tag "$TAG_ARTISUMMON"; + } + States + { + Spawn: + SUMN A 350; + Loop; + } +} + +// Summoning Doll ----------------------------------------------------------- + +class SummoningDoll : Actor +{ + Default + { + Speed 20; + +NOBLOCKMAP +DROPOFF +MISSILE + +NOTELEPORT + } + + native void A_Summon(); + + States + { + Spawn: + SUMN A 4; + Loop; + Death: + SUMN AA 4; + SUMN A 4 A_Summon; + Stop; + } +} + +// Minotaur Smoke ----------------------------------------------------------- + +class MinotaurSmoke : Actor +{ + Default + { + +NOBLOCKMAP +NOGRAVITY + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.6; + + } + States + { + Spawn: + MNSM ABCDEFGHIJKLMNOPQ 3; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/teleportother.txt b/wadsrc/static/zscript/hexen/teleportother.txt new file mode 100644 index 000000000..2de144d5f --- /dev/null +++ b/wadsrc/static/zscript/hexen/teleportother.txt @@ -0,0 +1,130 @@ + +// Teleport Other Artifact -------------------------------------------------- + +class ArtiTeleportOther : Inventory native +{ + Default + { + +COUNTITEM + +FLOATBOB + +INVENTORY.INVBAR + +INVENTORY.FANCYPICKUPSOUND + Inventory.PickupFlash "PickupFlash"; + Inventory.DefMaxAmount; + Inventory.Icon "ARTITELO"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTITELEPORTOTHER"; + Tag "$TAG_ARTITELEPORTOTHER"; + } + States + { + Spawn: + TELO ABCD 5; + Loop; + } +} + + +// Teleport Other FX -------------------------------------------------------- + +class TelOtherFX1 : Actor native +{ + Default + { + Damage 10001; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + +BLOODLESSIMPACT + Radius 16; + Height 16; + Speed 20; + } + + native void A_TeloSpawnA(); + native void A_TeloSpawnB(); + native void A_TeloSpawnC(); + native void A_TeloSpawnD(); + native void A_CheckTeleRing (); + + States + { + Spawn: + TRNG E 5 Bright; + TRNG D 4 Bright; + TRNG C 3 Bright A_TeloSpawnC; + TRNG B 3 Bright A_TeloSpawnB; + TRNG A 3 Bright A_TeloSpawnA; + TRNG B 3 Bright A_TeloSpawnB; + TRNG C 3 Bright A_TeloSpawnC; + TRNG D 3 Bright A_TeloSpawnD; + Goto Spawn+2; + Death: + TRNG E 3 Bright; + Stop; + } +} + + +class TelOtherFX2 : TelOtherFX1 +{ + Default + { + Speed 16; + } + States + { + Spawn: + TRNG BCDCB 4 Bright; + TRNG A 4 Bright A_CheckTeleRing; + Loop; + } +} + +class TelOtherFX3 : TelOtherFX1 +{ + Default + { + Speed 16; + } + States + { + Spawn: + TRNG CDCBA 4 Bright; + TRNG B 4 Bright A_CheckTeleRing; + Loop; + } +} + +class TelOtherFX4 : TelOtherFX1 +{ + Default + { + Speed 16; + } + States + { + Spawn: + TRNG DCBAB 4 Bright; + TRNG C 4 Bright A_CheckTeleRing; + Loop; + } + +} + +class TelOtherFX5 : TelOtherFX1 +{ + Default + { + Speed 16; + } + States + { + Spawn: + TRNG CBABC 4 Bright; + TRNG D 4 Bright A_CheckTeleRing; + Loop; + } +} + + diff --git a/wadsrc/static/zscript/hexen/wraith.txt b/wadsrc/static/zscript/hexen/wraith.txt new file mode 100644 index 000000000..86df72d94 --- /dev/null +++ b/wadsrc/static/zscript/hexen/wraith.txt @@ -0,0 +1,236 @@ + +// Wraith ------------------------------------------------------------------- + +class Wraith : Actor +{ + Default + { + Health 150; + PainChance 25; + Speed 11; + Height 55; + Mass 75; + Damage 10; + Monster; + +NOGRAVITY +DROPOFF +FLOAT + +FLOORCLIP +TELESTOMP + SeeSound "WraithSight"; + AttackSound "WraithAttack"; + PainSound "WraithPain"; + DeathSound "WraithDeath"; + ActiveSound "WraithActive"; + HitObituary "$OB_WRAITHHIT"; + Obituary "$OB_WRAITH"; + } + + native void A_WraithInit(); + native void A_WraithChase(); + native void A_WraithFX3(); + native void A_WraithMelee(); + + States + { + Spawn: + WRTH A 10; + WRTH B 5 A_WraithInit; + Goto Look; + Look: + WRTH AB 15 A_Look; + Loop; + See: + WRTH ABCD 4 A_WraithChase; + Loop; + Pain: + WRTH A 2; + WRTH H 6 A_Pain; + Goto See; + Melee: + WRTH E 6 A_FaceTarget; + WRTH F 6 A_WraithFX3; + WRTH G 6 A_WraithMelee; + Goto See; + Missile: + WRTH E 6 A_FaceTarget; + WRTH F 6; + WRTH G 6 A_CustomMissile("WraithFX1"); + Goto See; + Death: + WRTH I 4; + WRTH J 4 A_Scream; + WRTH KL 4; + WRTH M 4 A_NoBlocking; + WRTH N 4 A_QueueCorpse; + WRTH O 4; + WRTH PQ 5; + WRTH R -1; + Stop; + XDeath: + WRT2 A 5; + WRT2 B 5 A_Scream; + WRT2 CD 5; + WRT2 E 5 A_NoBlocking; + WRT2 F 5 A_QueueCorpse; + WRT2 G 5; + WRT2 H -1; + Stop; + Ice: + WRT2 I 5 A_FreezeDeath; + WRT2 I 1 A_FreezeDeathChunks; + Wait; + } +} + +// Buried wraith ------------------------------------------------------------ + +class WraithBuried : Wraith +{ + Default + { + Height 68; + -SHOOTABLE + -SOLID + +DONTMORPH + +DONTBLAST + +SPECIALFLOORCLIP + +STAYMORPHED + +INVISIBLE + PainChance 0; + } + + native void A_WraithRaiseInit(); + native void A_WraithRaise(); + + States + { + Spawn: + Goto Super::Look; + See: + WRTH A 2 A_WraithRaiseInit; + WRTH A 2 A_WraithRaise; + WRTH A 2 A_FaceTarget; + WRTH BB 2 A_WraithRaise; + Goto See + 1; + Chase: + Goto Super::See; + } +} + +// Wraith FX 1 -------------------------------------------------------------- + +class WraithFX1 : Actor +{ + Default + { + Speed 14; + Radius 10; + Height 6; + Mass 5; + Damage 5; + DamageType "Fire"; + Projectile; + +FLOORCLIP + SeeSound "WraithMissileFire"; + DeathSound "WraithMissileExplode"; + } + + native void A_WraithFX2(); + + States + { + Spawn: + WRBL A 3 Bright; + WRBL B 3 Bright A_WraithFX2; + WRBL C 3 Bright; + Loop; + Death: + WRBL D 4 Bright; + WRBL E 4 Bright A_WraithFX2; + WRBL F 4 Bright; + WRBL GH 3 Bright A_WraithFX2; + WRBL I 3 Bright; + Stop; + } +} + +// Wraith FX 2 -------------------------------------------------------------- + +class WraithFX2 : Actor +{ + Default + { + Radius 2; + Height 5; + Mass 5; + +NOBLOCKMAP +DROPOFF + +FLOORCLIP +NOTELEPORT + } + States + { + Spawn: + WRBL JKLMNOP 4 Bright; + Stop; + } +} + +// Wraith FX 3 -------------------------------------------------------------- + +class WraithFX3 : Actor +{ + Default + { + Radius 2; + Height 5; + Mass 5; + +NOBLOCKMAP +DROPOFF +MISSILE + +FLOORCLIP +NOTELEPORT + DeathSound "Drip"; + } + States + { + Spawn: + WRBL QRS 4 Bright; + Loop; + Death: + WRBL S 4 Bright; + Stop; + } +} + +// Wraith FX 4 -------------------------------------------------------------- + +class WraithFX4 : Actor +{ + Default + { + Radius 2; + Height 5; + Mass 5; + +NOBLOCKMAP +DROPOFF +MISSILE + +NOTELEPORT + DeathSound "Drip"; + } + States + { + Spawn: + WRBL TUVW 4; + Loop; + Death: + WRBL W 10; + Stop; + } +} + +// Wraith FX 5 -------------------------------------------------------------- + +class WraithFX5 : WraithFX4 +{ + States + { + Spawn: + WRBL XYZ 7; + Loop; + Death: + WRBL Z 35; + Stop; + } +} diff --git a/wadsrc/static/zscript/raven/artiegg.txt b/wadsrc/static/zscript/raven/artiegg.txt new file mode 100644 index 000000000..ef3c6e2be --- /dev/null +++ b/wadsrc/static/zscript/raven/artiegg.txt @@ -0,0 +1,114 @@ + +// Egg missile -------------------------------------------------------------- + +class EggFX : MorphProjectile +{ + Default + { + Radius 8; + Height 8; + Speed 18; + MorphProjectile.PlayerClass "ChickenPlayer"; + MorphProjectile.MonsterClass "Chicken"; + MorphProjectile.MorphStyle MRF_UNDOBYTOMEOFPOWER; + } + States + { + Spawn: + EGGM ABCDE 4; + Loop; + Death: + FX01 FFGH 3 Bright; + Stop; + } +} + + +// Morph Ovum ---------------------------------------------------------------- + +class ArtiEgg : CustomInventory +{ + Default + { + +COUNTITEM + +FLOATBOB + +INVENTORY.INVBAR + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTIEGGC"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIEGG"; + Inventory.DefMaxAmount; + Tag "$TAG_ARTIEGG"; + } + States + { + Spawn: + EGGC ABCB 6; + Loop; + Use: + TNT1 A 0 A_FireCustomMissile("EggFX", -15, 0, 0, 0, 1); + TNT1 A 0 A_FireCustomMissile("EggFX", -7.5, 0, 0, 0, 1); + TNT1 A 0 A_FireCustomMissile("EggFX", 0, 0, 0, 0, 1); + TNT1 A 0 A_FireCustomMissile("EggFX", 7.5, 0, 0, 0, 1); + TNT1 A 0 A_FireCustomMissile("EggFX", 15, 0, 0, 0, 1); + Stop; + } +} + +// Pork missile -------------------------------------------------------------- + +class PorkFX : MorphProjectile +{ + Default + { + Radius 8; + Height 8; + Speed 18; + MorphProjectile.PlayerClass "PigPlayer"; + MorphProjectile.MonsterClass "Pig"; + MorphProjectile.MorphStyle MRF_UNDOBYTOMEOFPOWER|MRF_UNDOBYCHAOSDEVICE; + } + States + { + Spawn: + PRKM ABCDE 4; + Loop; + Death: + FHFX IJKL 3 Bright; + Stop; + } +} + +// Porkalator --------------------------------------------------------------- + +class ArtiPork : CustomInventory +{ + Default + { + +COUNTITEM + +FLOATBOB + +INVENTORY.INVBAR + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTIPORK"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIEGG2"; + Inventory.DefMaxAmount; + Tag "$TAG_ARTIPORK"; + } + States + { + Spawn: + PORK ABCDEFGH 5; + Loop; + Use: + TNT1 A 0 A_FireCustomMissile("PorkFX", -15, 0, 0, 0, 1); + TNT1 A 0 A_FireCustomMissile("PorkFX", -7.5, 0, 0, 0, 1); + TNT1 A 0 A_FireCustomMissile("PorkFX", 0, 0, 0, 0, 1); + TNT1 A 0 A_FireCustomMissile("PorkFX", 7.5, 0, 0, 0, 1); + TNT1 A 0 A_FireCustomMissile("PorkFX", 15, 0, 0, 0, 1); + Stop; + } +} + diff --git a/wadsrc/static/zscript/raven/artitele.txt b/wadsrc/static/zscript/raven/artitele.txt new file mode 100644 index 000000000..9f21bd733 --- /dev/null +++ b/wadsrc/static/zscript/raven/artitele.txt @@ -0,0 +1,27 @@ + +// Teleport (self) ---------------------------------------------------------- + +class ArtiTeleport : Inventory native +{ + Default + { + +COUNTITEM + +FLOATBOB + +INVENTORY.INVBAR + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.FANCYPICKUPSOUND + Inventory.DefMaxAmount; + Inventory.Icon "ARTIATLP"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTITELEPORT"; + Tag "$TAG_ARTITELEPORT"; + } + States + { + Spawn: + ATLP ABCB 4; + Loop; + } +} + + diff --git a/wadsrc/static/zscript/raven/minotaur.txt b/wadsrc/static/zscript/raven/minotaur.txt new file mode 100644 index 000000000..9bbbe81a0 --- /dev/null +++ b/wadsrc/static/zscript/raven/minotaur.txt @@ -0,0 +1,236 @@ +class Minotaur : Actor native +{ + Default + { + Health 3000; + Radius 28; + Height 100; + Mass 800; + Speed 16; + Damage 7; + Painchance 25; + Monster; + +DROPOFF + +FLOORCLIP + +BOSS + +NORADIUSDMG + +DONTMORPH + +NOTARGET + +BOSSDEATH + SeeSound "minotaur/sight"; + AttackSound "minotaur/attack1"; + PainSound "minotaur/pain"; + DeathSound "minotaur/death"; + ActiveSound "minotaur/active"; + DropItem "ArtiSuperHealth", 51; + DropItem "PhoenixRodAmmo", 84, 10; + } + + native void A_MinotaurDecide(); + native void A_MinotaurAtk1(); + native void A_MinotaurAtk2(); + native void A_MinotaurAtk3(); + native void A_MinotaurCharge(); + native void A_MinotaurLook(); + native void A_MinotaurRoam(); + native void A_MinotaurChase(); + native void A_MinotaurDeath(); + + States + { + Spawn: + MNTR AB 10 A_MinotaurLook; + Loop; + Roam: + MNTR ABCD 5 A_MinotaurRoam; + Loop; + See: + MNTR ABCD 5 A_MinotaurChase; + Loop; + Melee: + MNTR V 10 A_FaceTarget; + MNTR W 7 A_FaceTarget; + MNTR X 12 A_MinotaurAtk1; + Goto See; + Missile: + MNTR V 10 A_MinotaurDecide; + MNTR Y 4 A_FaceTarget; + MNTR Z 9 A_MinotaurAtk2; + Goto See; + Hammer: + MNTR V 10 A_FaceTarget; + MNTR W 7 A_FaceTarget; + MNTR X 12 A_MinotaurAtk3; + Goto See; + HammerLoop: + MNTR X 12; + Goto Hammer; + Charge: + MNTR U 2 A_MinotaurCharge; + Loop; + Pain: + MNTR E 3; + MNTR E 6 A_Pain; + Goto See; + Death: + MNTR F 6 A_MinotaurDeath; + MNTR G 5; + MNTR H 6 A_Scream; + MNTR I 5; + MNTR J 6; + MNTR K 5; + MNTR L 6; + MNTR M 5 A_NoBlocking; + MNTR N 6; + MNTR O 5; + MNTR P 6; + MNTR Q 5; + MNTR R 6; + MNTR S 5; + MNTR T -1 A_BossDeath; + Stop; + FadeOut: + MNTR E 6; + MNTR E 2 A_Scream; + MNTR E 5 A_SpawnItemEx("MinotaurSmokeExit"); + MNTR E 5; + MNTR E 5 A_NoBlocking; + MNTR E 5; + MNTR E 5 A_SetTranslucent(0.66, 0); + MNTR E 5 A_SetTranslucent(0.33, 0); + MNTR E 10 A_BossDeath; + Stop; + } +} + +class MinotaurFriend : Minotaur native +{ + Default + { + Health 2500; + -DROPOFF + -BOSS + -DONTMORPH + +FRIENDLY + +NOTARGETSWITCH + +STAYMORPHED + +TELESTOMP + +SUMMONEDMONSTER + RenderStyle "Translucent"; + Alpha 0.3333; + DropItem "None"; + } + States + { + Spawn: + MNTR A 15; + MNTR A 15 A_SetTranslucent(0.66, 0); + MNTR A 3 A_SetTranslucent(1, 0); + Goto Super::Spawn; + Idle: + Goto Super::Spawn; + Death: + Goto FadeOut; + } +} + +// Minotaur FX 1 ------------------------------------------------------------ + +class MinotaurFX1 : Actor +{ + Default + { + Radius 10; + Height 6; + Speed 20; + FastSpeed 26; + Damage 3; + DamageType "Fire"; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + RenderStyle "Add"; + } + States + { + Spawn: + FX12 AB 6 Bright; + Loop; + Death: + FX12 CDEFGH 5 Bright; + Stop; + } +} + + +// Minotaur FX 2 ------------------------------------------------------------ + +class MinotaurFX2 : MinotaurFX1 +{ + Default + { + Radius 5; + Height 12; + Speed 14; + FastSpeed 20; + Damage 4; + +FLOORHUGGER + ExplosionDamage 24; + DeathSound "minotaur/fx2hit"; + } + + native void A_MntrFloorFire(); + + states + { + Spawn: + FX13 A 2 Bright A_MntrFloorFire; + Loop; + Death: + FX13 I 4 Bright A_Explode; + FX13 JKLM 4 Bright; + Stop; + } +} + +// Minotaur FX 3 ------------------------------------------------------------ + +class MinotaurFX3 : MinotaurFX2 +{ + Default + { + Radius 8; + Height 16; + Speed 0; + DeathSound "minotaur/fx3hit"; + ExplosionDamage 128; + } + States + { + Spawn: + FX13 DC 4 Bright; + FX13 BCDE 5 Bright; + FX13 FGH 4 Bright; + Stop; + } +} + +// Minotaur Smoke Exit ------------------------------------------------------ + +class MinotaurSmokeExit : Actor +{ + Default + { + +NOBLOCKMAP + +NOTELEPORT + RenderStyle "Translucent"; + Alpha 0.4; + } + States + { + Spawn: + MNSM ABCDEFGHIJIHGFEDCBA 3; + Stop; + } +} + diff --git a/wadsrc/static/zscript/raven/ravenambient.txt b/wadsrc/static/zscript/raven/ravenambient.txt new file mode 100644 index 000000000..3495dc4e0 --- /dev/null +++ b/wadsrc/static/zscript/raven/ravenambient.txt @@ -0,0 +1,42 @@ + + +// Wind --------------------------------------------------------------------- + +class SoundWind : Actor +{ + Default + { + +NOBLOCKMAP + +NOSECTOR + +DONTSPLASH + } + States + { + Spawn: + TNT1 A 2 A_PlaySound("world/wind", CHAN_6); + Loop; + } +} + +class SoundWindHexen : SoundWind +{ +} + + +// Waterfall ---------------------------------------------------------------- + +class SoundWaterfall : Actor +{ + Default + { + +NOBLOCKMAP + +NOSECTOR + +DONTSPLASH + } + States + { + Spawn: + TNT1 A 2 A_PlaySound("world/waterfall", CHAN_6); + Loop; + } +} diff --git a/wadsrc/static/zscript/raven/ravenartifacts.txt b/wadsrc/static/zscript/raven/ravenartifacts.txt new file mode 100644 index 000000000..443816788 --- /dev/null +++ b/wadsrc/static/zscript/raven/ravenartifacts.txt @@ -0,0 +1,143 @@ + +// Health ------------------------------------------------------------------- + +class ArtiHealth : HealthPickup +{ + Default + { + Health 25; + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTIPTN2"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTIHEALTH"; + Tag "$TAG_ARTIHEALTH"; + HealthPickup.Autouse 1; + } + States + { + Spawn: + PTN2 ABC 4; + Loop; + } +} + +// Super health ------------------------------------------------------------- + +class ArtiSuperHealth : HealthPickup +{ + Default + { + Health 100; + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + +INVENTORY.FANCYPICKUPSOUND + Inventory.Icon "ARTISPHL"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_ARTISUPERHEALTH"; + Tag "$TAG_ARTISUPERHEALTH"; + HealthPickup.Autouse 2; + } + States + { + Spawn: + SPHL A 350; + Loop; + } +} + +// Flight ------------------------------------------------------------------- + +class ArtiFly : PowerupGiver +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + Inventory.InterHubAmount 0; + Inventory.RespawnTics 4230; + Inventory.Icon "ARTISOAR"; + Inventory.PickupMessage "$TXT_ARTIFLY"; + Tag "$TAG_ARTIFLY"; + Powerup.Type "PowerFlight"; + } + States + { + Spawn: + SOAR ABCB 5; + Loop; + } +} + +// Invulnerability Heretic (Ring of invincibility) -------------------------- + +class ArtiInvulnerability : PowerupGiver +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + Inventory.RespawnTics 4230; + Inventory.Icon "ARTIINVU"; + Inventory.PickupMessage "$TXT_ARTIINVULNERABILITY"; + Tag "$TAG_ARTIINVULNERABILITY"; + Powerup.Type "PowerInvulnerable"; + Powerup.Color "GoldMap"; + } + States + { + Spawn: + INVU ABCD 3; + Loop; + } +} + +// Invulnerability Hexen (Icon of the defender) ----------------------------- + +class ArtiInvulnerability2 : PowerupGiver +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + Inventory.RespawnTics 4230; + Inventory.Icon "ARTIDEFN"; + Inventory.PickupMessage "$TXT_ARTIINVULNERABILITY2"; + Powerup.Type "PowerInvulnerable"; + Tag "$TAG_ARTIDEFENDER"; + } + States + { + Spawn: + DEFN ABCD 3; + Loop; + } +} + +// Torch -------------------------------------------------------------------- + +class ArtiTorch : PowerupGiver +{ + Default + { + +COUNTITEM + +FLOATBOB + Inventory.PickupFlash "PickupFlash"; + Inventory.Icon "ARTITRCH"; + Inventory.PickupMessage "$TXT_ARTITORCH"; + Tag "$TAG_ARTITORCH"; + Powerup.Type "PowerTorch"; + } + States + { + Spawn: + TRCH ABC 3 Bright; + Loop; + } +} diff --git a/wadsrc/static/zscript/raven/ravenhealth.txt b/wadsrc/static/zscript/raven/ravenhealth.txt new file mode 100644 index 000000000..cf7c79d0a --- /dev/null +++ b/wadsrc/static/zscript/raven/ravenhealth.txt @@ -0,0 +1,16 @@ +class CrystalVial : Health +{ + Default + { + +FLOATBOB + Inventory.Amount 10; + Inventory.PickupMessage "$TXT_ITEMHEALTH"; + } + States + { + Spawn: + PTN1 ABC 3; + Loop; + } +} + diff --git a/wadsrc/static/zscript/shared/blood.txt b/wadsrc/static/zscript/shared/blood.txt new file mode 100644 index 000000000..e5f05de05 --- /dev/null +++ b/wadsrc/static/zscript/shared/blood.txt @@ -0,0 +1,78 @@ + +// Blood sprite ------------------------------------------------------------ + +class Blood : Actor +{ + Default + { + Mass 5; + +NOBLOCKMAP + +NOTELEPORT + +ALLOWPARTICLES + } + States + { + Spawn: + BLUD CBA 8; + Stop; + Spray: + SPRY ABCDEF 3; + SPRY G 2; + Stop; + } +} + +// Blood splatter ----------------------------------------------------------- + +class BloodSplatter : Actor +{ + Default + { + Radius 2; + Height 4; + +NOBLOCKMAP + +MISSILE + +DROPOFF + +NOTELEPORT + +CANNOTPUSH + +ALLOWPARTICLES + Mass 5; + } + States + { + Spawn: + BLUD CBA 8; + Stop; + Death: + BLUD A 6; + Stop; + } +} + +// Axe Blood ---------------------------------------------------------------- + +class AxeBlood : Actor +{ + Default + { + Radius 2; + Height 4; + +NOBLOCKMAP + +NOGRAVITY + +DROPOFF + +NOTELEPORT + +CANNOTPUSH + +ALLOWPARTICLES + Mass 5; + } + States + { + Spawn: + FAXE FGHIJ 3; + Death: + FAXE K 3; + Stop; + } +} + + \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/botstuff.txt b/wadsrc/static/zscript/shared/botstuff.txt new file mode 100644 index 000000000..cf671ea8b --- /dev/null +++ b/wadsrc/static/zscript/shared/botstuff.txt @@ -0,0 +1,25 @@ + +class CajunBodyNode : Actor +{ + Default + { + +NOSECTOR + +NOGRAVITY + +INVISIBLE + } +} + +class CajunTrace : Actor +{ + Default + { + Speed 12; + Radius 6; + Height 8; + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOGRAVITY + +NOTELEPORT + } +} diff --git a/wadsrc/static/zscript/shared/bridge.txt b/wadsrc/static/zscript/shared/bridge.txt new file mode 100644 index 000000000..ea38796a7 --- /dev/null +++ b/wadsrc/static/zscript/shared/bridge.txt @@ -0,0 +1,129 @@ +// Bridge ball ------------------------------------------------------------- + +class BridgeBall : Actor +{ + default + { + +NOBLOCKMAP + +NOTELEPORT + +NOGRAVITY + } + + native void A_BridgeOrbit(); + + States + { + Spawn: + TLGL A 2 Bright; + TLGL A 1 Bright A_BridgeOrbit; + Wait; + } + +} + +// The bridge itself ------------------------------------------------------- + +class CustomBridge : Actor native +{ + default + { + +SOLID + +NOGRAVITY + +NOLIFTDROP + +ACTLIKEBRIDGE + Radius 32; + Height 2; + RenderStyle "None"; + } + + native void A_BridgeInit(class balltype = "BridgeBall"); + + states + { + Spawn: + TLGL ABCDE 3 Bright; + Loop; + See: + TLGL A 2; + TLGL A 2 A_BridgeInit; + TLGL A -1; + Stop; + Death: + TLGL A 2; + TLGL A 300; + Stop; + } +} + +// The Hexen bridge ------------------------------------------------------- + +class Bridge : CustomBridge +{ + default + { + RenderStyle "None"; + Args 32, 2, 3, 0; + } +} + +// The ZDoom bridge ------------------------------------------------------- + +class ZBridge : CustomBridge +{ + default + { + Args 36, 4, 0, 0; + } +} + + +// Invisible bridge -------------------------------------------------------- + +class InvisibleBridge : Actor native +{ + default + { + RenderStyle "None"; + Radius 32; + Height 4; + +SOLID + +NOGRAVITY + +NOLIFTDROP + +ACTLIKEBRIDGE + } + States + { + Spawn: + TNT1 A -1; + Stop; + } +} + +// And some invisible bridges from Skull Tag ------------------------------- + +class InvisibleBridge32 : InvisibleBridge +{ + default + { + Radius 32; + Height 8; + } +} + +class InvisibleBridge16 : InvisibleBridge +{ + default + { + Radius 16; + Height 8; + } +} + +class InvisibleBridge8 : InvisibleBridge +{ + default + { + Radius 8; + Height 8; + } +} diff --git a/wadsrc/static/zscript/shared/camera.txt b/wadsrc/static/zscript/shared/camera.txt new file mode 100644 index 000000000..9420c98d5 --- /dev/null +++ b/wadsrc/static/zscript/shared/camera.txt @@ -0,0 +1,29 @@ +class DoomBuilderCamera : Actor +{ + States + { + Spawn: + TNT1 A 1; + Stop; + } +} + + +class SecurityCamera : Actor native +{ + default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + } + default + { + RenderStyle "None"; + CameraHeight 0; + } +} + +class AimingCamera : SecurityCamera native +{ +} diff --git a/wadsrc/static/zscript/shared/debris.txt b/wadsrc/static/zscript/shared/debris.txt new file mode 100644 index 000000000..24eae25be --- /dev/null +++ b/wadsrc/static/zscript/shared/debris.txt @@ -0,0 +1,364 @@ + +// Rocks -------------------------------------------------------------------- + +class Rock1 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK A 20; + Loop; + Death: + ROKK A 10; + Stop; + } +} + +class Rock2 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK B 20; + Loop; + Death: + ROKK B 10; + Stop; + } +} + + +class Rock3 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK C 20; + Loop; + Death: + ROKK C 10; + Stop; + } +} + + +// Dirt -------------------------------------------------------------------- + +class Dirt1 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK D 20; + Loop; + Death: + ROKK D 10; + Stop; + } +} + +class Dirt2 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK E 20; + Loop; + Death: + ROKK E 10; + Stop; + } +} + +class Dirt3 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK F 20; + Loop; + Death: + ROKK F 10; + Stop; + } +} + +class Dirt4 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK G 20; + Loop; + Death: + ROKK G 10; + Stop; + } +} + +class Dirt5 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK H 20; + Loop; + Death: + ROKK H 10; + Stop; + } +} + +class Dirt6 : Actor +{ + Default + { + +NOBLOCKMAP + +DROPOFF + +MISSILE + +NOTELEPORT + } + States + { + Spawn: + ROKK I 20; + Loop; + Death: + ROKK I 10; + Stop; + } +} + +// Stained glass ------------------------------------------------------------ + +class GlassShard : Actor native +{ + Default + { + Radius 5; + Mass 5; + Projectile; + -ACTIVATEPCROSS + -ACTIVATEIMPACT + BounceType "HexenCompat"; + BounceFactor 0.3; + } +} + +class SGShard1 : GlassShard +{ + States + { + Spawn: + SGSA ABCDE 4; + Loop; + Death: + SGSA E 30; + Stop; + } +} + +class SGShard2 : GlassShard +{ + States + { + Spawn: + SGSA FGHIJ 4; + Loop; + Death: + SGSA J 30; + Stop; + } +} + +class SGShard3 : GlassShard +{ + States + { + Spawn: + SGSA KLMNO 4; + Loop; + Death: + SGSA O 30; + Stop; + } +} + +class SGShard4 : GlassShard +{ + States + { + Spawn: + SGSA PQRST 4; + Loop; + Death: + SGSA T 30; + Stop; + } +} + +class SGShard5 : GlassShard +{ + States + { + Spawn: + SGSA UVWXY 4; + Loop; + Death: + SGSA Y 30; + Stop; + } +} + +class SGShard6 : GlassShard +{ + States + { + Spawn: + SGSB A 4; + Loop; + Death: + SGSB A 30; + Stop; + } +} + +class SGShard7 : GlassShard +{ + States + { + Spawn: + SGSB B 4; + Loop; + Death: + SGSB B 30; + Stop; + } +} + +class SGShard8 : GlassShard +{ + States + { + Spawn: + SGSB C 4; + Loop; + Death: + SGSB C 30; + Stop; + } +} + +class SGShard9 : GlassShard +{ + States + { + Spawn: + SGSB D 4; + Loop; + Death: + SGSB D 30; + Stop; + } +} + +class SGShard0 : GlassShard +{ + States + { + Spawn: + SGSB E 4; + Loop; + Death: + SGSB E 30; + Stop; + } +} + +class GlassJunk : Actor +{ + Default + { + +NOCLIP + +NOBLOCKMAP + RenderStyle "Translucent"; + Alpha 0.4; + Health 3; // Number of different shards + } + States + { + // Are the first three frames used anywhere? + SHAR A 128; + Goto Death; + SHAR B 128; + Goto Death; + SHAR C 128; + Goto Death; + Spawn: + SHAR D 128; + Goto Death; + SHAR E 128; + Goto Death; + SHAR F 128; + Goto Death; + Death: + "----" A 1 A_FadeOut(0.03); + Wait; + } +} diff --git a/wadsrc/static/zscript/shared/decal.txt b/wadsrc/static/zscript/shared/decal.txt new file mode 100644 index 000000000..0614f6235 --- /dev/null +++ b/wadsrc/static/zscript/shared/decal.txt @@ -0,0 +1,3 @@ +class Decal : Actor native +{ +} diff --git a/wadsrc/static/zscript/shared/dog.txt b/wadsrc/static/zscript/shared/dog.txt new file mode 100644 index 000000000..663dd6b98 --- /dev/null +++ b/wadsrc/static/zscript/shared/dog.txt @@ -0,0 +1,47 @@ +class MBFHelperDog : Actor +{ + default + { + Health 500; + Speed 10; + PainChance 180; + Radius 12; + Height 28; + Mass 100; + Monster; + +JUMPDOWN + ActiveSound "dog/active"; + AttackSound "dog/attack"; + DeathSound "dog/death"; + PainSound "dog/pain"; + SeeSound "dog/sight"; + Obituary "$OB_DOG"; + } + States + { + Spawn: + DOGS AB 10 A_Look; + Loop; + See: + DOGS AABBCCDD 2 A_Chase; + Loop; + Melee: + DOGS EF 8 A_FaceTarget; + DOGS G 8 A_SargAttack; + Goto See; + Pain: + DOGS H 2; + DOGS H 2 A_Pain; + Goto See; + Death: + DOGS I 8; + DOGS J 8 A_Scream; + DOGS K 4; + DOGS L 4 A_Fall; + DOGS M 4; + DOGS N -1; + Raise: + DOGS NMLKJI 5; + Goto See; + } +} diff --git a/wadsrc/static/zscript/shared/fountain.txt b/wadsrc/static/zscript/shared/fountain.txt new file mode 100644 index 000000000..60129a8c5 --- /dev/null +++ b/wadsrc/static/zscript/shared/fountain.txt @@ -0,0 +1,66 @@ +class ParticleFountain : Actor native +{ + default + { + Height 0; + +NOBLOCKMAP + +NOGRAVITY + +INVISIBLE + } +} + +class RedParticleFountain : ParticleFountain +{ + default + { + Health 1; + } +} + +class GreenParticleFountain : ParticleFountain +{ + default + { + Health 2; + } +} + +class BlueParticleFountain : ParticleFountain +{ + default + { + Health 3; + } +} + +class YellowParticleFountain : ParticleFountain +{ + default + { + Health 4; + } +} + +class PurpleParticleFountain : ParticleFountain +{ + default + { + Health 5; + } +} + +class BlackParticleFountain : ParticleFountain +{ + default + { + Health 6; + } +} + +class WhiteParticleFountain : ParticleFountain +{ + default + { + Health 7; + } +} diff --git a/wadsrc/static/zscript/shared/hatetarget.txt b/wadsrc/static/zscript/shared/hatetarget.txt new file mode 100644 index 000000000..6d2263f61 --- /dev/null +++ b/wadsrc/static/zscript/shared/hatetarget.txt @@ -0,0 +1,22 @@ + + +// Hate Target -------------------------------------------------------------- + +class HateTarget : Actor native +{ + default + { + Radius 20; + Height 56; + +SHOOTABLE + +NOGRAVITY + +NOBLOOD + +DONTSPLASH + Mass 0x7fffffff; + } + States + { + Spawn: + TNT1 A -1; + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/ice.txt b/wadsrc/static/zscript/shared/ice.txt new file mode 100644 index 000000000..534113785 --- /dev/null +++ b/wadsrc/static/zscript/shared/ice.txt @@ -0,0 +1,61 @@ + + +//========================================================================== +// +// Ice chunk +// +//========================================================================== + +class IceChunk : Actor +{ + Default + { + Radius 3; + Height 4; + Mass 5; + Gravity 0.125; + +DROPOFF + +CANNOTPUSH + +FLOORCLIP + +NOTELEPORT + +NOBLOCKMAP + +MOVEWITHSECTOR + } + native void A_IceSetTics (); + + States + { + Spawn: + ICEC A 1; + ICEC ABCD 10 A_IceSetTics; + Stop; + } +} + +//========================================================================== +// +// A chunk of ice that is also a player +// +//========================================================================== + +class IceChunkHead : PlayerChunk +{ + Default + { + Radius 3; + Height 4; + Mass 5; + Gravity 0.125; + DamageType "Ice"; + +DROPOFF + +CANNOTPUSH + } + States + { + Spawn: + ICEC A 0; + ICEC A 10 A_CheckPlayerDone; + wait; + } +} + diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt new file mode 100644 index 000000000..a6d7af835 --- /dev/null +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -0,0 +1,513 @@ +class Inventory : Actor native +{ + Default + { + Inventory.Amount 1; + Inventory.MaxAmount 1; + Inventory.InterHubAmount 1; + Inventory.UseSound "misc/invuse"; + Inventory.PickupSound "misc/i_pkup"; + Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"; + } + + // These are regular functions for the item itself. + private native void A_RestoreSpecialPosition(); + private native void A_RestoreSpecialDoomThing(); + private native void A_RestoreSpecialThing1(); + private native void A_RestoreSpecialThing2(); + + States(Actor, Overlay, Weapon, Item) + { + HideDoomish: + TNT1 A 1050; + TNT1 A 0 A_RestoreSpecialPosition; + TNT1 A 1 A_RestoreSpecialDoomThing; + Stop; + HideSpecial: + ACLO E 1400; + ACLO A 0 A_RestoreSpecialPosition; + ACLO A 4 A_RestoreSpecialThing1; + ACLO BABCBCDC 4; + ACLO D 4 A_RestoreSpecialThing2; + Stop; + Held: + TNT1 A -1; + Stop; + HoldAndDestroy: + TNT1 A 1; + Stop; + } +} + +class StateProvider : Inventory native +{ + action native state A_JumpIfNoAmmo(statelabel 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 = 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 = 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 action void A_Light(int extralight); + action void A_Light0() { A_Light(0); } + action void A_Light1() { A_Light(1); } + action void A_Light2() { A_Light(2); } + action native void A_LightInverse(); + action native void A_WeaponReady(int flags = 0); + action native void A_Lower(); + action native void A_Raise(); + action native void A_FirePistol(); + action native void A_FireShotgun(); + action native void A_FireShotgun2(); + + action void A_OpenShotgun2() { A_PlaySound("weapons/sshoto", CHAN_WEAPON); } + action void A_LoadShotgun2() { A_PlaySound("weapons/sshotl", CHAN_WEAPON); } + action void A_CloseShotgun2() { A_PlaySound("weapons/sshotc", CHAN_WEAPON); } + + action native void A_FireCGun(); + action native void A_FireSTGrenade(class grenadetype = "Grenade"); + action native void A_FireMissile(); + action native void A_FirePlasma(); + action native void A_FireRailgun(); + action native void A_FireRailgunLeft(); + action native void A_FireRailgunRight(); + action void A_RailWait() {} + action void A_BFGsound() { A_PlaySound("weapons/bfgf", CHAN_WEAPON); } + action native void A_FireBFG(); + action native void A_FireOldBFG(); + action native void A_ReFire(statelabel flash = null); + action native void A_ClearReFire(); + action native void A_CheckReload(); + action native void A_GunFlash(statelabel flash = null, int flags = 0); + action native void A_FireAssaultGun(); + 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"); + action native state A_CheckForReload(int counter, statelabel label, bool dontincrement = false); + action native void A_ResetReloadCounter(); +} + +class ScoreItem : Inventory native +{ + Default + { + Height 10; + +COUNTITEM + Inventory.Amount 1; + +Inventory.ALWAYSPICKUP + } +} + +class Ammo : Inventory native +{ + Default + { + +INVENTORY.KEEPDEPLETED + Inventory.PickupSound "misc/ammo_pkup"; + } +} + +class BackpackItem : Inventory native +{ +} + +class Armor : Inventory native +{ + Default + { + Inventory.PickupSound "misc/armor_pkup"; + } +} + +class BasicArmor : Armor native +{ + Default + { + +Inventory.KEEPDEPLETED + } +} + +class BasicArmorBonus : Armor native +{ + Default + { + +Inventory.AUTOACTIVATE + +Inventory.ALWAYSPICKUP + Inventory.MaxAmount 0; + Armor.SavePercent 33.335; + } +} + +class BasicArmorPickup : Armor native +{ + Default + { + +Inventory.AUTOACTIVATE; + Inventory.MaxAmount 0; + } +} + +class HexenArmor : Armor native +{ + Default + { + +Inventory.KEEPDEPLETED + +Inventory.UNDROPPABLE + } +} + +class DehackedPickup : Inventory native {} + +class FakeInventory : Inventory native {} + +class CustomInventory : StateProvider native +{ + Default + { + DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_ITEM; + } +} + +class Health : Inventory native +{ + Default + { + Inventory.Amount 1; + Inventory.MaxAmount 0; + Inventory.PickupSound "misc/health_pkup"; + } +} + +class HealthPickup : Inventory native +{ + Default + { + Inventory.DefMaxAmount; + +INVENTORY.INVBAR + } +} + +class Key : Inventory native +{ + Default + { + +DONTGIB; // Don't disappear due to a crusher + Inventory.InterHubAmount 0; + Inventory.PickupSound "misc/k_pkup"; + } +} + +class PowerupGiver : Inventory native +{ + Default + { + Inventory.DefMaxAmount; + +INVENTORY.INVBAR + +INVENTORY.FANCYPICKUPSOUND + Inventory.PickupSound "misc/p_pkup"; + } +} + +class Powerup : Inventory native {} + +class PowerInvulnerable : Powerup native +{ + Default + { + Powerup.Duration -30; + inventory.icon "SPSHLD0"; + } +} + +class PowerStrength : Powerup native +{ + Default + { + Powerup.Duration 1; + Powerup.Color "ff 00 00", 0.5; + +INVENTORY.HUBPOWER + } +} + +class PowerInvisibility : Powerup native +{ + Default + { + +SHADOW; + Powerup.Duration -60; + Powerup.Strength 80; + Powerup.Mode "Fuzzy"; + } +} + +class PowerGhost : PowerInvisibility +{ + Default + { + +GHOST; + Powerup.Duration -60; + Powerup.Strength 60; + Powerup.Mode "None"; + } +} + +class PowerShadow : PowerInvisibility +{ + Default + { + +INVENTORY.HUBPOWER + Powerup.Duration -55; + Powerup.Strength 75; + Powerup.Mode "Cumulative"; + } +} + +class PowerIronFeet : Powerup native +{ + Default + { + Powerup.Duration -60; + Powerup.Color "00 ff 00", 0.125; + } +} + +class PowerMask : PowerIronFeet native +{ + Default + { + Powerup.Duration -80; + Powerup.Color "00 00 00", 0; + +INVENTORY.HUBPOWER + Inventory.Icon "I_MASK"; + } +} + +class PowerLightAmp : Powerup native +{ + Default + { + Powerup.Duration -120; + } +} + +class PowerTorch : PowerLightAmp native {} + +class PowerFlight : Powerup native +{ + Default + { + Powerup.Duration -60; + +INVENTORY.HUBPOWER + } +} + +class PowerWeaponLevel2 : Powerup native +{ + Default + { + Powerup.Duration -40; + Inventory.Icon "SPINBK0"; + +INVENTORY.NOTELEPORTFREEZE + } +} + +class PowerSpeed : Powerup native +{ + Default + { + Powerup.Duration -45; + Speed 1.5; + Inventory.Icon "SPBOOT0"; + +INVENTORY.NOTELEPORTFREEZE + } +} + +// Player Speed Trail (used by the Speed Powerup) ---------------------------- + +class PlayerSpeedTrail native +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + Alpha 0.6; + RenderStyle "Translucent"; + } +} + +class PowerMinotaur : Powerup native +{ + Default + { + Powerup.Duration -25; + Inventory.Icon "SPMINO0"; + } +} + +class PowerTargeter : Powerup native +{ + Default + { + Powerup.Duration -160; + +INVENTORY.HUBPOWER + } + States + { + Targeter: + TRGT A -1; + Stop; + TRGT B -1; + Stop; + TRGT C -1; + Stop; + } +} + +class PowerFrightener : Powerup native +{ + Default + { + Powerup.Duration -60; + } +} + +class PowerBuddha : Powerup native +{ + Default + { + Powerup.Duration -60; + } +} + +class PowerScanner : Powerup native +{ + Default + { + Powerup.Duration -80; + +INVENTORY.HUBPOWER + } +} + +class PowerTimeFreezer : Powerup native +{ + Default + { + Powerup.Duration -12; + } +} + +class PowerDamage : Powerup native +{ + Default + { + Powerup.Duration -25; + } +} + +class PowerProtection : Powerup native +{ + Default + { + Powerup.Duration -25; + } +} + +class PowerDrain : Powerup native +{ + Default + { + Powerup.Duration -60; + } +} + +class PowerRegeneration : Powerup native +{ + Default + { + Powerup.Duration -120; + Powerup.Strength 5; + } +} + +class PowerHighJump : Powerup native {} + +class PowerDoubleFiringSpeed : Powerup native {} + +class PowerMorph : Powerup native +{ + Default + { + Powerup.Duration -40; + } +} + +class PowerInfiniteAmmo : Powerup native +{ + Default + { + Powerup.Duration -30; + } +} + +class MapRevealer : Inventory native {} + +class PuzzleItem : Inventory native +{ + Default + { + +NOGRAVITY + +INVENTORY.INVBAR + Inventory.DefMaxAmount; + Inventory.UseSound "PuzzleSuccess"; + Inventory.PickupSound "misc/i_pkup"; + } +} + +class Weapon : StateProvider native +{ + Default + { + Inventory.PickupSound "misc/w_pkup"; + Weapon.DefaultKickback; + Weapon.BobSpeed 1.0; + Weapon.BobRangeX 1.0; + Weapon.BobRangeY 1.0; + +WEAPONSPAWN + DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_WEAPON; + } + States + { + LightDone: + SHTG E 0 A_Light0; + Stop; + } + + native void A_ZoomFactor(float scale = 1, int flags = 0); + const ZOOM_INSTANT = 1; + const ZOOM_NOSCALETURNING = 2; + + native void A_SetCrosshair(int xhair); +} + +class WeaponGiver : Weapon native +{ + Default + { + Weapon.AmmoGive1 -1; + Weapon.AmmoGive2 -1; + } +} + +class WeaponHolder : Inventory native +{ + Default + { + +NOBLOCKMAP + +NOSECTOR + +INVENTORY.UNDROPPABLE + } +} + +class WeaponPiece : Inventory native +{ + Default + { + +WEAPONSPAWN; + } +} diff --git a/wadsrc/static/zscript/shared/mapmarker.txt b/wadsrc/static/zscript/shared/mapmarker.txt new file mode 100644 index 000000000..1afa00459 --- /dev/null +++ b/wadsrc/static/zscript/shared/mapmarker.txt @@ -0,0 +1,18 @@ + +class MapMarker : Actor native +{ + default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + +INVISIBLE + Scale 0.5; + } + States + { + Spawn: + AMRK A -1; + Stop; + } +} diff --git a/wadsrc/static/zscript/shared/morph.txt b/wadsrc/static/zscript/shared/morph.txt new file mode 100644 index 000000000..ff58d897b --- /dev/null +++ b/wadsrc/static/zscript/shared/morph.txt @@ -0,0 +1,21 @@ +class MorphProjectile : Actor native +{ + Default + { + Damage 1; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + } +} + +class MorphedMonster : Actor native +{ + Default + { + Monster; + -COUNTKILL + +FLOORCLIP + } +} + diff --git a/wadsrc/static/zscript/shared/movingcamera.txt b/wadsrc/static/zscript/shared/movingcamera.txt new file mode 100644 index 000000000..c5b8534db --- /dev/null +++ b/wadsrc/static/zscript/shared/movingcamera.txt @@ -0,0 +1,46 @@ +class InterpolationPoint : Actor native +{ + default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + RenderStyle "None"; + } +} + +class InterpolationSpecial : Actor native +{ + default + { + +NOBLOCKMAP + +NOSECTOR + +NOGRAVITY + +DONTSPLASH + } +} + +class PathFollower : Actor native +{ + default + { + +NOBLOCKMAP + +NOSECTOR + +NOGRAVITY + +DONTSPLASH + } +} + +class ActorMover : PathFollower native +{ +} + +class MovingCamera : PathFollower native +{ + default + { + CameraHeight 0; + } +} + + diff --git a/wadsrc/static/actors/shared/pickups.txt b/wadsrc/static/zscript/shared/pickups.txt similarity index 65% rename from wadsrc/static/actors/shared/pickups.txt rename to wadsrc/static/zscript/shared/pickups.txt index a9ee0b2d7..8e1e88233 100644 --- a/wadsrc/static/actors/shared/pickups.txt +++ b/wadsrc/static/zscript/shared/pickups.txt @@ -4,28 +4,34 @@ // /***************************************************************************/ -ACTOR ItemFog +class ItemFog : Actor { - +NOBLOCKMAP - +NOGRAVITY + default + { + +NOBLOCKMAP + +NOGRAVITY + } States { Spawn: - IFOG ABABCDE 6 BRIGHT - Stop + IFOG ABABCDE 6 BRIGHT; + Stop; } } // Pickup flash ------------------------------------------------------------- -ACTOR PickupFlash +class PickupFlash : Actor { - +NOGRAVITY + default + { + +NOGRAVITY + } States { Spawn: - ACLO DCDCBCBABA 3 - Stop + ACLO DCDCBCBABA 3; + Stop; } } diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt new file mode 100644 index 000000000..224011acd --- /dev/null +++ b/wadsrc/static/zscript/shared/player.txt @@ -0,0 +1,59 @@ +class PlayerPawn : Actor native +{ + Default + { + Health 100; + Radius 16; + Height 56; + Mass 100; + Painchance 255; + Speed 1; + +SOLID + +SHOOTABLE + +DROPOFF + +PICKUP + +NOTDMATCH + +FRIENDLY + +SLIDESONWALLS + +CANPASS + +CANPUSHWALLS + +FLOORCLIP + +WINDTHRUST + +TELESTOMP + +NOBLOCKMONST + Player.AttackZOffset 8; + Player.JumpZ 8; + Player.GruntSpeed 12; + Player.FallingScreamSpeed 35,40; + Player.ViewHeight 41; + Player.UseRange 64; + Player.ForwardMove 1,1; + Player.SideMove 1,1; + Player.ColorRange 0,0; + Player.SoundClass "player"; + Player.DamageScreenColor "ff 00 00"; + Player.MugShotMaxHealth 0; + Player.FlechetteType "ArtiPoisonBag3"; + Player.AirCapacity 1; + Player.ViewBob 1; + Obituary "$OB_MPDEFAULT"; + } +} + +class PlayerChunk : PlayerPawn native +{ + Default + { + +NOSKIN + -SOLID + -SHOOTABLE + -PICKUP + -NOTDMATCH + -FRIENDLY + -SLIDESONWALLS + -CANPUSHWALLS + -FLOORCLIP + -WINDTHRUST + -TELESTOMP + } +} diff --git a/wadsrc/static/zscript/shared/secrettrigger.txt b/wadsrc/static/zscript/shared/secrettrigger.txt new file mode 100644 index 000000000..48c93686e --- /dev/null +++ b/wadsrc/static/zscript/shared/secrettrigger.txt @@ -0,0 +1,12 @@ + +class SecretTrigger : Actor native +{ + default + { + +NOBLOCKMAP + +NOSECTOR + +NOGRAVITY + +DONTSPLASH + } +} + diff --git a/wadsrc/static/actors/shared/sectoraction.txt b/wadsrc/static/zscript/shared/sectoraction.txt similarity index 61% rename from wadsrc/static/actors/shared/sectoraction.txt rename to wadsrc/static/zscript/shared/sectoraction.txt index f8db34323..03278f2d3 100644 --- a/wadsrc/static/actors/shared/sectoraction.txt +++ b/wadsrc/static/zscript/shared/sectoraction.txt @@ -1,81 +1,84 @@ -ACTOR SectorAction native +class SectorAction : Actor native { - +NOBLOCKMAP - +NOSECTOR - +NOGRAVITY - +DONTSPLASH + default + { + +NOBLOCKMAP + +NOSECTOR + +NOGRAVITY + +DONTSPLASH + } } // Triggered when entering sector ------------------------------------------- -ACTOR SecActEnter : SectorAction native +class SecActEnter : SectorAction native { } // Triggered when leaving sector -------------------------------------------- -ACTOR SecActExit : SectorAction native +class SecActExit : SectorAction native { } // Triggered when hitting sector's floor ------------------------------------ -ACTOR SecActHitFloor : SectorAction native +class SecActHitFloor : SectorAction native { } // Triggered when hitting sector's ceiling ---------------------------------- -ACTOR SecActHitCeil : SectorAction native +class SecActHitCeil : SectorAction native { } // Triggered when using inside sector --------------------------------------- -ACTOR SecActUse : SectorAction native +class SecActUse : SectorAction native { } // Triggered when using a sector's wall ------------------------------------- -ACTOR SecActUseWall : SectorAction native +class SecActUseWall : SectorAction native { } // Triggered when eyes go below fake floor ---------------------------------- -ACTOR SecActEyesDive : SectorAction native +class SecActEyesDive : SectorAction native { } // Triggered when eyes go above fake floor ---------------------------------- -ACTOR SecActEyesSurface : SectorAction native +class SecActEyesSurface : SectorAction native { } // Triggered when eyes go below fake floor ---------------------------------- -ACTOR SecActEyesBelowC : SectorAction native +class SecActEyesBelowC : SectorAction native { } // Triggered when eyes go above fake floor ---------------------------------- -ACTOR SecActEyesAboveC : SectorAction native +class SecActEyesAboveC : SectorAction native { } // Triggered when eyes go below fake floor ---------------------------------- -ACTOR SecActHitFakeFloor : SectorAction native +class SecActHitFakeFloor : SectorAction native { } // Music changer ---------------------------------- -ACTOR MusicChanger : SectorAction native +class MusicChanger : SectorAction native { } diff --git a/wadsrc/static/zscript/shared/setcolor.txt b/wadsrc/static/zscript/shared/setcolor.txt new file mode 100644 index 000000000..8689e5fd1 --- /dev/null +++ b/wadsrc/static/zscript/shared/setcolor.txt @@ -0,0 +1,22 @@ +class ColorSetter : Actor native +{ + default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + RenderStyle "None"; + } +} + + +class FadeSetter : Actor native +{ + default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + RenderStyle "None"; + } +} diff --git a/wadsrc/static/zscript/shared/sharedmisc.txt b/wadsrc/static/zscript/shared/sharedmisc.txt new file mode 100644 index 000000000..bebf28549 --- /dev/null +++ b/wadsrc/static/zscript/shared/sharedmisc.txt @@ -0,0 +1,220 @@ + +// Default class for unregistered doomednums ------------------------------- + +class Unknown : Actor +{ + Default + { + Radius 32; + Height 56; + +NOGRAVITY + +NOBLOCKMAP + +DONTSPLASH + } + States + { + Spawn: + UNKN A -1; + Stop; + } +} + +// Route node for monster patrols ------------------------------------------- + +class PatrolPoint : Actor +{ + Default + { + Radius 8; + Height 8; + Mass 10; + +NOGRAVITY + +NOBLOCKMAP + +DONTSPLASH + RenderStyle "None"; + } +} + +// A special to execute when a monster reaches a matching patrol point ------ + +class PatrolSpecial : Actor +{ + Default + { + Radius 8; + Height 8; + Mass 10; + +NOGRAVITY + +NOBLOCKMAP + +DONTSPLASH + RenderStyle "None"; + } +} + +// Map spot ---------------------------------------------------------------- + +class MapSpot : Actor +{ + Default + { + +NOBLOCKMAP + +NOSECTOR + +NOGRAVITY + +DONTSPLASH + RenderStyle "None"; + CameraHeight 0; + } +} + +// same with different editor number for Legacy maps ----------------------- + +class FS_Mapspot : Mapspot +{ +} + +// Map spot with gravity --------------------------------------------------- + +class MapSpotGravity : MapSpot +{ + Default + { + -NOBLOCKMAP + -NOSECTOR + -NOGRAVITY + } +} + +// Point Pushers ----------------------------------------------------------- + +class PointPusher : Actor +{ + Default + { + +NOBLOCKMAP + +INVISIBLE + +NOCLIP + } +} + +class PointPuller : Actor +{ + Default + { + +NOBLOCKMAP + +INVISIBLE + +NOCLIP + } +} + +// Bloody gibs ------------------------------------------------------------- + +class RealGibs : Actor +{ + Default + { + +DROPOFF + +CORPSE + +NOTELEPORT + +DONTGIB + } + States + { + Spawn: + goto GenericCrush; + } +} + +// Gibs that can be placed on a map. --------------------------------------- +// +// These need to be a separate class from the above, in case someone uses +// a deh patch to change the gibs, since ZDoom actually creates a gib class +// for actors that get crushed instead of changing their state as Doom did. + +class Gibs : RealGibs +{ + Default + { + ClearFlags; + } +} + +// Needed for loading Build maps ------------------------------------------- + +class CustomSprite : Actor native +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + } + States + { + Spawn: + TNT1 A -1; + Stop; + } +} + +// SwitchableDecoration: Activate and Deactivate change state -------------- + +class SwitchableDecoration : Actor native +{ +} + + +class SwitchingDecoration : SwitchableDecoration native +{ +} + +// Random spawner ---------------------------------------------------------- + +class RandomSpawner : Actor native +{ + Default + { + +NOBLOCKMAP + +NOSECTOR + +NOGRAVITY + +THRUACTORS + } +} + +// Fast projectiles -------------------------------------------------------- + +class FastProjectile : Actor native +{ + Default + { + Projectile; + MissileHeight 0; + } +} + +// Sector flag setter ------------------------------------------------------ + +class SectorFlagSetter : Actor native +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + RenderStyle "None"; + } +} + +// Marker for sounds : Actor ------------------------------------------------------- + +class SpeakerIcon : Unknown +{ + States + { + Spawn: + SPKR A -1 BRIGHT; + Stop; + } + Default + { + Scale 0.125; + } +} diff --git a/wadsrc/static/zscript/shared/skies.txt b/wadsrc/static/zscript/shared/skies.txt new file mode 100644 index 000000000..35077ee5c --- /dev/null +++ b/wadsrc/static/zscript/shared/skies.txt @@ -0,0 +1,49 @@ +class SkyViewpoint : Actor native +{ + default + { + +NOSECTOR + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + } +} + +class SkyPicker : Actor native +{ + default + { + +NOSECTOR + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + } +} + +class SkyCamCompat : SkyViewpoint native +{ +} + +class StackPoint : SkyViewpoint native +{ +} + +class UpperStackLookOnly : StackPoint +{ +} + +class LowerStackLookOnly : StackPoint +{ +} + + +class SectorSilencer native +{ + default + { + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + RenderStyle "None"; + } +} diff --git a/wadsrc/static/zscript/shared/soundenvironment.txt b/wadsrc/static/zscript/shared/soundenvironment.txt new file mode 100644 index 000000000..2a4d66adb --- /dev/null +++ b/wadsrc/static/zscript/shared/soundenvironment.txt @@ -0,0 +1,12 @@ + +class SoundEnvironment : Actor native +{ + default + { + +NOSECTOR + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + } +} + diff --git a/wadsrc/static/zscript/shared/soundsequence.txt b/wadsrc/static/zscript/shared/soundsequence.txt new file mode 100644 index 000000000..97ff8e9aa --- /dev/null +++ b/wadsrc/static/zscript/shared/soundsequence.txt @@ -0,0 +1,121 @@ + +class AmbientSound : Actor native +{ + default + { + +NOBLOCKMAP + +NOSECTOR + +DONTSPLASH + } +} + +class AmbientSoundNoGravity : AmbientSound +{ + default + { + +NOGRAVITY + } +} + +class SoundSequenceSlot : Actor native +{ + default + { + +NOSECTOR + +NOBLOCKMAP + +DONTSPLASH + } +} + +class SoundSequence : Actor native +{ + default + { + +NOSECTOR + +NOBLOCKMAP + +DONTSPLASH + } +} + +// Heretic Sound sequences ----------------------------------------------------------- + +class HereticSoundSequence1 : SoundSequence +{ + default + { + Args 0; + } +} + +class HereticSoundSequence2 : SoundSequence +{ + default + { + Args 1; + } +} + +class HereticSoundSequence3 : SoundSequence +{ + default + { + Args 2; + } +} + +class HereticSoundSequence4 : SoundSequence +{ + default + { + Args 3; + } +} + +class HereticSoundSequence5 : SoundSequence +{ + default + { + Args 4; + } +} + +class HereticSoundSequence6 : SoundSequence +{ + default + { + Args 5; + } +} + +class HereticSoundSequence7 : SoundSequence +{ + default + { + Args 6; + } +} + +class HereticSoundSequence8 : SoundSequence +{ + default + { + Args 7; + } +} + +class HereticSoundSequence9 : SoundSequence +{ + default + { + Args 8; + } +} + +class HereticSoundSequence10 : SoundSequence +{ + default + { + Args 9; + } +} + diff --git a/wadsrc/static/zscript/shared/spark.txt b/wadsrc/static/zscript/shared/spark.txt new file mode 100644 index 000000000..5adffdfe1 --- /dev/null +++ b/wadsrc/static/zscript/shared/spark.txt @@ -0,0 +1,11 @@ + +class Spark : Actor native +{ + default + { + +NOSECTOR + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/specialspot.txt b/wadsrc/static/zscript/shared/specialspot.txt new file mode 100644 index 000000000..c0bf84de5 --- /dev/null +++ b/wadsrc/static/zscript/shared/specialspot.txt @@ -0,0 +1,5 @@ + +class SpecialSpot : Actor native +{ + native void A_SpawnSingleItem(class type, int fail_sp = 0, int fail_co = 0, int fail_dm = 0); +} diff --git a/wadsrc/static/zscript/shared/splashes.txt b/wadsrc/static/zscript/shared/splashes.txt new file mode 100644 index 000000000..8b16d85b8 --- /dev/null +++ b/wadsrc/static/zscript/shared/splashes.txt @@ -0,0 +1,273 @@ + +// Water -------------------------------------------------------------------- + +class WaterSplash : Actor +{ + default + { + Radius 2; + Height 4; + Gravity 0.125; + +NOBLOCKMAP + +MISSILE + +DROPOFF + +NOTELEPORT + +CANNOTPUSH + +DONTSPLASH + +DONTBLAST + } + States + { + Spawn: + SPSH ABC 8; + SPSH D 16; + Stop; + Death: + SPSH D 10; + Stop; + } +} + + +class WaterSplashBase : Actor +{ + default + { + +NOBLOCKMAP + +NOCLIP + +NOGRAVITY + +DONTSPLASH + +DONTBLAST + } + States + { + Spawn: + SPSH EFGHIJK 5; + Stop; + } +} + +// Lava --------------------------------------------------------------------- + +class LavaSplash : Actor +{ + default + { + +NOBLOCKMAP + +NOCLIP + +NOGRAVITY + +DONTSPLASH + +DONTBLAST + } + States + { + Spawn: + LVAS ABCDEF 5 Bright; + Stop; + } +} + +class LavaSmoke : Actor +{ + default + { + +NOBLOCKMAP + +NOCLIP + +NOGRAVITY + +DONTSPLASH + RenderStyle "Translucent"; + DefaultAlpha; + } + States + { + Spawn: + LVAS GHIJK 5 Bright; + Stop; + } +} + +// Sludge ------------------------------------------------------------------- + +class SludgeChunk : Actor +{ + default + { + Radius 2; + Height 4; + Gravity 0.125; + +NOBLOCKMAP + +MISSILE + +DROPOFF + +NOTELEPORT + +CANNOTPUSH + +DONTSPLASH + } + States + { + Spawn: + SLDG ABCD 8; + Stop; + Death: + SLDG D 6; + Stop; + } +} + +class SludgeSplash : Actor +{ + default + { + +NOBLOCKMAP + +NOCLIP + +NOGRAVITY + +DONTSPLASH + } + States + { + Spawn: + SLDG EFGH 6; + Stop; + } +} + +/* + * These next four classes are not used by me anywhere. + * They are for people who want to use them in a TERRAIN lump. + */ + +// Blood (water with a different sprite) ------------------------------------ + +class BloodSplash : Actor +{ + default + { + Radius 2; + Height 4; + Gravity 0.125; + +NOBLOCKMAP + +MISSILE + +DROPOFF + +NOTELEPORT + +CANNOTPUSH + +DONTSPLASH + +DONTBLAST + } + States + { + Spawn: + BSPH ABC 8; + BSPH D 16; + Stop; + Death: + BSPH D 10; + Stop; + } +} + + +class BloodSplashBase : Actor +{ + default + { + +NOBLOCKMAP + +NOCLIP + +NOGRAVITY + +DONTSPLASH + +DONTBLAST + } + States + { + Spawn: + BSPH EFGHIJK 5; + Stop; + } +} + +// Slime (sludge with a different sprite) ----------------------------------- + +class SlimeChunk : Actor +{ + default + { + Radius 2; + Height 4; + Gravity 0.125; + +NOBLOCKMAP + +MISSILE + +DROPOFF + +NOTELEPORT + +CANNOTPUSH + +DONTSPLASH + } + States + { + Spawn: + SLIM ABCD 8; + Stop; + Death: + SLIM D 6; + Stop; + } +} + +class SlimeSplash : Actor +{ + default + { + +NOBLOCKMAP + +NOCLIP + +NOGRAVITY + +DONTSPLASH + } + States + { + Spawn: + SLIM EFGH 6; + Stop; + } +} + +// Smoke trail for rocket ----------------------------------- + +class RocketSmokeTrail : Actor +{ + default + { + RenderStyle "Translucent"; + Alpha 0.4; + VSpeed 1; + +NOBLOCKMAP + +NOCLIP + +NOGRAVITY + +DONTSPLASH + +NOTELEPORT + } + States + { + Spawn: + RSMK ABCDE 5; + Stop; + } +} + +class GrenadeSmokeTrail : Actor +{ + default + { + RenderStyle "Translucent"; + Alpha 0.4; + +NOBLOCKMAP + +NOCLIP + +DONTSPLASH + +NOTELEPORT + Gravity 0.1; + VSpeed 0.5; + Scale 0.6; + } + States + { + Spawn: + RSMK ABCDE 4; + Stop; + } +} diff --git a/wadsrc/static/zscript/shared/teleport.txt b/wadsrc/static/zscript/shared/teleport.txt new file mode 100644 index 000000000..55308415f --- /dev/null +++ b/wadsrc/static/zscript/shared/teleport.txt @@ -0,0 +1,54 @@ + +class TeleportFog : Actor native +{ + default + { + +NOBLOCKMAP + +NOTELEPORT + +NOGRAVITY + RenderStyle "Add"; + } + States + { + Spawn: + TFOG ABABCDEFGHIJ 6 Bright; + Stop; + + Raven: + TELE ABCDEFGHGFEDC 6 Bright; + Stop; + + Strife: + TFOG ABCDEFEDCB 6 Bright; + Stop; + } +} + + + +class TeleportDest : Actor +{ + default + { + +NOBLOCKMAP + +NOSECTOR + +DONTSPLASH + } +} + +class TeleportDest2 : TeleportDest +{ + default + { + +NOGRAVITY + } +} + +class TeleportDest3 : TeleportDest2 +{ + default + { + -NOGRAVITY + } +} + diff --git a/wadsrc/static/zscript/shared/waterzone.txt b/wadsrc/static/zscript/shared/waterzone.txt new file mode 100644 index 000000000..975c8a473 --- /dev/null +++ b/wadsrc/static/zscript/shared/waterzone.txt @@ -0,0 +1,10 @@ +class WaterZone : Actor native +{ + default + { + +NOSECTOR + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + } +} diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt new file mode 100644 index 000000000..0c1305b57 --- /dev/null +++ b/wadsrc/static/zscript/strife/acolyte.txt @@ -0,0 +1,218 @@ + +// Base class for the acolytes ---------------------------------------------- + +class Acolyte : StrifeHumanoid +{ + Default + { + Health 70; + PainChance 150; + Speed 7; + Radius 24; + Height 64; + Mass 400; + Monster; + +SEESDAGGERS + +NOSPLASHALERT + +FLOORCLIP + +NEVERRESPAWN + MinMissileChance 150; + Tag "$TAG_ACOLYTE"; + SeeSound "acolyte/sight"; + PainSound "acolyte/pain"; + AttackSound "acolyte/rifle"; + DeathSound "acolyte/death"; + ActiveSound "acolyte/active"; + Obituary "$OB_ACOLYTE"; + } + + native void A_BeShadowyFoe (); + native void A_AcolyteBits (); + native void A_AcolyteDie (); + + States + { + Spawn: + AGRD A 5 A_Look2; + Wait; + AGRD B 8 A_ClearShadow; + Loop; + AGRD D 8; + Loop; + AGRD ABCDABCD 5 A_Wander; + Loop; + See: + AGRD A 6 Fast Slow A_AcolyteBits; + AGRD BCD 6 Fast Slow A_Chase; + Loop; + Missile: + AGRD E 8 Fast Slow A_FaceTarget; + AGRD FE 4 Fast Slow A_ShootGun; + AGRD F 6 Fast Slow A_ShootGun; + Goto See; + Pain: + AGRD O 8 Fast Slow A_Pain; + Goto See; + Death: + AGRD G 4; + AGRD H 4 A_Scream; + AGRD I 4; + AGRD J 3; + AGRD K 3 A_NoBlocking; + AGRD L 3; + AGRD M 3 A_AcolyteDie; + AGRD N -1; + Stop; + XDeath: + GIBS A 5 A_NoBlocking; + GIBS BC 5 A_TossGib; + GIBS D 4 A_TossGib; + GIBS E 4 A_XScream; + GIBS F 4 A_TossGib; + GIBS GH 4; + GIBS I 5; + GIBS J 5 A_AcolyteDie; + GIBS K 5; + GIBS L 1400; + Stop; + } +} + + +// Acolyte 1 ---------------------------------------------------------------- + +class AcolyteTan : Acolyte +{ + Default + { + +MISSILEMORE +MISSILEEVENMORE + DropItem "ClipOfBullets"; + } +} + +// Acolyte 2 ---------------------------------------------------------------- + +class AcolyteRed : Acolyte +{ + Default + { + +MISSILEMORE +MISSILEEVENMORE + Translation 0; + } +} + +// Acolyte 3 ---------------------------------------------------------------- + +class AcolyteRust : Acolyte +{ + Default + { + +MISSILEMORE +MISSILEEVENMORE + Translation 1; + } +} + +// Acolyte 4 ---------------------------------------------------------------- + +class AcolyteGray : Acolyte +{ + Default + { + +MISSILEMORE +MISSILEEVENMORE + Translation 2; + } +} + +// Acolyte 5 ---------------------------------------------------------------- + +class AcolyteDGreen : Acolyte +{ + Default + { + +MISSILEMORE +MISSILEEVENMORE + Translation 3; + } +} + +// Acolyte 6 ---------------------------------------------------------------- + +class AcolyteGold : Acolyte +{ + Default + { + +MISSILEMORE +MISSILEEVENMORE + Translation 4; + } +} + +// Acolyte 7 ---------------------------------------------------------------- + +class AcolyteLGreen : Acolyte +{ + Default + { + Health 60; + Translation 5; + } +} + +// Acolyte 8 ---------------------------------------------------------------- + +class AcolyteBlue : Acolyte +{ + Default + { + Health 60; + Translation 6; + } +} + +// Shadow Acolyte ----------------------------------------------------------- + +class AcolyteShadow : Acolyte +{ + Default + { + +MISSILEMORE + DropItem "ClipOfBullets"; + } + States + { + See: + AGRD A 6 A_BeShadowyFoe; + Goto Super::See+1; + Pain: + AGRD O 0 Fast Slow A_SetShadow; + AGRD O 8 Fast Slow A_Pain; + Goto See; + } +} + +// Some guy turning into an acolyte ----------------------------------------- + +class AcolyteToBe : Acolyte +{ + Default + { + Health 61; + Radius 20; + Height 56; + DeathSound "becoming/death"; + -COUNTKILL + -ISMONSTER + } + + native void A_HideDecepticon (); + + States + { + Spawn: + ARMR A -1; + Stop; + Pain: + ARMR A -1 A_HideDecepticon; + Stop; + Death: + Goto XDeath; + } +} diff --git a/wadsrc/static/zscript/strife/alienspectres.txt b/wadsrc/static/zscript/strife/alienspectres.txt new file mode 100644 index 000000000..0fe9826f0 --- /dev/null +++ b/wadsrc/static/zscript/strife/alienspectres.txt @@ -0,0 +1,223 @@ + +// Alien Spectre 1 ----------------------------------------------------------- + +class AlienSpectre1 : SpectralMonster +{ + Default + { + Health 1000; + Painchance 250; + Speed 12; + Radius 64; + Height 64; + FloatSpeed 5; + Mass 1000; + MinMissileChance 150; + RenderStyle "Translucent"; + Alpha 0.666; + SeeSound "alienspectre/sight"; + AttackSound "alienspectre/blade"; + PainSound "alienspectre/pain"; + DeathSound "alienspectre/death"; + ActiveSound "alienspectre/active"; + Obituary "$OB_ALIENSPECTRE"; + +NOGRAVITY + +FLOAT + +SHADOW + +NOTDMATCH + +DONTMORPH + +NOBLOCKMONST + +INCOMBAT + +LOOKALLAROUND + +NOICEDEATH + } + + native void A_AlienSpectreDeath (); + + States + { + Spawn: + ALN1 A 10 A_Look; + ALN1 B 10 A_SentinelBob; + Loop; + See: + ALN1 AB 4 Bright A_Chase; + ALN1 C 4 Bright A_SentinelBob; + ALN1 DEF 4 Bright A_Chase; + ALN1 G 4 Bright A_SentinelBob; + ALN1 HIJ 4 Bright A_Chase; + ALN1 K 4 Bright A_SentinelBob; + Loop; + Melee: + ALN1 J 4 Bright A_FaceTarget; + ALN1 I 4 Bright A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5); + ALN1 H 4 Bright; + Goto See; + Missile: + ALN1 J 4 Bright A_FaceTarget; + ALN1 I 4 Bright A_SpotLightning; + ALN1 H 4 Bright; + Goto See+10; + Pain: + ALN1 J 2 A_Pain; + Goto See+6; + Death: + AL1P A 6 Bright A_SpectreChunkSmall; + AL1P B 6 Bright A_Scream; + AL1P C 6 Bright A_SpectreChunkSmall; + AL1P DE 6 Bright; + AL1P F 6 Bright A_SpectreChunkSmall; + AL1P G 6 Bright; + AL1P H 6 Bright A_SpectreChunkSmall; + AL1P IJK 6 Bright; + AL1P LM 5 Bright; + AL1P N 5 Bright A_SpectreChunkLarge; + AL1P OPQ 5 Bright; + AL1P R 5 Bright A_AlienSpectreDeath; + Stop; + } +} + + +// Alien Spectre 2 ----------------------------------------------------------- + +class AlienSpectre2 : AlienSpectre1 +{ + Default + { + Health 1200; + Painchance 50; + Radius 24; + DropItem "Sigil2"; + } + States + { + Missile: + ALN1 F 4 A_FaceTarget; + ALN1 I 4 A_CustomMissile("SpectralLightningH3", 32, 0); + ALN1 E 4; + Goto See+10; + } +} + +// Alien Spectre 3 ---------------------------------------------------------- +// This is the Oracle's personal spectre, so it's a little different. + +class AlienSpectre3 : AlienSpectre1 +{ + Default + { + Health 1500; + Painchance 50; + Radius 24; + +SPAWNCEILING + DropItem "Sigil3"; + DamageFactor "SpectralLow", 0; + } + States + { + Spawn: + ALN1 ABCDEFGHIJK 5; + Loop; + See: + ALN1 AB 5 A_Chase; + ALN1 C 5 A_SentinelBob; + ALN1 DEF 5 A_Chase; + ALN1 G 5 A_SentinelBob; + ALN1 HIJ 5 A_Chase; + ALN1 K 5 A_SentinelBob; + Loop; + Melee: + ALN1 J 4 A_FaceTarget; + ALN1 I 4 A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5); + ALN1 C 4; + Goto See+2; + Missile: + ALN1 F 4 A_FaceTarget; + ALN1 I 4 A_Spectre3Attack; + ALN1 E 4; + Goto See+10; + Pain: + ALN1 J 2 A_Pain; + Goto See+6; + } +} + + +// Alien Spectre 4 ----------------------------------------------------------- + +class AlienSpectre4 : AlienSpectre1 +{ + Default + { + Health 1700; + Painchance 50; + Radius 24; + DropItem "Sigil4"; + } + States + { + Missile: + ALN1 F 4 A_FaceTarget; + ALN1 I 4 A_CustomMissile("SpectralLightningBigV2", 32, 0); + ALN1 E 4; + Goto See+10; + } +} + + +// Alien Spectre 5 ----------------------------------------------------------- + +class AlienSpectre5 : AlienSpectre1 +{ + Default + { + Health 2000; + Painchance 50; + Radius 24; + DropItem "Sigil5"; + } + States + { + Missile: + ALN1 F 4 A_FaceTarget; + ALN1 I 4 A_CustomMissile("SpectralLightningBigBall2", 32, 0); + ALN1 E 4; + Goto See+10; + } +} + +// Small Alien Chunk -------------------------------------------------------- + +class AlienChunkSmall : Actor +{ + Default + { + +NOBLOCKMAP + +NOCLIP + } + States + { + Spawn: + NODE ABCDEFG 6 Bright; + Stop; + } +} + +// Large Alien Chunk -------------------------------------------------------- + +class AlienChunkLarge : Actor +{ + Default + { + +NOBLOCKMAP + +NOCLIP + } + States + { + Spawn: + MTHD ABCDEFGHIJK 5 Bright; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/beggars.txt b/wadsrc/static/zscript/strife/beggars.txt new file mode 100644 index 000000000..e70a3a8e7 --- /dev/null +++ b/wadsrc/static/zscript/strife/beggars.txt @@ -0,0 +1,90 @@ + +// Base class for the beggars --------------------------------------------- + +class Beggar : StrifeHumanoid +{ + Default + { + Health 20; + PainChance 250; + Speed 3; + Radius 20; + Height 56; + Monster; + +JUSTHIT + -COUNTKILL + +NOSPLASHALERT + MinMissileChance 150; + Tag "$TAG_BEGGAR"; + MaxStepHeight 16; + MaxDropoffHeight 32; + HitObituary "$OB_BEGGAR"; + + AttackSound "beggar/attack"; + PainSound "beggar/pain"; + DeathSound "beggar/death"; + } + States + { + Spawn: + BEGR A 10 A_Look; + Loop; + See: + BEGR AABBCC 4 A_Wander; + Loop; + Melee: + BEGR D 8; + BEGR D 8 A_CustomMeleeAttack(2*random[PeasantAttack](1,5)+2); + BEGR E 1 A_Chase; + BEGR D 8 A_SentinelRefire; + Loop; + Pain: + BEGR A 3 A_Pain; + BEGR A 3 A_Chase; + Goto Melee; + Death: + BEGR F 4; + BEGR G 4 A_Scream; + BEGR H 4; + BEGR I 4 A_NoBlocking; + BEGR JKLM 4; + BEGR N -1; + Stop; + XDeath: + BEGR F 5 A_TossGib; + GIBS M 5 A_TossGib; + GIBS N 5 A_XScream; + GIBS O 5 A_NoBlocking; + GIBS PQRST 4 A_TossGib; + GIBS U 5; + GIBS V 1400; + Stop; + } +} + + +// Beggars ----------------------------------------------------------------- + +class Beggar1 : Beggar +{ +} + + +class Beggar2 : Beggar +{ +} + + +class Beggar3 : Beggar +{ +} + + +class Beggar4 : Beggar +{ +} + + +class Beggar5 : Beggar +{ +} diff --git a/wadsrc/static/zscript/strife/coin.txt b/wadsrc/static/zscript/strife/coin.txt new file mode 100644 index 000000000..a930cb0ba --- /dev/null +++ b/wadsrc/static/zscript/strife/coin.txt @@ -0,0 +1,99 @@ + +// Coin --------------------------------------------------------------------- + +class Coin : Inventory native +{ + Default + { + +DROPPED + +NOTDMATCH + +FLOORCLIP + Inventory.MaxAmount 0x7fffffff; + +INVENTORY.INVBAR + Tag "$TAG_COIN"; + Inventory.Icon "I_COIN"; + Inventory.PickupMessage "$TXT_COIN"; + } + States + { + Spawn: + COIN A -1; + Stop; + } +} + + +// 10 Gold ------------------------------------------------------------------ + +class Gold10 : Coin +{ + Default + { + Inventory.Amount 10; + Tag "$TAG_10GOLD"; + Inventory.PickupMessage "$TXT_10GOLD"; + } + States + { + Spawn: + CRED A -1; + Stop; + } +} + +// 25 Gold ------------------------------------------------------------------ + +class Gold25 : Coin +{ + Default + { + Inventory.Amount 25; + Tag "$TAG_25GOLD"; + Inventory.PickupMessage "$TXT_25GOLD"; + } + States + { + Spawn: + SACK A -1; + Stop; + } +} + +// 50 Gold ------------------------------------------------------------------ + +class Gold50 : Coin +{ + Default + { + Inventory.Amount 50; + Tag "$TAG_50GOLD"; + Inventory.PickupMessage "$TXT_50GOLD"; + } + States + { + Spawn: + CHST A -1; + Stop; + } +} + +// 300 Gold ------------------------------------------------------------------ + +class Gold300 : Coin +{ + Default + { + Inventory.Amount 300; + Tag "$TAG_300GOLD"; + Inventory.PickupMessage "$TXT_300GOLD"; + Inventory.GiveQuest 3; + +INVENTORY.ALWAYSPICKUP + } + States + { + Spawn: + TOKN A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/crusader.txt b/wadsrc/static/zscript/strife/crusader.txt new file mode 100644 index 000000000..02b08fc93 --- /dev/null +++ b/wadsrc/static/zscript/strife/crusader.txt @@ -0,0 +1,131 @@ + +// Crusader ----------------------------------------------------------------- + +class Crusader : Actor +{ + Default + { + Speed 8; + Radius 40; + Height 56; + Mass 400; + Health 400; + Painchance 128; + Monster; + +FLOORCLIP + +DONTMORPH + +MISSILEMORE + +INCOMBAT + +NOICEDEATH + +NOBLOOD + MinMissileChance 120; + MaxDropoffHeight 32; + DropItem "EnergyPod", 256, 20; + SeeSound "crusader/sight"; + PainSound "crusader/pain"; + DeathSound "crusader/death"; + ActiveSound "crusader/active"; + Obituary "$OB_CRUSADER"; + } + + native void A_CrusaderChoose (); + native void A_CrusaderSweepLeft (); + native void A_CrusaderSweepRight (); + native void A_CrusaderRefire (); + native void A_CrusaderDeath (); + + States + { + Spawn: + ROB2 Q 10 A_Look; + Loop; + See: + ROB2 AABBCCDD 3 A_Chase; + Loop; + Missile: + ROB2 E 3 Slow A_FaceTarget; + ROB2 F 2 Slow Bright A_CrusaderChoose; + ROB2 E 2 Slow Bright A_CrusaderSweepLeft; + ROB2 F 3 Slow Bright A_CrusaderSweepLeft; + ROB2 EF 2 Slow Bright A_CrusaderSweepLeft; + ROB2 EFE 2 Slow Bright A_CrusaderSweepRight; + ROB2 F 2 Slow A_CrusaderRefire; + Loop; + Pain: + ROB2 D 1 Slow A_Pain; + Goto See; + Death: + ROB2 G 3 A_Scream; + ROB2 H 5 A_TossGib; + ROB2 I 4 Bright A_TossGib; + ROB2 J 4 Bright A_Explode(64,64,1,1); + ROB2 K 4 Bright A_Fall; + ROB2 L 4 A_Explode(64,64,1,1); + ROB2 MN 4 A_TossGib; + ROB2 O 4 A_Explode(64,64,1,1); + ROB2 P -1 A_CrusaderDeath; + Stop; + } +} + + +// Fast Flame Projectile (used by Crusader) --------------------------------- + +class FastFlameMissile : FlameMissile +{ + Default + { + Mass 50; + Damage 1; + Speed 35; + } +} + +// Crusader Missile --------------------------------------------------------- +// This is just like the mini missile the player shoots, except it doesn't +// explode when it dies, and it does slightly less damage for a direct hit. + +class CrusaderMissile : Actor +{ + Default + { + Speed 20; + Radius 10; + Height 14; + Damage 7; + Projectile; + +STRIFEDAMAGE + MaxStepHeight 4; + SeeSound "crusader/misl"; + DeathSound "crusader/mislx"; + } + States + { + Spawn: + MICR A 6 Bright A_RocketInFlight; + Loop; + Death: + SMIS A 0 Bright A_SetTranslucent(1,1); + SMIS A 5 Bright; + SMIS B 5 Bright; + SMIS C 4 Bright; + SMIS DEFG 2 Bright; + Stop; + } +} + + +// Dead Crusader ------------------------------------------------------------ + +class DeadCrusader : Actor +{ + States + { + Spawn: + ROB2 N 4; + ROB2 O 4; + ROB2 P -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/entityboss.txt b/wadsrc/static/zscript/strife/entityboss.txt new file mode 100644 index 000000000..8ccdbbd02 --- /dev/null +++ b/wadsrc/static/zscript/strife/entityboss.txt @@ -0,0 +1,211 @@ + +// Entity Nest -------------------------------------------------------------- + +class EntityNest : Actor +{ + Default + { + Radius 84; + Height 47; + +SOLID + +NOTDMATCH + +FLOORCLIP + } + States + { + Spawn: + NEST A -1; + Stop; + } +} + +// Entity Pod --------------------------------------------------------------- + +class EntityPod : Actor +{ + Default + { + Radius 25; + Height 91; + +SOLID + +NOTDMATCH + SeeSound "misc/gibbed"; + } + + native void A_SpawnEntity (); + + States + { + Spawn: + PODD A 60 A_Look; + Loop; + See: + PODD A 360; + PODD B 9 A_NoBlocking; + PODD C 9; + PODD D 9 A_SpawnEntity; + PODD E -1; + Stop; + } +} + + +// Entity Boss -------------------------------------------------------------- + +class EntityBoss : SpectralMonster +{ + Default + { + Health 2500; + Painchance 255; + Speed 13; + Radius 130; + Height 200; + FloatSpeed 5; + Mass 1000; + Monster; + +SPECIAL + +NOGRAVITY + +FLOAT + +SHADOW + +NOTDMATCH + +DONTMORPH + +NOTARGET + +NOBLOCKMONST + +INCOMBAT + +LOOKALLAROUND + +SPECTRAL + +NOICEDEATH + MinMissileChance 150; + RenderStyle "Translucent"; + Alpha 0.5; + SeeSound "entity/sight"; + AttackSound "entity/melee"; + PainSound "entity/pain"; + DeathSound "entity/death"; + ActiveSound "entity/active"; + Obituary "$OB_ENTITY"; + } + + native void A_EntityAttack(); + native void A_EntityDeath(); + + States + { + Spawn: + MNAM A 100; + MNAM B 60 Bright; + MNAM CDEFGHIJKL 4 Bright; + MNAL A 4 Bright A_Look; + MNAL B 4 Bright A_SentinelBob; + Goto Spawn+12; + See: + MNAL AB 4 Bright A_Chase; + MNAL C 4 Bright A_SentinelBob; + MNAL DEF 4 Bright A_Chase; + MNAL G 4 Bright A_SentinelBob; + MNAL HIJ 4 Bright A_Chase; + MNAL K 4 Bright A_SentinelBob; + Loop; + Melee: + MNAL J 4 Bright A_FaceTarget; + MNAL I 4 Bright A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5); + MNAL C 4 Bright; + Goto See+2; + Missile: + MNAL F 4 Bright A_FaceTarget; + MNAL I 4 Bright A_EntityAttack; + MNAL E 4 Bright; + Goto See+10; + Pain: + MNAL J 2 Bright A_Pain; + Goto See+6; + Death: + MNAL L 7 Bright A_SpectreChunkSmall; + MNAL M 7 Bright A_Scream; + MNAL NO 7 Bright A_SpectreChunkSmall; + MNAL P 7 Bright A_SpectreChunkLarge; + MNAL Q 64 Bright A_SpectreChunkSmall; + MNAL Q 6 Bright A_EntityDeath; + Stop; + } +} + +// Second Entity Boss ------------------------------------------------------- + +class EntitySecond : SpectralMonster +{ + Default + { + Health 990; + Painchance 255; + Speed 14; + Radius 130; + Height 200; + FloatSpeed 5; + Mass 1000; + Monster; + +SPECIAL + +NOGRAVITY + +FLOAT + +SHADOW + +NOTDMATCH + +DONTMORPH + +NOBLOCKMONST + +INCOMBAT + +LOOKALLAROUND + +SPECTRAL + +NOICEDEATH + MinMissileChance 150; + RenderStyle "Translucent"; + Alpha 0.25; + SeeSound "alienspectre/sight"; + AttackSound "alienspectre/blade"; + PainSound "alienspectre/pain"; + DeathSound "alienspectre/death"; + ActiveSound "alienspectre/active"; + Obituary "$OB_ENTITY"; + } + + native void A_SubEntityDeath (); + + States + { + Spawn: + MNAL R 10 Bright A_Look; + Loop; + See: + MNAL R 5 Bright A_SentinelBob; + MNAL ST 5 Bright A_Chase; + MNAL U 5 Bright A_SentinelBob; + MNAL V 5 Bright A_Chase; + MNAL W 5 Bright A_SentinelBob; + Loop; + Melee: + MNAL S 4 Bright A_FaceTarget; + MNAL R 4 Bright A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5); + MNAL T 4 Bright A_SentinelBob; + Goto See+1; + Missile: + MNAL W 4 Bright A_FaceTarget; + MNAL U 4 Bright A_CustomMissile("SpectralLightningH3",32,0); + MNAL V 4 Bright A_SentinelBob; + Goto See+4; + Pain: + MNAL R 2 Bright A_Pain; + Goto See; + Death: + MDTH A 3 Bright A_Scream; + MDTH B 3 Bright A_TossGib; + MDTH C 3 Bright A_NoBlocking; + MDTH DEFGHIJKLMN 3 Bright A_TossGib; + MDTH O 3 Bright A_SubEntityDeath; + Stop; + } +} + + + + + + diff --git a/wadsrc/static/zscript/strife/inquisitor.txt b/wadsrc/static/zscript/strife/inquisitor.txt new file mode 100644 index 000000000..b27818a61 --- /dev/null +++ b/wadsrc/static/zscript/strife/inquisitor.txt @@ -0,0 +1,150 @@ + +// Inquisitor --------------------------------------------------------------- + +class Inquisitor : Actor +{ + Default + { + Health 1000; + Speed 12; + Radius 40; + Height 110; + Mass 0x7fffffff; + Monster; + +DROPOFF + +NOBLOOD + +BOSS + +FLOORCLIP + +DONTMORPH + +NORADIUSDMG + MaxDropOffHeight 32; + MinMissileChance 150; + SeeSound "inquisitor/sight"; + DeathSound "inquisitor/death"; + ActiveSound "inquisitor/active"; + Obituary "$OB_INQUISITOR"; + } + + native void A_InquisitorWalk (); + native void A_InquisitorDecide (); + native void A_InquisitorAttack (); + native void A_InquisitorJump (); + native void A_InquisitorCheckLand (); + native void A_TossArm (); + native void A_ReaverRanged (); + + States + { + Spawn: + ROB3 AB 10 A_Look; + Loop; + See: + ROB3 B 3 A_InquisitorWalk; + ROB3 B 3 A_Chase; + ROB3 CCDD 4 A_Chase; + ROB3 E 3 A_InquisitorWalk; + ROB3 E 3 A_InquisitorDecide; + Loop; + Missile: + ROB3 A 2 A_InquisitorDecide; + ROB3 F 6 A_FaceTarget; + ROB3 G 8 Bright A_ReaverRanged; + ROB3 G 8 A_ReaverRanged; + Goto See; + Grenade: + ROB3 K 12 A_FaceTarget; + ROB3 J 6 Bright A_InquisitorAttack; + ROB3 K 12; + Goto See; + Jump: + ROB3 H 8 Bright A_InquisitorJump; + ROB3 I 4 Bright A_InquisitorCheckLand; + ROB3 H 4 Bright A_InquisitorCheckLand; + Goto Jump+1; + Death: + ROB3 L 0 A_StopSound(CHAN_ITEM); + ROB3 L 4 A_TossGib; + ROB3 M 4 A_Scream; + ROB3 N 4 A_TossGib; + ROB3 O 4 Bright A_Explode(128,128,1,1); + ROB3 P 4 Bright A_TossGib; + ROB3 Q 4 Bright A_NoBlocking; + ROB3 RSTUV 4 A_TossGib; + ROB3 W 4 Bright A_Explode(128,128,1,1); + ROB3 XY 4 Bright A_TossGib; + ROB3 Z 4 A_TossGib; + ROB3 [ 4 A_TossGib; + ROB3 \ 3 A_TossGib; + ROB3 ] 3 Bright A_Explode(128,128,1,1); + RBB3 A 3 Bright A_TossArm; + RBB3 B 3 Bright A_TossGib; + RBB3 CD 3 A_TossGib; + RBB3 E -1; + Stop; + } +} + +// Inquisitor Shot ---------------------------------------------------------- + +class InquisitorShot : Actor +{ + Default + { + ReactionTime 15; + Speed 25; + Radius 13; + Height 13; + Mass 15; + Projectile; + -ACTIVATEIMPACT + -ACTIVATEPCROSS + -NOGRAVITY + +STRIFEDAMAGE + MaxStepHeight 4; + SeeSound "inquisitor/attack"; + DeathSound "inquisitor/atkexplode"; + } + States + { + Spawn: + UBAM AB 3 A_Countdown; + Loop; + Death: + BNG2 A 0 Bright A_SetTranslucent(1,1); + BNG2 A 4 Bright A_Explode(192, 192, 1, 1); + BNG2 B 4 Bright; + BNG2 C 4 Bright; + BNG2 D 4 Bright; + BNG2 E 4 Bright; + BNG2 F 4 Bright; + BNG2 G 4 Bright; + BNG2 H 4 Bright; + BNG2 I 4 Bright; + Stop; + } + +} + + +// The Dead Inquisitor's Detached Arm --------------------------------------- + +class InquisitorArm : Actor +{ + Default + { + Speed 25; + +NOBLOCKMAP + +NOCLIP + +NOBLOOD + } + States + { + Spawn: + RBB3 FG 5 Bright; + RBB3 H -1; + Stop; + } +} + + + diff --git a/wadsrc/static/zscript/strife/loremaster.txt b/wadsrc/static/zscript/strife/loremaster.txt new file mode 100644 index 000000000..4a48cf4d3 --- /dev/null +++ b/wadsrc/static/zscript/strife/loremaster.txt @@ -0,0 +1,123 @@ + +// Loremaster (aka Priest) -------------------------------------------------- + +class Loremaster : Actor +{ + Default + { + Health 800; + Speed 10; + Radius 15; + Height 56; + FloatSpeed 5; + Monster; + +FLOAT + +NOBLOOD + +NOGRAVITY + +NOTDMATCH + +FLOORCLIP + +NOBLOCKMONST + +INCOMBAT + +LOOKALLAROUND + +NOICEDEATH + +NEVERRESPAWN + DamageFactor "Fire", 0.5; + MinMissileChance 150; + Tag "$TAG_PRIEST"; + SeeSound "loremaster/sight"; + AttackSound "loremaster/attack"; + PainSound "loremaster/pain"; + DeathSound "loremaster/death"; + ActiveSound "loremaster/active"; + Obituary "$OB_LOREMASTER"; + DropItem "Junk"; + } + States + { + Spawn: + PRST A 10 A_Look; + PRST B 10 A_SentinelBob; + Loop; + See: + PRST A 4 A_Chase; + PRST A 4 A_SentinelBob; + PRST B 4 A_Chase; + PRST B 4 A_SentinelBob; + PRST C 4 A_Chase; + PRST C 4 A_SentinelBob; + PRST D 4 A_Chase; + PRST D 4 A_SentinelBob; + Loop; + Melee: + PRST E 4 A_FaceTarget; + PRST F 4 A_CustomMeleeAttack((random[SpectreMelee](0,255)&9)*5); + PRST E 4 A_SentinelBob; + Goto See; + Missile: + PRST E 4 A_FaceTarget; + PRST F 4 A_CustomMissile("LoreShot", 32, 0); + PRST E 4 A_SentinelBob; + Goto See; + Death: + PDED A 6; + PDED B 6 A_Scream; + PDED C 6; + PDED D 6 A_Fall; + PDED E 6; + PDED FGHIJIJIJKL 5; + PDED MNOP 4; + PDED Q 4 A_SpawnItemEx("AlienSpectre5", 0, 0, 0, 0, 0, random[spectrespawn](0,255)*0.0078125, 0, SXF_NOCHECKPOSITION); + PDED RS 4; + PDED T -1; + Stop; + } +} + + +// Loremaster Projectile ---------------------------------------------------- + +class LoreShot : Actor native +{ + Default + { + Speed 20; + Height 14; + Radius 10; + Projectile; + +STRIFEDAMAGE + Damage 2; + MaxStepHeight 4; + SeeSound "loremaster/chain"; + ActiveSound "loremaster/swish"; + } + + native void A_LoremasterChain (); + + States + { + Spawn: + OCLW A 2 A_LoremasterChain; + Loop; + Death: + OCLW A 6; + Stop; + } +} + +// Loremaster Subprojectile ------------------------------------------------- + +class LoreShot2 : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + } + States + { + Spawn: + TEND A 20; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/macil.txt b/wadsrc/static/zscript/strife/macil.txt new file mode 100644 index 000000000..870f0db35 --- /dev/null +++ b/wadsrc/static/zscript/strife/macil.txt @@ -0,0 +1,95 @@ + +// Macil (version 1) --------------------------------------------------------- + +class Macil1 : Actor +{ + Default + { + Health 95; + Radius 20; + Height 56; + Speed 8; + Painchance 250; + Monster; + -COUNTKILL + +NOTDMATCH + +NOICEDEATH + +NOSPLASHALERT + +NODAMAGE + +NEVERRESPAWN + DamageFactor "Fire", 0.5; + MinMissileChance 150; + SeeSound "macil/sight"; + PainSound "macil/pain"; + ActiveSound "macil/active"; + CrushPainSound "misc/pcrush"; + Tag "$TAG_MACIL1"; + Obituary "$OB_MACIL"; + DropItem "BoxOfBullets"; + MaxStepHeight 16; + MaxDropoffHeight 32; + } + States + { + Spawn: + LEDR C 5 A_Look2; + Loop; + LEDR A 8; + Loop; + LEDR B 8; + Loop; + LEAD ABCD 6 A_Wander; + Loop; + See: + LEAD AABBCCDD 3 A_Chase; + Loop; + Missile: + Death: + LEAD E 2 A_FaceTarget; + LEAD F 2 BRIGHT A_ShootGun; + LEAD E 1 A_SentinelRefire; + Loop; + Pain: + LEAD Y 3; + LEAD Y 3 A_Pain; + Goto See; + } +} + + +// Macil (version 2) --------------------------------------------------------- + +class Macil2 : Macil1 +{ + Default + { + Painchance 200; + +COUNTKILL + +SPECTRAL + -NODAMAGE + Tag "$TAG_MACIL2"; + DeathSound "macil/slop"; + DropItem "None"; + DamageFactor "SpectralLow", 0; + } + States + { + Missile: + LEAD E 4 A_FaceTarget; + LEAD F 4 BRIGHT A_ShootGun; + LEAD E 2 A_SentinelRefire; + Loop; + Death: + LEAD G 5; + LEAD H 5 A_Scream; + LEAD IJ 4; + LEAD K 3; + LEAD L 3 A_NoBlocking; + LEAD MNOPQRSTUV 3; + LEAD W 3 A_SpawnItemEx("AlienSpectre4", 0, 0, 0, 0, 0, random[spectrespawn](0,255)*0.0078125, 0, SXF_NOCHECKPOSITION); + LEAD X -1; + Stop; + } +} + + diff --git a/wadsrc/static/zscript/strife/merchants.txt b/wadsrc/static/zscript/strife/merchants.txt new file mode 100644 index 000000000..71b797639 --- /dev/null +++ b/wadsrc/static/zscript/strife/merchants.txt @@ -0,0 +1,108 @@ +// Base class for the merchants --------------------------------------------- + +class Merchant : Actor +{ + Default + { + Health 10000000; + PainChance 256; // a merchant should always enter the pain state when getting hurt + Radius 20; + Height 56; + Mass 5000; + CrushPainSound "misc/pcrush"; + +SOLID + +SHOOTABLE + +NOTDMATCH + +NOSPLASHALERT + +NODAMAGE + } + States + { + Spawn: + MRST A 10 A_Look2; + Loop; + MRLK A 30 A_ActiveSound; + Loop; + MRLK B 30; + Loop; + MRBD ABCDEDCB 4; + MRBD A 5; + MRBD F 6; + Loop; + See: + Pain: + MRPN A 1; + MRPN A 2 A_AlertMonsters; + MRPN B 3 A_Pain; + MRPN C 3; + MRPN D 9 Door_CloseWaitOpen(999, 64, 960); + MRPN C 4; + MRPN B 3; + MRPN A 3 A_ClearSoundTarget; + Goto Spawn; + Yes: + MRYS A 20; + // Fall through + Greetings: + MRGT ABCDEFGHI 5; + Goto Spawn; + No: + MRNO AB 6; + MRNO C 10; + MRNO BA 6; + Goto Greetings; + } +} + + +// Weapon Smith ------------------------------------------------------------- + +class WeaponSmith : Merchant +{ + Default + { + PainSound "smith/pain"; + Tag "$TAG_WEAPONSMITH"; + } +} + + +// Bar Keep ----------------------------------------------------------------- + +class BarKeep : Merchant +{ + Default + { + Translation 4; + PainSound "barkeep/pain"; + ActiveSound "barkeep/active"; + Tag "$TAG_BARKEEP"; + } +} + + +// Armorer ------------------------------------------------------------------ + +class Armorer : Merchant +{ + Default + { + Translation 5; + PainSound "armorer/pain"; + Tag "$TAG_ARMORER"; + } +} + + +// Medic -------------------------------------------------------------------- + +class Medic : Merchant +{ + Default + { + Translation 6; + PainSound "medic/pain"; + Tag "$TAG_MEDIC"; + } +} + diff --git a/wadsrc/static/zscript/strife/oracle.txt b/wadsrc/static/zscript/strife/oracle.txt new file mode 100644 index 000000000..6023629c2 --- /dev/null +++ b/wadsrc/static/zscript/strife/oracle.txt @@ -0,0 +1,38 @@ + +// Oracle ------------------------------------------------------------------- + +class Oracle : Actor +{ + Default + { + Health 1; + Radius 15; + Height 56; + Monster; + +NOTDMATCH + +NOBLOOD + +NEVERRESPAWN + DamageFactor "Fire", 0.5; + DamageFactor "SpectralLow", 0; + MaxDropoffHeight 32; + Tag "$TAG_ORACLE"; + DropItem "Meat"; + } + + native void A_WakeOracleSpectre (); + + States + { + Spawn: + ORCL A -1; + Stop; + Death: + ORCL BCDEFGHIJK 5; + ORCL L 5 A_NoBlocking; + ORCL M 5; + ORCL N 5 A_WakeOracleSpectre; + ORCL OP 5; + ORCL Q -1; + Stop; + } +} diff --git a/wadsrc/static/zscript/strife/peasants.txt b/wadsrc/static/zscript/strife/peasants.txt new file mode 100644 index 000000000..6645c69fa --- /dev/null +++ b/wadsrc/static/zscript/strife/peasants.txt @@ -0,0 +1,251 @@ + +// Peasant Base Class ------------------------------------------------------- + +class Peasant : StrifeHumanoid +{ + Default + { + Health 31; + PainChance 200; + Speed 8; + Radius 20; + Height 56; + Monster; + +NEVERTARGET + -COUNTKILL + +NOSPLASHALERT + +FLOORCLIP + +JUSTHIT + MinMissileChance 150; + MaxStepHeight 16; + MaxDropoffHeight 32; + SeeSound "peasant/sight"; + AttackSound "peasant/attack"; + PainSound "peasant/pain"; + DeathSound "peasant/death"; + HitObituary "$OB_PEASANT"; + } + States + { + Spawn: + PEAS A 10 A_Look2; + Loop; + See: + PEAS AABBCCDD 5 A_Wander; + Goto Spawn; + Melee: + PEAS E 10 A_FaceTarget; + PEAS F 8 A_CustomMeleeAttack(2*random[PeasantAttack](1,5)+2); + PEAS E 8; + Goto See; + Pain: + PEAS O 3; + PEAS O 3 A_Pain; + Goto Melee; + Wound: + PEAS G 5; + PEAS H 10 A_GetHurt; + PEAS I 6; + Goto Wound+1; + Death: + PEAS G 5; + PEAS H 5 A_Scream; + PEAS I 6; + PEAS J 5 A_NoBlocking; + PEAS K 5; + PEAS L 6; + PEAS M 8; + PEAS N 1400; + GIBS U 5; + GIBS V 1400; + Stop; + XDeath: + GIBS M 5 A_TossGib; + GIBS N 5 A_XScream; + GIBS O 5 A_NoBlocking; + GIBS PQRS 4 A_TossGib; + Goto Death+8; + } +} + +// Peasant Variant 1 -------------------------------------------------------- + +class Peasant1 : Peasant +{ + Default + { + Speed 4; + } +} + +class Peasant2 : Peasant +{ + Default + { + Speed 5; + } +} + +class Peasant3 : Peasant +{ + Default + { + Speed 5; + } +} + +class Peasant4 : Peasant +{ + Default + { + Translation 0; + Speed 7; + } +} + +class Peasant5 : Peasant +{ + Default + { + Translation 0; + Speed 7; + } +} + +class Peasant6 : Peasant +{ + Default + { + Translation 0; + Speed 7; + } +} + +class Peasant7 : Peasant +{ + Default + { + Translation 2; + } +} + +class Peasant8 : Peasant +{ + Default + { + Translation 2; + } +} + +class Peasant9 : Peasant +{ + Default + { + Translation 2; + } +} + +class Peasant10 : Peasant +{ + Default + { + Translation 1; + } +} + +class Peasant11 : Peasant +{ + Default + { + Translation 1; + } +} + +class Peasant12 : Peasant +{ + Default + { + Translation 1; + } +} + +class Peasant13 : Peasant +{ + Default + { + Translation 3; + } +} + +class Peasant14 : Peasant +{ + Default + { + Translation 3; + } +} + +class Peasant15 : Peasant +{ + Default + { + Translation 3; + } +} + +class Peasant16 : Peasant +{ + Default + { + Translation 5; + } +} + +class Peasant17 : Peasant +{ + Default + { + Translation 5; + } +} + +class Peasant18 : Peasant +{ + Default + { + Translation 5; + } +} + +class Peasant19 : Peasant +{ + Default + { + Translation 4; + } +} + +class Peasant20 : Peasant +{ + Default + { + Translation 4; + } +} + +class Peasant21 : Peasant +{ + Default + { + Translation 4; + } +} + +class Peasant22 : Peasant +{ + Default + { + Translation 6; + } +} + diff --git a/wadsrc/static/zscript/strife/programmer.txt b/wadsrc/static/zscript/strife/programmer.txt new file mode 100644 index 000000000..dc88a790f --- /dev/null +++ b/wadsrc/static/zscript/strife/programmer.txt @@ -0,0 +1,116 @@ + +// Programmer --------------------------------------------------------------- + +class Programmer : Actor +{ + Default + { + Health 1100; + PainChance 50; + Speed 26; + FloatSpeed 5; + Radius 45; + Height 60; + Mass 800; + Damage 4; + Monster; + +NOGRAVITY + +FLOAT + +NOBLOOD + +NOTDMATCH + +DONTMORPH + +NOBLOCKMONST + +LOOKALLAROUND + +NOICEDEATH + +NOTARGETSWITCH + DamageFactor "Fire", 0.5; + MinMissileChance 150; + AttackSound "programmer/attack"; + PainSound "programmer/pain"; + DeathSound "programmer/death"; + ActiveSound "programmer/active"; + Obituary "$OB_PROGRAMMER"; + DropItem "Sigil1"; + } + + native void A_ProgrammerMelee (); + native void A_SpawnProgrammerBase (); + native void A_ProgrammerDeath (); + native void A_SpotLightning(); + + States + { + Spawn: + PRGR A 5 A_Look; + PRGR A 1 A_SentinelBob; + Loop; + See: + PRGR A 160 A_SentinelBob; + PRGR BCD 5 A_SentinelBob; + PRGR EF 2 A_SentinelBob; + PRGR EF 3 A_Chase; + Goto See+4; + Melee: + PRGR E 2 A_SentinelBob; + PRGR F 3 A_SentinelBob; + PRGR E 3 A_FaceTarget; + PRGR F 4 A_ProgrammerMelee; + Goto See+4; + Missile: + PRGR G 5 A_FaceTarget; + PRGR H 5 A_SentinelBob; + PRGR I 5 Bright A_FaceTarget; + PRGR J 5 Bright A_SpotLightning; + Goto See+4; + Pain: + PRGR K 5 A_Pain; + PRGR L 5 A_SentinelBob; + Goto See+4; + Death: + PRGR L 7 Bright A_TossGib; + PRGR M 7 Bright A_Scream; + PRGR N 7 Bright A_TossGib; + PRGR O 7 Bright A_NoBlocking; + PRGR P 7 Bright A_TossGib; + PRGR Q 7 Bright A_SpawnProgrammerBase; + PRGR R 7 Bright; + PRGR S 6 Bright; + PRGR TUVW 5 Bright; + PRGR X 32 Bright; + PRGR X -1 Bright A_ProgrammerDeath; + Stop; + } +} + + +// The Programmer's base for when he dies ----------------------------------- + +class ProgrammerBase : Actor +{ + Default + { + +NOBLOCKMAP + +NOCLIP + +NOBLOOD + } + States + { + Spawn: + BASE A 5 Bright A_Explode(32,32,1,1); + BASE BCD 5 Bright; + BASE EFG 5; + BASE H -1; + Stop; + } +} + + +// The Programmer level ending thing ---------------------------------------- + +class ProgLevelEnder : Inventory native +{ + Default + { + +INVENTORY.UNDROPPABLE + } +} diff --git a/wadsrc/static/actors/strife/questitems.txt b/wadsrc/static/zscript/strife/questitems.txt similarity index 51% rename from wadsrc/static/actors/strife/questitems.txt rename to wadsrc/static/zscript/strife/questitems.txt index 11da7c90f..4946f0414 100644 --- a/wadsrc/static/actors/strife/questitems.txt +++ b/wadsrc/static/zscript/strife/questitems.txt @@ -16,11 +16,11 @@ * 13 You've freed the prisoners! * 14 You've Blown Up the Crystal * 15 You got the guard uniform - * 16 You've Blown Up the Gates (/Piston) - * 17 You watched the Sigil slideshow on map10 + * 16 You've Blown Up the Gates (/Piston); + * 17 You watched the Sigil slideshow on map10; * 18 You got the Oracle pass * 19 You met Quincy and talked to him about the Bishop - * 20 + * 20; * 21 You Killed the Bishop! * 22 The Oracle has told you to kill Macil * 23 You've Killed The Oracle! @@ -30,146 +30,155 @@ * 27 You've Blown Up the Computer * 28 You got the catacomb key * 29 You destroyed the mind control device in the mines - * 30 - * 31 + * 30; + * 31; */ -ACTOR QuestItem : Inventory +class QuestItem : Inventory { States { Spawn: - TOKN A -1 - Stop + TOKN A -1; + Stop; } } // Quest Items ------------------------------------------------------------- -ACTOR QuestItem1 : QuestItem +class QuestItem1 : QuestItem { } -ACTOR QuestItem2 : QuestItem +class QuestItem2 : QuestItem { } -ACTOR QuestItem3 : QuestItem +class QuestItem3 : QuestItem { } -ACTOR QuestItem4 : QuestItem +class QuestItem4 : QuestItem { - Tag "$TAG_QUEST4" + Default + { + Tag "$TAG_QUEST4"; + } } -ACTOR QuestItem5 : QuestItem +class QuestItem5 : QuestItem { - Tag "$TAG_QUEST5" + Default + { + Tag "$TAG_QUEST5"; + } } -ACTOR QuestItem6 : QuestItem +class QuestItem6 : QuestItem { - Tag "TAG_QUEST6" + Default + { + Tag "TAG_QUEST6"; + } } -ACTOR QuestItem7 : QuestItem +class QuestItem7 : QuestItem { } -ACTOR QuestItem8 : QuestItem +class QuestItem8 : QuestItem { } -ACTOR QuestItem9 : QuestItem +class QuestItem9 : QuestItem { } -ACTOR QuestItem10 : QuestItem +class QuestItem10 : QuestItem { } -ACTOR QuestItem11 : QuestItem +class QuestItem11 : QuestItem { } -ACTOR QuestItem12 : QuestItem +class QuestItem12 : QuestItem { } -ACTOR QuestItem13 : QuestItem +class QuestItem13 : QuestItem { } -ACTOR QuestItem14 : QuestItem +class QuestItem14 : QuestItem { } -ACTOR QuestItem15 : QuestItem +class QuestItem15 : QuestItem { } -ACTOR QuestItem16 : QuestItem +class QuestItem16 : QuestItem { } -ACTOR QuestItem17 : QuestItem +class QuestItem17 : QuestItem { } -ACTOR QuestItem18 : QuestItem +class QuestItem18 : QuestItem { } -ACTOR QuestItem19 : QuestItem +class QuestItem19 : QuestItem { } -ACTOR QuestItem20 : QuestItem +class QuestItem20 : QuestItem { } -ACTOR QuestItem21 : QuestItem +class QuestItem21 : QuestItem { } -ACTOR QuestItem22 : QuestItem +class QuestItem22 : QuestItem { } -ACTOR QuestItem23 : QuestItem +class QuestItem23 : QuestItem { } -ACTOR QuestItem24 : QuestItem +class QuestItem24 : QuestItem { } -ACTOR QuestItem25 : QuestItem +class QuestItem25 : QuestItem { } -ACTOR QuestItem26 : QuestItem +class QuestItem26 : QuestItem { } -ACTOR QuestItem27 : QuestItem +class QuestItem27 : QuestItem { } -ACTOR QuestItem28 : QuestItem +class QuestItem28 : QuestItem { } -ACTOR QuestItem29 : QuestItem +class QuestItem29 : QuestItem { } -ACTOR QuestItem30 : QuestItem +class QuestItem30 : QuestItem { } -ACTOR QuestItem31 : QuestItem +class QuestItem31 : QuestItem { } diff --git a/wadsrc/static/zscript/strife/ratbuddy.txt b/wadsrc/static/zscript/strife/ratbuddy.txt new file mode 100644 index 000000000..fc0c9c63e --- /dev/null +++ b/wadsrc/static/zscript/strife/ratbuddy.txt @@ -0,0 +1,37 @@ + +class RatBuddy : Actor +{ + Default + { + Health 5; + Speed 13; + Radius 10; + Height 16; + +NOBLOOD +FLOORCLIP +CANPASS + +ISMONSTER +INCOMBAT + MinMissileChance 150; + MaxStepHeight 16; + MaxDropoffHeight 32; + Tag "$TAG_RATBUDDY"; + SeeSound "rat/sight"; + DeathSound "rat/death"; + ActiveSound "rat/active"; + } + States + { + Spawn: + RATT A 10 A_Look; + Loop; + See: + RATT AABB 4 A_Chase; + Loop; + Melee: + RATT A 8 A_Wander; + RATT B 4 A_Wander; + Goto See; + Death: + MEAT Q 700; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/reaver.txt b/wadsrc/static/zscript/strife/reaver.txt new file mode 100644 index 000000000..7656a37a9 --- /dev/null +++ b/wadsrc/static/zscript/strife/reaver.txt @@ -0,0 +1,67 @@ + +class Reaver : Actor +{ + Default + { + Health 150; + Painchance 128; + Speed 12; + Radius 20; + Height 60; + Monster; + +NOBLOOD + +INCOMBAT + MinMissileChance 150; + MaxDropoffHeight 32; + Mass 500; + SeeSound "reaver/sight"; + PainSound "reaver/pain"; + DeathSound "reaver/death"; + ActiveSound "reaver/active"; + HitObituary "$OB_REAVERHIT"; + Obituary "$OB_REAVER"; + } + + native void A_ReaverRanged (); + + States + { + Spawn: + ROB1 A 10 A_Look; + Loop; + See: + ROB1 BBCCDDEE 3 A_Chase; + Loop; + Melee: + ROB1 H 6 Slow A_FaceTarget; + ROB1 I 8 Slow A_CustomMeleeAttack(random[ReaverMelee](1,8)*3, "reaver/blade"); + ROB1 H 6 Slow; + Goto See; + Missile: + ROB1 F 8 Slow A_FaceTarget; + ROB1 G 11 Slow BRIGHT A_ReaverRanged; + Goto See; + Pain: + ROB1 A 2 Slow; + ROB1 A 2 A_Pain; + Goto See; + Death: + ROB1 J 6; + ROB1 K 6 A_Scream; + ROB1 L 5; + ROB1 M 5 A_NoBlocking; + ROB1 NOP 5; + ROB1 Q 6 A_Explode(32,32,1,1); + ROB1 R -1; + Stop; + XDeath: + ROB1 L 5 A_TossGib; + ROB1 M 5 A_Scream; + ROB1 N 5 A_TossGib; + ROB1 O 5 A_NoBlocking; + ROB1 P 5 A_TossGib; + Goto Death+7; + } + +} + \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/rebels.txt b/wadsrc/static/zscript/strife/rebels.txt new file mode 100644 index 000000000..d9e65560f --- /dev/null +++ b/wadsrc/static/zscript/strife/rebels.txt @@ -0,0 +1,140 @@ + + +// Base class for the rebels ------------------------------------------------ + +class Rebel : StrifeHumanoid +{ + Default + { + Health 60; + Painchance 250; + Speed 8; + Radius 20; + Height 56; + Monster; + +FRIENDLY + -COUNTKILL + +NOSPLASHALERT + MinMissileChance 150; + Tag "$TAG_REBEL"; + SeeSound "rebel/sight"; + PainSound "rebel/pain"; + DeathSound "rebel/death"; + ActiveSound "rebel/active"; + Obituary "$OB_REBEL"; + } + States + { + Spawn: + HMN1 P 5 A_Look2; + Loop; + HMN1 Q 8; + Loop; + HMN1 R 8; + Loop; + HMN1 ABCDABCD 6 A_Wander; + Loop; + See: + HMN1 AABBCCDD 3 A_Chase; + Loop; + Missile: + HMN1 E 10 A_FaceTarget; + HMN1 F 10 BRIGHT A_ShootGun; + HMN1 E 10 A_ShootGun; + Goto See; + Pain: + HMN1 O 3; + HMN1 O 3 A_Pain; + Goto See; + Death: + HMN1 G 5; + HMN1 H 5 A_Scream; + HMN1 I 3 A_NoBlocking; + HMN1 J 4; + HMN1 KLM 3; + HMN1 N -1; + Stop; + XDeath: + RGIB A 4 A_TossGib; + RGIB B 4 A_XScream; + RGIB C 3 A_NoBlocking; + RGIB DEF 3 A_TossGib; + RGIB G 3; + RGIB H 1400; + Stop; + } +} + +// Rebel 1 ------------------------------------------------------------------ + +class Rebel1 : Rebel +{ + Default + { + DropItem "ClipOfBullets"; + } +} + +// Rebel 2 ------------------------------------------------------------------ + +class Rebel2 : Rebel +{ +} + +// Rebel 3 ------------------------------------------------------------------ + +class Rebel3 : Rebel +{ +} + +// Rebel 4 ------------------------------------------------------------------ + +class Rebel4 : Rebel +{ +} + +// Rebel 5 ------------------------------------------------------------------ + +class Rebel5 : Rebel +{ +} + +// Rebel 6 ------------------------------------------------------------------ + +class Rebel6 : Rebel +{ +} + +// Teleporter Beacon -------------------------------------------------------- + +class TeleporterBeacon : Inventory native +{ + Default + { + Health 5; + Radius 16; + Height 16; + Inventory.MaxAmount 3; + +DROPPED + +INVENTORY.INVBAR + Inventory.Icon "I_BEAC"; + Tag "$TAG_TELEPORTERBEACON"; + Inventory.PickupMessage "$TXT_BEACON"; + } + + native void A_Beacon (); + + States + { + Spawn: + BEAC A -1; + Stop; + Drop: + BEAC A 30; + BEAC A 160 A_Beacon; + Wait; + Death: + BEAC A 1 A_FadeOut(0.015); + Loop; + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/sentinel.txt b/wadsrc/static/zscript/strife/sentinel.txt new file mode 100644 index 000000000..946a99ea2 --- /dev/null +++ b/wadsrc/static/zscript/strife/sentinel.txt @@ -0,0 +1,104 @@ + +// Sentinel ----------------------------------------------------------------- + +class Sentinel : Actor +{ + Default + { + Health 100; + Painchance 255; + Speed 7; + Radius 23; + Height 53; + Mass 300; + Monster; + +SPAWNCEILING + +NOGRAVITY + +DROPOFF + +NOBLOOD + +NOBLOCKMONST + +INCOMBAT + +MISSILEMORE + +LOOKALLAROUND + +NEVERRESPAWN + MinMissileChance 150; + SeeSound "sentinel/sight"; + DeathSound "sentinel/death"; + ActiveSound "sentinel/active"; + Obituary "$OB_SENTINEL"; + } + + native void A_SentinelAttack (); + + States + { + Spawn: + SEWR A 10 A_Look; + Loop; + See: + SEWR A 6 A_SentinelBob; + SEWR A 6 A_Chase; + Loop; + Missile: + SEWR B 4 A_FaceTarget; + SEWR C 8 Bright A_SentinelAttack; + SEWR C 4 Bright A_SentinelRefire; + Goto Missile+1; + Pain: + SEWR D 5 A_Pain; + Goto Missile+2; + Death: + SEWR D 7 A_Fall; + SEWR E 8 Bright A_TossGib; + SEWR F 5 Bright A_Scream; + SEWR GH 4 Bright A_TossGib; + SEWR I 4; + SEWR J 5; + Stop; + } +} + +// Sentinel FX 1 ------------------------------------------------------------ + +class SentinelFX1 : Actor +{ + Default + { + Speed 40; + Radius 10; + Height 8; + Damage 0; + DamageType "Disintegrate"; + Projectile; + +STRIFEDAMAGE + MaxStepHeight 4; + RenderStyle "Add"; + } + States + { + Spawn: + SHT1 AB 4; + Loop; + Death: + POW1 J 4; + Stop; + } +} + +// Sentinel FX 2 ------------------------------------------------------------ + +class SentinelFX2 : SentinelFX1 +{ + Default + { + SeeSound "sentinel/plasma"; + Damage 1; + } + States + { + Death: + POW1 FGHI 4; + Goto Super::Death; + } +} + diff --git a/wadsrc/static/zscript/strife/sigil.txt b/wadsrc/static/zscript/strife/sigil.txt new file mode 100644 index 000000000..d8b1f80f8 --- /dev/null +++ b/wadsrc/static/zscript/strife/sigil.txt @@ -0,0 +1,178 @@ + +// The Almighty Sigil! ------------------------------------------------------ + +class Sigil : Weapon native +{ + Default + { + Weapon.Kickback 100; + Weapon.SelectionOrder 4000; + Health 1; + +FLOORCLIP + +WEAPON.CHEATNOTWEAPON + Inventory.PickupSound "weapons/sigilcharge"; + Tag "$TAG_SIGIL"; + Inventory.Icon "I_SGL1"; + Inventory.PickupMessage "$TXT_SIGIL"; + } + + action native void A_SelectPiece (); + action native void A_SelectSigilView (); + action native void A_SelectSigilDown (); + action native void A_SelectSigilAttack (); + action native void A_SigilCharge (); + action native void A_FireSigil1 (); + action native void A_FireSigil2 (); + action native void A_FireSigil3 (); + action native void A_FireSigil4 (); + action native void A_FireSigil5 (); + + States + { + Spawn: + SIGL A 1; + SIGL A -1 A_SelectPiece; + Stop; + SIGL B -1; + Stop; + SIGL C -1; + Stop; + SIGL D -1; + Stop; + SIGL E -1; + Stop; + Ready: + SIGH A 0 Bright A_SelectSigilView; + Wait; + SIGH A 1 Bright A_WeaponReady; + Wait; + SIGH B 1 Bright A_WeaponReady; + Wait; + SIGH C 1 Bright A_WeaponReady; + Wait; + SIGH D 1 Bright A_WeaponReady; + Wait; + SIGH E 1 Bright A_WeaponReady; + Wait; + Deselect: + SIGH A 1 Bright A_SelectSigilDown; + Wait; + SIGH A 1 Bright A_Lower; + Wait; + SIGH B 1 Bright A_Lower; + Wait; + SIGH C 1 Bright A_Lower; + Wait; + SIGH D 1 Bright A_Lower; + Wait; + SIGH E 1 Bright A_Lower; + Wait; + Select: + SIGH A 1 Bright A_SelectSigilView; + Wait; + SIGH A 1 Bright A_Raise; + Wait; + SIGH B 1 Bright A_Raise; + Wait; + SIGH C 1 Bright A_Raise; + Wait; + SIGH D 1 Bright A_Raise; + Wait; + SIGH E 1 Bright A_Raise; + Wait; + + Fire: + SIGH A 0 Bright A_SelectSigilAttack; + + SIGH A 18 Bright A_SigilCharge; + SIGH A 3 Bright A_GunFlash; + SIGH A 10 A_FireSigil1; + SIGH A 5; + Goto Ready; + + SIGH B 18 Bright A_SigilCharge; + SIGH B 3 Bright A_GunFlash; + SIGH B 10 A_FireSigil2; + SIGH B 5; + Goto Ready; + + SIGH C 18 Bright A_SigilCharge; + SIGH C 3 Bright A_GunFlash; + SIGH C 10 A_FireSigil3; + SIGH C 5; + Goto Ready; + + SIGH D 18 Bright A_SigilCharge; + SIGH D 3 Bright A_GunFlash; + SIGH D 10 A_FireSigil4; + SIGH D 5; + Goto Ready; + + SIGH E 18 Bright A_SigilCharge; + SIGH E 3 Bright A_GunFlash; + SIGH E 10 A_FireSigil5; + SIGH E 5; + Goto Ready; + Flash: + SIGF A 4 Bright A_Light2; + SIGF B 6 Bright A_LightInverse; + SIGF C 4 Bright A_Light1; + SIGF C 0 Bright A_Light0; + Stop; + } +} + +// Sigil 1 ------------------------------------------------------------------ + +class Sigil1 : Sigil +{ + Default + { + Inventory.Icon "I_SGL1"; + Health 1; + } +} + +// Sigil 2 ------------------------------------------------------------------ + +class Sigil2 : Sigil +{ + Default + { + Inventory.Icon "I_SGL2"; + Health 2; + } +} + +// Sigil 3 ------------------------------------------------------------------ + +class Sigil3 : Sigil +{ + Default + { + Inventory.Icon "I_SGL3"; + Health 3; + } +} + +// Sigil 4 ------------------------------------------------------------------ + +class Sigil4 : Sigil +{ + Default + { + Inventory.Icon "I_SGL4"; + Health 4; + } +} + +// Sigil 5 ------------------------------------------------------------------ + +class Sigil5 : Sigil +{ + Default + { + Inventory.Icon "I_SGL5"; + Health 5; + } +} diff --git a/wadsrc/static/zscript/strife/spectral.txt b/wadsrc/static/zscript/strife/spectral.txt new file mode 100644 index 000000000..d6a234904 --- /dev/null +++ b/wadsrc/static/zscript/strife/spectral.txt @@ -0,0 +1,307 @@ + + +// base for all spectral monsters which hurt when being touched-------------- + +class SpectralMonster : Actor native +{ + Default + { + Monster; + +SPECIAL + +SPECTRAL + +NOICEDEATH + } + + native void A_SpectreChunkSmall (); + native void A_SpectreChunkLarge (); + native void A_Spectre3Attack (); + native void A_SpotLightning (); +} + + +// Container for all spectral lightning deaths ------------------------------ + +class SpectralLightningBase : Actor +{ + Default + { + +NOTELEPORT + +ACTIVATEIMPACT + +ACTIVATEPCROSS + +STRIFEDAMAGE + MaxStepHeight 4; + RenderStyle "Add"; + SeeSound "weapons/sigil"; + DeathSound "weapons/sigilhit"; + } + States + { + Death: + ZAP1 B 3 A_Explode(32,32); + ZAP1 A 3 A_AlertMonsters; + ZAP1 BCDEFE 3; + ZAP1 DCB 2; + ZAP1 A 1; + Stop; + } +} + +// Spectral Lightning death that does not explode --------------------------- + +class SpectralLightningDeath1 : SpectralLightningBase +{ + States + { + Death: + Goto Super::Death+1; + } +} + +// Spectral Lightning death that does not alert monsters -------------------- + +class SpectralLightningDeath2 : SpectralLightningBase +{ + States + { + Death: + Goto Super::Death+2; + } +} + +// Spectral Lightning death that is shorter than the rest ------------------- + +class SpectralLightningDeathShort : SpectralLightningBase +{ + States + { + Death: + Goto Super::Death+6; + } +} + +// Spectral Lightning (Ball Shaped #1) -------------------------------------- + +class SpectralLightningBall1 : SpectralLightningBase +{ + Default + { + Speed 30; + Radius 8; + Height 16; + Damage 70; + Projectile; + +SPECTRAL + } + States + { + Spawn: + ZOT3 ABCDE 4 Bright; + Loop; + } +} + +// Spectral Lightning (Ball Shaped #2) -------------------------------------- + +class SpectralLightningBall2 : SpectralLightningBall1 +{ + Default + { + Damage 20; + } +} + +// Spectral Lightning (Horizontal #1) --------------------------------------- + +class SpectralLightningH1 : SpectralLightningBase +{ + Default + { + Speed 30; + Radius 8; + Height 16; + Damage 70; + Projectile; + +SPECTRAL + } + + native void A_SpectralLightningTail (); + + States + { + Spawn: + ZAP6 A 4 Bright; + ZAP6 BC 4 Bright A_SpectralLightningTail; + Loop; + } +} + + +// Spectral Lightning (Horizontal #2) ------------------------------------- + +class SpectralLightningH2 : SpectralLightningH1 +{ + Default + { + Damage 20; + } +} + +// Spectral Lightning (Horizontal #3) ------------------------------------- + +class SpectralLightningH3 : SpectralLightningH1 +{ + Default + { + Damage 10; + } +} + +// ASpectralLightningHTail -------------------------------------------------- + +class SpectralLightningHTail : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +DROPOFF + RenderStyle "Add"; + } + States + { + Spawn: + ZAP6 ABC 5 Bright; + Stop; + } +} + +// Spectral Lightning (Big Ball #1) ----------------------------------------- + +class SpectralLightningBigBall1 : SpectralLightningDeath2 +{ + Default + { + Speed 18; + Radius 20; + Height 40; + Damage 130; + Projectile; + +SPECTRAL + } + + native void A_SpectralBigBallLightning (); + + States + { + Spawn: + ZAP7 AB 4 Bright A_SpectralBigBallLightning; + ZAP7 CDE 6 Bright A_SpectralBigBallLightning; + Loop; + } +} + + +// Spectral Lightning (Big Ball #2 - less damaging) ------------------------- + +class SpectralLightningBigBall2 : SpectralLightningBigBall1 +{ + Default + { + Damage 30; + } +} + +// Sigil Lightning (Vertical #1) -------------------------------------------- + +class SpectralLightningV1 : SpectralLightningDeathShort +{ + Default + { + Speed 22; + Radius 8; + Height 24; + Damage 100; + Projectile; + DamageType "SpectralLow"; + +SPECTRAL + } + States + { + Spawn: + ZOT1 AB 4 Bright; + ZOT1 CDE 6 Bright; + Loop; + } +} + +// Sigil Lightning (Vertical #2 - less damaging) ---------------------------- + +class SpectralLightningV2 : SpectralLightningV1 +{ + Default + { + Damage 50; + } +} + +// Sigil Lightning Spot (roams around dropping lightning from above) -------- + +class SpectralLightningSpot : SpectralLightningDeath1 +{ + Default + { + Speed 18; + ReactionTime 70; + +NOBLOCKMAP + +NOBLOCKMONST + +NODROPOFF + RenderStyle "Translucent"; + Alpha 0.6; + } + + native void A_SpectralLightning (); + + States + { + Spawn: + ZAP5 A 4 Bright A_Countdown; + ZAP5 B 4 Bright A_SpectralLightning; + ZAP5 CD 4 Bright A_Countdown; + Loop; + } +} + +// Sigil Lightning (Big Vertical #1) ---------------------------------------- + +class SpectralLightningBigV1 : SpectralLightningDeath1 +{ + Default + { + Speed 28; + Radius 8; + Height 16; + Damage 120; + Projectile; + +SPECTRAL + } + States + { + Spawn: + ZOT2 ABCDE 4 Bright A_Tracer2; + Loop; + } +} + +// Actor 90 ----------------------------------------------------------------- + +class SpectralLightningBigV2 : SpectralLightningBigV1 +{ + Default + { + Damage 60; + } +} + + + + diff --git a/wadsrc/static/zscript/strife/stalker.txt b/wadsrc/static/zscript/strife/stalker.txt new file mode 100644 index 000000000..51a919041 --- /dev/null +++ b/wadsrc/static/zscript/strife/stalker.txt @@ -0,0 +1,79 @@ + + +// Stalker ------------------------------------------------------------------ + +class Stalker : Actor +{ + Default + { + Health 80; + Painchance 40; + Speed 16; + Radius 31; + Height 25; + Monster; + +NOGRAVITY + +DROPOFF + +NOBLOOD + +SPAWNCEILING + +INCOMBAT + +NOVERTICALMELEERANGE + MaxDropOffHeight 32; + MinMissileChance 150; + SeeSound "stalker/sight"; + AttackSound "stalker/attack"; + PainSound "stalker/pain"; + DeathSound "stalker/death"; + ActiveSound "stalker/active"; + HitObituary "$OB_STALKER"; + } + + native void A_StalkerLookInit (); + native void A_StalkerChaseDecide (); + native void A_StalkerWalk (); + native void A_StalkerDrop (); + native void A_StalkerAttack (); + + States + { + Spawn: + STLK A 1 A_StalkerLookInit; + Loop; + LookCeiling: + STLK A 10 A_Look; + Loop; + LookFloor: + STLK J 10 A_Look; + Loop; + See: + STLK A 1 Slow A_StalkerChaseDecide; + STLK ABB 3 Slow A_Chase; + STLK C 3 Slow A_StalkerWalk; + STLK C 3 Slow A_Chase; + Loop; + Melee: + STLK J 3 Slow A_FaceTarget; + STLK K 3 Slow A_StalkerAttack; + SeeFloor: + STLK J 3 A_StalkerWalk; + STLK KK 3 A_Chase; + STLK L 3 A_StalkerWalk; + STLK L 3 A_Chase; + Loop; + Pain: + STLK L 1 A_Pain; + Goto See; + Drop: + STLK C 2 A_StalkerDrop; + STLK IHGFED 3; + Goto SeeFloor; + Death: + STLK O 4; + STLK P 4 A_Scream; + STLK QRST 4; + STLK U 4 A_NoBlocking; + STLK VW 4; + STLK "XYZ[" 4 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/strife/strifeammo.txt b/wadsrc/static/zscript/strife/strifeammo.txt new file mode 100644 index 000000000..dcc31b2c7 --- /dev/null +++ b/wadsrc/static/zscript/strife/strifeammo.txt @@ -0,0 +1,235 @@ +// HE-Grenade Rounds -------------------------------------------------------- + +class HEGrenadeRounds : Ammo +{ + Default + { + +FLOORCLIP + Inventory.Amount 6; + Inventory.MaxAmount 30; + Ammo.BackpackAmount 6; + Ammo.BackpackMaxAmount 60; + Inventory.Icon "I_GRN1"; + Tag "$TAG_HEGRENADES"; + Inventory.PickupMessage "$TXT_HEGRENADES"; + } + States + { + Spawn: + GRN1 A -1; + Stop; + } +} + +// Phosphorus-Grenade Rounds ------------------------------------------------ + +class PhosphorusGrenadeRounds : Ammo +{ + Default + { + +FLOORCLIP + Inventory.Amount 4; + Inventory.MaxAmount 16; + Ammo.BackpackAmount 4; + Ammo.BackpackMaxAmount 32; + Inventory.Icon "I_GRN2"; + Tag "$TAG_PHGRENADES"; + Inventory.PickupMessage "$TXT_PHGRENADES"; + } + States + { + Spawn: + GRN2 A -1; + Stop; + } +} + +// Clip of Bullets ---------------------------------------------------------- + +class ClipOfBullets : Ammo +{ + Default + { + +FLOORCLIP + Inventory.Amount 10; + Inventory.MaxAmount 250; + Ammo.BackpackAmount 10; + Ammo.BackpackMaxAmount 500; + Inventory.Icon "I_BLIT"; + Tag "$TAG_CLIPOFBULLETS"; + Inventory.PickupMessage "$TXT_CLIPOFBULLETS"; + } + States + { + Spawn: + BLIT A -1; + Stop; + } +} + +// Box of Bullets ----------------------------------------------------------- + +class BoxOfBullets : ClipOfBullets +{ + Default + { + Inventory.Amount 50; + Tag "$TAG_BOXOFBULLETS"; + Inventory.PickupMessage "$TXT_BOXOFBULLETS"; + } + States + { + Spawn: + BBOX A -1; + Stop; + } +} + +// Mini Missiles ------------------------------------------------------------ + +class MiniMissiles : Ammo +{ + Default + { + +FLOORCLIP + Inventory.Amount 4; + Inventory.MaxAmount 100; + Ammo.BackpackAmount 4; + Ammo.BackpackMaxAmount 200; + Inventory.Icon "I_ROKT"; + Tag "$TAG_MINIMISSILES"; + Inventory.PickupMessage "$TXT_MINIMISSILES"; + } + States + { + Spawn: + MSSL A -1; + Stop; + } +} + +// Crate of Missiles -------------------------------------------------------- + +class CrateOfMissiles : MiniMissiles +{ + Default + { + Inventory.Amount 20; + Tag "$TAG_CRATEOFMISSILES"; + Inventory.PickupMessage "$TXT_CRATEOFMISSILES"; + } + States + { + Spawn: + ROKT A -1; + Stop; + } +} + +// Energy Pod --------------------------------------------------------------- + +class EnergyPod : Ammo +{ + Default + { + +FLOORCLIP + Inventory.Amount 20; + Inventory.MaxAmount 400; + Ammo.BackpackAmount 20; + Ammo.BackpackMaxAmount 800; + Ammo.DropAmount 20; + Inventory.Icon "I_BRY1"; + Tag "$TAG_ENERGYPOD"; + Inventory.PickupMessage "$TXT_ENERGYPOD"; + } + States + { + Spawn: + BRY1 AB 6; + Loop; + } +} + +// Energy pack --------------------------------------------------------------- + +class EnergyPack : EnergyPod +{ + Default + { + Inventory.Amount 100; + Tag "$TAG_ENERGYPACK"; + Inventory.PickupMessage "$TXT_ENERGYPACK"; + } + States + { + Spawn: + CPAC AB 6; + Loop; + } +} + +// Poison Bolt Quiver ------------------------------------------------------- + +class PoisonBolts : Ammo +{ + Default + { + +FLOORCLIP + Inventory.Amount 10; + Inventory.MaxAmount 25; + Ammo.BackpackAmount 2; + Ammo.BackpackMaxAmount 50; + Inventory.Icon "I_PQRL"; + Tag "$TAG_POISONBOLTS"; + Inventory.PickupMessage "$TXT_POISONBOLTS"; + } + States + { + Spawn: + PQRL A -1; + Stop; + } +} + +// Electric Bolt Quiver ------------------------------------------------------- + +class ElectricBolts : Ammo +{ + Default + { + +FLOORCLIP + Inventory.Amount 20; + Inventory.MaxAmount 50; + Ammo.BackpackAmount 4; + Ammo.BackpackMaxAmount 100; + Inventory.Icon "I_XQRL"; + Tag "$TAG_ELECTRICBOLTS"; + Inventory.PickupMessage "$TXT_ELECTRICBOLTS"; + } + States + { + Spawn: + XQRL A -1; + Stop; + } +} + +// Ammo Satchel ------------------------------------------------------------- + +class AmmoSatchel : BackpackItem +{ + Default + { + +FLOORCLIP + Inventory.Icon "I_BKPK"; + Tag "$TAG_AMMOSATCHEL"; + Inventory.PickupMessage "$TXT_AMMOSATCHEL"; + } + States + { + Spawn: + BKPK A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/strifearmor.txt b/wadsrc/static/zscript/strife/strifearmor.txt new file mode 100644 index 000000000..8d2c7fad5 --- /dev/null +++ b/wadsrc/static/zscript/strife/strifearmor.txt @@ -0,0 +1,49 @@ + +class MetalArmor : BasicArmorPickup +{ + Default + { + Radius 20; + Height 16; + +FLOORCLIP + +INVENTORY.AUTOACTIVATE + +INVENTORY.INVBAR + Inventory.MaxAmount 3; + Inventory.Icon "I_ARM1"; + Inventory.PickupMessage "$TXT_METALARMOR"; + Armor.SaveAmount 200; + Armor.SavePercent 50; + Tag "$TAG_METALARMOR"; + } + States + { + Spawn: + ARM3 A -1; + Stop; + } +} + +class LeatherArmor : BasicArmorPickup +{ + Default + { + Radius 20; + Height 16; + +FLOORCLIP + +INVENTORY.AUTOACTIVATE + +INVENTORY.INVBAR + Inventory.MaxAmount 5; + Inventory.Icon "I_ARM2"; + Inventory.PickupMessage "$TXT_LEATHERARMOR"; + Armor.SaveAmount 100; + Armor.SavePercent 33.335; + Tag "$TAG_LEATHER"; + } + States + { + Spawn: + ARM4 A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/strifebishop.txt b/wadsrc/static/zscript/strife/strifebishop.txt new file mode 100644 index 000000000..98b09ecee --- /dev/null +++ b/wadsrc/static/zscript/strife/strifebishop.txt @@ -0,0 +1,99 @@ + +// Bishop ------------------------------------------------------------------- + +class StrifeBishop : Actor +{ + Default + { + Health 500; + Painchance 128; + Speed 8; + Radius 40; + Height 56; + Mass 500; + Monster; + +NOBLOOD + +NOTDMATCH + +FLOORCLIP + +INCOMBAT + +NOICEDEATH + +NEVERRESPAWN + DamageFactor "Fire", 0.5; + MinMissileChance 150; + MaxDropoffHeight 32; + SeeSound "bishop/sight"; + PainSound "bishop/pain"; + DeathSound "bishop/death"; + ActiveSound "bishop/active"; + DropItem "CrateOfMissiles", 256, 20; + Obituary "$OB_STFBISHOP"; + } + States + { + Spawn: + MLDR A 10 A_Look; + Loop; + See: + MLDR AABBCCDD 3 A_Chase; + Loop; + Missile: + MLDR E 3 A_FaceTarget; + MLDR F 2 Bright A_CustomMissile("BishopMissile", 64, 0, 0, CMF_AIMOFFSET); + Goto See; + Pain: + MLDR D 1 A_Pain; + Goto See; + Death: + MLDR G 3 Bright; + MLDR H 5 Bright A_Scream; + MLDR I 4 Bright A_TossGib; + MLDR J 4 Bright A_Explode(64,64,1,1); + MLDR KL 3 Bright; + MLDR M 4 Bright A_NoBlocking; + MLDR N 4 Bright; + MLDR O 4 Bright A_TossGib; + MLDR P 4 Bright; + MLDR Q 4 Bright A_TossGib; + MLDR R 4 Bright; + MLDR S 4 Bright A_TossGib; + MLDR T 4 Bright; + MLDR U 4 Bright A_TossGib; + MLDR V 4 Bright A_SpawnItemEx("AlienSpectre2", 0, 0, 0, 0, 0, random[spectrespawn](0,255)*0.0078125, 0, SXF_NOCHECKPOSITION); + Stop; + } +} + + +// The Bishop's missile ----------------------------------------------------- + +class BishopMissile : Actor +{ + Default + { + Speed 20; + Radius 10; + Height 14; + Damage 10; + Projectile; + +SEEKERMISSILE + +STRIFEDAMAGE + MaxStepHeight 4; + SeeSound "bishop/misl"; + DeathSound "bishop/mislx"; + } + States + { + Spawn: + MISS A 4 Bright A_RocketInFlight; + MISS B 3 Bright A_Tracer2; + Loop; + Death: + SMIS A 0 Bright A_SetTranslucent(1,1); + SMIS A 5 Bright A_Explode(64,64,1,1); + SMIS B 5 Bright; + SMIS C 4 Bright; + SMIS DEFG 2 Bright; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/strifehumanoid.txt b/wadsrc/static/zscript/strife/strifehumanoid.txt new file mode 100644 index 000000000..7ac776026 --- /dev/null +++ b/wadsrc/static/zscript/strife/strifehumanoid.txt @@ -0,0 +1,58 @@ + +// Humanoid Base Class ------------------------------------------------------ + + +class StrifeHumanoid : Actor +{ + Default + { + MaxStepHeight 16; + MaxDropoffHeight 32; + CrushPainSound "misc/pcrush"; + } + States + { + Burn: + BURN A 3 Bright A_PlaySound("human/imonfire", CHAN_VOICE); + BURN B 3 Bright A_DropFire; + BURN C 3 Bright A_Wander; + BURN D 3 Bright A_NoBlocking; + BURN E 5 Bright A_DropFire; + BURN FGH 5 Bright A_Wander; + BURN I 5 Bright A_DropFire; + BURN JKL 5 Bright A_Wander; + BURN M 5 Bright A_DropFire; + BURN N 5 Bright; + BURN OPQPQ 5 Bright; + BURN RSTU 7 Bright; + BURN V -1; + Stop; + Disintegrate: + DISR A 5 A_PlaySound("misc/disruptordeath", CHAN_VOICE); + DISR BC 5; + DISR D 5 A_NoBlocking; + DISR EF 5; + DISR GHIJ 4; + MEAT D 700; + Stop; + } +} + +// Fire Droplet ------------------------------------------------------------- + +class FireDroplet : Actor +{ + Default + { + +NOBLOCKMAP + +NOCLIP + } + States + { + Spawn: + FFOT ABCD 9 Bright; + Stop; + } +} + + diff --git a/wadsrc/static/zscript/strife/strifeitems.txt b/wadsrc/static/zscript/strife/strifeitems.txt new file mode 100644 index 000000000..cfc939413 --- /dev/null +++ b/wadsrc/static/zscript/strife/strifeitems.txt @@ -0,0 +1,597 @@ +// Med patch ----------------------------------------------------------------- + +class MedPatch : HealthPickup +{ + Default + { + Health 10; + +FLOORCLIP + +INVENTORY.INVBAR + Inventory.MaxAmount 20; + Tag "$TAG_MEDPATCH"; + Inventory.Icon "I_STMP"; + Inventory.PickupMessage "$TXT_MEDPATCH"; + HealthPickup.Autouse 3; + } + States + { + Spawn: + STMP A -1; + Stop; + } +} + + +// Medical Kit --------------------------------------------------------------- + +class MedicalKit : HealthPickup +{ + Default + { + Health 25; + +FLOORCLIP + +INVENTORY.INVBAR + Inventory.MaxAmount 15; + Tag "$TAG_MEDICALKIT"; + Inventory.Icon "I_MDKT"; + Inventory.PickupMessage "$TXT_MEDICALKIT"; + HealthPickup.Autouse 3; + } + States + { + Spawn: + MDKT A -1; + Stop; + } +} + + +// Surgery Kit -------------------------------------------------------------- + +class SurgeryKit : HealthPickup +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + Health -100; + Inventory.MaxAmount 5; + Tag "$TAG_SURGERYKIT"; + Inventory.Icon "I_FULL"; + Inventory.PickupMessage "$TXT_SURGERYKIT"; + } + States + { + Spawn: + FULL AB 35; + Loop; + } +} + + +// StrifeMap ---------------------------------------------------------------- + +class StrifeMap : MapRevealer +{ + Default + { + +FLOORCLIP + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_STRIFEMAP"; + } + States + { + Spawn: + SMAP AB 6 Bright; + Loop; + } +} + + +// Beldin's Ring ------------------------------------------------------------ + +class BeldinsRing : Inventory +{ + Default + { + +NOTDMATCH + +FLOORCLIP + +INVENTORY.INVBAR + Tag "$TAG_BELDINSRING"; + Inventory.Icon "I_RING"; + Inventory.GiveQuest 1; + Inventory.PickupMessage "$TXT_BELDINSRING"; + } + States + { + Spawn: + RING A -1; + Stop; + } +} + + +// Offering Chalice --------------------------------------------------------- + +class OfferingChalice : Inventory +{ + Default + { + +DROPPED + +FLOORCLIP + +INVENTORY.INVBAR + Radius 10; + Height 16; + Tag "$TAG_OFFERINGCHALICE"; + Inventory.Icon "I_RELC"; + Inventory.PickupMessage "$TXT_OFFERINGCHALICE"; + Inventory.GiveQuest 2; + } + States + { + Spawn: + RELC A -1; + Stop; + } +} + + +// Ear ---------------------------------------------------------------------- + +class Ear : Inventory +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + Tag "$TAG_EAR"; + Inventory.Icon "I_EARS"; + Inventory.PickupMessage "$TXT_EAR"; + Inventory.GiveQuest 9; + } + States + { + Spawn: + EARS A -1; + Stop; + } +} + + +// Broken Power Coupling ---------------------------------------------------- + +class BrokenPowerCoupling : Inventory +{ + Default + { + Health 40; + +DROPPED + +FLOORCLIP + +INVENTORY.INVBAR + Radius 16; + Height 16; + Tag "$TAG_BROKENCOUPLING"; + Inventory.MaxAmount 1; + Inventory.Icon "I_COUP"; + Inventory.PickupMessage "$TXT_BROKENCOUPLING"; + Inventory.GiveQuest 8; + } + States + { + Spawn: + COUP C -1; + Stop; + } +} + + +// Shadow Armor ------------------------------------------------------------- + +class ShadowArmor : PowerupGiver +{ + Default + { + +FLOORCLIP + +VISIBILITYPULSE + +INVENTORY.INVBAR + -INVENTORY.FANCYPICKUPSOUND + RenderStyle "Translucent"; + Tag "$TAG_SHADOWARMOR"; + Inventory.MaxAmount 2; + Powerup.Type "PowerShadow"; + Inventory.Icon "I_SHD1"; + Inventory.PickupSound "misc/i_pkup"; + Inventory.PickupMessage "$TXT_SHADOWARMOR"; + } + States + { + Spawn: + SHD1 A -1 Bright; + Stop; + } +} + + +// Environmental suit ------------------------------------------------------- + +class EnvironmentalSuit : PowerupGiver +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + -INVENTORY.FANCYPICKUPSOUND + Inventory.MaxAmount 5; + Powerup.Type "PowerMask"; + Tag "$TAG_ENVSUIT"; + Inventory.Icon "I_MASK"; + Inventory.PickupSound "misc/i_pkup"; + Inventory.PickupMessage "$TXT_ENVSUIT"; + } + States + { + Spawn: + MASK A -1; + Stop; + } +} + + +// Guard Uniform ------------------------------------------------------------ + +class GuardUniform : Inventory +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + Tag "$TAG_GUARDUNIFORM"; + Inventory.Icon "I_UNIF"; + Inventory.PickupMessage "$TXT_GUARDUNIFORM"; + Inventory.GiveQuest 15; + } + States + { + Spawn: + UNIF A -1; + Stop; + } +} + + +// Officer's Uniform -------------------------------------------------------- + +class OfficersUniform : Inventory +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + Tag "$TAG_OFFICERSUNIFORM"; + Inventory.Icon "I_OFIC"; + Inventory.PickupMessage "$TXT_OFFICERSUNIFORM"; + } + States + { + Spawn: + OFIC A -1; + Stop; + } +} + + +// Flame Thrower Parts ------------------------------------------------------ + +class FlameThrowerParts : Inventory +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + Inventory.Icon "I_BFLM"; + Tag "$TAG_FTHROWERPARTS"; + Inventory.PickupMessage "$TXT_FTHROWERPARTS"; + } + States + { + Spawn: + BFLM A -1; + Stop; + } +} + +// InterrogatorReport ------------------------------------------------------- +// SCRIPT32 in strife0.wad has an Acolyte that drops this, but I couldn't +// find that Acolyte in the map. It seems to be totally unused in the +// final game. + +class InterrogatorReport : Inventory +{ + Default + { + +FLOORCLIP + Tag "$TAG_REPORT"; + Inventory.PickupMessage "$TXT_REPORT"; + } + States + { + Spawn: + TOKN A -1; + Stop; + } +} + + +// Info --------------------------------------------------------------------- + +class Info : Inventory +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + Tag "$TAG_INFO"; + Inventory.Icon "I_TOKN"; + Inventory.PickupMessage "$TXT_INFO"; + } + States + { + Spawn: + TOKN A -1; + Stop; + } +} + + +// Targeter ----------------------------------------------------------------- + +class Targeter : PowerupGiver +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + -INVENTORY.FANCYPICKUPSOUND + Tag "$TAG_TARGETER"; + Powerup.Type "PowerTargeter"; + Inventory.MaxAmount 5; + Inventory.Icon "I_TARG"; + Inventory.PickupSound "misc/i_pkup"; + Inventory.PickupMessage "$TXT_TARGETER"; + } + States + { + Spawn: + TARG A -1; + Stop; + } +} + +// Communicator ----------------------------------------------------------------- + +class Communicator : Inventory +{ + Default + { + +NOTDMATCH + Tag "$TAG_COMMUNICATOR"; + Inventory.Icon "I_COMM"; + Inventory.PickupSound "misc/p_pkup"; + Inventory.PickupMessage "$TXT_COMMUNICATOR"; + } + States + { + Spawn: + COMM A -1; + Stop; + } +} + +// Degnin Ore --------------------------------------------------------------- + +class DegninOre : Inventory native +{ + Default + { + Health 10; + Radius 16; + Height 16; + Inventory.MaxAmount 10; + +SOLID + +SHOOTABLE + +NOBLOOD + +FLOORCLIP + +INCOMBAT + +INVENTORY.INVBAR + Tag "$TAG_DEGNINORE"; + DeathSound "ore/explode"; + Inventory.Icon "I_XPRK"; + Inventory.PickupMessage "$TXT_DEGNINORE"; + } + States + { + Spawn: + XPRK A -1; + Stop; + Death: + XPRK A 1 A_RemoveForceField; + BNG3 A 0 A_SetTranslucent(1,1); + BNG3 A 0 A_Scream; + BNG3 A 3 Bright A_Explode(192,192,1,1); + BNG3 BCDEFGH 3 Bright; + Stop; + } +} + +// Gun Training ------------------------------------------------------------- + +class GunTraining : Inventory +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + +INVENTORY.UNDROPPABLE + Inventory.MaxAmount 100; + Tag "$TAG_GUNTRAINING"; + Inventory.Icon "I_GUNT"; + } + States + { + Spawn: + GUNT A -1; + Stop; + } +} + +// Health Training ---------------------------------------------------------- + +class HealthTraining : Inventory native +{ + Default + { + +FLOORCLIP + +INVENTORY.INVBAR + +INVENTORY.UNDROPPABLE + Inventory.MaxAmount 100; + Tag "$TAG_HEALTHTRAINING"; + Inventory.Icon "I_HELT"; + } + States + { + Spawn: + HELT A -1; + Stop; + } +} + + + +// Scanner ------------------------------------------------------------------ + +class Scanner : PowerupGiver native +{ + Default + { + +FLOORCLIP + +INVENTORY.FANCYPICKUPSOUND + Inventory.MaxAmount 1; + Tag "$TAG_SCANNER"; + Inventory.Icon "I_PMUP"; + Powerup.Type "PowerScanner"; + Inventory.PickupSound "misc/i_pkup"; + Inventory.PickupMessage "$TXT_SCANNER"; + } + States + { + Spawn: + PMUP AB 6; + Loop; + } +} + +// Prison Pass -------------------------------------------------------------- + +class PrisonPass : Key native +{ + Default + { + Inventory.Icon "I_TOKN"; + Tag "$TAG_PRISONPASS"; + Inventory.PickupMessage "$TXT_PRISONPASS"; + } + States + { + Spawn: + TOKN A -1; + Stop; + } +} + +//--------------------------------------------------------------------------- +// Dummy items. They are just used by Strife to perform --------------------- +// actions and cannot be held. ---------------------------------------------- +//--------------------------------------------------------------------------- + +class DummyStrifeItem : Inventory native +{ + States + { + Spawn: + TOKN A -1; + Stop; + } +} + +// Sound the alarm! --------------------------------------------------------- + +class RaiseAlarm : DummyStrifeItem native +{ + Default + { + Tag "$TAG_ALARM"; + } +} + +// Open door tag 222 -------------------------------------------------------- + +class OpenDoor222 : DummyStrifeItem native +{ +} + +// Close door tag 222 ------------------------------------------------------- + +class CloseDoor222 : DummyStrifeItem native +{ +} + +// Open door tag 224 -------------------------------------------------------- + +class OpenDoor224 : DummyStrifeItem native +{ +} + +// Ammo --------------------------------------------------------------------- + +class AmmoFillup : DummyStrifeItem native +{ + Default + { + Tag "$TAG_AMMOFILLUP"; + } +} + +// Health ------------------------------------------------------------------- + +class HealthFillup : DummyStrifeItem native +{ + Default + { + Tag "$TAG_HEALTHFILLUP"; + } +} + +// Upgrade Stamina ---------------------------------------------------------- + +class UpgradeStamina : DummyStrifeItem native +{ + Default + { + Inventory.Amount 10; + Inventory.MaxAmount 100; + } +} + +// Upgrade Accuracy --------------------------------------------------------- + +class UpgradeAccuracy : DummyStrifeItem native +{ +} + +// Start a slideshow -------------------------------------------------------- + +class SlideshowStarter : DummyStrifeItem native +{ +} + + diff --git a/wadsrc/static/zscript/strife/strifekeys.txt b/wadsrc/static/zscript/strife/strifekeys.txt new file mode 100644 index 000000000..024144384 --- /dev/null +++ b/wadsrc/static/zscript/strife/strifekeys.txt @@ -0,0 +1,547 @@ +class StrifeKey : Key +{ + Default + { + Radius 20; + Height 16; + +NOTDMATCH + +FLOORCLIP + } +} + +// Base Key ----------------------------------------------------------------- + +class BaseKey : StrifeKey +{ + Default + { + Inventory.Icon "I_FUSL"; + Tag "$TAG_BASEKEY"; + Inventory.PickupMessage "$TXT_BASEKEY"; + } + States + { + Spawn: + FUSL A -1; + Stop; + } +} + + +// Govs Key ----------------------------------------------------------------- + +class GovsKey : StrifeKey +{ + Default + { + Inventory.Icon "I_REBL"; + Tag "$TAG_GOVSKEY"; + Inventory.PickupMessage "$TXT_GOVSKEY"; + } + States + { + Spawn: + REBL A -1; + Stop; + } +} + + +// Passcard ----------------------------------------------------------------- + +class Passcard : StrifeKey +{ + Default + { + Inventory.Icon "I_TPAS"; + Tag "$TAG_PASSCARD"; + Inventory.PickupMessage "$TXT_PASSCARD"; + } + States + { + Spawn: + TPAS A -1; + Stop; + } +} + + +// ID Badge ----------------------------------------------------------------- + +class IDBadge : StrifeKey +{ + Default + { + Inventory.Icon "I_CRD1"; + Tag "$TAG_IDBADGE"; + Inventory.PickupMessage "$TXT_IDBADGE"; + } + States + { + Spawn: + CRD1 A -1; + Stop; + } +} + + +// Prison Key --------------------------------------------------------------- + +class PrisonKey : StrifeKey +{ + Default + { + Inventory.Icon "I_PRIS"; + Tag "$TAG_PRISONKEY"; + Inventory.GiveQuest 11; + Inventory.PickupMessage "$TXT_PRISONKEY"; + } + States + { + Spawn: + PRIS A -1; + Stop; + } +} + + +// Severed Hand ------------------------------------------------------------- + +class SeveredHand : StrifeKey +{ + Default + { + Inventory.Icon "I_HAND"; + Tag "$TAG_SEVEREDHAND"; + Inventory.GiveQuest 12; + Inventory.PickupMessage "$TXT_SEVEREDHAND"; + } + States + { + Spawn: + HAND A -1; + Stop; + } +} + + +// Power1 Key --------------------------------------------------------------- + +class Power1Key : StrifeKey +{ + Default + { + Inventory.Icon "I_PWR1"; + Tag "$TAG_POWER1KEY"; + Inventory.PickupMessage "$TXT_POWER1KEY"; + } + States + { + Spawn: + PWR1 A -1; + Stop; + } +} + + +// Power2 Key --------------------------------------------------------------- + +class Power2Key : StrifeKey +{ + Default + { + Inventory.Icon "I_PWR2"; + Tag "$TAG_POWER2KEY"; + Inventory.PickupMessage "$TXT_POWER2KEY"; + } + States + { + Spawn: + PWR2 A -1; + Stop; + } +} + + +// Power3 Key --------------------------------------------------------------- + +class Power3Key : StrifeKey +{ + Default + { + Inventory.Icon "I_PWR3"; + Tag "$TAG_POWER3KEY"; + Inventory.PickupMessage "$TXT_POWER3KEY"; + } + States + { + Spawn: + PWR3 A -1; + Stop; + } +} + + +// Gold Key ----------------------------------------------------------------- + +class GoldKey : StrifeKey +{ + Default + { + Inventory.Icon "I_KY1G"; + Tag "$TAG_GOLDKEY"; + Inventory.PickupMessage "$TXT_GOLDKEY"; + } + States + { + Spawn: + KY1G A -1; + Stop; + } +} + + +// ID Card ------------------------------------------------------------------ + +class IDCard : StrifeKey +{ + Default + { + Inventory.Icon "I_CRD2"; + Tag "$TAG_IDCARD"; + Inventory.PickupMessage "$TXT_IDCARD"; + } + States + { + Spawn: + CRD2 A -1; + Stop; + } +} + + +// Silver Key --------------------------------------------------------------- + +class SilverKey : StrifeKey +{ + Default + { + Inventory.Icon "I_KY2S"; + Tag "$TAG_SILVERKEY"; + Inventory.PickupMessage "$TXT_SILVERKEY"; + } + States + { + Spawn: + KY2S A -1; + Stop; + } +} + + +// Oracle Key --------------------------------------------------------------- + +class OracleKey : StrifeKey +{ + Default + { + Inventory.Icon "I_ORAC"; + Tag "$TAG_ORACLEKEY"; + Inventory.PickupMessage "$TXT_ORACLEKEY"; + } + States + { + Spawn: + ORAC A -1; + Stop; + } +} + + +// Military ID -------------------------------------------------------------- + +class MilitaryID : StrifeKey +{ + Default + { + Inventory.Icon "I_GYID"; + Tag "$TAG_MILITARYID"; + Inventory.PickupMessage "$TXT_MILITARYID"; + } + States + { + Spawn: + GYID A -1; + Stop; + } +} + + +// Order Key ---------------------------------------------------------------- + +class OrderKey : StrifeKey +{ + Default + { + Inventory.Icon "I_FUBR"; + Tag "$TAG_ORDERKEY"; + Inventory.PickupMessage "$TXT_ORDERKEY"; + } + States + { + Spawn: + FUBR A -1; + Stop; + } +} + + +// Warehouse Key ------------------------------------------------------------ + +class WarehouseKey : StrifeKey +{ + Default + { + Inventory.Icon "I_WARE"; + Tag "$TAG_WAREHOUSEKEY"; + Inventory.PickupMessage "$TXT_WAREHOUSEKEY"; + } + States + { + Spawn: + WARE A -1; + Stop; + } +} + + +// Brass Key ---------------------------------------------------------------- + +class BrassKey : StrifeKey +{ + Default + { + Inventory.Icon "I_KY3B"; + Tag "$TAG_BRASSKEY"; + Inventory.PickupMessage "$TXT_BRASSKEY"; + } + States + { + Spawn: + KY3B A -1; + Stop; + } +} + + +// Red Crystal Key ---------------------------------------------------------- + +class RedCrystalKey : StrifeKey +{ + Default + { + Inventory.Icon "I_RCRY"; + Tag "$TAG_REDCRYSTALKEY"; + Inventory.PickupMessage "$TXT_REDCRYSTAL"; + } + States + { + Spawn: + RCRY A -1 Bright; + Stop; + } +} + + +// Blue Crystal Key --------------------------------------------------------- + +class BlueCrystalKey : StrifeKey +{ + Default + { + Inventory.Icon "I_BCRY"; + Tag "$TAG_BLUECRYSTALKEY"; + Inventory.PickupMessage "$TXT_BLUECRYSTAL"; + } + States + { + Spawn: + BCRY A -1 Bright; + Stop; + } +} + + +// Chapel Key --------------------------------------------------------------- + +class ChapelKey : StrifeKey +{ + Default + { + Inventory.Icon "I_CHAP"; + Tag "$TAG_CHAPELKEY"; + Inventory.PickupMessage "$TXT_CHAPELKEY"; + } + States + { + Spawn: + CHAP A -1; + Stop; + } +} + + +// Catacomb Key ------------------------------------------------------------- + +class CatacombKey : StrifeKey +{ + Default + { + Inventory.Icon "I_TUNL"; + Tag "$TAG_CATACOMBKEY"; + Inventory.GiveQuest 28; + Inventory.PickupMessage "$TXT_CATACOMBKEY"; + } + States + { + Spawn: + TUNL A -1; + Stop; + } +} + + +// Security Key ------------------------------------------------------------- + +class SecurityKey : StrifeKey +{ + Default + { + Inventory.Icon "I_SECK"; + Tag "$TAG_SECURITYKEY"; + Inventory.PickupMessage "$TXT_SECURITYKEY"; + } + States + { + Spawn: + SECK A -1; + Stop; + } +} + + +// Core Key ----------------------------------------------------------------- + +class CoreKey : StrifeKey +{ + Default + { + Inventory.Icon "I_GOID"; + Tag "$TAG_COREKEY"; + Inventory.PickupMessage "$TXT_COREKEY"; + } + States + { + Spawn: + GOID A -1; + Stop; + } +} + + +// Mauler Key --------------------------------------------------------------- + +class MaulerKey : StrifeKey +{ + Default + { + Inventory.Icon "I_BLTK"; + Tag "$TAG_MAULERKEY"; + Inventory.PickupMessage "$TXT_MAULERKEY"; + } + States + { + Spawn: + BLTK A -1; + Stop; + } +} + + +// Factory Key -------------------------------------------------------------- + +class FactoryKey : StrifeKey +{ + Default + { + Inventory.Icon "I_PROC"; + Tag "$TAG_FACTORYKEY"; + Inventory.PickupMessage "$TXT_FACTORYKEY"; + } + States + { + Spawn: + PROC A -1; + Stop; + } +} + + +// Mine Key ----------------------------------------------------------------- + +class MineKey : StrifeKey +{ + Default + { + Inventory.Icon "I_MINE"; + Tag "$TAG_MINEKEY"; + Inventory.PickupMessage "$TXT_MINEKEY"; + } + States + { + Spawn: + MINE A -1; + Stop; + } +} + + +// New Key5 ----------------------------------------------------------------- + +class NewKey5 : StrifeKey +{ + Default + { + Inventory.Icon "I_BLTK"; + Tag "$TAG_NEWKEY5"; + Inventory.PickupMessage "$TXT_NEWKEY5"; + } + States + { + Spawn: + BLTK A -1; + Stop; + } +} + + +// Oracle Pass -------------------------------------------------------------- + +class OraclePass : Inventory +{ + Default + { + +INVENTORY.INVBAR + Inventory.Icon "I_OTOK"; + Inventory.GiveQuest 18; + Inventory.PickupMessage "$TXT_ORACLEPASS"; + Tag "$TAG_ORACLEPASS"; + } + States + { + Spawn: + OTOK A -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/strifeplayer.txt b/wadsrc/static/zscript/strife/strifeplayer.txt new file mode 100644 index 000000000..0b61e3122 --- /dev/null +++ b/wadsrc/static/zscript/strife/strifeplayer.txt @@ -0,0 +1,105 @@ +// The player --------------------------------------------------------------- + +class StrifePlayer : PlayerPawn +{ + Default + { + Health 100; + Radius 18; + Height 56; + Mass 100; + PainChance 255; + Speed 1; + MaxStepHeight 16; + CrushPainSound "misc/pcrush"; + Player.DisplayName "Rebel"; + Player.StartItem "PunchDagger"; + Player.RunHealth 15; + Player.WeaponSlot 1, "PunchDagger"; + Player.WeaponSlot 2, "StrifeCrossbow2", "StrifeCrossbow"; + Player.WeaponSlot 3, "AssaultGun"; + Player.WeaponSlot 4, "MiniMissileLauncher"; + Player.WeaponSlot 5, "StrifeGrenadeLauncher2", "StrifeGrenadeLauncher"; + Player.WeaponSlot 6, "FlameThrower"; + Player.WeaponSlot 7, "Mauler2", "Mauler"; + Player.WeaponSlot 8, "Sigil"; + + Player.ColorRange 128, 143; + Player.Colorset 0, "Brown", 0x80, 0x8F, 0x82; + Player.Colorset 1, "Red", 0x40, 0x4F, 0x42, 0x20, 0x3F, 0x00, 0x1F, 0xF1, 0xF6, 0xE0, 0xE5, 0xF7, 0xFB, 0xF1, 0xF5; + Player.Colorset 2, "Rust", 0xB0, 0xBF, 0xB2, 0x20, 0x3F, 0x00, 0x1F; + Player.Colorset 3, "Gray", 0x10, 0x1F, 0x12, 0x20, 0x2F, 0xD0, 0xDF, 0x30, 0x3F, 0xD0, 0xDF; + Player.Colorset 4, "Dark Green", 0x30, 0x3F, 0x32, 0x20, 0x2F, 0xD0, 0xDF, 0x30, 0x3F, 0xD0, 0xDF; + + Player.Colorset 5, "Gold", 0x50, 0x5F, 0x52, 0x20, 0x3F, 0x00, 0x1F, 0x50, 0x5F, 0x80, 0x8F, 0xC0, 0xCF, 0xA0, 0xAF, 0xD0, 0xDF, 0xB0, 0xBF; + Player.Colorset 6, "Bright Green", 0x60, 0x6F, 0x62, 0x20, 0x3F, 0x00, 0x1F, 0x50, 0x5F, 0x10, 0x1F, 0xC0, 0xCF, 0x20, 0x2F, 0xD0, 0xDF, 0x30, 0x3F; + Player.Colorset 7, "Blue", 0x90, 0x9F, 0x92, 0x20, 0x3F, 0x00, 0x1F, 0x50, 0x5F, 0x40, 0x4F, 0xC1, 0xCF, 0x01, 0x0F, 0xC0,0xC0,1,1, 0xD0, 0xDF, 0x10, 0x1F; + } + + native void A_ItBurnsItBurns(); + native void A_CrispyPlayer(); + native void A_HandLower(); + + States + { + Spawn: + PLAY A -1; + stop; + See: + PLAY ABCD 4; + loop; + Missile: + PLAY E 12; + goto Spawn; + Melee: + PLAY F 6; + goto Missile; + Pain: + PLAY Q 4; + PLAY Q 4 A_Pain; + Goto Spawn; + Death: + PLAY H 3; + PLAY I 3 A_PlayerScream; + PLAY J 3 A_NoBlocking; + PLAY KLMNO 4; + PLAY P -1; + Stop; + XDeath: + RGIB A 5 A_TossGib; + RGIB B 5 A_XScream; + RGIB C 5 A_NoBlocking; + RGIB DEFG 5 A_TossGib; + RGIB H -1 A_TossGib; + Burn: + BURN A 3 Bright A_ItBurnsItBurns; + BURN B 3 Bright A_DropFire; + BURN C 3 Bright A_Wander; + BURN D 3 Bright A_NoBlocking; + BURN E 5 Bright A_DropFire; + BURN FGH 5 Bright A_Wander; + BURN I 5 Bright A_DropFire; + BURN JKL 5 Bright A_Wander; + BURN M 5 Bright A_DropFire; + BURN N 5 Bright A_CrispyPlayer; + BURN OPQPQ 5 Bright; + BURN RSTU 7 Bright; + BURN V -1; + Stop; + Disintegrate: + DISR A 5 A_PlaySound("misc/disruptordeath", CHAN_VOICE); + DISR BC 5; + DISR D 5 A_NoBlocking; + DISR EF 5; + DISR GHIJ 4; + MEAT D -1; + Stop; + Firehands: + WAVE ABCD 3; + Loop; + Firehandslower: + WAVE ABCD 3 A_HandLower; + Loop; + } +} + diff --git a/wadsrc/static/zscript/strife/strifestuff.txt b/wadsrc/static/zscript/strife/strifestuff.txt new file mode 100644 index 000000000..e72e8d924 --- /dev/null +++ b/wadsrc/static/zscript/strife/strifestuff.txt @@ -0,0 +1,2002 @@ +// Tank 1 Huge ------------------------------------------------------------ + +class Tank1 : Actor +{ + Default + { + Radius 16; + Height 192; + +SOLID + } + States + { + Spawn: + TNK1 A 15; + TNK1 B 11; + TNK1 C 40; + Loop; + } +} + +// Tank 2 Huge ------------------------------------------------------------ + +class Tank2 : Actor +{ + Default + { + Radius 16; + Height 192; + +SOLID + } + States + { + Spawn: + TNK2 A 15; + TNK2 B 11; + TNK2 C 40; + Loop; + } +} + +// Tank 3 Huge ------------------------------------------------------------ + +class Tank3 : Actor +{ + Default + { + Radius 16; + Height 192; + +SOLID + } + States + { + Spawn: + TNK3 A 15; + TNK3 B 11; + TNK3 C 40; + Loop; + } +} + +// Tank 4 ------------------------------------------------------------------- + +class Tank4 : Actor +{ + Default + { + Radius 16; + Height 56; + +SOLID + } + States + { + Spawn: + TNK4 A 15; + TNK4 B 11; + TNK4 C 40; + Loop; + } +} + +// Tank 5 ------------------------------------------------------------------- + +class Tank5 : Actor +{ + Default + { + Radius 16; + Height 56; + +SOLID + } + States + { + Spawn: + TNK5 A 15; + TNK5 B 11; + TNK5 C 40; + Loop; + } +} + +// Tank 6 ------------------------------------------------------------------- + +class Tank6 : Actor +{ + Default + { + Radius 16; + Height 56; + +SOLID + } + States + { + Spawn: + TNK6 A 15; + TNK6 B 11; + TNK6 C 40; + Loop; + } +} + +// Water Bottle ------------------------------------------------------------- + +class WaterBottle : Actor +{ + States + { + Spawn: + WATR A -1; + Stop; + } +} + +// Mug ---------------------------------------------------------------------- + +class Mug : Actor +{ + States + { + Spawn: + MUGG A -1; + Stop; + } +} + +// Wooden Barrel ------------------------------------------------------------ + +class WoodenBarrel : Actor +{ + Default + { + Health 10; + Radius 10; + Height 32; + +SOLID +SHOOTABLE +NOBLOOD + +INCOMBAT + DeathSound "woodenbarrel/death"; + } + States + { + Spawn: + BARW A -1; + Stop; + Death: + BARW B 2 A_Scream; + BARW C 2; + BARW D 2 A_NoBlocking; + BARW EFG 2; + BARW H -1; + Stop; + } +} + +// Strife's explosive barrel ------------------------------------------------ + +class ExplosiveBarrel2 : Actor +{ + Default + { + Health 30; + Radius 10; + Height 32; + +SOLID +SHOOTABLE +NOBLOOD +OLDRADIUSDMG + DeathSound "world/barrelx"; + +INCOMBAT + } + States + { + Spawn: + BART A -1; + Stop; + Death: + BART B 2 Bright A_Scream; + BART CD 2 Bright; + BART E 2 Bright A_NoBlocking; + BART F 2 Bright A_Explode(64, 64, 1, 1); + BART GHIJ 2 Bright; + BART K 3 Bright; + BART L -1; + Stop; + } +} + +// Light Silver, Fluorescent ---------------------------------------------- + +class LightSilverFluorescent : Actor +{ + Default + { + Radius 2.5; + Height 16; + +NOBLOCKMAP + +FIXMAPTHINGPOS + } + States + { + Spawn: + LITS A -1 Bright; + Stop; + } +} + +// Light Brown, Fluorescent ----------------------------------------------- + +class LightBrownFluorescent : Actor +{ + Default + { + Radius 2.5; + Height 16; + +NOBLOCKMAP + +FIXMAPTHINGPOS + } + States + { + Spawn: + LITB A -1 Bright; + Stop; + } +} + +// Light Gold, Fluorescent ------------------------------------------------ + +class LightGoldFluorescent : Actor +{ + Default + { + Radius 2.5; + Height 16; + +NOBLOCKMAP + +FIXMAPTHINGPOS + } + States + { + Spawn: + LITG A -1 Bright; + Stop; + } +} + +// Light Globe -------------------------------------------------------------- + +class LightGlobe : Actor +{ + Default + { + Radius 16; + Height 16; + +SOLID + } + States + { + Spawn: + LITE A -1 Bright; + Stop; + } +} + +// Techno Pillar ------------------------------------------------------------ + +class PillarTechno : Actor +{ + Default + { + Radius 20; + Height 128; + +SOLID + } + States + { + Spawn: + MONI A -1; + Stop; + } +} + +// Aztec Pillar ------------------------------------------------------------- + +class PillarAztec : Actor +{ + Default + { + Radius 16; + Height 128; + +SOLID + } + States + { + Spawn: + STEL A -1; + Stop; + } +} + +// Damaged Aztec Pillar ----------------------------------------------------- + +class PillarAztecDamaged : Actor +{ + Default + { + Radius 16; + Height 80; + +SOLID + } + States + { + Spawn: + STLA A -1; + Stop; + } +} + +// Ruined Aztec Pillar ------------------------------------------------------ + +class PillarAztecRuined : Actor +{ + Default + { + Radius 16; + Height 40; + +SOLID + } + States + { + Spawn: + STLE A -1; + Stop; + } +} + +// Huge Tech Pillar --------------------------------------------------------- + +class PillarHugeTech : Actor +{ + Default + { + Radius 24; + Height 192; + +SOLID + } + States + { + Spawn: + HUGE ABCD 4; + Loop; + } +} + +// Alien Power Crystal in a Pillar ------------------------------------------ + +class PillarAlienPower : Actor +{ + Default + { + Radius 24; + Height 192; + +SOLID + ActiveSound "ambient/alien2"; + } + States + { + Spawn: + APOW A 4 A_LoopActiveSound; + Loop; + } +} + +// SStalactiteBig ----------------------------------------------------------- + +class SStalactiteBig : Actor +{ + Default + { + Radius 16; + Height 54; + +SOLID +SPAWNCEILING +NOGRAVITY + } + States + { + Spawn: + STLG C -1; + Stop; + } +} + +// SStalactiteSmall --------------------------------------------------------- + +class SStalactiteSmall : Actor +{ + Default + { + Radius 16; + Height 40; + +SOLID +SPAWNCEILING +NOGRAVITY + } + States + { + Spawn: + STLG A -1; + Stop; + } +} + +// SStalagmiteBig ----------------------------------------------------------- + +class SStalagmiteBig : Actor +{ + Default + { + Radius 16; + Height 40; + +SOLID + } + States + { + Spawn: + STLG B -1; + Stop; + } +} + +// Cave Pillar Top ---------------------------------------------------------- + +class CavePillarTop : Actor +{ + Default + { + Radius 16; + Height 128; + +SOLID +SPAWNCEILING +NOGRAVITY + } + States + { + Spawn: + STLG D -1; + Stop; + } +} + +// Cave Pillar Bottom ------------------------------------------------------- + +class CavePillarBottom : Actor +{ + Default + { + Radius 16; + Height 128; + +SOLID + } + States + { + Spawn: + STLG E -1; + Stop; + } +} + +// SStalagmiteSmall --------------------------------------------------------- + +class SStalagmiteSmall : Actor +{ + Default + { + Radius 16; + Height 25; + +SOLID + } + States + { + Spawn: + STLG F -1; + Stop; + } +} + +// Candle ------------------------------------------------------------------- + +class Candle : Actor +{ + States + { + Spawn: + KNDL A -1 Bright; + Stop; + } +} + +// StrifeCandelabra --------------------------------------------------------- + +class StrifeCandelabra : Actor +{ + Default + { + Radius 16; + Height 40; + +SOLID + } + States + { + Spawn: + CLBR A -1; + Stop; + } +} + +// Floor Water Drop --------------------------------------------------------- + +class WaterDropOnFloor : Actor +{ + Default + { + +NOBLOCKMAP + ActiveSound "world/waterdrip"; + } + States + { + Spawn: + DRIP A 6 A_FLoopActiveSound; + DRIP BC 4; + DRIP D 4 A_FLoopActiveSound; + DRIP EF 4; + DRIP G 4 A_FLoopActiveSound; + DRIP H 4; + Loop; + } +} + +// Waterfall Splash --------------------------------------------------------- + +class WaterfallSplash : Actor +{ + Default + { + +NOBLOCKMAP + ActiveSound "world/waterfall"; + } + States + { + Spawn: + SPLH ABCDEFG 4; + SPLH H 4 A_LoopActiveSound; + Loop; + } +} + +// Ceiling Water Drip ------------------------------------------------------- + +class WaterDrip : Actor +{ + Default + { + Height 1; + +NOBLOCKMAP +SPAWNCEILING +NOGRAVITY + } + States + { + Spawn: + CDRP A 10; + CDRP BCD 8; + Loop; + } +} + +// WaterFountain ------------------------------------------------------------ + +class WaterFountain : Actor +{ + Default + { + +NOBLOCKMAP + ActiveSound "world/watersplash"; + } + States + { + Spawn: + WTFT ABC 4; + WTFT D 4 A_LoopActiveSound; + Loop; + } +} + +// Hearts in Tank ----------------------------------------------------------- + +class HeartsInTank : Actor +{ + Default + { + Radius 16; + Height 56; + +SOLID + } + States + { + Spawn: + HERT ABC 4 Bright; + Loop; + } +} + +// Teleport Swirl ----------------------------------------------------------- + +class TeleportSwirl : Actor +{ + Default + { + +NOBLOCKMAP + RenderStyle "Add"; + Alpha 0.25; + } + States + { + Spawn: + TELP ABCD 3 Bright; + Loop; + } +} + +// Dead Player -------------------------------------------------------------- +// Strife's disappeared. This one doesn't. + +class DeadStrifePlayer : Actor +{ + States + { + Spawn: + PLAY P 700; + RGIB H -1; + Stop; + } +} + +// Dead Peasant ------------------------------------------------------------- +// Unlike Strife's, this one does not turn into gibs and disappear. + +class DeadPeasant : Actor +{ + States + { + Spawn: + PEAS N -1; + Stop; + } +} + +// Dead Acolyte ------------------------------------------------------------- +// Unlike Strife's, this one does not turn into gibs and disappear. + +class DeadAcolyte : Actor +{ + States + { + Spawn: + AGRD N -1; + Stop; + } +} + +// Dead Reaver -------------------------------------------------------------- + +class DeadReaver : Actor +{ + States + { + Spawn: + ROB1 R -1; + Stop; + } +} + +// Dead Rebel --------------------------------------------------------------- + +class DeadRebel : Actor +{ + States + { + Spawn: + HMN1 N -1; + Stop; + } +} + +// Sacrificed Guy ----------------------------------------------------------- + +class SacrificedGuy : Actor +{ + States + { + Spawn: + SACR A -1; + Stop; + } +} + +// Pile of Guts ------------------------------------------------------------- + +class PileOfGuts : Actor +{ + // Strife used a doomednum, which is the same as the Aztec Pillar. Since + // the pillar came first in the mobjinfo list, you could not spawn this + // in a map. Pity. + States + { + Spawn: + DEAD A -1; + Stop; + } +} + +// Burning Barrel ----------------------------------------------------------- + +class StrifeBurningBarrel : Actor +{ + Default + { + Radius 16; + Height 48; + +SOLID + } + States + { + Spawn: + BBAR ABCD 4 Bright; + Loop; + } +} + +// Burning Bowl ----------------------------------------------------------- + +class BurningBowl : Actor +{ + Default + { + Radius 16; + Height 16; + +SOLID + ActiveSound "world/smallfire"; + } + States + { + Spawn: + BOWL ABCD 4 Bright; + Loop; + } +} + +// Burning Brazier ----------------------------------------------------------- + +class BurningBrazier : Actor +{ + Default + { + Radius 10; + Height 32; + +SOLID + ActiveSound "world/smallfire"; + } + States + { + Spawn: + BRAZ ABCD 4 Bright; + Loop; + } +} + +// Small Torch Lit -------------------------------------------------------- + +class SmallTorchLit : Actor +{ + Default + { + Radius 2.5; + Height 16; + +NOBLOCKMAP + +FIXMAPTHINGPOS + + // It doesn't have any action functions, so how does it use this sound? + ActiveSound "world/smallfire"; + } + States + { + Spawn: + TRHL ABCD 4 Bright; + Loop; + } +} + +// Small Torch Unlit -------------------------------------------------------- + +class SmallTorchUnlit : Actor +{ + Default + { + Radius 2.5; + Height 16; + +NOBLOCKMAP + +FIXMAPTHINGPOS + } + States + { + Spawn: + TRHO A -1; + Stop; + } +} + +// Ceiling Chain ------------------------------------------------------------ + +class CeilingChain : Actor +{ + Default + { + Radius 20; + Height 93; + +NOBLOCKMAP +SPAWNCEILING +NOGRAVITY + } + States + { + Spawn: + CHAN A -1; + Stop; + } +} + +// Cage Light --------------------------------------------------------------- + +class CageLight : Actor +{ + Default + { + // No, it's not bright even though it's a light. + Height 3; + +NOBLOCKMAP +SPAWNCEILING +NOGRAVITY + } + States + { + Spawn: + CAGE A -1; + Stop; + } +} + +// Statue ------------------------------------------------------------------- + +class Statue : Actor +{ + Default + { + Radius 20; + Height 64; + +SOLID + } + States + { + Spawn: + STAT A -1; + Stop; + } +} + +// Ruined Statue ------------------------------------------------------------ + +class StatueRuined : Actor +{ + Default + { + Radius 20; + Height 56; + +SOLID + } + States + { + Spawn: + DSTA A -1; + Stop; + } +} + +// Medium Torch ------------------------------------------------------------- + +class MediumTorch : Actor +{ + Default + { + Radius 4; + Height 72; + +SOLID + } + States + { + Spawn: + LTRH ABCD 4; + Loop; + } +} + +// Outside Lamp ------------------------------------------------------------- + +class OutsideLamp : Actor +{ + Default + { + // No, it's not bright. + Radius 3; + Height 80; + +SOLID + } + States + { + Spawn: + LAMP A -1; + Stop; + } +} + +// Pole Lantern ------------------------------------------------------------- + +class PoleLantern : Actor +{ + Default + { + // No, it's not bright. + Radius 3; + Height 80; + +SOLID + } + States + { + Spawn: + LANT A -1; + Stop; + } +} + +// Rock 1 ------------------------------------------------------------------- + +class SRock1 : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + ROK1 A -1; + Stop; + } +} + +// Rock 2 ------------------------------------------------------------------- + +class SRock2 : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + ROK2 A -1; + Stop; + } +} + +// Rock 3 ------------------------------------------------------------------- + +class SRock3 : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + ROK3 A -1; + Stop; + } +} + +// Rock 4 ------------------------------------------------------------------- + +class SRock4 : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + ROK4 A -1; + Stop; + } +} + +// Stick in Water ----------------------------------------------------------- + +class StickInWater : Actor +{ + Default + { + +NOBLOCKMAP + +FLOORCLIP + ActiveSound "world/river"; + } + States + { + Spawn: + LOGW ABCD 5 A_LoopActiveSound; + Loop; + } +} + +// Rubble 1 ----------------------------------------------------------------- + +class Rubble1 : Actor +{ + Default + { + +NOBLOCKMAP +NOCLIP + } + States + { + Spawn: + RUB1 A -1; + Stop; + } +} + +// Rubble 2 ----------------------------------------------------------------- + +class Rubble2 : Actor +{ + Default + { + +NOBLOCKMAP +NOCLIP + } + States + { + Spawn: + RUB2 A -1; + Stop; + } +} + +// Rubble 3 ----------------------------------------------------------------- + +class Rubble3 : Actor +{ + Default + { + +NOBLOCKMAP +NOCLIP + } + States + { + Spawn: + RUB3 A -1; + Stop; + } +} + +// Rubble 4 ----------------------------------------------------------------- + +class Rubble4 : Actor +{ + Default + { + +NOBLOCKMAP +NOCLIP + } + States + { + Spawn: + RUB4 A -1; + Stop; + } +} + +// Rubble 5 ----------------------------------------------------------------- + +class Rubble5 : Actor +{ + Default + { + +NOBLOCKMAP +NOCLIP + } + States + { + Spawn: + RUB5 A -1; + Stop; + } +} + +// Rubble 6 ----------------------------------------------------------------- + +class Rubble6 : Actor +{ + Default + { + +NOBLOCKMAP +NOCLIP + } + States + { + Spawn: + RUB6 A -1; + Stop; + } +} + +// Rubble 7 ----------------------------------------------------------------- + +class Rubble7 : Actor +{ + Default + { + +NOBLOCKMAP +NOCLIP + } + States + { + Spawn: + RUB7 A -1; + Stop; + } +} + +// Rubble 8 ----------------------------------------------------------------- + +class Rubble8 : Actor +{ + Default + { + +NOBLOCKMAP +NOCLIP + } + States + { + Spawn: + RUB8 A -1; + Stop; + } +} + +// Surgery Crab ------------------------------------------------------------- + +class SurgeryCrab : Actor +{ + Default + { + +SOLID +SPAWNCEILING +NOGRAVITY + Radius 20; + Height 16; + } + States + { + Spawn: + CRAB A -1; + Stop; + } +} + +// Large Torch -------------------------------------------------------------- + +class LargeTorch : Actor +{ + Default + { + Radius 10; + Height 72; + +SOLID + ActiveSound "world/smallfire"; + } + States + { + Spawn: + LMPC ABCD 4 Bright; + Loop; + } +} + +// Huge Torch -------------------------------------------------------------- + +class HugeTorch : Actor +{ + Default + { + Radius 10; + Height 80; + +SOLID + ActiveSound "world/smallfire"; + } + States + { + Spawn: + LOGS ABCD 4; + Loop; + } +} + +// Palm Tree ---------------------------------------------------------------- + +class PalmTree : Actor +{ + Default + { + Radius 15; + Height 109; + +SOLID + } + States + { + Spawn: + TREE A -1; + Stop; + } +} + +// Big Tree ---------------------------------------------------------------- + +class BigTree2 : Actor +{ + Default + { + Radius 15; + Height 109; + +SOLID + } + States + { + Spawn: + TREE B -1; + Stop; + } +} + +// Potted Tree ---------------------------------------------------------------- + +class PottedTree : Actor +{ + Default + { + Radius 15; + Height 64; + +SOLID + } + States + { + Spawn: + TREE C -1; + Stop; + } +} + +// Tree Stub ---------------------------------------------------------------- + +class TreeStub : Actor +{ + Default + { + Radius 15; + Height 80; + +SOLID + } + States + { + Spawn: + TRET A -1; + Stop; + } +} + +// Short Bush --------------------------------------------------------------- + +class ShortBush : Actor +{ + Default + { + Radius 15; + Height 40; + +SOLID + } + States + { + Spawn: + BUSH A -1; + Stop; + } +} + +// Tall Bush --------------------------------------------------------------- + +class TallBush : Actor +{ + Default + { + Radius 20; + Height 64; + +SOLID + } + States + { + Spawn: + SHRB A -1; + Stop; + } +} + +// Chimney Stack ------------------------------------------------------------ + +class ChimneyStack : Actor +{ + Default + { + Radius 20; + Height 64; // This height does not fit the sprite + +SOLID + } + States + { + Spawn: + STAK A -1; + Stop; + } +} + +// Barricade Column --------------------------------------------------------- + +class BarricadeColumn : Actor +{ + Default + { + Radius 16; + Height 128; + +SOLID + } + States + { + Spawn: + BARC A -1; + Stop; + } +} + +// Pot ---------------------------------------------------------------------- + +class Pot : Actor +{ + Default + { + Radius 12; + Height 24; + +SOLID + } + States + { + Spawn: + VAZE A -1; + Stop; + } +} + +// Pitcher ------------------------------------------------------------------ + +class Pitcher : Actor +{ + Default + { + Radius 12; + Height 32; + +SOLID + } + States + { + Spawn: + VAZE B -1; + Stop; + } +} + +// Stool -------------------------------------------------------------------- + +class Stool : Actor +{ + Default + { + Radius 6; + Height 24; + +SOLID + } + States + { + Spawn: + STOL A -1; + Stop; + } +} + +// Metal Pot ---------------------------------------------------------------- + +class MetalPot : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + MPOT A -1; + Stop; + } +} + +// Tub ---------------------------------------------------------------------- + +class Tub : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + TUB1 A -1; + Stop; + } +} + +// Anvil -------------------------------------------------------------------- + +class Anvil : Actor +{ + Default + { + Radius 16; + Height 32; + +SOLID + } + States + { + Spawn: + ANVL A -1; + Stop; + } +} + +// Silver Tech Lamp ---------------------------------------------------------- + +class TechLampSilver : Actor +{ + Default + { + Radius 11; + Height 64; + +SOLID + } + States + { + Spawn: + TECH A -1; + Stop; + } +} + +// Brass Tech Lamp ---------------------------------------------------------- + +class TechLampBrass : Actor +{ + Default + { + Radius 8; + Height 64; + +SOLID + } + States + { + Spawn: + TECH B -1; + Stop; + } +} + +// Tray -------------------------------------------------------------------- + +class Tray : Actor +{ + Default + { + Radius 24; + Height 40; + +SOLID + } + States + { + Spawn: + TRAY A -1; + Stop; + } +} + +// AmmoFiller --------------------------------------------------------------- + +class AmmoFiller : Actor +{ + Default + { + Radius 12; + Height 24; + +SOLID + } + States + { + Spawn: + AFED A -1; + Stop; + } +} + +// Sigil Banner ------------------------------------------------------------- + +class SigilBanner : Actor +{ + Default + { + Radius 24; + Height 96; + +NOBLOCKMAP // I take it this was once solid, yes? + } + States + { + Spawn: + SBAN A -1; + Stop; + } +} + +// RebelBoots --------------------------------------------------------------- + +class RebelBoots : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + BOTR A -1; + Stop; + } +} + +// RebelHelmet -------------------------------------------------------------- + +class RebelHelmet : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + HATR A -1; + Stop; + } +} + +// RebelShirt --------------------------------------------------------------- + +class RebelShirt : Actor +{ + Default + { + +NOBLOCKMAP + } + States + { + Spawn: + TOPR A -1; + Stop; + } +} + +// Alien Bubble Column ------------------------------------------------------ + +class AlienBubbleColumn : Actor +{ + Default + { + Radius 16; + Height 128; + +SOLID + ActiveSound "ambient/alien5"; + } + States + { + Spawn: + BUBB A 4 A_LoopActiveSound; + Loop; + } +} + +// Alien Floor Bubble ------------------------------------------------------- + +class AlienFloorBubble : Actor +{ + Default + { + Radius 16; + Height 72; + +SOLID + ActiveSound "ambient/alien6"; + } + States + { + Spawn: + BUBF A 4 A_LoopActiveSound; + Loop; + } +} + +// Alien Ceiling Bubble ----------------------------------------------------- + +class AlienCeilingBubble : Actor +{ + Default + { + Radius 16; + Height 72; + +SOLID +SPAWNCEILING +NOGRAVITY + ActiveSound "ambient/alien4"; + } + States + { + Spawn: + BUBC A 4 A_LoopActiveSound; + Loop; + } +} + +// Alien Asp Climber -------------------------------------------------------- + +class AlienAspClimber : Actor +{ + Default + { + Radius 16; + Height 128; + +SOLID + ActiveSound "ambient/alien3"; + } + States + { + Spawn: + ASPR A 4 A_LoopActiveSound; + Loop; + } +} + +// Alien Spider Light ------------------------------------------------------- + +class AlienSpiderLight : Actor +{ + Default + { + Radius 32; + Height 56; + +SOLID + ActiveSound "ambient/alien1"; + } + States + { + Spawn: + SPDL ABC 5 A_LoopActiveSound; + Loop; + } +} + +// Target Practice ----------------------------------------------------------- + +class TargetPractice : Actor +{ + Default + { + Health 99999999; + PainChance 255; + Radius 10; + Height 72; + Mass 9999999; + +SOLID +SHOOTABLE +NOBLOOD + +INCOMBAT +NODAMAGE + PainSound "misc/metalhit"; + } + States + { + Spawn: + HOGN A 2 A_CheckTerrain; + Loop; + Pain: + HOGN B 1 A_CheckTerrain; + HOGN C 1 A_Pain; + Goto Spawn; + } +} + +// Force Field Guard -------------------------------------------------------- + +class ForceFieldGuard : Actor native +{ + Default + { + Health 10; + Radius 2; + Height 1; + Mass 10000; + +SHOOTABLE + +NOSECTOR + +NOBLOOD + +INCOMBAT + } + States + { + Spawn: + TNT1 A -1; + Stop; + Death: + TNT1 A 1 A_RemoveForceField; + Stop; + } +} + +// Kneeling Guy ------------------------------------------------------------- + +class KneelingGuy : Actor +{ + Default + { + Health 51; + Painchance 255; + Radius 6; + Height 17; + Mass 50000; + +SOLID + +SHOOTABLE + +NOBLOOD + +ISMONSTER + +INCOMBAT + PainSound "misc/static"; + DeathSound "misc/static"; + ActiveSound "misc/chant"; + } + States + { + Spawn: + See: + NEAL A 15 A_LoopActiveSound; + NEAL B 40 A_LoopActiveSound; + Loop; + Pain: + NEAL C 5 A_SetShadow; + NEAL B 4 A_Pain; + NEAL C 5 A_ClearShadow; + Goto Spawn; + Wound: + NEAL B 6; + NEAL C 13 A_GetHurt; + Loop; + Death: + NEAL D 5; + NEAL E 5 A_Scream; + NEAL F 6; + NEAL G 5 A_NoBlocking; + NEAL H 5; + NEAL I 6; + NEAL J -1; + Stop; + } + + +} + +// Klaxon Warning Light ----------------------------------------------------- + +class KlaxonWarningLight : Actor +{ + Default + { + ReactionTime 60; + Radius 5; + +NOBLOCKMAP +AMBUSH + +SPAWNCEILING +NOGRAVITY + +FIXMAPTHINGPOS +NOSPLASHALERT + +SYNCHRONIZED + } + States + { + Spawn: + KLAX A 5 A_TurretLook; + Loop; + See: + KLAX B 6 A_KlaxonBlare; + KLAX C 60; + Loop; + } + +} + +// CeilingTurret ------------------------------------------------------------ + +class CeilingTurret : Actor +{ + Default + { + Health 125; + Speed 0; + Painchance 0; + Mass 10000000; + Monster; + -SOLID + -CANPASS + +AMBUSH + +SPAWNCEILING + +NOGRAVITY + +NOBLOOD + +NOSPLASHALERT + +DONTFALL + MinMissileChance 150; + DeathSound "turret/death"; + } + States + { + Spawn: + TURT A 5 A_TurretLook; + Loop; + See: + TURT A 2 A_Chase; + Loop; + Missile: + Pain: + TURT B 4 Slow A_ShootGun; + TURT D 3 Slow A_SentinelRefire; + TURT A 4 A_SentinelRefire; + Loop; + Death: + BALL A 6 Bright A_Scream; + BALL BCDE 6 Bright; + TURT C -1; + Stop; + } +} + + +// Power Coupling ----------------------------------------------------------- + +class PowerCoupling : Actor native +{ + Default + { + Health 40; + Radius 17; + Height 64; + Mass 999999; + +SOLID + +SHOOTABLE + +DROPPED + +NOBLOOD + +NOTDMATCH + +INCOMBAT + } + States + { + Spawn: + COUP AB 5; + Loop; + } +} + +// Gibs for things that bleed ----------------------------------------------- + +class Meat : Actor native +{ + Default + { + +NOCLIP + } + States + { + Spawn: + MEAT A 700; + Stop; + MEAT B 700; + Stop; + MEAT C 700; + Stop; + MEAT D 700; + Stop; + MEAT E 700; + Stop; + MEAT F 700; + Stop; + MEAT G 700; + Stop; + MEAT H 700; + Stop; + MEAT I 700; + Stop; + MEAT J 700; + Stop; + MEAT K 700; + Stop; + MEAT L 700; + Stop; + MEAT M 700; + Stop; + MEAT N 700; + Stop; + MEAT O 700; + Stop; + MEAT P 700; + Stop; + MEAT Q 700; + Stop; + MEAT R 700; + Stop; + MEAT S 700; + Stop; + MEAT T 700; + Stop; + } +} + +// Gibs for things that don't bleed ----------------------------------------- + +class Junk : Meat +{ + States + { + Spawn: + JUNK A 700; + Stop; + JUNK B 700; + Stop; + JUNK C 700; + Stop; + JUNK D 700; + Stop; + JUNK E 700; + Stop; + JUNK F 700; + Stop; + JUNK G 700; + Stop; + JUNK H 700; + Stop; + JUNK I 700; + Stop; + JUNK J 700; + Stop; + JUNK K 700; + Stop; + JUNK L 700; + Stop; + JUNK M 700; + Stop; + JUNK N 700; + Stop; + JUNK O 700; + Stop; + JUNK P 700; + Stop; + JUNK Q 700; + Stop; + JUNK R 700; + Stop; + JUNK S 700; + Stop; + JUNK T 700; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt new file mode 100644 index 000000000..9e4463893 --- /dev/null +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -0,0 +1,891 @@ + +class StrifeWeapon : Weapon +{ + Default + { + Weapon.Kickback 100; + } +} + +// Same as the bullet puff for Doom ----------------------------------------- + +class StrifePuff : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +ALLOWPARTICLES + RenderStyle "Translucent"; + Alpha 0.25; + } + + States + { + Spawn: + POW3 ABCDEFGH 3; + Stop; + Crash: + PUFY A 4 Bright; + PUFY BCD 4; + Stop; + } +} + + +// A spark when you hit something that doesn't bleed ------------------------ +// Only used by the dagger. + +class StrifeSpark : StrifePuff +{ + Default + { + RenderStyle "Add"; + } + States + { + Crash: + POW2 ABCD 4; + Stop; + } +} + +// Punch Dagger ------------------------------------------------------------- + +class PunchDagger : StrifeWeapon +{ + Default + { + Weapon.SelectionOrder 3900; + +WEAPON.NOALERT + Obituary "$OB_MPPUNCHDAGGER"; + Tag "$TAG_PUNCHDAGGER"; + } + + action native void A_JabDagger (); + + States + { + Ready: + PNCH A 1 A_WeaponReady; + Loop; + Deselect: + PNCH A 1 A_Lower; + Loop; + Select: + PNCH A 1 A_Raise; + Loop; + Fire: + PNCH B 4; + PNCH C 4 A_JabDagger; + PNCH D 5; + PNCH C 4; + PNCH B 5 A_ReFire; + Goto Ready; + } + +} + + +// The base for Strife projectiles that die with ZAP1 ----------------------- + +class StrifeZap1 : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +DROPOFF + } + States + { + Spawn: + Death: + ZAP1 A 3 A_AlertMonsters; + ZAP1 BCDEFE 3; + ZAP1 DCB 2; + ZAP1 A 1; + Stop; + } +} + + +// Electric Bolt ------------------------------------------------------------ + +class ElectricBolt : StrifeZap1 +{ + Default + { + Speed 30; + Radius 10; + Height 10; + Damage 10; + Projectile; + +STRIFEDAMAGE + MaxStepHeight 4; + SeeSound "misc/swish"; + ActiveSound "misc/swish"; + DeathSound "weapons/xbowhit"; + Obituary "$OB_MPELECTRICBOLT"; + } + States + { + Spawn: + AROW A 10 A_LoopActiveSound; + Loop; + } +} + + +// Poison Bolt -------------------------------------------------------------- + +class PoisonBolt : Actor native +{ + Default + { + Speed 30; + Radius 10; + Height 10; + Damage 500; + Projectile; + +STRIFEDAMAGE + MaxStepHeight 4; + SeeSound "misc/swish"; + ActiveSound "misc/swish"; + Obituary "$OB_MPPOISONBOLT"; + } + States + { + Spawn: + ARWP A 10 A_LoopActiveSound; + Loop; + Death: + AROW A 1; + Stop; + } +} + + +// Strife's Crossbow -------------------------------------------------------- + +class StrifeCrossbow : StrifeWeapon +{ + Default + { + +FLOORCLIP + Weapon.SelectionOrder 1200; + +WEAPON.NOALERT + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 8; + Weapon.AmmoType1 "ElectricBolts"; + Weapon.SisterWeapon "StrifeCrossbow2"; + Inventory.PickupMessage "$TXT_STRIFECROSSBOW"; + Tag "$TAG_STRIFECROSSBOW1"; + Inventory.Icon "CBOWA0"; + } + + action native void A_ClearFlash (); + action native void A_ShowElectricFlash (); + action native void A_FireArrow (class proj); + + States + { + Spawn: + CBOW A -1; + Stop; + Ready: + XBOW A 0 A_ShowElectricFlash; + XBOW A 1 A_WeaponReady; + Wait; + Deselect: + XBOW A 1 A_Lower; + Loop; + Select: + XBOW A 1 A_Raise; + Loop; + Fire: + XBOW A 3 A_ClearFlash; + XBOW B 6 A_FireArrow("ElectricBolt"); + XBOW C 4; + XBOW D 6; + XBOW E 3; + XBOW F 5; + XBOW G 0 A_ShowElectricFlash; + XBOW G 5 A_CheckReload; + Goto Ready+1; + Flash: + XBOW KLM 5; + Loop; + } +} + + +class StrifeCrossbow2 : StrifeCrossbow +{ + Default + { + Weapon.SelectionOrder 2700; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 0; + Weapon.AmmoType1 "PoisonBolts"; + Weapon.SisterWeapon "StrifeCrossbow"; + Tag "$TAG_STRIFECROSSBOW2"; + } + States + { + Ready: + XBOW H 1 A_WeaponReady; + Loop; + Deselect: + XBOW H 1 A_Lower; + Loop; + Select: + XBOW H 1 A_Raise; + Loop; + Fire: + XBOW H 3; + XBOW B 6 A_FireArrow("PoisonBolt"); + XBOW C 4; + XBOW D 6; + XBOW E 3; + XBOW I 5; + XBOW J 5 A_CheckReload; + Goto Ready; + Flash: + Stop; + } +} + +// Assault Gun -------------------------------------------------------------- + +class AssaultGun : StrifeWeapon +{ + Default + { + +FLOORCLIP + Weapon.SelectionOrder 600; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 20; + Weapon.AmmoType1 "ClipOfBullets"; + Inventory.Icon "RIFLA0"; + Tag "$TAG_ASSAULTGUN"; + Inventory.PickupMessage "$TXT_ASSAULTGUN"; + Obituary "$OB_MPASSAULTGUN"; + } + States + { + Spawn: + RIFL A -1; + Stop; + Ready: + RIFG A 1 A_WeaponReady; + Loop; + Deselect: + RIFG B 1 A_Lower; + Loop; + Select: + RIFG A 1 A_Raise; + Loop; + Fire: + RIFF AB 3 A_FireAssaultGun; + RIFG D 3 A_FireAssaultGun; + RIFG C 0 A_ReFire; + RIFG B 2 A_Light0; + Goto Ready; + } +} + + +// Standing variant of the assault gun -------------------------------------- + +class AssaultGunStanding : WeaponGiver +{ + Default + { + DropItem "AssaultGun"; + Inventory.PickupMessage "$TXT_ASSAULTGUN"; + } + States + { + Spawn: + RIFL B -1; + Stop; + } +} + + +// Mini-Missile Launcher ---------------------------------------------------- + + +class MiniMissileLauncher : StrifeWeapon +{ + Default + { + +FLOORCLIP + Weapon.SelectionOrder 1800; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 8; + Weapon.AmmoType1 "MiniMissiles"; + Inventory.Icon "MMSLA0"; + Tag "$TAG_MMLAUNCHER"; + Inventory.PickupMessage "$TXT_MMLAUNCHER"; + } + + action native void A_FireMiniMissile (); + + States + { + Spawn: + MMSL A -1; + Stop; + Ready: + MMIS A 1 A_WeaponReady; + Loop; + Deselect: + MMIS A 1 A_Lower; + Loop; + Select: + MMIS A 1 A_Raise; + Loop; + Fire: + MMIS A 4 A_FireMiniMissile; + MMIS B 4 A_Light1; + MMIS C 5 Bright; + MMIS D 2 Bright A_Light2; + MMIS E 2 Bright; + MMIS F 2 Bright A_Light0; + MMIS F 0 A_ReFire; + Goto Ready; + } +} + + +// Rocket Trail ------------------------------------------------------------- + +class RocketTrail : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + RenderStyle "Translucent"; + Alpha 0.25; + SeeSound "misc/missileinflight"; + } + States + { + Spawn: + PUFY BCBCD 4; + Stop; + } +} + +// Rocket Puff -------------------------------------------------------------- + +class MiniMissilePuff : StrifePuff +{ + Default + { + -ALLOWPARTICLES + } + States + { + Spawn: + Goto Crash; + } +} + +// Mini Missile ------------------------------------------------------------- + +class MiniMissile : Actor +{ + Default + { + Speed 20; + Radius 10; + Height 14; + Damage 10; + Projectile; + +STRIFEDAMAGE + MaxStepHeight 4; + SeeSound "weapons/minimissile"; + DeathSound "weapons/minimissilehit"; + Obituary "$OB_MPMINIMISSILELAUNCHER"; + } + States + { + Spawn: + MICR A 6 Bright A_RocketInFlight; + Loop; + Death: + SMIS A 0 Bright A_SetTranslucent(1,1); + SMIS A 5 Bright A_Explode(64,64,1,1); + SMIS B 5 Bright; + SMIS C 4 Bright; + SMIS DEFG 2 Bright; + Stop; + } +} + +// Flame Thrower ------------------------------------------------------------ + +class FlameThrower : StrifeWeapon +{ + Default + { + +FLOORCLIP + Weapon.SelectionOrder 2100; + Weapon.Kickback 0; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 100; + Weapon.UpSound "weapons/flameidle"; + Weapon.ReadySound "weapons/flameidle"; + Weapon.AmmoType1 "EnergyPod"; + Inventory.Icon "FLAMA0"; + Tag "$TAG_FLAMER"; + Inventory.PickupMessage "$TXT_FLAMER"; + } + + action native void A_FireFlamer (); + + States + { + Spawn: + FLAM A -1; + Stop; + Ready: + FLMT AB 3 A_WeaponReady; + Loop; + Deselect: + FLMT A 1 A_Lower; + Loop; + Select: + FLMT A 1 A_Raise; + Loop; + Fire: + FLMF A 2 A_FireFlamer; + FLMF B 3 A_ReFire; + Goto Ready; + } +} + + +// Flame Thrower Projectile ------------------------------------------------- + +class FlameMissile : Actor +{ + Default + { + Speed 15; + Height 11; + Radius 8; + Mass 10; + Damage 4; + DamageType "Fire"; + ReactionTime 8; + Projectile; + -NOGRAVITY + +STRIFEDAMAGE + MaxStepHeight 4; + RenderStyle "Add"; + SeeSound "weapons/flamethrower"; + Obituary "$OB_MPFLAMETHROWER"; + } + + native void A_FlameDie (); + + States + { + Spawn: + FRBL AB 3 Bright; + FRBL C 3 Bright A_Countdown; + Loop; + Death: + FRBL D 5 Bright A_FlameDie; + FRBL EFGHI 5 Bright; + Stop; + } + +} + + +// Mauler ------------------------------------------------------------------- +// The scatter version + +class Mauler : StrifeWeapon +{ + Default + { + +FLOORCLIP + Weapon.SelectionOrder 300; + Weapon.AmmoUse1 20; + Weapon.AmmoGive1 40; + Weapon.AmmoType1 "EnergyPod"; + Weapon.SisterWeapon "Mauler2"; + Inventory.Icon "TRPDA0"; + Tag "$TAG_MAULER1"; + Inventory.PickupMessage "$TXT_MAULER"; + Obituary "$OB_MPMAULER1"; + } + + action native void A_FireMauler1 (); + + States + { + Ready: + MAUL FGHA 6 A_WeaponReady; + Loop; + Deselect: + MAUL A 1 A_Lower; + Loop; + Select: + MAUL A 1 A_Raise; + Loop; + Fire: + BLSF A 5 Bright A_FireMauler1; + MAUL B 3 Bright A_Light1; + MAUL C 2 A_Light2; + MAUL DE 2; + MAUL A 7 A_Light0; + MAUL H 7; + MAUL G 7 A_CheckReload; + Goto Ready; + Spawn: + TRPD A -1; + Stop; + } +} + + +// Mauler Torpedo version --------------------------------------------------- + +class Mauler2 : Mauler +{ + Default + { + Weapon.SelectionOrder 3300; + Weapon.AmmoUse1 30; + Weapon.AmmoGive1 0; + Weapon.AmmoType1 "EnergyPod"; + Weapon.SisterWeapon "Mauler"; + Tag "$TAG_MAULER2"; + } + + action native void A_FireMauler2Pre (); + action native void A_FireMauler2 (); + + States + { + Ready: + MAUL IJKL 7 A_WeaponReady; + Loop; + Deselect: + MAUL I 1 A_Lower; + Loop; + Select: + MAUL I 1 A_Raise; + Loop; + Fire: + MAUL I 20 A_FireMauler2Pre; + MAUL J 10 A_Light1; + BLSF A 10 Bright A_FireMauler2; + MAUL B 10 Bright A_Light2; + MAUL C 2; + MAUL D 2 A_Light0; + MAUL E 2 A_ReFire; + Goto Ready; + } +} + + +// Mauler "Bullet" Puff ----------------------------------------------------- + +class MaulerPuff : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + +PUFFONACTORS + RenderStyle "Add"; + DamageType "Disintegrate"; + } + States + { + Spawn: + MPUF AB 5; + POW1 ABCDE 4; + Stop; + } +} + +// The Mauler's Torpedo ----------------------------------------------------- + +class MaulerTorpedo : Actor +{ + Default + { + Speed 20; + Height 8; + Radius 13; + Damage 1; + DamageType "Disintegrate"; + Projectile; + +STRIFEDAMAGE + MaxStepHeight 4; + RenderStyle "Add"; + SeeSound "weapons/mauler2fire"; + DeathSound "weapons/mauler2hit"; + Obituary "$OB_MPMAULER"; + } + + native void A_MaulerTorpedoWave (); + + States + { + Spawn: + TORP ABCD 4 Bright; + Loop; + Death: + THIT AB 8 Bright; + THIT C 8 Bright A_MaulerTorpedoWave; + THIT DE 8 Bright; + Stop; + } +} + + +// The mini torpedoes shot by the big torpedo -------------------------------- + +class MaulerTorpedoWave : Actor +{ + Default + { + Speed 35; + Radius 13; + Height 13; + Damage 10; + DamageType "Disintegrate"; + Projectile; + +STRIFEDAMAGE + MaxStepHeight 4; + RenderStyle "Add"; + Obituary "$OB_MPMAULER"; + } + States + { + Spawn: + TWAV AB 9 Bright; + Death: + TWAV C 9 Bright; + Stop; + } +} + + +// High-Explosive Grenade --------------------------------------------------- + +class HEGrenade : Actor +{ + Default + { + Speed 15; + Radius 13; + Height 13; + Mass 20; + Damage 1; + Reactiontime 30; + Projectile; + -NOGRAVITY + +STRIFEDAMAGE + +BOUNCEONACTORS + +EXPLODEONWATER + MaxStepHeight 4; + BounceType "Doom"; + BounceFactor 0.5; + BounceCount 2; + SeeSound "weapons/hegrenadeshoot"; + DeathSound "weapons/hegrenadebang"; + Obituary "$OB_MPSTRIFEGRENADE"; + } + States + { + Spawn: + GRAP AB 3 A_Countdown; + Loop; + Death: + BNG4 A 0 Bright A_NoGravity; + BNG4 A 0 Bright A_SetTranslucent(1,1); + BNG4 A 2 Bright A_Explode(192,192,1,1); + BNG4 BCDEFGHIJKLMN 3 Bright; + Stop; + } +} + +// White Phosphorous Grenade ------------------------------------------------ + +class PhosphorousGrenade : Actor +{ + Default + { + Speed 15; + Radius 13; + Height 13; + Mass 20; + Damage 1; + Reactiontime 40; + Projectile; + -NOGRAVITY + +STRIFEDAMAGE + +BOUNCEONACTORS + +EXPLODEONWATER + BounceType "Doom"; + MaxStepHeight 4; + BounceFactor 0.5; + BounceCount 2; + SeeSound "weapons/phgrenadeshoot"; + DeathSound "weapons/phgrenadebang"; + Obituary "$OB_MPPHOSPHOROUSGRENADE"; + } + States + { + Spawn: + GRIN AB 3 A_Countdown; + Loop; + Death: + BNG3 A 2 A_SpawnItemEx("PhosphorousFire"); + Stop; + } +} + +// Fire from the Phoshorous Grenade ----------------------------------------- + +class PhosphorousFire : Actor native +{ + Default + { + Reactiontime 120; + DamageType "Fire"; + +NOBLOCKMAP + +FLOORCLIP + +NOTELEPORT + +NODAMAGETHRUST + +DONTSPLASH + RenderStyle "Add"; + Obituary "$OB_MPPHOSPHOROUSGRENADE"; + } + + native void A_Burnarea (); + native void A_Burnination (); + + States + { + Spawn: + BNG3 B 2 Bright A_Burnarea; + BNG3 C 2 Bright A_Countdown; + FLBE A 2 Bright A_Burnination; + FLBE B 2 Bright A_Countdown; + FLBE C 2 Bright A_Burnarea; + FLBE D 3 Bright A_Countdown; + FLBE E 3 Bright A_Burnarea; + FLBE F 3 Bright A_Countdown; + FLBE G 3 Bright A_Burnination; + Goto Spawn+5; + Death: + FLBE H 2 Bright; + FLBE I 2 Bright A_Burnination; + FLBE JK 2 Bright; + Stop; + } +} + +// High-Explosive Grenade Launcher ------------------------------------------ + +class StrifeGrenadeLauncher : StrifeWeapon +{ + Default + { + +FLOORCLIP + Weapon.SelectionOrder 2400; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 12; + Weapon.AmmoType1 "HEGrenadeRounds"; + Weapon.SisterWeapon "StrifeGrenadeLauncher2"; + Inventory.Icon "GRNDA0"; + Tag "$TAG_GLAUNCHER1"; + Inventory.PickupMessage "$TXT_GLAUNCHER"; + } + + action native void A_FireGrenade (class grenadetype, float angleofs, statelabel flash); + + States + { + Spawn: + GRND A -1; + Stop; + Ready: + GREN A 1 A_WeaponReady; + Loop; + Deselect: + GREN A 1 A_Lower; + Loop; + Select: + GREN A 1 A_Raise; + Loop; + Fire: + GREN A 5 A_FireGrenade("HEGrenade", -90, "Flash"); + GREN B 10; + GREN A 5 A_FireGrenade("HEGrenade", 90, "Flash2"); + GREN C 10; + GREN A 0 A_ReFire; + Goto Ready; + Flash: + GREF A 5 Bright A_Light1; + Goto LightDone; + Flash2: + GREF B 5 Bright A_Light2; + Goto LightDone; + } + +} + +// White Phosphorous Grenade Launcher --------------------------------------- + +class StrifeGrenadeLauncher2 : StrifeGrenadeLauncher +{ + Default + { + Weapon.SelectionOrder 3200; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 0; + Weapon.AmmoType1 "PhosphorusGrenadeRounds"; + Weapon.SisterWeapon "StrifeGrenadeLauncher"; + Tag "$TAG_GLAUNCHER2"; + } + States + { + Ready: + GREN D 1 A_WeaponReady; + Loop; + Deselect: + GREN D 1 A_Lower; + Loop; + Select: + GREN D 1 A_Raise; + Loop; + Fire: + GREN D 5 A_FireGrenade("PhosphorousGrenade", -90, "Flash"); + GREN E 10; + GREN D 5 A_FireGrenade("PhosphorousGrenade", 90, "Flash2"); + GREN F 10; + GREN A 0 A_ReFire; + Goto Ready; + Flash: + GREF C 5 Bright A_Light1; + Goto LightDone; + Flash2: + GREF D 5 Bright A_Light2; + Goto LightDone; + } +} + diff --git a/wadsrc/static/zscript/strife/templar.txt b/wadsrc/static/zscript/strife/templar.txt new file mode 100644 index 000000000..5b1605cf4 --- /dev/null +++ b/wadsrc/static/zscript/strife/templar.txt @@ -0,0 +1,68 @@ + +class Templar : Actor +{ + Default + { + Health 300; + Painchance 100; + Speed 8; + Radius 20; + Height 60; + Mass 500; + Monster; + +NOBLOOD + +SEESDAGGERS + +NOSPLASHALERT + MaxdropoffHeight 32; + MinMissileChance 200; + SeeSound "templar/sight"; + PainSound "templar/pain"; + DeathSound "templar/death"; + ActiveSound "templar/active"; + CrushPainSound "misc/pcrush"; + Tag "$TAG_TEMPLAR"; + HitObituary "$OB_TEMPLARHIT"; + Obituary "$OB_TEMPLAR"; + DropItem "EnergyPod"; + } + native void A_TemplarAttack(); + + States + { + Spawn: + PGRD A 5 A_Look2; + Loop; + PGRD B 10; + Loop; + PGRD C 10; + Loop; + PGRD B 10 A_Wander; + Loop; + See: + PGRD AABBCCDD 3 A_Chase; + Loop; + Melee: + PGRD E 8 A_FaceTarget; + PGRD F 8 A_CustomMeleeAttack(random[ReaverMelee](1,8)*3, "reaver/blade"); + Goto See; + Missile: + PGRD G 8 BRIGHT A_FaceTarget; + PGRD H 8 BRIGHT A_TemplarAttack; + Goto See; + Pain: + PGRD A 2; + PGRD A 2 A_Pain; + Goto See; + Death: + PGRD I 4 A_TossGib; + PGRD J 4 A_Scream; + PGRD K 4 A_TossGib; + PGRD L 4 A_NoBlocking; + PGRD MN 4; + PGRD O 4 A_TossGib; + PGRD PQRSTUVWXYZ[ 4; + PGRD \ -1; + Stop; + } +} + diff --git a/wadsrc/static/zscript/strife/thingstoblowup.txt b/wadsrc/static/zscript/strife/thingstoblowup.txt new file mode 100644 index 000000000..dbbad8ed6 --- /dev/null +++ b/wadsrc/static/zscript/strife/thingstoblowup.txt @@ -0,0 +1,153 @@ + + +// A Cloud used for varius explosions --------------------------------------- +// This actor has no direct equivalent in strife. To create this, Strife +// spawned a spark and then changed its state to that of this explosion +// cloud. Weird. + +class Bang4Cloud : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + RenderStyle "Add"; + VSpeed 1; + } + States + { + Spawn: + BNG4 BCDEFGHIJKLMN 3 Bright; + Stop; + } +} + +// Piston ------------------------------------------------------------------- + +class Piston : Actor +{ + Default + { + Health 100; + Speed 16; + Radius 20; + Height 76; + Mass 10000000; + +SOLID + +SHOOTABLE + +NOBLOOD + +FLOORCLIP + +INCOMBAT + DeathSound "misc/explosion"; + } + States + { + Spawn: + PSTN AB 8; + Loop; + Death: + PSTN A 4 Bright A_Scream; + PSTN B 4 Bright A_NoBlocking; + PSTN C 4 Bright A_GiveQuestItem(16); + PSTN D 4 Bright A_Bang4Cloud; + PSTN E 4 Bright A_TossGib; + PSTN F 4 Bright; + PSTN G 4 Bright A_Bang4Cloud; + PSTN H 4; + PSTN I -1; + Stop; + } + +} + +// Computer ----------------------------------------------------------------- + +class Computer : Actor +{ + Default + { + Health 80; + Speed 27; + Radius 26; + Height 128; + Mass 10000000; + +SOLID + +SHOOTABLE + +NOBLOOD + +FLOORCLIP + +INCOMBAT + DeathSound "misc/explosion"; + } + States + { + Spawn: + SECR ABCD 4 Bright; + Loop; + Death: + SECR E 5 Bright A_Bang4Cloud; + SECR F 5 Bright A_NoBlocking; + SECR G 5 Bright A_GiveQuestItem(27); + SECR H 5 Bright A_TossGib; + SECR I 5 Bright A_Bang4Cloud; + SECR J 5; + SECR K 5 A_Bang4Cloud; + SECR L 5; + SECR M 5 A_Bang4Cloud; + SECR N 5; + SECR O 5 A_Bang4Cloud; + SECR P -1; + Stop; + } +} + + +// Power Crystal ------------------------------------------------------------ + +class PowerCrystal : Actor +{ + Default + { + Health 50; + Speed 14; + Radius 20; + Height 16; + Mass 99999999; + +SOLID + +SHOOTABLE + +NOGRAVITY + +NOBLOOD + +FLOORCLIP + DeathSound "misc/explosion"; + ActiveSound "misc/reactor"; + } + + native void A_ExtraLightOff (); + native void A_Explode512 (); + native void A_LightGoesOut (); + + States + { + Spawn: + CRYS A 16 A_LoopActiveSound; + CRYS B 5 A_LoopActiveSound; + CRYS CDEF 4 A_LoopActiveSound; + Loop; + Death: + BOOM A 0 Bright A_Scream; + BOOM A 1 Bright A_Explode512; + BOOM B 3 Bright A_GiveQuestItem(14); + BOOM C 2 Bright A_LightGoesOut; + BOOM D 3 Bright A_Bang4Cloud; + BOOM EF 3 Bright; + BOOM G 3 Bright A_Bang4Cloud; + BOOM H 1 Bright A_Explode512; + BOOM I 3 Bright; + BOOM JKL 3 Bright A_Bang4Cloud; + BOOM MN 3 Bright; + BOOM O 3 Bright A_Bang4Cloud; + BOOM PQRST 3 Bright; + BOOM U 3 Bright A_ExtraLightOff; + BOOM VWXY 3 Bright; + Stop; + } +} diff --git a/wadsrc/static/zscript/strife/zombie.txt b/wadsrc/static/zscript/strife/zombie.txt new file mode 100644 index 000000000..c7a7cea59 --- /dev/null +++ b/wadsrc/static/zscript/strife/zombie.txt @@ -0,0 +1,64 @@ + +// Zombie ------------------------------------------------------------------- + +class Zombie : StrifeHumanoid +{ + Default + { + Health 31; + Radius 20; + Height 56; + PainChance 0; + +SOLID + +SHOOTABLE + +FLOORCLIP + +CANPASS + +CANPUSHWALLS + +ACTIVATEMCROSS + MinMissileChance 150; + MaxStepHeight 16; + MaxDropOffHeight 32; + Translation 0; + DeathSound "zombie/death"; + CrushPainSound "misc/pcrush"; + } + States + { + Spawn: + PEAS A 5 A_CheckTerrain; + Loop; + Pain: + AGRD A 5 A_CheckTerrain; + Loop; + Death: + GIBS M 5 A_TossGib; + GIBS N 5 A_XScream; + GIBS O 5 A_NoBlocking; + GIBS PQRST 4 A_TossGib; + GIBS U 5; + GIBS V -1; + Stop; + } +} + + +// Zombie Spawner ----------------------------------------------------------- + +class ZombieSpawner : Actor +{ + Default + { + Health 20; + +SHOOTABLE + +NOSECTOR + RenderStyle "None"; + ActiveSound "zombie/spawner"; // Does Strife use this somewhere else? + } + States + { + Spawn: + TNT1 A 175 A_SpawnItemEx("Zombie"); + Loop; + } +} +