From 6487681736ab205a6c99df5e91b2f59456914692 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 7 Oct 2016 17:49:00 +0200 Subject: [PATCH 001/471] - started porting constants.txt --- wadsrc/static/decorate.txt | 1 - wadsrc/static/{actors => zscript}/constants.txt | 0 2 files changed, 1 deletion(-) rename wadsrc/static/{actors => zscript}/constants.txt (100%) diff --git a/wadsrc/static/decorate.txt b/wadsrc/static/decorate.txt index c6a205d42a..a77a4d5831 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,4 +1,3 @@ -#include "actors/constants.txt" #include "actors/actor.txt" #include "actors/shared/inventory.txt" diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/zscript/constants.txt similarity index 100% rename from wadsrc/static/actors/constants.txt rename to wadsrc/static/zscript/constants.txt From 04d4bda2621eda7562f70df7906681b9f67f1421 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 7 Oct 2016 18:09:28 +0200 Subject: [PATCH 002/471] - converted all constants to enums and gave the enums names. --- wadsrc/static/zscript/constants.txt | 612 ++++++++++++++++------------ 1 file changed, 355 insertions(+), 257 deletions(-) diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index dce2488c25..da22b4180d 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,92 +1,119 @@ // 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, +}; // 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 +129,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 +166,137 @@ 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 = 1 << 3, +}; // 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 ECustomMissileFlags +{ + FPF_AIMATANGLE = 1, + FPF_TRANSFERTRANSLATION = 2, + FPF_NOAUTOAIM = 4, + FBF_PUFFTARGET = 64, + FBF_PUFFMASTER = 128, + FBF_PUFFTRACER = 256, +}; // 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 +316,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 +346,7 @@ enum }; // Activation flags -enum +enum EActivationFlags { THINGSPEC_Default = 0, THINGSPEC_ThingActs = 1, @@ -282,23 +357,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 +397,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 +543,7 @@ enum }; // Flags for A_Kill (Master/Target/Tracer/Children/Siblings) series -enum +enum EKillFlags { KILS_FOILINVUL = 0x00000001, KILS_KILLMISSILES = 0x00000002, @@ -461,7 +555,7 @@ enum }; // Flags for A_Damage (Master/Target/Tracer/Children/Siblings/Self) series -enum +enum EDamageFlags { DMSS_FOILINVUL = 0x00000001, DMSS_AFFECTARMOR = 0x00000002, @@ -476,12 +570,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 +590,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 +606,7 @@ enum }; // Flags for A_QuakeEx -enum +enum EQuakeFlags { QF_RELATIVE = 1, QF_SCALEDOWN = 1 << 1, @@ -520,7 +617,7 @@ enum }; // A_CheckProximity flags -enum +enum EProximityFlags { CPXF_ANCESTOR = 1, CPXF_LESSOREQUAL = 1 << 1, @@ -539,7 +636,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 +649,7 @@ enum CBF_ABSOLUTEANGLE = 1 << 8, //Absolute angle for offsets. }; -enum +enum EParticleFlags { SPF_FULLBRIGHT = 1, SPF_RELPOS = 1 << 1, @@ -565,7 +662,7 @@ enum }; //Flags for A_FaceMovementDirection -enum +enum EMovementFlags { FMDF_NOPITCH = 1 << 0, FMDF_INTERPOLATE = 1 << 1, @@ -573,7 +670,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 +681,7 @@ enum }; // Flags for A_WeaponOffset -enum +enum EWeaponOffsetFlags { WOF_KEEPX = 1, WOF_KEEPY = 1 << 1, @@ -592,7 +689,7 @@ enum }; // Flags for psprite layers -enum +enum EPSpriteFlags { PSPF_ADDWEAPON = 1 << 0, PSPF_ADDBOB = 1 << 1, @@ -601,13 +698,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, @@ -633,7 +730,7 @@ enum MODINPUT_UPMOVE }; -enum +enum EButtons { BT_ATTACK = 1<<0, // Press "Fire". BT_USE = 1<<1, // Use button, to open doors, activate switches. @@ -665,22 +762,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, @@ -691,7 +789,7 @@ enum VRF_NOPITCH = VRF_NOPITCHSTART|VRF_NOPITCHEND, }; -enum +enum ERenderStyles { STYLE_None, STYLE_Normal, From 994bb4fc7ab6f6c4f5b5567c63125bb711105f98 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 01:05:27 +0200 Subject: [PATCH 003/471] - started to make ZScript parser work on real-life data. It will now read a lump named ZSCRIPT which is a list of filenames to be compiled. - place generated symbols into GlobalSymbols instead of a scratch table that will be discarded right away. - allow the state object to change source file scanners (I hope this works, but the old implementation was unable to do more than one with with a parse state so I had to change it.) - It can now parse constants.txt and insert everything in it into the global symbol table and make subsequent DECORATE compile properly. --- src/thingdef/thingdef.cpp | 12 +---- src/zscript/zcc-parse.lemon | 20 ++++---- src/zscript/zcc_parser.cpp | 92 ++++++++++++++++++++++++------------- src/zscript/zcc_parser.h | 4 +- 4 files changed, 75 insertions(+), 53 deletions(-) diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 41e1e95422..abc136291f 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -445,6 +445,7 @@ static void FinishThingdef() // Called from FActor::StaticInit() // //========================================================================== +void ParseScripts(); void LoadActors () { @@ -456,19 +457,10 @@ void LoadActors () FScriptPosition::ResetErrorCounter(); InitThingdef(); lastlump = 0; + ParseScripts(); 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(); diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index ee8296ff66..cd2ed8efe3 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -96,9 +96,9 @@ 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()); } -%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. @@ -124,7 +124,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; } @@ -339,7 +339,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; } @@ -398,7 +398,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; } @@ -538,7 +538,7 @@ type_name(X) ::= DOT dottable_id(A). * straight away.) */ %token_class intconst INTCONST|UINTCONST. -vector_size(X) ::= . { X.Int = ZCC_Vector3; X.SourceLoc = stat->sc.GetMessageLine(); } +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) @@ -548,7 +548,7 @@ vector_size(X) ::= LT intconst(A) GT. else { X.Int = ZCC_Vector3; - stat->sc.ScriptMessage("Invalid vector size %d\n", A.Int); + stat->sc->ScriptMessage("Invalid vector size %d\n", A.Int); } X.SourceLoc = A.SourceLoc; } @@ -656,11 +656,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; } @@ -750,7 +750,7 @@ decl_flags(X) ::= decl_flags(A) ACTION(T). { X.Int = A.Int | ZCC_Action; X.Sour 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; } -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; } diff --git a/src/zscript/zcc_parser.cpp b/src/zscript/zcc_parser.cpp index 1f1fa45411..054954b54a 100644 --- a/src/zscript/zcc_parser.cpp +++ b/src/zscript/zcc_parser.cpp @@ -5,6 +5,7 @@ #include "w_wad.h" #include "cmdlib.h" #include "m_alloc.h" +#include "i_system.h" #include "zcc_parser.h" #include "zcc_compile.h" @@ -161,44 +162,26 @@ static void InitTokenMap() #undef TOKENDEF #undef TOKENDEF2 -static void DoParse(const char *filename) +static void ParseSingleFile(const char *filename, 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) { sc.OpenLumpNum(lump); } - 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); + state.sc = ≻ while (sc.GetToken()) { value.SourceLoc = sc.GetMessageLine(); @@ -241,7 +224,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,20 +237,55 @@ 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) +{ + if (TokenMap.CountUsed() == 0) + { + InitTokenMap(); + } + + FScanner sc; + void *parser; + ZCCToken value; + + parser = ZCCParseAlloc(malloc); + ZCCParseState state; +#ifdef _DEBUG + FILE *f = fopen("trace.txt", "w"); + char prompt = '\0'; + ZCCParseTrace(f, &prompt); +#endif + + sc.OpenLumpNum(lumpnum); + // parse all files from this list in one go. + while (sc.GetString()) + { + 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, 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); + ZCCCompiler cc(state, NULL, GlobalSymbols); cc.Compile(); #ifdef _DEBUG if (f != NULL) @@ -275,6 +293,7 @@ parse_end: fclose(f); } FString ast = ZCC_PrintAST(state.TopNode); + FString filename = Wads.GetLumpFullName(lumpnum); FString astfile = ExtractFileBase(filename, false); astfile << ".ast"; f = fopen(astfile, "w"); @@ -286,6 +305,16 @@ parse_end: #endif } +void ParseScripts() +{ + int lump, lastlump = 0; + while ((lump = Wads.FindLump("ZSCRIPT", &lastlump)) != -1) + { + DoParse(lump); + } +} + +/* CCMD(parse) { if (argv.argc() == 2) @@ -293,6 +322,7 @@ CCMD(parse) DoParse(argv[1]); } } +*/ static FString ZCCTokenName(int terminal) { @@ -333,6 +363,6 @@ 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); return node; } diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index e74b5263ec..507f80b9ed 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -514,10 +514,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 From fff428c71d5941a02d1032ff26a06f28979d54a3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 08:35:16 +0200 Subject: [PATCH 004/471] - added copyright headers to scripting files. --- src/zscript/ast.cpp | 33 +++++++++++++++++++++++++++++++++ src/zscript/vmbuilder.cpp | 33 +++++++++++++++++++++++++++++++++ src/zscript/vmdisasm.cpp | 33 +++++++++++++++++++++++++++++++++ src/zscript/vmexec.cpp | 33 +++++++++++++++++++++++++++++++++ src/zscript/vmframe.cpp | 33 +++++++++++++++++++++++++++++++++ src/zscript/zcc_compile.cpp | 33 +++++++++++++++++++++++++++++++++ src/zscript/zcc_expr.cpp | 33 +++++++++++++++++++++++++++++++++ src/zscript/zcc_parser.cpp | 33 +++++++++++++++++++++++++++++++++ 8 files changed, 264 insertions(+) diff --git a/src/zscript/ast.cpp b/src/zscript/ast.cpp index a68b1c69f3..efb4a020b3 100644 --- a/src/zscript/ast.cpp +++ b/src/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" diff --git a/src/zscript/vmbuilder.cpp b/src/zscript/vmbuilder.cpp index 8d7b5a8c12..fd9a0063ef 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/zscript/vmbuilder.cpp @@ -1,3 +1,36 @@ +/* +** 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" //========================================================================== diff --git a/src/zscript/vmdisasm.cpp b/src/zscript/vmdisasm.cpp index 4e6f33ec75..68b92f9f3d 100644 --- a/src/zscript/vmdisasm.cpp +++ b/src/zscript/vmdisasm.cpp @@ -1,3 +1,36 @@ +/* +** 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" diff --git a/src/zscript/vmexec.cpp b/src/zscript/vmexec.cpp index 454f02d03f..651090c6ba 100644 --- a/src/zscript/vmexec.cpp +++ b/src/zscript/vmexec.cpp @@ -1,3 +1,36 @@ +/* +** 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 "vm.h" #include "xs_Float.h" diff --git a/src/zscript/vmframe.cpp b/src/zscript/vmframe.cpp index 50c7d78d9e..e5e58aa477 100644 --- a/src/zscript/vmframe.cpp +++ b/src/zscript/vmframe.cpp @@ -1,3 +1,36 @@ +/* +** 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" diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index b7bfe81ba1..e6d2e6d961 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -1,3 +1,36 @@ +/* +** zcc_compile.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" diff --git a/src/zscript/zcc_expr.cpp b/src/zscript/zcc_expr.cpp index e1a091b180..6f640d8f16 100644 --- a/src/zscript/zcc_expr.cpp +++ b/src/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" diff --git a/src/zscript/zcc_parser.cpp b/src/zscript/zcc_parser.cpp index 054954b54a..ed41253e19 100644 --- a/src/zscript/zcc_parser.cpp +++ b/src/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" From b71e8d09edd031f8b8a42c985f1610ae539abef2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 11:54:33 +0200 Subject: [PATCH 005/471] - create class types from the AST. This is the first thing the compiler has to do to get access to the class's symbol table. Of course at this point the final size of a class is not known yet so these are currently all treated as tentative. --- src/zscript/zcc-parse.lemon | 5 +- src/zscript/zcc_compile.cpp | 118 ++++++++++++++++++++++++++++++++++++ src/zscript/zcc_compile.h | 1 + src/zscript/zcc_parser.cpp | 27 ++++++++- src/zscript/zcc_parser.h | 4 +- 5 files changed, 149 insertions(+), 6 deletions(-) diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index cd2ed8efe3..6d22f9ea40 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -175,6 +175,7 @@ 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; X = head; } @@ -184,8 +185,8 @@ 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) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; } /*----- Dottable Identifier -----*/ diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index e6d2e6d961..68261635f5 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -181,10 +181,128 @@ void ZCCCompiler::MessageV(ZCC_TreeNode *node, const char *txtcolor, const char int ZCCCompiler::Compile() { + CreateClasses(); CompileConstants(Constants); return ErrorCount; } +//========================================================================== +// +// 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::CreateClasses() +{ + auto OrigClasses = std::move(Classes); + Classes.Clear(); + bool donesomething = true; + while (donesomething) + { + for (unsigned i=0;iParentName != nullptr && c->ParentName->SiblingNext == c->ParentName) parent = PClass::FindClass(c->ParentName->Id); + else if (c->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 = c->ParentName; + FString build; + + do + { + if (build.IsNotEmpty()) build += '.'; + build += FName(p->Id); + p = static_cast(p->SiblingNext); + } while (p != c->ParentName); + Error(c, "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->Flags & ZCC_Native) + { + // If this is a native class, its own type must also already exist. + auto me = PClass::FindClass(c->NodeName); + if (me == nullptr) + { + Error(c, "Unknown native class %s", FName(c->NodeName).GetChars()); + me = parent->FindClassTentative(c->NodeName); + } + else + { + DPrintf(DMSG_SPAMMY, "Registered %s as native with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars()); + } + c->Type = me; + } + else + { + auto me = PClass::FindClass(c->NodeName); + if (me != nullptr) + { + Error(c, "Redefining class %s", FName(c->NodeName).GetChars()); + } + else + { + me = parent->FindClassTentative(c->NodeName); + DPrintf(DMSG_SPAMMY, "Created %s with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars()); + } + c->Type = me; + } + Classes.Push(c); + OrigClasses.Delete(i); + 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->ParentName->Id) + { + found = true; + break; + } + } + if (!found) + { + Error(c, "Class %s has unknown base class %s", FName(c->NodeName).GetChars(), FName(c->ParentName->Id).GetChars()); + // create a placeholder so that the compiler can continue looking for errors. + c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName); + 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, "Class %s has circular inheritance", FName(c->NodeName).GetChars()); + c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName); + Classes.Push(c); + } +} + //========================================================================== // // ZCCCompiler :: CompileConstants diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index d034464b77..24497acd9b 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -8,6 +8,7 @@ public: int Compile(); private: + void CreateClasses(); void CompileConstants(const TArray &defs); PSymbolConst *CompileConstant(ZCC_ConstantDef *def); diff --git a/src/zscript/zcc_parser.cpp b/src/zscript/zcc_parser.cpp index ed41253e19..3a34abe074 100644 --- a/src/zscript/zcc_parser.cpp +++ b/src/zscript/zcc_parser.cpp @@ -318,8 +318,8 @@ static void DoParse(int lumpnum) ZCCParse(parser, 0, value, &state); ZCCParseFree(parser, free); - ZCCCompiler cc(state, NULL, GlobalSymbols); - cc.Compile(); + { + // Make a dump of the AST before running the compiler for diagnostic purposes. #ifdef _DEBUG if (f != NULL) { @@ -328,7 +328,28 @@ static void DoParse(int lumpnum) FString ast = ZCC_PrintAST(state.TopNode); FString filename = Wads.GetLumpFullName(lumpnum); FString astfile = ExtractFileBase(filename, false); - astfile << ".ast"; + astfile << "-before.ast"; + f = fopen(astfile, "w"); + if (f != NULL) + { + fputs(ast.GetChars(), f); + fclose(f); + } +#endif + } + + ZCCCompiler cc(state, NULL, GlobalSymbols); + cc.Compile(); + // ... and another one afterward so we can see what the compiler does with the data. +#ifdef _DEBUG + if (f != NULL) + { + fclose(f); + } + FString ast = ZCC_PrintAST(state.TopNode); + FString filename = Wads.GetLumpFullName(lumpnum); + FString astfile = ExtractFileBase(filename, false); + astfile << "-after.ast"; f = fopen(astfile, "w"); if (f != NULL) { diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 507f80b9ed..8b82b7eaea 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -16,7 +16,7 @@ struct ZCCToken ENamedName Name() { return ENamedName(Int); } }; -// Variable / Function modifiers +// Variable / Function / Class modifiers enum { ZCC_Native = 1 << 0, @@ -30,6 +30,7 @@ enum ZCC_Deprecated = 1 << 8, ZCC_ReadOnly = 1 << 9, ZCC_FuncConst = 1 << 10, + ZCC_Abstract = 1 << 11, }; // Function parameter modifiers @@ -185,6 +186,7 @@ struct ZCC_Class : ZCC_NamedNode ZCC_Identifier *Replaces; VM_UWORD Flags; ZCC_TreeNode *Body; + PClass *Type; }; struct ZCC_Struct : ZCC_NamedNode From 82ac2081b68b7efc2af584b8ff65fd43dfecf0e0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 13:34:37 +0200 Subject: [PATCH 006/471] - create struct types. - fixed class creation. There was an infinite loop and some missing checks for native classes. - do not write the compiler's symbols to the same symbol table as the output. The output must go to GlobalSymbols but the internal symbols must go to a namespace specific table that can be discarded after compilation. --- src/dobjtype.cpp | 2 +- src/zscript/zcc-parse.lemon | 1 + src/zscript/zcc_compile.cpp | 52 +++++++++++++++++++++++-------------- src/zscript/zcc_compile.h | 6 +++-- src/zscript/zcc_parser.cpp | 3 ++- src/zscript/zcc_parser.h | 1 + 6 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 37ff26fe30..38c9f6fa2a 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3197,7 +3197,7 @@ void PClass::BuildFlatPointers () // // PClass :: NativeClass // -// Finds the underlying native type underlying this class. +// Finds the native type underlying this class. // //========================================================================== diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index 6d22f9ea40..9fdc4603c4 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -248,6 +248,7 @@ 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; X = def; } diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 68261635f5..9dfbab8470 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -51,8 +51,8 @@ // //========================================================================== -ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols) -: Outer(_outer), Symbols(&_symbols), AST(ast), ErrorCount(0), WarnCount(0) +ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PSymbolTable &_outsymbols) +: Outer(_outer), Symbols(&_symbols), OutputSymbols(&_outsymbols), AST(ast), ErrorCount(0), WarnCount(0) { // Group top-level nodes by type if (ast.TopNode != NULL) @@ -181,11 +181,28 @@ void ZCCCompiler::MessageV(ZCC_TreeNode *node, const char *txtcolor, const char int ZCCCompiler::Compile() { - CreateClasses(); + CreateClassTypes(); + CreateStructTypes(); CompileConstants(Constants); return ErrorCount; } +//========================================================================== +// +// ZCCCompiler :: CreateStructTypes +// +// Creates a PStruct for every struct. +// +//========================================================================== + +void ZCCCompiler::CreateStructTypes() +{ + for(auto s : Structs) + { + s->Type = NewStruct(s->NodeName, nullptr); + } +} + //========================================================================== // // ZCCCompiler :: CreateClassTypes @@ -197,20 +214,20 @@ int ZCCCompiler::Compile() // //========================================================================== -void ZCCCompiler::CreateClasses() +void ZCCCompiler::CreateClassTypes() { auto OrigClasses = std::move(Classes); Classes.Clear(); bool donesomething = true; while (donesomething) { - for (unsigned i=0;iParentName != nullptr && c->ParentName->SiblingNext == c->ParentName) parent = PClass::FindClass(c->ParentName->Id); else if (c->ParentName == nullptr) parent = RUNTIME_CLASS(DObject); else @@ -235,13 +252,17 @@ void ZCCCompiler::CreateClasses() // The parent exists, we may create a type for this class if (c->Flags & ZCC_Native) { - // If this is a native class, its own type must also already exist. + // 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, "Unknown native class %s", FName(c->NodeName).GetChars()); me = parent->FindClassTentative(c->NodeName); } + else if (me->bRuntimeClass) + { + Error(c, "%s is not a native class", FName(c->NodeName).GetChars()); + } else { DPrintf(DMSG_SPAMMY, "Registered %s as native with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars()); @@ -250,17 +271,8 @@ void ZCCCompiler::CreateClasses() } else { - auto me = PClass::FindClass(c->NodeName); - if (me != nullptr) - { - Error(c, "Redefining class %s", FName(c->NodeName).GetChars()); - } - else - { - me = parent->FindClassTentative(c->NodeName); - DPrintf(DMSG_SPAMMY, "Created %s with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars()); - } - c->Type = me; + // We will never get here if the name is a duplicate, so we can just do the assignment. + c->Type = parent->FindClassTentative(c->NodeName); } Classes.Push(c); OrigClasses.Delete(i); @@ -371,7 +383,7 @@ PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def) sym = new PSymbolConstNumeric(def->NodeName, TypeError, 0); } def->Symbol = sym; - Symbols->ReplaceSymbol(sym); + OutputSymbols->ReplaceSymbol(sym); return sym; } diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index 24497acd9b..6ef4a34f28 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -4,11 +4,12 @@ class ZCCCompiler { public: - ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols); + ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PSymbolTable &outsymbols); int Compile(); private: - void CreateClasses(); + void CreateStructTypes(); + void CreateClassTypes(); void CompileConstants(const TArray &defs); PSymbolConst *CompileConstant(ZCC_ConstantDef *def); @@ -47,6 +48,7 @@ private: DObject *Outer; PSymbolTable *Symbols; + PSymbolTable *OutputSymbols; ZCC_AST &AST; int ErrorCount; int WarnCount; diff --git a/src/zscript/zcc_parser.cpp b/src/zscript/zcc_parser.cpp index 3a34abe074..4f226f3f9c 100644 --- a/src/zscript/zcc_parser.cpp +++ b/src/zscript/zcc_parser.cpp @@ -338,7 +338,8 @@ static void DoParse(int lumpnum) #endif } - ZCCCompiler cc(state, NULL, GlobalSymbols); + PSymbolTable symtable(&GlobalSymbols); + ZCCCompiler cc(state, NULL, symtable, GlobalSymbols); cc.Compile(); // ... and another one afterward so we can see what the compiler does with the data. #ifdef _DEBUG diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 8b82b7eaea..31ad22c5ee 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -192,6 +192,7 @@ struct ZCC_Class : ZCC_NamedNode struct ZCC_Struct : ZCC_NamedNode { ZCC_TreeNode *Body; + PStruct *Type; }; struct ZCC_Enum : ZCC_NamedNode From d139ee9f682b76b7b134360f1c94fcaba9433cc3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 15:27:20 +0200 Subject: [PATCH 007/471] - give the 'default' block its own node type in the AST. - group a class's body the same way as the global AST. Only partially implemented so far so that constants can be processed. --- src/dobjtype.h | 25 +++++++-------- src/zscript/ast.cpp | 12 +++++++- src/zscript/zcc-parse.lemon | 2 +- src/zscript/zcc_compile.cpp | 61 ++++++++++++++++++++++++++++++++----- src/zscript/zcc_compile.h | 57 ++++++++++++++++++++++++++++++++-- src/zscript/zcc_parser.h | 5 +++ 6 files changed, 138 insertions(+), 24 deletions(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index 338c51f982..d2a8aabf5e 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -86,18 +86,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 @@ -141,6 +129,19 @@ private: friend class DObject; }; +// A symbol for a compiler tree node ---------------------------------------- + +class PSymbolTreeNode : public PSymbol +{ + DECLARE_CLASS(PSymbolTreeNode, PSymbol); +public: + struct ZCC_NamedNode *Node; + PSymbolTable Symbols; + + PSymbolTreeNode(FName name, struct ZCC_NamedNode *node) : PSymbol(name), Node(node) {} + PSymbolTreeNode() : PSymbol(NAME_None) {} +}; + extern PSymbolTable GlobalSymbols; // Basic information shared by all types ------------------------------------ diff --git a/src/zscript/ast.cpp b/src/zscript/ast.cpp index efb4a020b3..a0a823b130 100644 --- a/src/zscript/ast.cpp +++ b/src/zscript/ast.cpp @@ -629,6 +629,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(); @@ -853,7 +862,8 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintConstantDef, PrintDeclarator, PrintVarDeclarator, - PrintFuncDeclarator + PrintFuncDeclarator, + PrintDefault }; FString ZCC_PrintAST(ZCC_TreeNode *root) diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index 9fdc4603c4..09faf9272a 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -491,7 +491,7 @@ state_call_params(X) ::= LPAREN func_expr_list(A) RPAREN. { X = A; /*X-overwrite /* Definition of a default class instance. */ %type default_def {ZCC_CompoundStmt *} -default_def(X) ::= DEFAULT compound_statement(A). { X = A; /*X-overwrites-A*/ } +default_def(X) ::= DEFAULT compound_statement(A). { X = A; /*X-overwrites-A*/ X->NodeType = AST_Default; } /* Type names */ %type type_name {ZCC_BasicType *} diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 9dfbab8470..d8af55394d 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -45,6 +45,50 @@ #define DEFINING_CONST ((PSymbolConst *)(void *)1) +//========================================================================== +// +// ZCCCompiler :: ProcessClass +// +//========================================================================== + +void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *tnode) +{ + Classes.Push(ZCC_ClassWork(static_cast(cnode), tnode)); + ZCC_ClassWork &cls = Classes.Last(); + + auto node = cnode->Body; + + do + { + switch (node->NodeType) + { + case AST_Struct: + case AST_ConstantDef: + if ((tnode = AddNamedNode(static_cast(node)))) + { + switch (node->NodeType) + { + case AST_Struct: cls.Structs.Push(ZCC_StructWork(static_cast(node), tnode)); break; + case AST_ConstantDef: cls.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; + + // todo + case AST_States: + case AST_VarDeclarator: + case AST_FuncDeclarator: + break; + } + node = node->SiblingNext; + } + while (node != cnode->Body); +} + //========================================================================== // // ZCCCompiler Constructor @@ -58,6 +102,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, if (ast.TopNode != NULL) { ZCC_TreeNode *node = ast.TopNode; + PSymbolTreeNode *tnode; do { switch (node->NodeType) @@ -65,12 +110,12 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, case AST_Class: case AST_Struct: case AST_ConstantDef: - if (AddNamedNode(static_cast(node))) + if ((tnode = 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_Class: ProcessClass(static_cast(node), tnode); break; + case AST_Struct: Structs.Push(ZCC_StructWork(static_cast(node), tnode)); 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"); } @@ -99,7 +144,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, // //========================================================================== -bool ZCCCompiler::AddNamedNode(ZCC_NamedNode *node) +PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *parentsym) { FName name = node->NodeName; PSymbol *check = Symbols->FindSymbol(name, false); @@ -108,12 +153,14 @@ bool ZCCCompiler::AddNamedNode(ZCC_NamedNode *node) 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; + return nullptr; } else { - Symbols->AddSymbol(new PSymbolTreeNode(name, node)); - return true; + auto sy = new PSymbolTreeNode(name, node); + sy->Symbols.SetParentTable(parentsym); + Symbols->AddSymbol(sy); + return sy; } } diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index 6ef4a34f28..8b21f2617e 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -1,6 +1,56 @@ #ifndef ZCC_COMPILE_H #define ZCC_COMPILE_H +struct ZCC_StructWork +{ + ZCC_Struct *strct; + PSymbolTreeNode *node; + TArray Constants; + + ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n) + { + strct = s; + node = n; + }; + + ZCC_Struct *operator->() + { + return strct; + } + + operator ZCC_Struct *() + { + return strct; + } + + +}; + +struct ZCC_ClassWork +{ + ZCC_Class *cls; + PSymbolTreeNode *node; + TArray Constants; + TArray Structs; + + ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n) + { + cls = s; + node = n; + }; + + ZCC_Class *operator->() + { + return cls; + } + + operator ZCC_Class *() + { + return cls; + } + +}; + class ZCCCompiler { public: @@ -8,16 +58,17 @@ public: int Compile(); private: + void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); void CreateStructTypes(); void CreateClassTypes(); void CompileConstants(const TArray &defs); PSymbolConst *CompileConstant(ZCC_ConstantDef *def); TArray Constants; - TArray Structs; - TArray Classes; + TArray Structs; + TArray Classes; - bool AddNamedNode(ZCC_NamedNode *node); + PSymbolTreeNode *AddNamedNode(ZCC_NamedNode *node, PSymbolTable *parentsym = nullptr); ZCC_Expression *Simplify(ZCC_Expression *root); ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary); diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 31ad22c5ee..8de0c39522 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -93,6 +93,7 @@ enum EZCCTreeNodeType AST_Declarator, AST_VarDeclarator, AST_FuncDeclarator, + AST_Default, NUM_AST_NODE_TYPES }; @@ -463,6 +464,10 @@ struct ZCC_FuncDeclarator : ZCC_Declarator ZCC_Statement *Body; }; +struct ZCC_Default : ZCC_CompoundStmt +{ +}; + typedef ZCC_ExprConstant *(*EvalConst1op)(ZCC_ExprConstant *); typedef ZCC_ExprConstant *(*EvalConst2op)(ZCC_ExprConstant *, ZCC_ExprConstant *, FSharedStringArena &); From 5bb6bb31cacc2406c9fb701eb82f8c7ebae03a2e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 15:39:54 +0200 Subject: [PATCH 008/471] - added ProcessStruct, analogous to ProcessClass. Now everything should be in place to resolve all constants - inside and outside classes or structs. --- src/zscript/zcc_compile.cpp | 49 +++++++++++++++++++++++++++++++++++-- src/zscript/zcc_compile.h | 1 + 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index d8af55394d..b282c29f3f 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -82,13 +82,58 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *tnode) case AST_States: case AST_VarDeclarator: case AST_FuncDeclarator: + case AST_Default: break; + + default: + assert(0 && "Unhandled AST node type"); + break; } node = node->SiblingNext; } while (node != cnode->Body); } +//========================================================================== +// +// ZCCCompiler :: ProcessClass +// +//========================================================================== + +void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *tnode) +{ + Structs.Push(ZCC_StructWork(static_cast(cnode), tnode)); + ZCC_StructWork &cls = Structs.Last(); + + auto node = cnode->Body; + + do + { + switch (node->NodeType) + { + case AST_ConstantDef: + if ((tnode = AddNamedNode(static_cast(node)))) + { + cls.Constants.Push(static_cast(node)); break; + } + break; + + case AST_Enum: break; + case AST_EnumTerminator:break; + + // todo + case AST_VarDeclarator: + break; + + default: + assert(0 && "Unhandled AST node type"); + break; + } + node = node->SiblingNext; + } + while (node != cnode->Body); +} + //========================================================================== // // ZCCCompiler Constructor @@ -114,8 +159,8 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, { switch (node->NodeType) { - case AST_Class: ProcessClass(static_cast(node), tnode); break; - case AST_Struct: Structs.Push(ZCC_StructWork(static_cast(node), tnode)); break; + case AST_Class: ProcessClass(static_cast(node), tnode); break; + case AST_Struct: ProcessStruct(static_cast(node), tnode); 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"); } diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index 8b21f2617e..f92d8ad2dc 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -59,6 +59,7 @@ public: private: void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); + void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode); void CreateStructTypes(); void CreateClassTypes(); void CompileConstants(const TArray &defs); From 08f313d0118151f9641d37867020187c9bb33d65 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 22:16:10 +0200 Subject: [PATCH 009/471] - implemented complete resolving of constants - both global and class-local. This uses a different algorithm as the old implementation - instead of recursively resolving unknown symbols it will first collect all constants from all scopes and then process them in one operation, doing multiple passes over the list until no more constants can be resolved anymore. --- src/dobjtype.cpp | 11 + src/dobjtype.h | 15 ++ src/info.cpp | 1 - src/zscript/zcc-parse.lemon | 2 + src/zscript/zcc_compile.cpp | 324 +++++++++++++++++----------- src/zscript/zcc_compile.h | 27 ++- src/zscript/zcc_parser.cpp | 3 +- src/zscript/zcc_parser.h | 2 + wadsrc/static/zscript/constants.txt | 3 +- 9 files changed, 252 insertions(+), 136 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 38c9f6fa2a..800416612c 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2647,6 +2647,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); + } + } + } //========================================================================== @@ -3131,6 +3141,7 @@ PClass *PClass::FindClassTentative(FName name, bool fatal) type->ParentClass = this; type->Size = TentativeClass; type->bRuntimeClass = true; + type->Symbols.SetParentTable(&Symbols); TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket); return type; } diff --git a/src/dobjtype.h b/src/dobjtype.h index d2a8aabf5e..1b230452b1 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -99,6 +99,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. @@ -108,6 +112,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. @@ -120,6 +125,15 @@ struct PSymbolTable // Frees all symbols from this table. void ReleaseSymbols(); + // add a name to help debugging. +#ifdef _DEBUG + FString name; + void SetName(const char *nm) { name = nm; } +#else + void SetName(const char *) {} +#endif + + private: typedef TMap MapType; @@ -702,6 +716,7 @@ protected: TArray SpecialInits; virtual void Derive(PClass *newclass); void InitializeSpecials(void *addr) const; + void SetSuper(); public: typedef PClassClass MetaClass; MetaClass *GetClass() const; diff --git a/src/info.cpp b/src/info.cpp index 79c8e4268e..ea6701facf 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -361,7 +361,6 @@ size_t PClassActor::PropagateMark() void PClassActor::InitializeNativeDefaults() { - Symbols.SetParentTable(&ParentClass->Symbols); assert(Defaults == NULL); Defaults = (BYTE *)M_Malloc(Size); if (ParentClass->Defaults != NULL) diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index 09faf9272a..7acc392128 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -176,6 +176,7 @@ class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C). head->Flags = C.Flags; head->Replaces = C.Replaces; head->Type = nullptr; + head->Symbol = nullptr; X = head; } @@ -249,6 +250,7 @@ struct_def(X) ::= STRUCT(T) IDENTIFIER(A) LBRACE opt_struct_body(B) RBRACE opt_s def->NodeName = A.Name(); def->Body = B; def->Type = nullptr; + def->Symbol = nullptr; X = def; } diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index b282c29f3f..59fcdf9149 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -3,6 +3,7 @@ ** **--------------------------------------------------------------------------- ** Copyright -2016 Randy Heit +** Copyright 2016 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -41,6 +42,7 @@ #include "zcc_parser.h" #include "zcc_compile.h" #include "v_text.h" +#include "p_lnspec.h" #include "gdtoa.h" #define DEFINING_CONST ((PSymbolConst *)(void *)1) @@ -155,7 +157,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, case AST_Class: case AST_Struct: case AST_ConstantDef: - if ((tnode = AddNamedNode(static_cast(node)))) + if ((tnode = AddNamedNode(static_cast(node), Symbols))) { switch (node->NodeType) { @@ -204,6 +206,9 @@ PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *pa { auto sy = new PSymbolTreeNode(name, node); sy->Symbols.SetParentTable(parentsym); + FString name; + name << "nodes - " << FName(node->NodeName); + sy->Symbols.SetName(name); Symbols->AddSymbol(sy); return sy; } @@ -275,7 +280,7 @@ int ZCCCompiler::Compile() { CreateClassTypes(); CreateStructTypes(); - CompileConstants(Constants); + CompileAllConstants(); return ErrorCount; } @@ -292,6 +297,9 @@ void ZCCCompiler::CreateStructTypes() for(auto s : Structs) { s->Type = NewStruct(s->NodeName, nullptr); + s->Symbol = new PSymbolType(s->NodeName, s->Type); + s->Type->Symbols.SetName(FName(s->NodeName)); + GlobalSymbols.AddSymbol(s->Symbol); } } @@ -366,6 +374,9 @@ void ZCCCompiler::CreateClassTypes() // We will never get here if the name is a duplicate, so we can just do the assignment. c->Type = parent->FindClassTentative(c->NodeName); } + c->Symbol = new PSymbolType(c->NodeName, c->Type); + GlobalSymbols.AddSymbol(c->Symbol); + c->Type->Symbols.SetName(FName(c->NodeName).GetChars()); Classes.Push(c); OrigClasses.Delete(i); i--; @@ -389,6 +400,9 @@ void ZCCCompiler::CreateClassTypes() Error(c, "Class %s has unknown base class %s", FName(c->NodeName).GetChars(), FName(c->ParentName->Id).GetChars()); // create a placeholder so that the compiler can continue looking for errors. c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName); + c->Symbol = new PSymbolType(c->NodeName, c->Type); + GlobalSymbols.AddSymbol(c->Symbol); + c->Type->Symbols.SetName(FName(c->NodeName).GetChars()); Classes.Push(c); OrigClasses.Delete(i); donesomething = true; @@ -403,28 +417,132 @@ void ZCCCompiler::CreateClassTypes() { Error(c, "Class %s has circular inheritance", FName(c->NodeName).GetChars()); c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName); + c->Symbol = new PSymbolType(c->NodeName, c->Type); + c->Type->Symbols.SetName(FName(c->NodeName).GetChars()); + GlobalSymbols.AddSymbol(c->Symbol); Classes.Push(c); } } //========================================================================== // -// ZCCCompiler :: CompileConstants +// ZCCCompiler :: AddConstants // -// Make symbols from every constant defined at this level. +// Helper for CompileAllConstants // //========================================================================== -void ZCCCompiler::CompileConstants(const TArray &defs) +void ZCCCompiler::AddConstants(TArray &dest, TArray &Constants, PSymbolTable *nt, PSymbolTable *ot) { - for (unsigned i = 0; i < defs.Size(); ++i) + for (auto c : Constants) { - ZCC_ConstantDef *def = defs[i]; - if (def->Symbol == NULL) + dest.Push({ c, nt, 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; + + AddConstants(constantwork, Constants, Symbols, OutputSymbols); + for (auto &c : Classes) + { + AddConstants(constantwork, c.Constants, &c.node->Symbols, &c->Type->Symbols); + for (auto &s : c.Structs) { - PSymbolConst *sym = CompileConstant(def); + AddConstants(constantwork, s.Constants, &s.node->Symbols, &s->Type->Symbols); } } + for (auto &s : Structs) + { + AddConstants(constantwork, s.Constants, &s.node->Symbols, &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))) + { + def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal); + } + else if (cval->Type->IsA(RUNTIME_CLASS(PFloat))) + { + 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); + } } //========================================================================== @@ -432,51 +550,19 @@ void ZCCCompiler::CompileConstants(const TArray &defs) // 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. +// in a constant), and create a symbol for it. // //========================================================================== -PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def) +bool ZCCCompiler::CompileConstant(ZCC_ConstantDef *def, PSymbolTable *sym) { - assert(def->Symbol == NULL); + assert(def->Symbol == nullptr); def->Symbol = DEFINING_CONST; // avoid recursion - ZCC_Expression *val = Simplify(def->Value); + ZCC_Expression *val = Simplify(def->Value, sym); 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; - OutputSymbols->ReplaceSymbol(sym); - return sym; + if (def->Symbol == DEFINING_CONST) def->Symbol = nullptr; + return (val->NodeType == AST_ExprConstant); } @@ -493,27 +579,27 @@ PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def) // //========================================================================== -ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root) +ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root, PSymbolTable *sym) { if (root->NodeType == AST_ExprUnary) { - return SimplifyUnary(static_cast(root)); + return SimplifyUnary(static_cast(root), sym); } else if (root->NodeType == AST_ExprBinary) { - return SimplifyBinary(static_cast(root)); + return SimplifyBinary(static_cast(root), sym); } else if (root->Operation == PEX_ID) { - return IdentifyIdentifier(static_cast(root)); + return IdentifyIdentifier(static_cast(root), sym); } else if (root->Operation == PEX_MemberAccess) { - return SimplifyMemberAccess(static_cast(root)); + return SimplifyMemberAccess(static_cast(root), sym); } else if (root->Operation == PEX_FuncCall) { - return SimplifyFunctionCall(static_cast(root)); + return SimplifyFunctionCall(static_cast(root), sym); } return root; } @@ -524,9 +610,13 @@ ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root) // //========================================================================== -ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary) +ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *sym) { - unary->Operand = Simplify(unary->Operand); + unary->Operand = Simplify(unary->Operand, sym); + if (unary->Operand->Type == nullptr) + { + return unary; + } ZCC_OpProto *op = PromoteUnary(unary->Operation, unary->Operand); if (op == NULL) { // Oh, poo! @@ -545,10 +635,15 @@ ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary) // //========================================================================== -ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary) +ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary, PSymbolTable *sym) { - binary->Left = Simplify(binary->Left); - binary->Right = Simplify(binary->Right); + binary->Left = Simplify(binary->Left, sym); + binary->Right = Simplify(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) { @@ -569,32 +664,41 @@ ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary) // //========================================================================== -ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop) +ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop, PSymbolTable *symt) { - dotop->Left = Simplify(dotop->Left); + PSymbolTable *symtable; + + dotop->Left = Simplify(dotop->Left, symt); 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 + if (sym != nullptr) { ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable); - if (expr == NULL) - { - Error(dotop, "Unhandled symbol type encountered"); - } - else + 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; } @@ -607,12 +711,12 @@ ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop) // //========================================================================== -ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop) +ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSymbolTable *sym) { ZCC_FuncParm *parm; int parmcount = 0; - callop->Function = Simplify(callop->Function); + callop->Function = Simplify(callop->Function, sym); parm = callop->Parameters; if (parm != NULL) { @@ -620,7 +724,7 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop) { parmcount++; assert(parm->NodeType == AST_FuncParm); - parm->Value = Simplify(parm->Value); + parm->Value = Simplify(parm->Value, sym); parm = static_cast(parm->SiblingNext); } while (parm != callop->Parameters); @@ -751,12 +855,14 @@ ZCC_Expression *ZCCCompiler::AddCastNode(PType *type, ZCC_Expression *expr) // //========================================================================== -ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode) +ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable *symt) { // Check the symbol table for the identifier. PSymbolTable *table; - PSymbol *sym = Symbols->FindSymbolInTable(idnode->Identifier, table); - if (sym != NULL) + 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) @@ -766,46 +872,26 @@ ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode) } else { + // 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; + } + symt->DumpSymbolTable(); + GlobalSymbols.DumpSymbolTable(); + Error(idnode, "Unknown identifier '%s'", FName(idnode->Identifier).GetChars()); + idnode->ToErrorNode(); } - // 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 @@ -814,18 +900,8 @@ PSymbol *ZCCCompiler::CompileNode(ZCC_NamedNode *node) 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; - } - } + assert(sym != nullptr); + if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) { return NodeFromSymbolConst(static_cast(sym), source); diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index f92d8ad2dc..fd6cdaee4e 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -51,6 +51,13 @@ struct ZCC_ClassWork }; +struct ZCC_ConstantWork +{ + ZCC_ConstantDef *node; + PSymbolTable *nodetable; + PSymbolTable *outputtable; +}; + class ZCCCompiler { public: @@ -62,8 +69,11 @@ private: void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode); void CreateStructTypes(); void CreateClassTypes(); - void CompileConstants(const TArray &defs); - PSymbolConst *CompileConstant(ZCC_ConstantDef *def); + void AddConstants(TArray &dest, TArray &Constants, PSymbolTable *nt, PSymbolTable *ot); + void CompileAllConstants(); + void AddConstant(ZCC_ConstantWork &constant); + int CompileConstants(const TArray &defs, PSymbolTable *Nodes, PSymbolTable *Output); + bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols); TArray Constants; TArray Structs; @@ -71,11 +81,11 @@ private: PSymbolTreeNode *AddNamedNode(ZCC_NamedNode *node, PSymbolTable *parentsym = nullptr); - 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_Expression *Simplify(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); @@ -87,11 +97,10 @@ private: 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 *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); - PSymbol *CompileNode(ZCC_NamedNode *node); void Warn(ZCC_TreeNode *node, const char *msg, ...); diff --git a/src/zscript/zcc_parser.cpp b/src/zscript/zcc_parser.cpp index 4f226f3f9c..ba08f91eff 100644 --- a/src/zscript/zcc_parser.cpp +++ b/src/zscript/zcc_parser.cpp @@ -338,7 +338,8 @@ static void DoParse(int lumpnum) #endif } - PSymbolTable symtable(&GlobalSymbols); + PSymbolTable symtable; + symtable.SetName("Global_Node"); ZCCCompiler cc(state, NULL, symtable, GlobalSymbols); cc.Compile(); // ... and another one afterward so we can see what the compiler does with the data. diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 8de0c39522..1da9f79cae 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -188,12 +188,14 @@ struct ZCC_Class : ZCC_NamedNode VM_UWORD Flags; ZCC_TreeNode *Body; PClass *Type; + PSymbolType *Symbol; }; struct ZCC_Struct : ZCC_NamedNode { ZCC_TreeNode *Body; PStruct *Type; + PSymbolType *Symbol; }; struct ZCC_Enum : ZCC_NamedNode diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index da22b4180d..fdd1bf9773 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,4 +1,4 @@ - +/* // Flags for A_PainAttack enum EPainAttackFlags { @@ -806,3 +806,4 @@ enum ERenderStyles STYLE_AddStencil, STYLE_AddShaded, }; +*/ \ No newline at end of file From efcd5a86833ff671e396c8ae0b84f9c3dd629188 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 22:18:51 +0200 Subject: [PATCH 010/471] - forgot to delete these lines. --- src/zscript/zcc_compile.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 59fcdf9149..2a244d5290 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -883,8 +883,6 @@ ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable val->IntVal = spec; return val; } - symt->DumpSymbolTable(); - GlobalSymbols.DumpSymbolTable(); Error(idnode, "Unknown identifier '%s'", FName(idnode->Identifier).GetChars()); idnode->ToErrorNode(); From 6bad4809c1a479a988e3eb72b403abd441a970e6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 8 Oct 2016 22:20:38 +0200 Subject: [PATCH 011/471] - uncommendted constants.txt after finishing work on the constants creation code. --- wadsrc/static/zscript/constants.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index fdd1bf9773..49ca667f7c 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,4 +1,3 @@ -/* // Flags for A_PainAttack enum EPainAttackFlags { @@ -806,4 +805,3 @@ enum ERenderStyles STYLE_AddStencil, STYLE_AddShaded, }; -*/ \ No newline at end of file From 49f18c0a1912894a8fa8ada64b4a7be923acadb5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 9 Oct 2016 09:09:17 +0200 Subject: [PATCH 012/471] - renamed the symbol tables holding the tree nodes so that the code becomes clearer to read. Necessary because the unclear naming caused: - fixed: The tree nodes for classes and struct members were stored in the global tree nodes table. - sort variable declarations into their own list for processing. --- src/dobjtype.h | 2 +- src/zscript/zcc_compile.cpp | 57 ++++++++++++++++------------- src/zscript/zcc_compile.h | 10 +++-- wadsrc/static/zscript/constants.txt | 2 +- 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index 1b230452b1..92316107f6 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -150,7 +150,7 @@ class PSymbolTreeNode : public PSymbol DECLARE_CLASS(PSymbolTreeNode, PSymbol); public: struct ZCC_NamedNode *Node; - PSymbolTable Symbols; + PSymbolTable TreeNodes; PSymbolTreeNode(FName name, struct ZCC_NamedNode *node) : PSymbol(name), Node(node) {} PSymbolTreeNode() : PSymbol(NAME_None) {} diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 2a244d5290..0ecd60dee7 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -53,12 +53,13 @@ // //========================================================================== -void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *tnode) +void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) { - Classes.Push(ZCC_ClassWork(static_cast(cnode), tnode)); + Classes.Push(ZCC_ClassWork(static_cast(cnode), treenode)); ZCC_ClassWork &cls = Classes.Last(); auto node = cnode->Body; + PSymbolTreeNode *childnode; do { @@ -66,12 +67,14 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *tnode) { case AST_Struct: case AST_ConstantDef: - if ((tnode = AddNamedNode(static_cast(node)))) + case AST_VarDeclarator: + if ((childnode = AddNamedNode(static_cast(node), &treenode->TreeNodes))) { switch (node->NodeType) { - case AST_Struct: cls.Structs.Push(ZCC_StructWork(static_cast(node), tnode)); break; + case AST_Struct: cls.Structs.Push(ZCC_StructWork(static_cast(node), childnode)); break; case AST_ConstantDef: cls.Constants.Push(static_cast(node)); break; + case AST_VarDeclarator: cls.Fields.Push(static_cast(node)); break; default: assert(0 && "Default case is just here to make GCC happy. It should never be reached"); } } @@ -82,7 +85,6 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *tnode) // todo case AST_States: - case AST_VarDeclarator: case AST_FuncDeclarator: case AST_Default: break; @@ -102,31 +104,34 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *tnode) // //========================================================================== -void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *tnode) +void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode) { - Structs.Push(ZCC_StructWork(static_cast(cnode), tnode)); + Structs.Push(ZCC_StructWork(static_cast(cnode), treenode)); ZCC_StructWork &cls = Structs.Last(); auto node = cnode->Body; + PSymbolTreeNode *childnode; do { switch (node->NodeType) { case AST_ConstantDef: - if ((tnode = AddNamedNode(static_cast(node)))) + case AST_VarDeclarator: + if ((childnode = AddNamedNode(static_cast(node), &treenode->TreeNodes))) { - cls.Constants.Push(static_cast(node)); break; + switch (node->NodeType) + { + case AST_ConstantDef: cls.Constants.Push(static_cast(node)); break; + case AST_VarDeclarator: cls.Fields.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; - // todo - case AST_VarDeclarator: - break; - default: assert(0 && "Unhandled AST node type"); break; @@ -143,7 +148,7 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *tnode) //========================================================================== ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PSymbolTable &_outsymbols) -: Outer(_outer), Symbols(&_symbols), OutputSymbols(&_outsymbols), AST(ast), ErrorCount(0), WarnCount(0) +: Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), ErrorCount(0), WarnCount(0) { // Group top-level nodes by type if (ast.TopNode != NULL) @@ -157,7 +162,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, case AST_Class: case AST_Struct: case AST_ConstantDef: - if ((tnode = AddNamedNode(static_cast(node), Symbols))) + if ((tnode = AddNamedNode(static_cast(node), GlobalTreeNodes))) { switch (node->NodeType) { @@ -191,10 +196,10 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, // //========================================================================== -PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *parentsym) +PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *treenodes) { FName name = node->NodeName; - PSymbol *check = Symbols->FindSymbol(name, false); + PSymbol *check = treenodes->FindSymbol(name, false); if (check != NULL) { assert(check->IsA(RUNTIME_CLASS(PSymbolTreeNode))); @@ -205,11 +210,10 @@ PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *pa else { auto sy = new PSymbolTreeNode(name, node); - sy->Symbols.SetParentTable(parentsym); FString name; name << "nodes - " << FName(node->NodeName); - sy->Symbols.SetName(name); - Symbols->AddSymbol(sy); + sy->TreeNodes.SetName(name); + treenodes->AddSymbol(sy); return sy; } } @@ -281,6 +285,7 @@ int ZCCCompiler::Compile() CreateClassTypes(); CreateStructTypes(); CompileAllConstants(); + //CompileAllFields(); return ErrorCount; } @@ -432,11 +437,11 @@ void ZCCCompiler::CreateClassTypes() // //========================================================================== -void ZCCCompiler::AddConstants(TArray &dest, TArray &Constants, PSymbolTable *nt, PSymbolTable *ot) +void ZCCCompiler::CopyConstants(TArray &dest, TArray &Constants, PSymbolTable *ot) { for (auto c : Constants) { - dest.Push({ c, nt, ot }); + dest.Push({ c, ot }); } } @@ -455,18 +460,18 @@ void ZCCCompiler::CompileAllConstants() // put all constants in one list to make resolving this easier. TArray constantwork; - AddConstants(constantwork, Constants, Symbols, OutputSymbols); + CopyConstants(constantwork, Constants, OutputSymbols); for (auto &c : Classes) { - AddConstants(constantwork, c.Constants, &c.node->Symbols, &c->Type->Symbols); + CopyConstants(constantwork, c.Constants, &c->Type->Symbols); for (auto &s : c.Structs) { - AddConstants(constantwork, s.Constants, &s.node->Symbols, &s->Type->Symbols); + CopyConstants(constantwork, s.Constants, &s->Type->Symbols); } } for (auto &s : Structs) { - AddConstants(constantwork, s.Constants, &s.node->Symbols, &s->Type->Symbols); + 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. diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index fd6cdaee4e..c21aabc2ab 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -6,6 +6,7 @@ struct ZCC_StructWork ZCC_Struct *strct; PSymbolTreeNode *node; TArray Constants; + TArray Fields; ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n) { @@ -32,6 +33,7 @@ struct ZCC_ClassWork PSymbolTreeNode *node; TArray Constants; TArray Structs; + TArray Fields; ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n) { @@ -54,7 +56,6 @@ struct ZCC_ClassWork struct ZCC_ConstantWork { ZCC_ConstantDef *node; - PSymbolTable *nodetable; PSymbolTable *outputtable; }; @@ -69,10 +70,11 @@ private: void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode); void CreateStructTypes(); void CreateClassTypes(); - void AddConstants(TArray &dest, TArray &Constants, PSymbolTable *nt, PSymbolTable *ot); + void CopyConstants(TArray &dest, TArray &Constants, PSymbolTable *ot); + void CompileAllFields(); void CompileAllConstants(); void AddConstant(ZCC_ConstantWork &constant); - int CompileConstants(const TArray &defs, PSymbolTable *Nodes, PSymbolTable *Output); + int CompileConstants(const TArray &defs, PSymbolTable *Output); bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols); TArray Constants; @@ -108,7 +110,7 @@ private: void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr); DObject *Outer; - PSymbolTable *Symbols; + PSymbolTable *GlobalTreeNodes; PSymbolTable *OutputSymbols; ZCC_AST &AST; int ErrorCount; diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 49ca667f7c..62ac81a76f 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -788,7 +788,7 @@ enum EMaskRotationFlags VRF_NOPITCH = VRF_NOPITCHSTART|VRF_NOPITCHEND, }; -enum ERenderStyles +enum ERenderStyle { STYLE_None, STYLE_Normal, From ad43f2bc7ea41211214dc25ccfd166b3deb9af68 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 9 Oct 2016 15:47:31 +0200 Subject: [PATCH 013/471] - parse the list of class/struct fields and add the PField entries to their type. - fixed a few issues with trying to access a class's Type before it got initialized. --- src/dobjtype.cpp | 17 + src/dobjtype.h | 18 +- src/namedef.h | 2 + src/zscript/ast.cpp | 2 +- src/zscript/zcc-parse.lemon | 1 + src/zscript/zcc_compile.cpp | 506 ++++++++++++++++++++++++++-- src/zscript/zcc_compile.h | 19 +- src/zscript/zcc_parser.h | 4 +- wadsrc/static/zscript/constants.txt | 9 +- 9 files changed, 528 insertions(+), 50 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 800416612c..78e57c2292 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -82,6 +82,8 @@ PName *TypeName; PSound *TypeSound; PColor *TypeColor; PStatePointer *TypeState; +PStruct *TypeVector2; +PStruct *TypeVector3; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -590,6 +592,19 @@ void PType::StaticInit() TypeTable.AddType(TypeColor = new PColor); TypeTable.AddType(TypeState = new PStatePointer); + TypeVector2 = new PStruct(NAME_Vector2, nullptr); + TypeVector2->AddField(NAME_X, TypeFloat64); + TypeVector2->AddField(NAME_Y, TypeFloat64); + TypeTable.AddType(TypeVector2); + + TypeVector3 = new PStruct(NAME_Vector3, nullptr); + TypeVector3->AddField(NAME_X, TypeFloat64); + TypeVector3->AddField(NAME_Y, TypeFloat64); + TypeVector3->AddField(NAME_Z, TypeFloat64); + TypeTable.AddType(TypeVector3); + + + GlobalSymbols.AddSymbol(new PSymbolType(NAME_sByte, TypeSInt8)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_Byte, TypeUInt8)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_Short, TypeSInt16)); @@ -606,6 +621,8 @@ 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)); } diff --git a/src/dobjtype.h b/src/dobjtype.h index 92316107f6..b776fa165d 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -14,11 +14,17 @@ 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. +}; // Symbol information ------------------------------------------------------- @@ -872,6 +878,8 @@ extern PString *TypeString; extern PName *TypeName; extern PSound *TypeSound; extern PColor *TypeColor; +extern PStruct *TypeVector2; +extern PStruct *TypeVector3; extern PStatePointer *TypeState; // A constant value --------------------------------------------------------- diff --git a/src/namedef.h b/src/namedef.h index 36953e385f..f07db2ce94 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -697,6 +697,8 @@ xx(Array) xx(Sound) xx(State) xx(Fixed) +xx(Vector2) +xx(Vector3) xx(Min) xx(Max) diff --git a/src/zscript/ast.cpp b/src/zscript/ast.cpp index a0a823b130..26601d6582 100644 --- a/src/zscript/ast.cpp +++ b/src/zscript/ast.cpp @@ -65,7 +65,7 @@ public: FLispString() { NestDepth = Column = 0; - WrapWidth = 72; + WrapWidth = 200; NeedSpace = false; ConsecOpens = 0; } diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index 7acc392128..564b33b74d 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -290,6 +290,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) diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 0ecd60dee7..10f84b1d38 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -60,28 +60,47 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) auto node = cnode->Body; PSymbolTreeNode *childnode; + ZCC_Enum *enumType = nullptr; - do + // 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_VarDeclarator: + case AST_Enum: if ((childnode = AddNamedNode(static_cast(node), &treenode->TreeNodes))) { switch (node->NodeType) { - case AST_Struct: cls.Structs.Push(ZCC_StructWork(static_cast(node), childnode)); break; - case AST_ConstantDef: cls.Constants.Push(static_cast(node)); break; - case AST_VarDeclarator: cls.Fields.Push(static_cast(node)); break; - default: assert(0 && "Default case is just here to make GCC happy. It should never be reached"); + 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_Enum: break; - case AST_EnumTerminator:break; + case AST_VarDeclarator: + cls.Fields.Push(static_cast(node)); + break; + + case AST_EnumTerminator: + enumType = nullptr; + break; // todo case AST_States: @@ -100,37 +119,53 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) //========================================================================== // -// ZCCCompiler :: ProcessClass +// ZCCCompiler :: ProcessStruct // //========================================================================== -void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode) +void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZCC_Class *outer) { - Structs.Push(ZCC_StructWork(static_cast(cnode), treenode)); + Structs.Push(ZCC_StructWork(static_cast(cnode), treenode, outer)); ZCC_StructWork &cls = Structs.Last(); auto node = cnode->Body; PSymbolTreeNode *childnode; + ZCC_Enum *enumType = nullptr; - do + // Need to check if the struct actually has a body. + if (node != nullptr) do { switch (node->NodeType) { case AST_ConstantDef: - case AST_VarDeclarator: + case AST_Enum: if ((childnode = AddNamedNode(static_cast(node), &treenode->TreeNodes))) { switch (node->NodeType) { - case AST_ConstantDef: cls.Constants.Push(static_cast(node)); break; - case AST_VarDeclarator: cls.Fields.Push(static_cast(node)); break; - default: assert(0 && "Default case is just here to make GCC happy. It should never be reached"); + 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_Enum: break; - case AST_EnumTerminator:break; + case AST_VarDeclarator: + cls.Fields.Push(static_cast(node)); + break; + + case AST_EnumTerminator: + enumType = nullptr; + break; default: assert(0 && "Unhandled AST node type"); @@ -148,13 +183,16 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode) //========================================================================== ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PSymbolTable &_outsymbols) -: Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), ErrorCount(0), WarnCount(0) + : Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), ErrorCount(0), WarnCount(0) { // 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) @@ -162,28 +200,46 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, case AST_Class: case AST_Struct: case AST_ConstantDef: + case AST_Enum: if ((tnode = AddNamedNode(static_cast(node), GlobalTreeNodes))) { switch (node->NodeType) { - case AST_Class: ProcessClass(static_cast(node), tnode); break; - case AST_Struct: ProcessStruct(static_cast(node), tnode); 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"); + 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_Enum: break; - case AST_EnumTerminator:break; + case AST_EnumTerminator: + zenumType = nullptr; + break; default: assert(0 && "Unhandled AST node type"); break; } node = node->SiblingNext; - } - while (node != ast.TopNode); + } while (node != ast.TopNode); } } @@ -285,7 +341,7 @@ int ZCCCompiler::Compile() CreateClassTypes(); CreateStructTypes(); CompileAllConstants(); - //CompileAllFields(); + CompileAllFields(); return ErrorCount; } @@ -301,10 +357,17 @@ void ZCCCompiler::CreateStructTypes() { for(auto s : Structs) { - s->Type = NewStruct(s->NodeName, nullptr); + s.Outer = s.OuterDef == nullptr? nullptr : s.OuterDef->Type; + s->Type = NewStruct(s->NodeName, s.Outer); s->Symbol = new PSymbolType(s->NodeName, s->Type); s->Type->Symbols.SetName(FName(s->NodeName)); GlobalSymbols.AddSymbol(s->Symbol); + + for (auto e : s.Enums) + { + auto etype = NewEnum(e->NodeName, s->Type); + s->Type->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + } } } @@ -427,6 +490,16 @@ void ZCCCompiler::CreateClassTypes() GlobalSymbols.AddSymbol(c->Symbol); Classes.Push(c); } + + // Last but not least: Now that all classes have been created, we can create the symbols for the internal enums + 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)); + } + } } //========================================================================== @@ -464,10 +537,6 @@ void ZCCCompiler::CompileAllConstants() for (auto &c : Classes) { CopyConstants(constantwork, c.Constants, &c->Type->Symbols); - for (auto &s : c.Structs) - { - CopyConstants(constantwork, s.Constants, &s->Type->Symbols); - } } for (auto &s : Structs) { @@ -529,10 +598,16 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) } 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 @@ -974,3 +1049,368 @@ ZCC_ExprTypeRef *ZCCCompiler::NodeFromSymbolType(PSymbolType *sym, ZCC_Expressio 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, "Trying to add fields to class '%s' with native children", c->Type->TypeName.GetChars()); + Classes.Delete(i); + 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, true)) + { + // Remove from the list if all fields got compiled. + Structs.Delete(i); + i--; + donesomething = true; + } + } + for (unsigned i = 0; i < Classes.Size(); i++) + { + if (Classes[i]->Type->Size == TentativeClass) + { + if (Classes[i]->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 + Classes[i]->Type->Size = Classes[i]->Type->ParentClass->Size; + } + } + if (CompileFields(Classes[i]->Type, Classes[i].Fields, nullptr, false)) + { + // Remove from the list if all fields got compiled. + Classes.Delete(i); + i--; + donesomething = true; + } + } + } + // report all entries + if (Structs.Size() > 0) + { + } + if (Classes.Size() > 0) + { + } +} + +//========================================================================== +// +// ZCCCompiler :: CompileFields +// +// builds the internal structure of a single class or struct +// +//========================================================================== + +bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, bool forstruct) +{ + Printf("Adding fields to %s, original size is %d\n", type->TypeName.GetChars(), type->Size); + while (Fields.Size() > 0) + { + auto field = Fields[0]; + + PType *fieldtype = DetermineType(type, field, field->Type, 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; + + if (field->Flags & notallowed) + { + Error(field, "Invalid qualifiers for %s (%s not allowed)", FName(field->Names->Name).GetChars(), FlagsToString(field->Flags & notallowed)); + field->Flags &= notallowed; + } + uint32_t varflags; + + // 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 + { + auto thisfieldtype = fieldtype; + if (name->ArraySize != nullptr) + { + thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, &type->Symbols); + } + + type->AddField(name->Name, thisfieldtype, varflags); + Printf("Added field %s, new size is %d\n", FName(name->Name).GetChars(), type->Size); + name = static_cast(name->SiblingNext); + } while (name != field->Names); + Fields.Delete(0); + + + + + } + if (Fields.Size() > 0) + { + Printf("%d fields unprocessed\n", Fields.Size()); + } + 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_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes) +{ + if (!allowarraytypes && ztype->ArraySize != nullptr) + { + Error(field, "%s: Array type not allowed", FName(field->Names->Name).GetChars()); + return TypeError; + } + switch (ztype->NodeType) + { + case AST_BasicType: + { + auto btype = static_cast(ztype); + switch (btype->Type) + { + case ZCC_SInt8: + return TypeSInt8; + + case ZCC_UInt8: + return TypeUInt8; + + case ZCC_SInt16: + return TypeSInt16; + + case ZCC_UInt16: + return TypeUInt16; + + case ZCC_SInt32: + case ZCC_IntAuto: // todo: for enums, autoselect appropriately sized int + return TypeSInt32; + + case ZCC_UInt32: + return TypeUInt32; + + case ZCC_Bool: + return TypeBool; + + // 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: + return TypeFloat64; + + case ZCC_String: + return TypeString; + + case ZCC_Name: + return TypeName; + + case ZCC_Vector2: + return TypeVector2; + + case ZCC_Vector3: + return TypeVector3; + + case ZCC_Vector4: + // This has almost no use, so we really shouldn't bother. + Error(field, "vector<4> not implemented for %s", FName(field->Names->Name).GetChars()); + return TypeError; + + case ZCC_UserType: + return ResolveUserType(btype, &outertype->Symbols); + break; + } + } + + case AST_MapType: + if (allowarraytypes) + { + Error(field, "%s: Map types not implemented yet", FName(field->Names->Name).GetChars()); + // Todo: Decide what we allow here and if it makes sense to allow more complex constructs. + auto mtype = static_cast(ztype); + return NewMap(DetermineType(outertype, field, mtype->KeyType, false), DetermineType(outertype, field, mtype->ValueType, false)); + } + break; + + case AST_DynArrayType: + if (allowarraytypes) + { + Error(field, "%s: Dynamic array types not implemented yet", FName(field->Names->Name).GetChars()); + auto atype = static_cast(ztype); + return NewDynArray(DetermineType(outertype, field, atype->ElementType, false)); + } + break; + + case AST_ClassType: + { + auto ctype = static_cast(ztype); + if (ctype->Restriction == nullptr) + { + return 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; + } + return NewClassPointer(static_cast(typesym->Type)); + } + } + } + return TypeError; +} + +//========================================================================== +// +// ZCCCompiler :: ResolveUserType +// +// resolves a user type and returns a matching PType +// +//========================================================================== + +PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) +{ + Printf("Resolving user type %s\n", FName(type->UserType->Id).GetChars()); + // 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 type = static_cast(sym)->Type; + if (type->IsKindOf(RUNTIME_CLASS(PEnum))) + { + return TypeSInt32; // hack this to an integer until we can resolve the enum mess. + } + return type; + } + 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); + ZCC_Expression *val; + do + { + val = Simplify(arraysize, sym); + 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; +} diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index c21aabc2ab..cf871cfaa1 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -4,14 +4,19 @@ struct ZCC_StructWork { ZCC_Struct *strct; + ZCC_Class *OuterDef; + PClass *Outer; PSymbolTreeNode *node; + TArray Enums; TArray Constants; TArray Fields; - ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n) + ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n, ZCC_Class *outer) { strct = s; node = n; + OuterDef = outer; + Outer = nullptr; }; ZCC_Struct *operator->() @@ -31,8 +36,8 @@ struct ZCC_ClassWork { ZCC_Class *cls; PSymbolTreeNode *node; + TArray Enums; TArray Constants; - TArray Structs; TArray Fields; ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n) @@ -67,16 +72,22 @@ public: private: void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); - void ProcessStruct(ZCC_Struct *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 CompileAllFields(); void CompileAllConstants(); void AddConstant(ZCC_ConstantWork &constant); int CompileConstants(const TArray &defs, PSymbolTable *Output); bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols); + void CompileAllFields(); + bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, bool forstruct); + FString FlagsToString(uint32_t flags); + PType *DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes); + PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym); + PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym); + TArray Constants; TArray Structs; TArray Classes; diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 1da9f79cae..8db0221eee 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -179,6 +179,7 @@ struct ZCC_Identifier : ZCC_TreeNode struct ZCC_NamedNode : ZCC_TreeNode { ENamedName NodeName; + PSymbolType *Symbol; }; struct ZCC_Class : ZCC_NamedNode @@ -188,14 +189,12 @@ struct ZCC_Class : ZCC_NamedNode VM_UWORD Flags; ZCC_TreeNode *Body; PClass *Type; - PSymbolType *Symbol; }; struct ZCC_Struct : ZCC_NamedNode { ZCC_TreeNode *Body; PStruct *Type; - PSymbolType *Symbol; }; struct ZCC_Enum : ZCC_NamedNode @@ -444,6 +443,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 diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 62ac81a76f..12604234dd 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -74,6 +74,9 @@ enum EFireBulletsFlags FBF_NOPITCH = 8, FBF_NOFLASH = 16, FBF_NORANDOMPUFFZ = 32, + FBF_PUFFTARGET = 64, + FBF_PUFFMASTER = 128, + FBF_PUFFTRACER = 256, }; // Flags for A_SpawnItemEx @@ -283,15 +286,11 @@ enum ECustomPunchFlags CPF_STEALARMOR = 32, }; -// Flags for A_CustomMissile -enum ECustomMissileFlags +enum EFireCustomMissileFlags { FPF_AIMATANGLE = 1, FPF_TRANSFERTRANSLATION = 2, FPF_NOAUTOAIM = 4, - FBF_PUFFTARGET = 64, - FBF_PUFFMASTER = 128, - FBF_PUFFTRACER = 256, }; // Flags for A_Teleport From 4ecd7dd13ab409045dc15ef270ae7ac8ebb711a0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 9 Oct 2016 22:01:23 +0200 Subject: [PATCH 014/471] - a bit of cleanup. --- src/zscript/zcc_compile.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 10f84b1d38..609236b49a 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -1123,12 +1123,14 @@ void ZCCCompiler::CompileAllFields() } } } - // report all entries - if (Structs.Size() > 0) + // 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()); } - if (Classes.Size() > 0) + for (auto s : Classes) { + Error(s.cls, "Unable to resolve all fields for class %s", FName(s->NodeName).GetChars()); } } @@ -1142,7 +1144,6 @@ void ZCCCompiler::CompileAllFields() bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, bool forstruct) { - Printf("Adding fields to %s, original size is %d\n", type->TypeName.GetChars(), type->Size); while (Fields.Size() > 0) { auto field = Fields[0]; @@ -1190,18 +1191,9 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel } type->AddField(name->Name, thisfieldtype, varflags); - Printf("Added field %s, new size is %d\n", FName(name->Name).GetChars(), type->Size); name = static_cast(name->SiblingNext); } while (name != field->Names); Fields.Delete(0); - - - - - } - if (Fields.Size() > 0) - { - Printf("%d fields unprocessed\n", Fields.Size()); } return Fields.Size() == 0; } @@ -1363,7 +1355,6 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZC PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) { - Printf("Resolving user type %s\n", FName(type->UserType->Id).GetChars()); // Check the symbol table for the identifier. PSymbolTable *table; PSymbol *sym = symt->FindSymbolInTable(type->UserType->Id, table); From e84d6a06d8c4ba8aa67a9b48fe4a2e8e9030d712 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 10 Oct 2016 01:18:47 +0200 Subject: [PATCH 015/471] - changed PClass:AddField so that it doesn't create defaults if none are present. The ZScript compiler will not create any defaults until after all fields have been added and this function created bad data if it was run on a class without defaults. - added checks for duplicate field names. - moved the tree node symbol tables out of PSymbolTreeNode to the worker data. That symbol is a bad location because it restricts the usefulness of the symbol class which is also needed for variables which use different AST structs. - fixed some memory management issues with the work classes for the compiler that became apparent after moving the symbol tables in there. In several places these were copied around, possibly losing data. --- src/dobjtype.cpp | 29 +++-- src/dobjtype.h | 5 +- src/zscript/zcc_compile.cpp | 208 ++++++++++++++++++++---------------- src/zscript/zcc_compile.h | 35 +++--- 4 files changed, 156 insertions(+), 121 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 78e57c2292..e27559902a 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1325,7 +1325,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)); @@ -1340,7 +1340,14 @@ void PString::SetDefaultValue(void *base, unsigned offset, TArrayInitializeSpecials(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); } } @@ -3113,15 +3120,15 @@ 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); + type->SetDefaultValue(Defaults, field->Offset, &SpecialInits); } return field; } diff --git a/src/dobjtype.h b/src/dobjtype.h index b776fa165d..0b4235a764 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -155,10 +155,9 @@ class PSymbolTreeNode : public PSymbol { DECLARE_CLASS(PSymbolTreeNode, PSymbol); public: - struct ZCC_NamedNode *Node; - PSymbolTable TreeNodes; + struct ZCC_TreeNode *Node; - PSymbolTreeNode(FName name, struct ZCC_NamedNode *node) : PSymbol(name), Node(node) {} + PSymbolTreeNode(FName name, struct ZCC_TreeNode *node) : PSymbol(name), Node(node) {} PSymbolTreeNode() : PSymbol(NAME_None) {} }; diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 609236b49a..7a8f7092dc 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -55,13 +55,18 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) { - Classes.Push(ZCC_ClassWork(static_cast(cnode), treenode)); - ZCC_ClassWork &cls = Classes.Last(); + Classes.Push(new ZCC_ClassWork(static_cast(cnode), treenode)); + auto cls = Classes.Last(); auto node = cnode->Body; PSymbolTreeNode *childnode; ZCC_Enum *enumType = nullptr; + FString name; + name << "nodes - " << FName(cnode->NodeName); + cls->TreeNodes.SetName(name); + + // Need to check if the class actually has a body. if (node != nullptr) do { @@ -70,22 +75,22 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) case AST_Struct: case AST_ConstantDef: case AST_Enum: - if ((childnode = AddNamedNode(static_cast(node), &treenode->TreeNodes))) + if ((childnode = AddTreeNode(static_cast(node)->NodeName, node, &cls->TreeNodes))) { switch (node->NodeType) { case AST_Enum: enumType = static_cast(node); - cls.Enums.Push(enumType); + cls->Enums.Push(enumType); break; case AST_Struct: - ProcessStruct(static_cast(node), childnode, cls.cls); + ProcessStruct(static_cast(node), childnode, cls->cls); break; case AST_ConstantDef: - cls.Constants.Push(static_cast(node)); - cls.Constants.Last()->Type = enumType; + cls->Constants.Push(static_cast(node)); + cls->Constants.Last()->Type = enumType; break; default: @@ -95,7 +100,7 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) break; case AST_VarDeclarator: - cls.Fields.Push(static_cast(node)); + cls->Fields.Push(static_cast(node)); break; case AST_EnumTerminator: @@ -125,8 +130,8 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZCC_Class *outer) { - Structs.Push(ZCC_StructWork(static_cast(cnode), treenode, outer)); - ZCC_StructWork &cls = Structs.Last(); + Structs.Push(new ZCC_StructWork(static_cast(cnode), treenode, outer)); + ZCC_StructWork *cls = Structs.Last(); auto node = cnode->Body; PSymbolTreeNode *childnode; @@ -139,18 +144,18 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC { case AST_ConstantDef: case AST_Enum: - if ((childnode = AddNamedNode(static_cast(node), &treenode->TreeNodes))) + if ((childnode = AddTreeNode(static_cast(node)->NodeName, node, &cls->TreeNodes))) { switch (node->NodeType) { case AST_Enum: enumType = static_cast(node); - cls.Enums.Push(enumType); + cls->Enums.Push(enumType); break; case AST_ConstantDef: - cls.Constants.Push(static_cast(node)); - cls.Constants.Last()->Type = enumType; + cls->Constants.Push(static_cast(node)); + cls->Constants.Last()->Type = enumType; break; default: @@ -160,7 +165,7 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC break; case AST_VarDeclarator: - cls.Fields.Push(static_cast(node)); + cls->Fields.Push(static_cast(node)); break; case AST_EnumTerminator: @@ -201,7 +206,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, case AST_Struct: case AST_ConstantDef: case AST_Enum: - if ((tnode = AddNamedNode(static_cast(node), GlobalTreeNodes))) + if ((tnode = AddTreeNode(static_cast(node)->NodeName, node, GlobalTreeNodes))) { switch (node->NodeType) { @@ -243,19 +248,32 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, } } +ZCCCompiler::~ZCCCompiler() +{ + for (auto s : Structs) + { + delete s; + } + for (auto c : Classes) + { + delete c; + } + Structs.Clear(); + Classes.Clear(); +} + //========================================================================== // -// ZCCCompiler :: AddNamedNode +// ZCCCompiler :: AddTreeNode // // Keeps track of definition nodes by their names. Ensures that all names // in this scope are unique. // //========================================================================== -PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *treenodes) +PSymbolTreeNode *ZCCCompiler::AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents) { - FName name = node->NodeName; - PSymbol *check = treenodes->FindSymbol(name, false); + PSymbol *check = treenodes->FindSymbol(name, searchparents); if (check != NULL) { assert(check->IsA(RUNTIME_CLASS(PSymbolTreeNode))); @@ -267,8 +285,6 @@ PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *tr { auto sy = new PSymbolTreeNode(name, node); FString name; - name << "nodes - " << FName(node->NodeName); - sy->TreeNodes.SetName(name); treenodes->AddSymbol(sy); return sy; } @@ -357,16 +373,16 @@ void ZCCCompiler::CreateStructTypes() { for(auto s : Structs) { - s.Outer = s.OuterDef == nullptr? nullptr : s.OuterDef->Type; - s->Type = NewStruct(s->NodeName, s.Outer); - s->Symbol = new PSymbolType(s->NodeName, s->Type); - s->Type->Symbols.SetName(FName(s->NodeName)); - GlobalSymbols.AddSymbol(s->Symbol); + 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()); + s->Type()->Symbols.SetName(FName(s->NodeName())); + GlobalSymbols.AddSymbol(s->strct->Symbol); - for (auto e : s.Enums) + for (auto e : s->Enums) { - auto etype = NewEnum(e->NodeName, s->Type); - s->Type->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + auto etype = NewEnum(e->NodeName, s->Type()); + s->Type()->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); } } } @@ -384,6 +400,8 @@ void ZCCCompiler::CreateStructTypes() 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; @@ -395,14 +413,15 @@ void ZCCCompiler::CreateClassTypes() auto c = OrigClasses[i]; // Check if we got the parent already defined. PClass *parent; + auto ParentName = c->cls->ParentName; - if (c->ParentName != nullptr && c->ParentName->SiblingNext == c->ParentName) parent = PClass::FindClass(c->ParentName->Id); - else if (c->ParentName == nullptr) parent = RUNTIME_CLASS(DObject); + 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 = c->ParentName; + auto p = ParentName; FString build; do @@ -410,44 +429,43 @@ void ZCCCompiler::CreateClassTypes() if (build.IsNotEmpty()) build += '.'; build += FName(p->Id); p = static_cast(p->SiblingNext); - } while (p != c->ParentName); - Error(c, "Qualified name '%s' for base class not supported in '%s'", build.GetChars(), FName(c->NodeName).GetChars()); + } 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->Flags & ZCC_Native) + 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); + auto me = PClass::FindClass(c->NodeName()); if (me == nullptr) { - Error(c, "Unknown native class %s", FName(c->NodeName).GetChars()); - me = parent->FindClassTentative(c->NodeName); + Error(c->cls, "Unknown native class %s", c->NodeName().GetChars()); + me = parent->FindClassTentative(c->NodeName()); } else if (me->bRuntimeClass) { - Error(c, "%s is not a native class", FName(c->NodeName).GetChars()); + 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->Type = me; + c->cls->Type = me; } else { // We will never get here if the name is a duplicate, so we can just do the assignment. - c->Type = parent->FindClassTentative(c->NodeName); + c->cls->Type = parent->FindClassTentative(c->NodeName()); } - c->Symbol = new PSymbolType(c->NodeName, c->Type); - GlobalSymbols.AddSymbol(c->Symbol); - c->Type->Symbols.SetName(FName(c->NodeName).GetChars()); + c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); + GlobalSymbols.AddSymbol(c->cls->Symbol); + c->Type()->Symbols.SetName(c->NodeName()); Classes.Push(c); - OrigClasses.Delete(i); - i--; + OrigClasses.Delete(i--); donesomething = true; } else @@ -457,7 +475,7 @@ void ZCCCompiler::CreateClassTypes() bool found = false; for (auto d : OrigClasses) { - if (d->NodeName == c->ParentName->Id) + if (d->NodeName() == c->cls->ParentName->Id) { found = true; break; @@ -465,14 +483,14 @@ void ZCCCompiler::CreateClassTypes() } if (!found) { - Error(c, "Class %s has unknown base class %s", FName(c->NodeName).GetChars(), FName(c->ParentName->Id).GetChars()); + 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->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName); - c->Symbol = new PSymbolType(c->NodeName, c->Type); - GlobalSymbols.AddSymbol(c->Symbol); - c->Type->Symbols.SetName(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); + c->Type()->Symbols.SetName(c->NodeName()); Classes.Push(c); - OrigClasses.Delete(i); + OrigClasses.Delete(i--); donesomething = true; } } @@ -483,21 +501,30 @@ void ZCCCompiler::CreateClassTypes() // This normally means a circular reference. for (auto c : OrigClasses) { - Error(c, "Class %s has circular inheritance", FName(c->NodeName).GetChars()); - c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName); - c->Symbol = new PSymbolType(c->NodeName, c->Type); - c->Type->Symbols.SetName(FName(c->NodeName).GetChars()); - GlobalSymbols.AddSymbol(c->Symbol); + 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()); + c->Type()->Symbols.SetName(FName(c->NodeName()).GetChars()); + 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 + // 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 for (auto cd : Classes) { - for (auto e : cd.Enums) + for (auto e : cd->Enums) { - auto etype = NewEnum(e->NodeName, cd->Type); - cd->Type->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + 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; + } } } } @@ -534,13 +561,13 @@ void ZCCCompiler::CompileAllConstants() TArray constantwork; CopyConstants(constantwork, Constants, OutputSymbols); - for (auto &c : Classes) + for (auto c : Classes) { - CopyConstants(constantwork, c.Constants, &c->Type->Symbols); + CopyConstants(constantwork, c->Constants, &c->Type()->Symbols); } - for (auto &s : Structs) + for (auto s : Structs) { - CopyConstants(constantwork, s.Constants, &s->Type->Symbols); + 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. @@ -1070,16 +1097,15 @@ void ZCCCompiler::CompileAllFields() { auto c = Classes[i]; - if (c->Type->Size != TentativeClass && c.Fields.Size() > 0) + 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) + if (ac->ParentClass == c->Type() && ac->Size != TentativeClass) { - Error(c, "Trying to add fields to class '%s' with native children", c->Type->TypeName.GetChars()); - Classes.Delete(i); - i--; + Error(c->cls, "Trying to add fields to class '%s' with native children", c->Type()->TypeName.GetChars()); + Classes.Delete(i--); break; } } @@ -1091,19 +1117,19 @@ void ZCCCompiler::CompileAllFields() donesomething = false; for (unsigned i = 0; i < Structs.Size(); i++) { - if (CompileFields(Structs[i]->Type, Structs[i].Fields, Structs[i].Outer, true)) + 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); - i--; + Structs.Delete(i--); donesomething = true; } } for (unsigned i = 0; i < Classes.Size(); i++) { - if (Classes[i]->Type->Size == TentativeClass) + auto type = Classes[i]->Type(); + if (type->Size == TentativeClass) { - if (Classes[i]->Type->ParentClass->Size == TentativeClass) + if (type->ParentClass->Size == TentativeClass) { // we do not know the parent class's size yet, so skip this class for now. continue; @@ -1111,14 +1137,13 @@ void ZCCCompiler::CompileAllFields() else { // Inherit the size of the parent class - Classes[i]->Type->Size = Classes[i]->Type->ParentClass->Size; + type->Size = Classes[i]->Type()->ParentClass->Size; } } - if (CompileFields(Classes[i]->Type, Classes[i].Fields, nullptr, false)) + if (CompileFields(type, Classes[i]->Fields, nullptr, &Classes[i]->TreeNodes, false)) { // Remove from the list if all fields got compiled. - Classes.Delete(i); - i--; + Classes.Delete(i--); donesomething = true; } } @@ -1126,11 +1151,11 @@ void ZCCCompiler::CompileAllFields() // 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()); + 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()); + Error(s->cls, "Unable to resolve all fields for class %s", FName(s->NodeName()).GetChars()); } } @@ -1142,7 +1167,7 @@ void ZCCCompiler::CompileAllFields() // //========================================================================== -bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, bool forstruct) +bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct) { while (Fields.Size() > 0) { @@ -1158,7 +1183,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel Error(field, "Invalid qualifiers for %s (%s not allowed)", FName(field->Names->Name).GetChars(), FlagsToString(field->Flags & notallowed)); field->Flags &= notallowed; } - uint32_t varflags; + uint32_t varflags = 0; // These map directly to implementation flags. if (field->Flags & ZCC_Private) varflags |= VARF_Private; @@ -1184,13 +1209,16 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel auto name = field->Names; do { - auto thisfieldtype = fieldtype; - if (name->ArraySize != nullptr) + if (AddTreeNode(name->Name, name, TreeNodes, !forstruct)) { - thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, &type->Symbols); - } + auto thisfieldtype = fieldtype; + if (name->ArraySize != nullptr) + { + thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, &type->Symbols); + } - type->AddField(name->Name, thisfieldtype, varflags); + type->AddField(name->Name, thisfieldtype, varflags); + } name = static_cast(name->SiblingNext); } while (name != field->Names); Fields.Delete(0); diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index cf871cfaa1..2fb83d7e60 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -3,6 +3,7 @@ struct ZCC_StructWork { + PSymbolTable TreeNodes; ZCC_Struct *strct; ZCC_Class *OuterDef; PClass *Outer; @@ -19,22 +20,22 @@ struct ZCC_StructWork Outer = nullptr; }; - ZCC_Struct *operator->() + FName NodeName() const { - return strct; + return strct->NodeName; } - operator ZCC_Struct *() + PStruct *Type() { - return strct; + return strct->Type; } - }; struct ZCC_ClassWork { ZCC_Class *cls; + PSymbolTable TreeNodes; PSymbolTreeNode *node; TArray Enums; TArray Constants; @@ -44,16 +45,16 @@ struct ZCC_ClassWork { cls = s; node = n; - }; - - ZCC_Class *operator->() - { - return cls; } - operator ZCC_Class *() + FName NodeName() const { - return cls; + return cls->NodeName; + } + + PClass *Type() + { + return cls->Type; } }; @@ -68,6 +69,7 @@ class ZCCCompiler { public: ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PSymbolTable &outsymbols); + ~ZCCCompiler(); int Compile(); private: @@ -78,21 +80,20 @@ private: void CopyConstants(TArray &dest, TArray &Constants, PSymbolTable *ot); void CompileAllConstants(); void AddConstant(ZCC_ConstantWork &constant); - int CompileConstants(const TArray &defs, PSymbolTable *Output); bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols); void CompileAllFields(); - bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, bool forstruct); + bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct); FString FlagsToString(uint32_t flags); PType *DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym); PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym); TArray Constants; - TArray Structs; - TArray Classes; + TArray Structs; + TArray Classes; - PSymbolTreeNode *AddNamedNode(ZCC_NamedNode *node, PSymbolTable *parentsym = nullptr); + PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false); ZCC_Expression *Simplify(ZCC_Expression *root, PSymbolTable *Symbols); ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *Symbols); From 2b9af0176ce6429bc8746c50ded8233fd11b74e2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 10 Oct 2016 16:53:24 +0200 Subject: [PATCH 016/471] - changed grammar for a class's default block to look and act like DECORATE, so that it can hook into the same property dispatcher. This had been defined as a regular compound statement but in the context this will be used in, that makes very little sense, because all it can do is set some constant values. The most important thing here is that it doesn't provide an unnecessary learning curve to its users and doing it this way will not only ensure that but also avoid redundant documentation. To allow initialization of other user-defined properties it will require some extensions but that's a job for later and can just as easily be done in the current framework, rather than throwing everything out and start from zero. --- src/zscript/ast.cpp | 24 ++++++++++++- src/zscript/zcc-parse.lemon | 68 +++++++++++++++++++++++++++++++++++-- src/zscript/zcc_parser.h | 15 ++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/src/zscript/ast.cpp b/src/zscript/ast.cpp index 26601d6582..f80498738e 100644 --- a/src/zscript/ast.cpp +++ b/src/zscript/ast.cpp @@ -814,6 +814,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, @@ -863,7 +883,9 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintDeclarator, PrintVarDeclarator, PrintFuncDeclarator, - PrintDefault + PrintDefault, + PrintFlagStmt, + PrintPropertyStmt }; FString ZCC_PrintAST(ZCC_TreeNode *root) diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index 564b33b74d..f54a4ba74f 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -493,8 +493,72 @@ 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*/ X->NodeType = AST_Default; } +%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) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } +default_statement(X) ::= property_statement(A) SEMICOLON. { 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). +{ + NEW_AST_NODE(PropertyStmt,stmt,A); + stmt->Prop = A; + stmt->Values = B; + X = stmt; +} + + /* Type names */ %type type_name {ZCC_BasicType *} diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 8db0221eee..7500185f80 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -94,6 +94,8 @@ enum EZCCTreeNodeType AST_VarDeclarator, AST_FuncDeclarator, AST_Default, + AST_FlagStmt, + AST_PropertyStmt, NUM_AST_NODE_TYPES }; @@ -470,6 +472,19 @@ 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 &); From 3b198876372976e3dbb00002a36dd65354909194 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 00:56:47 +0200 Subject: [PATCH 017/471] - implemented the Defaults property initializer. This uses the same property and flag tables as DECORATE with a few changes: * it sets the parse mode to strict, so that several DECORATE warnings are now errors. * trying to change a deprecated flag will print a warning. * setting of editor numbers, spawn and conversation ID id not possible. Use MAPINFO to do this. * all subclass flags must use the qualified name now (e.g. +ALWAYSPICKUP will print an error.) * the scriptable Damage property is not yet implemented. This will require a special case with a differently named property in the processing function because in the AST it is no longer possible to distinguish between a damage value and a constant damage function. --- src/dobjtype.cpp | 1 + src/g_shared/a_pickups.cpp | 2 +- src/sc_man.cpp | 3 +- src/sc_man.h | 1 + src/thingdef/thingdef.h | 5 +- src/thingdef/thingdef_data.cpp | 5 +- src/thingdef/thingdef_parse.cpp | 4 +- src/thingdef/thingdef_properties.cpp | 17 +- src/zscript/zcc-parse.lemon | 12 +- src/zscript/zcc_compile.cpp | 395 ++++++++++++++++++++++++++- src/zscript/zcc_compile.h | 18 +- 11 files changed, 438 insertions(+), 25 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index e27559902a..7709bfa8f0 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3163,6 +3163,7 @@ PClass *PClass::FindClassTentative(FName name, bool fatal) type->TypeName = name; type->ParentClass = this; + type->ConstructNative = ConstructNative; type->Size = TentativeClass; type->bRuntimeClass = true; type->Symbols.SetParentTable(&Symbols); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index e80e548183..00a6692b25 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1696,7 +1696,7 @@ PClassHealth::PClassHealth() //=========================================================================== // -// PClassHealth :: Derive +// PClassHealth :: DeriveData // //=========================================================================== diff --git a/src/sc_man.cpp b/src/sc_man.cpp index 3f5530ff36..97f384f3df 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -1006,6 +1006,7 @@ void FScanner::CheckOpen() // //========================================================================== int FScriptPosition::ErrorCounter; +bool FScriptPosition::StrictErrors; // makes all OPTERRPR messages real errors. FScriptPosition::FScriptPosition(const FScriptPosition &other) { @@ -1047,7 +1048,7 @@ void FScriptPosition::Message (int severity, const char *message, ...) const if ((severity == MSG_DEBUG || severity == MSG_DEBUGLOG) && developer < DMSG_NOTIFY) return; if (severity == MSG_OPTERROR) { - severity = strictdecorate ? MSG_ERROR : MSG_WARNING; + severity = StrictErrors || strictdecorate ? MSG_ERROR : MSG_WARNING; } if (message == NULL) diff --git a/src/sc_man.h b/src/sc_man.h index 359dd81405..c319a7a2f6 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -140,6 +140,7 @@ enum struct FScriptPosition { static int ErrorCounter; + static bool StrictErrors; FString FileName; int ScriptLine; diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 3a419b112a..426eddd41e 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -25,7 +25,7 @@ struct FFlagDef int fieldsize; }; -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); @@ -146,6 +146,7 @@ struct Baggage PClassActor *Info; bool DropItemSet; bool StateSet; + bool fromZScript; int CurrentState; int Lumpnum; FStateDefinitions statedef; @@ -272,7 +273,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 diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index efdd649216..bdb992fba9 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -436,14 +436,15 @@ 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 ? 1 : NUM_FLAG_LISTS; + for (i = 0; i < max; ++i) { if (type->IsDescendantOf (*FlagLists[i].Type)) { diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 963165ab13..5789038b7e 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -1063,7 +1063,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,7 +1073,7 @@ 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()); } } diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index d60cda823b..bcae82671f 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -514,10 +514,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) @@ -2484,7 +2485,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 +2552,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 +2585,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 +2603,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/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index f54a4ba74f..09fadedb49 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -528,7 +528,7 @@ default_statement_list(X) ::= default_statement_list(X) default_statement(B). default_statement(X) ::= SEMICOLON. { X = NULL; } //default_statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } -default_statement(X) ::= property_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 *} @@ -550,7 +550,7 @@ flag_statement(X) ::= SUB dottable_id(A). %type property_statement{ZCC_PropertyStmt *} -property_statement(X) ::= dottable_id(A) expr_list(B). +property_statement(X) ::= dottable_id(A) expr_list(B) SEMICOLON. { NEW_AST_NODE(PropertyStmt,stmt,A); stmt->Prop = A; @@ -558,6 +558,14 @@ property_statement(X) ::= dottable_id(A) expr_list(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 */ diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 7a8f7092dc..98448069ad 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -32,10 +32,12 @@ ** */ -#include "dobject.h" +#include "actor.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" @@ -110,8 +112,11 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) // todo case AST_States: case AST_FuncDeclarator: + break; + case AST_Default: - break; + cls->Defaults.Push(static_cast(node)); + break; default: assert(0 && "Unhandled AST node type"); @@ -358,6 +363,7 @@ int ZCCCompiler::Compile() CreateStructTypes(); CompileAllConstants(); CompileAllFields(); + InitDefaults(); return ErrorCount; } @@ -1433,3 +1439,388 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, } 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 0; + } + 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 0; + } +} + +//========================================================================== +// +// 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); // 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) + { + Error(exp, "%s: non-constant parameter", prop->name); + } + conv.s = nullptr; + pref.s = nullptr; + pref.i = -1; + switch ((*p) & 223) + { + + case 'I': + 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. + 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 numerical value. + if (!GetString(exp, true)) + { + // apply this expression to the next argument on the list. + params.Push(conv); + params[0].i++; + p++; + continue; + } + // fall through + + case 'C': // this parser accepts colors only in string form. + pref.i = 1; + case 'S': + conv.s = GetString(exp); + break; + + case 'T': // a filtered string + conv.s = strings[strings.Reserve(1)] = strbin1(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); + } 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); + endofparm: + p++; + // Skip the DECORATE 'no comma' marker + if (*p == '_') p++; + + else if (*p == 0) + { + if (exp != property->Values) + { + Error(property, "Too many values for '%s'", prop->name); + } + break; + } + else if (exp == property->Values) + { + if (*p < 'a') + { + Error(property, "Insufficient parameters for %s", prop->name); + } + 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) + { + // 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->structoffset == -1) + { + Warn(flg, "Deprecated flag '%s%s%s' used", n1, n2 ? "." : "", n2 ? n2 : ""); + 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()); + } + 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()); + ti->InitializeNativeDefaults(); + ti->ParentClass->DeriveData(ti); + + + Baggage bag; + #ifdef _DEBUG + bag.ClassName = c->Type()->TypeName; + #endif + bag.Info = ti; + bag.DropItemSet = false; + bag.StateSet = false; + bag.fromZScript = true; + bag.CurrentState = 0; + bag.Lumpnum = Wads.CheckNumForFullName(*c->cls->SourceName, true); + bag.DropItemList = nullptr; + bag.ScriptPosition.StrictErrors = true; + // The actual script position needs to be set per property. + + for (auto d : c->Defaults) + { + auto content = d->Content; + 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); + } + } + } + } +} + diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index 2fb83d7e60..9edd65b1d8 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -1,6 +1,10 @@ #ifndef ZCC_COMPILE_H #define ZCC_COMPILE_H +struct Baggage; +struct FPropertyInfo; +class AActor; + struct ZCC_StructWork { PSymbolTable TreeNodes; @@ -40,6 +44,7 @@ struct ZCC_ClassWork TArray Enums; TArray Constants; TArray Fields; + TArray Defaults; ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n) { @@ -89,6 +94,14 @@ private: 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); + TArray Constants; TArray Structs; TArray Classes; @@ -103,11 +116,6 @@ private: 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); From 6989b8168859a67dfb449ea51767cda727292940 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 13:11:40 +0200 Subject: [PATCH 018/471] - extended the grammar so that the DECORATE function declaration list can almost be used as-is, with the sole exception of requiring any action function to declare a return type, even if it is void. This adds: * builtin types color, state and sound. * ending a parameter list with an ellipsis to declare a varargs list. (A_Jump uses this.) * allowing to declare optional arguments by giving them a default value. * adding an 'action' qualifier for function declarations. --- src/zscript/ast.cpp | 8 +++++++- src/zscript/zcc-parse.lemon | 26 ++++++++++++++++++++++++++ src/zscript/zcc_parser.cpp | 5 +++++ src/zscript/zcc_parser.h | 6 ++++++ wadsrc/static/zscript/constants.txt | 15 +++++++++++++++ 5 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/zscript/ast.cpp b/src/zscript/ast.cpp index f80498738e..1f416f7ade 100644 --- a/src/zscript/ast.cpp +++ b/src/zscript/ast.cpp @@ -54,7 +54,12 @@ static const char *BuiltInTypeNames[] = "vector3", "vector4", "name", - "usertype" + "color", + "state", + "sound", + + "usertype", + }; class FLispString @@ -767,6 +772,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(); } diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index 09fadedb49..1861463f90 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -188,6 +188,7 @@ class_ancestry(X) ::= COLON dottable_id(A). { X = A; /*X-overwrites-A*/ } class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; } 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 -----*/ @@ -585,6 +586,9 @@ 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) ::= 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). { @@ -841,6 +845,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); } @@ -850,6 +865,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; } diff --git a/src/zscript/zcc_parser.cpp b/src/zscript/zcc_parser.cpp index ba08f91eff..ce2dc98e74 100644 --- a/src/zscript/zcc_parser.cpp +++ b/src/zscript/zcc_parser.cpp @@ -88,6 +88,7 @@ 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); @@ -112,6 +113,7 @@ 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); @@ -172,6 +174,9 @@ static void InitTokenMap() TOKENDEF (TK_Loop, ZCC_LOOP); TOKENDEF (TK_Goto, ZCC_GOTO); TOKENDEF (TK_States, ZCC_STATES); + TOKENDEF (TK_State, ZCC_STATE); + TOKENDEF (TK_Color, ZCC_COLOR); + TOKENDEF (TK_Sound, ZCC_SOUND); TOKENDEF (TK_Identifier, ZCC_IDENTIFIER); TOKENDEF (TK_StringConst, ZCC_STRCONST); diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 7500185f80..5d5c85827a 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -119,6 +119,11 @@ enum EZCCBuiltinType ZCC_Vector3, ZCC_Vector4, ZCC_Name, + + ZCC_Color, // special types for ZDoom. + ZCC_State, + ZCC_Sound, + ZCC_UserType, ZCC_NUM_BUILT_IN_TYPES @@ -437,6 +442,7 @@ struct ZCC_LocalVarStmt : ZCC_Statement struct ZCC_FuncParamDecl : ZCC_TreeNode { ZCC_Type *Type; + ZCC_Expression *Default; ENamedName Name; int Flags; }; diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 12604234dd..aa72ee8ec1 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -804,3 +804,18 @@ enum ERenderStyle 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; +} From d8c689d874a209728beddff319db6e9b4974ec92 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 18:53:10 +0200 Subject: [PATCH 019/471] - initialize function symbols. At the moment all it does is process the existing native functions. Any further processing will be done once the base classes of the engine can be parsed from the scripting files. - switched the types of the internal 'self' and 'stateowner' parameters so that they get assigned correctly. I can't tell if this will error out if fields get accessed from the caller with the wrong class, but for actual scripting to work these must be correct. The committed 'actor.txt' can be parsed successfully, with the exception of a few subclass references that cannot be resolved yet. --- src/dobjtype.h | 5 + src/namedef.h | 5 + src/thingdef/thingdef.h | 2 +- src/thingdef/thingdef_parse.cpp | 12 +- src/zscript/zcc_compile.cpp | 158 ++++++++++++- src/zscript/zcc_compile.h | 5 +- wadsrc/static/zscript/actor.txt | 399 ++++++++++++++++++++++++++++++++ 7 files changed, 570 insertions(+), 16 deletions(-) create mode 100644 wadsrc/static/zscript/actor.txt diff --git a/src/dobjtype.h b/src/dobjtype.h index 0b4235a764..8ccb62acaa 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -24,6 +24,11 @@ enum 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 when checking function signatures) }; // Symbol information ------------------------------------------------------- diff --git a/src/namedef.h b/src/namedef.h index f07db2ce94..8d883d5666 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -714,6 +714,11 @@ xx(Mant_Dig) xx(Min_10_Exp) xx(Max_10_Exp) +// implicit function parameters +xx(self) +xx(caller) +xx(stateinfo) + xx(__decorate_internal_int__) xx(__decorate_internal_bool__) xx(__decorate_internal_state__) diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 426eddd41e..107a496d88 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -195,7 +195,7 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray *args, TArray *argflags, PClassActor *cls, DWORD funcflags); +void SetImplicitArgs(TArray *args, TArray *argflags, PClass *cls, DWORD funcflags); PFunction *FindGlobalActionFunction(const char *name); diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 5789038b7e..6d1077ffe9 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -410,7 +410,7 @@ static void ParseArgListDef(FScanner &sc, PClassActor *cls, // //========================================================================== -void SetImplicitArgs(TArray *args, TArray *argflags, PClassActor *cls, DWORD funcflags) +void SetImplicitArgs(TArray *args, TArray *argflags, PClass *cls, DWORD funcflags) { // Must be called before adding any other arguments. assert(args == NULL || args->Size() == 0); @@ -419,21 +419,21 @@ void SetImplicitArgs(TArray *args, TArray *argflags, PClassActor if (funcflags & VARF_Method) { // implied self pointer - if (args != NULL) args->Push(NewClassPointer(cls)); - if (argflags != NULL) argflags->Push(0); + if (args != NULL) args->Push(NewClassPointer(RUNTIME_CLASS(AActor))); + if (argflags != NULL) argflags->Push(VARF_Implicit); } if (funcflags & VARF_Action) { // implied stateowner and callingstate pointers if (args != NULL) { - args->Push(NewClassPointer(RUNTIME_CLASS(AActor))); + args->Push(NewClassPointer(cls)); args->Push(TypeState); } if (argflags != NULL) { - argflags->Push(0); - argflags->Push(0); + argflags->Push(VARF_Implicit); + argflags->Push(VARF_Implicit); } } } diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 98448069ad..7e718b42f3 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -111,7 +111,10 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) // todo case AST_States: + break; + case AST_FuncDeclarator: + cls->Functions.Push(static_cast(node)); break; case AST_Default: @@ -364,6 +367,7 @@ int ZCCCompiler::Compile() CompileAllConstants(); CompileAllFields(); InitDefaults(); + InitFunctions(); return ErrorCount; } @@ -1179,7 +1183,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel { auto field = Fields[0]; - PType *fieldtype = DetermineType(type, field, field->Type, true); + PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, 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; @@ -1264,11 +1268,11 @@ FString ZCCCompiler::FlagsToString(uint32_t flags) // //========================================================================== -PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes) +PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes) { if (!allowarraytypes && ztype->ArraySize != nullptr) { - Error(field, "%s: Array type not allowed", FName(field->Names->Name).GetChars()); + Error(field, "%s: Array type not allowed", name.GetChars()); return TypeError; } switch (ztype->NodeType) @@ -1322,9 +1326,18 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZC case ZCC_Vector4: // This has almost no use, so we really shouldn't bother. - Error(field, "vector<4> not implemented for %s", FName(field->Names->Name).GetChars()); + Error(field, "vector<4> not implemented for %s", name.GetChars()); return TypeError; + case ZCC_State: + return TypeState; + + case ZCC_Color: + return TypeColor; + + case ZCC_Sound: + return TypeSound; + case ZCC_UserType: return ResolveUserType(btype, &outertype->Symbols); break; @@ -1334,19 +1347,19 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZC case AST_MapType: if (allowarraytypes) { - Error(field, "%s: Map types not implemented yet", FName(field->Names->Name).GetChars()); + 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); - return NewMap(DetermineType(outertype, field, mtype->KeyType, false), DetermineType(outertype, field, mtype->ValueType, false)); + return NewMap(DetermineType(outertype, field, name, mtype->KeyType, false), DetermineType(outertype, field, name, mtype->ValueType, false)); } break; case AST_DynArrayType: if (allowarraytypes) { - Error(field, "%s: Dynamic array types not implemented yet", FName(field->Names->Name).GetChars()); + Error(field, "%s: Dynamic array types not implemented yet", name.GetChars()); auto atype = static_cast(ztype); - return NewDynArray(DetermineType(outertype, field, atype->ElementType, false)); + return NewDynArray(DetermineType(outertype, field, name, atype->ElementType, false)); } break; @@ -1648,6 +1661,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper } } // call the handler + FScriptPosition::ErrorCounter = 0; try { prop->Handler(defaults, bag.Info, bag, ¶ms[0]); @@ -1656,6 +1670,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper { Error(property, "%s", error.GetMessage()); } + ErrorCount += FScriptPosition::ErrorCounter; } //========================================================================== @@ -1824,3 +1839,130 @@ void ZCCCompiler::InitDefaults() } } +//========================================================================== +// +// Parses the functions list +// +//========================================================================== + +void ZCCCompiler::InitFunctions() +{ + TArray rets(1); + TArray args; + TArray argflags; + TArray argnames; + + for (auto c : Classes) + { + for (auto f : c->Functions) + { + Printf("processing function %s\n", FName(f->Name).GetChars()); + rets.Clear(); + args.Clear(); + argflags.Clear(); + // 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); + // 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)); + f->Flags &= notallowed; + } + uint32_t varflags = VARF_Method; + 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_Action) varflags |= VARF_Action|VARF_Final; // Action implies Final. + if (f->Flags & ZCC_Static) varflags = (varflags & ~VARF_Method) | VARF_Final; // Static implies Final. + if ((f->Flags & (ZCC_Action | ZCC_Static)) == (ZCC_Action | ZCC_Static)) + { + Error(f, "%s: Action and Static on the same function is not allowed.", FName(f->Name).GetChars()); + varflags |= VARF_Method; + } + + 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()); + } + } + SetImplicitArgs(&args, &argflags, c->Type(), varflags); + // Give names to the implicit parameters. + // Note that 'self' is the second argument on action functions, because this is the one referring to the owning class. + if (varflags & VARF_Action) + { + argnames.Push(NAME_caller); + argnames.Push(NAME_self); + argnames.Push(NAME_stateinfo); + } + else if (varflags & VARF_Method) + { + argnames.Push(NAME_self); + } + + auto p = f->Params; + if (p != nullptr) + { + do + { + if (p->Type != nullptr) + { + auto type = DetermineType(c->Type(), p, f->Name, p->Type, false); + int flags; + if (p->Flags & ZCC_In) flags |= VARF_In; + if (p->Flags & ZCC_Out) flags |= VARF_Out; + if (p->Default != nullptr) + { + auto val = Simplify(p->Default, &c->Type()->Symbols); + flags |= VARF_Optional; + if (val->Operation != PEX_ConstValue) + { + Error(c->cls, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars()); + } + // Todo: Store and handle the default value (native functions will discard it anyway but for scripted ones this should be done decently.) + } + // TBD: disallow certain types? For now, let everything pass that isn't an array. + args.Push(type); + argflags.Push(flags); + } + else + { + args.Push(nullptr); + argflags.Push(0); + } + p = static_cast(p->SiblingNext); + } while (p != f->Params); + } + + PFunction *sym = new PFunction(f->Name); + sym->AddVariant(NewPrototype(rets, args), argflags, afd == nullptr? nullptr : *(afd->VMPointer)); + sym->Flags = varflags; + c->Type()->Symbols.ReplaceSymbol(sym); + + // todo: Check inheritance. + // todo: Process function bodies. + } + } + } +} + diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index 9edd65b1d8..e5fb241f35 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -45,6 +45,7 @@ struct ZCC_ClassWork TArray Constants; TArray Fields; TArray Defaults; + TArray Functions; ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n) { @@ -90,7 +91,7 @@ private: void CompileAllFields(); bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct); FString FlagsToString(uint32_t flags); - PType *DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes); + PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym); PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym); @@ -102,6 +103,8 @@ private: double GetDouble(ZCC_Expression *expr); const char *GetString(ZCC_Expression *expr, bool silent = false); + void InitFunctions(); + TArray Constants; TArray Structs; TArray Classes; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt new file mode 100644 index 0000000000..34c1271e02 --- /dev/null +++ b/wadsrc/static/zscript/actor.txt @@ -0,0 +1,399 @@ +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; + 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 void A_Turn(float angle = 0); + action native bool A_LineEffect(int boomspecial = 0, int tag = 0); + // End of MBF redundant functions. + + action native void A_MonsterRail(); + action 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); + action native void A_Pain(); + action native void A_NoBlocking(); + action native void A_XScream(); + action native void A_Look(); + action native void A_Chase(state melee = "*", state missile = "none", int flags = 0); + action native void A_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); + action native void A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); + action native void A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); + action native void A_PosAttack(); + action native void A_Scream(); + action native void A_SPosAttack(); + action native void A_SPosAttackUseAtkSound(); + action native void A_VileChase(); + action native void A_VileStart(); + action native void A_VileTarget(class fire = "ArchvileFire"); + action native void 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 void A_StartFire(); + action native void A_Fire(float spawnheight = 0); + action native void A_FireCrackle(); + action native void A_Tracer(); + action native void A_SkelWhoosh(); + action native void A_SkelFist(); + action native void A_SkelMissile(); + action native void A_FatRaise(); + action native void A_FatAttack1(class spawntype = "FatShot"); + action native void A_FatAttack2(class spawntype = "FatShot"); + action native void A_FatAttack3(class spawntype = "FatShot"); + action native void A_BossDeath(); + action native void A_CPosAttack(); + action native void A_CPosRefire(); + action native void A_TroopAttack(); + action native void A_SargAttack(); + action native void A_HeadAttack(); + action native void A_BruisAttack(); + action native void A_SkullAttack(float speed = 20); + action native void A_BetaSkullAttack(); + action native void A_Metal(); + action native void A_SpidRefire(); + action native void A_BabyMetal(); + action native void A_BspiAttack(); + action native void A_Hoof(); + action native void A_CyberAttack(); + action native void A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); + action native void A_DualPainAttack(class spawntype = "LostSoul"); + action native void A_PainDie(class spawntype = "LostSoul"); + action native void A_KeenDie(int doortag = 666); + action native void A_BrainPain(); + action native void A_BrainScream(); + action native void A_BrainDie(); + action native void A_BrainAwake(); + action native void A_BrainSpit(class spawntype = "none"); // needs special treatment for default + action native void A_SpawnSound(); + action native void A_SpawnFly(class spawntype = "none"); // needs special treatment for default + action native void A_BrainExplode(); + action native void A_Die(name damagetype = "none"); + action native void A_Detonate(); + action native void 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 void A_SetFloorClip(); + action native void A_UnSetFloorClip(); + action native void A_HideThing(); + action native void A_UnHideThing(); + action native void A_SetInvulnerable(); + action native void A_UnSetInvulnerable(); + action native void A_SetReflective(); + action native void A_UnSetReflective(); + action native void A_SetReflectiveInvulnerable(); + action native void A_UnSetReflectiveInvulnerable(); + action native void A_SetShootable(); + action native void A_UnSetShootable(); + action native void A_NoGravity(); + action native void A_Gravity(); + action native void A_LowGravity(); + native void A_SetGravity(float gravity); + action native void A_Fall(); + action native void A_SetSolid(); + action native void A_UnsetSolid(); + action native void A_SetFloat(); + action native void A_UnsetFloat(); + + action native void A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); + + action native void A_ScreamAndUnblock(); + action native void A_ActiveAndUnblock(); + action native void A_ActiveSound(); + + action native void A_FastChase(); + action native void A_FreezeDeath(); + action native void A_FreezeDeathChunks(); + action native void A_GenericFreezeDeath(); + action native void A_IceGuyDie(); + action native void A_CentaurDefend(); + action native void A_BishopMissileWeave(); + action native void A_CStaffMissileSlither(); + action native void A_PlayerScream(); + action native void A_SkullPop(class skulltype = "BloodySkull"); + action native void A_CheckPlayerDone(); + + action native void A_Wander(int flags = 0); + action native void A_Look2(); + action native void A_TossGib(); + action native void A_SentinelBob(); + action native void A_SentinelRefire(); + action native void A_Tracer2(); + action native void A_SetShadow(); + action native void A_ClearShadow(); + action native void A_GetHurt(); + action native void A_TurretLook(); + action native void A_KlaxonBlare(); + action native void A_Countdown(); + action native void A_AlertMonsters(float maxdist = 0, int flags = 0); + action native void A_ClearSoundTarget(); + action native void A_FireAssaultGun(); + action native void A_CheckTerrain(); + action native void A_FaceConsolePlayer(float MaxTurnAngle = 0); // [TP] no-op + + deprecated action native void A_MissileAttack(); + deprecated action native void A_MeleeAttack(); + deprecated action native void A_ComboAttack(); + deprecated action native void A_BulletAttack(); + action 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"); + action native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM); + native void A_PlayWeaponSound(sound whattoplay); + action native void A_FLoopActiveSound(); + action native void A_LoopActiveSound(); + action 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 state A_Jump(int chance = 256, state label, ...); + native void A_CustomMissile(class missiletype, float spawnheight = 32, float spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET); + native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); + native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + native 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); + 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 void A_FadeIn(float reduce = 0.1, int flags = 0); + action 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_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 void A_RaiseMaster(bool copy = 0); + action native void A_RaiseChildren(bool copy = 0); + action native void A_RaiseSiblings(bool copy = 0); + native state A_CheckFloor(state label); + native state A_CheckCeiling(state label); + native state A_PlayerSkinCheck(state label); + deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); + 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 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"); + action native void A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0); + action native void 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 void A_Stop(); + action native void A_Respawn(int flags = 1); + action native void A_BarrelDestroy(); + action native void A_QueueCorpse(); + action native void A_DeQueueCorpse(); + action native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = ""); + action native void A_ClearLastHeard(); + action native void A_ClearTarget(); + native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, float offsetforward = 0); + native state A_JumpIfTargetInLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); + native state A_JumpIfInTargetLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); + native bool A_SelectWeapon(class whichweapon, int flags = 0); + action native void A_Punch(); + action native void A_Feathers(); + action native void A_ClassBossHealth(); + action native void A_ShootGun(); + action native void A_RocketInFlight(); + action native void A_Bang4Cloud(); + action native void A_DropFire(); + native void A_GiveQuestItem(int itemno); + action native void A_RemoveForcefield(); + native void A_DropWeaponPieces(class p1, class p2, class p3); + action native void A_PigPain (); + native state A_MonsterRefire(int chance, state label); + action 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); + action native void 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 void 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 void A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native void A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native void A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native void A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native void A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native void A_RemoveTarget(int flags = 0, class filter = "None", name species = "None"); + action native void A_RemoveMaster(int flags = 0, class filter = "None", name species = "None"); + action native void A_RemoveTracer(int flags = 0, class filter = "None", name species = "None"); + action native void A_RemoveChildren(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); + action native void 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 void A_SwapTeleFog(); + native void A_SetFloatBobPhase(int bob); + native void A_SetHealth(int health, int ptr = AAPTR_DEFAULT); + action native void 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 void A_CopyFriendliness(int ptr_source = AAPTR_MASTER); + + action native bool A_Overlay(int layer, state start = "", bool nooverride = false); + action 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); + + 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 + deprecated private native state __decorate_internal_state__(state s); + 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); +} From f46b6b5be5cabb089ebe6cd3ba83e8ba335add22 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 12 Oct 2016 00:04:30 +0200 Subject: [PATCH 020/471] - fixed some issues with the grammar for parsing states: * Goto did not support the class scope operator '::'. Like in DECORATE, this cannot be done with a simple '.' because it creates semantic problems with first part of a state label. This requires different syntax so that it can unambiguously distinguish between a scope identifier and the actual label * Goto used the incorrect token PLUS for '+' instead of ADD. * The state's duration was not stored in the AST. * Truncating the sprite name inside the parser is probably not the best idea because it used a simple Printf to report this. Let's do this during processing of the AST where this can be properly handled as an error. --- src/zscript/ast.cpp | 4 +++- src/zscript/zcc-parse.lemon | 28 +++++++++++++++++----------- src/zscript/zcc_parser.h | 4 +++- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/zscript/ast.cpp b/src/zscript/ast.cpp index 1f416f7ade..45b8053ba6 100644 --- a/src/zscript/ast.cpp +++ b/src/zscript/ast.cpp @@ -405,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(); @@ -414,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); diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index 1861463f90..ae03248cc9 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -430,25 +430,31 @@ 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_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; diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 5d5c85827a..0cb3f79aed 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -260,19 +260,21 @@ 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_TreeNode *Action; }; From 6a8ab9a4d32a61f535b87922b6f2460f119003cb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 12 Oct 2016 17:50:23 +0200 Subject: [PATCH 021/471] - implemented the state compiler. So far all it can handle is parameter-less functions. To do the rest, some cleanup is needed first, to untangle the DECORATE parser from the actual code generation so that the low end stuff can actually be reused here instead of having to be redone. --- src/d_dehacked.cpp | 2 +- src/thingdef/thingdef_exp.cpp | 2 +- src/thingdef/thingdef_exp.h | 3 +- src/thingdef/thingdef_expression.cpp | 56 ++++-- src/thingdef/thingdef_states.cpp | 4 +- src/zscript/zcc-parse.lemon | 29 ++- src/zscript/zcc_compile.cpp | 279 ++++++++++++++++++++++++++- src/zscript/zcc_compile.h | 4 + src/zscript/zcc_parser.cpp | 17 -- src/zscript/zcc_parser.h | 8 + 10 files changed, 362 insertions(+), 42 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index dd71fdf756..d062ce5330 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -804,7 +804,7 @@ void SetDehParams(FState *state, int codepointer) } else { - VMFunctionBuilder buildit; + VMFunctionBuilder buildit(true); // Allocate registers used to pass parameters in. // self, stateowner, state (all are pointers) buildit.Registers[REGT_POINTER].Get(NAP); diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index cad6198f04..11baef7226 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -515,7 +515,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) args = nullptr; } - return new FxVMFunctionCall(func, args, sc); + return new FxVMFunctionCall(func, args, sc, false); } } diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 5fe8f252f9..65c3ace63f 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -948,11 +948,12 @@ public: class FxVMFunctionCall : public FxExpression { bool EmitTail; + bool OwnerIsSelf; // ZSCRIPT makes the state's owner the self pointer to ensure proper type handling PFunction *Function; FArgumentList *ArgList; public: - FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos); + FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool ownerisself); ~FxVMFunctionCall(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index c2b2d25e68..ae2639b733 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3858,12 +3858,13 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) // //========================================================================== -FxVMFunctionCall::FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos) +FxVMFunctionCall::FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool ownerisself) : FxExpression(pos) { Function = func; ArgList = args; EmitTail = false; + OwnerIsSelf = ownerisself; } //========================================================================== @@ -3968,28 +3969,55 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) return reg; } } - // Emit code to pass implied parameters - if (Function->Flags & VARF_Method) + + // Passing the caller as 'self' is a serious design mistake in DECORATE because it mixes up the types of the two actors involved. + // For ZSCRIPT 'self' is properly used for the state's owning actor, meaning we have to pass the second argument here. + + // If both functions are non-action or both are action, there is no need for special treatment. + if (!OwnerIsSelf || (!!(Function->Flags & VARF_Action) == build->IsActionFunc)) { - build->Emit(OP_PARAM, 0, REGT_POINTER, 0); - count += 1; + // 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; + } } - if (Function->Flags & VARF_Action) + else { - static_assert(NAP == 3, "This code needs to be updated if NAP changes"); - if (build->IsActionFunc) + // There are two possibilities here: + // Calling a non-action function from an action function. + // In that case the 'stateowner' pointer needs to be used as self. + if (build->IsActionFunc && (Function->Flags & VARF_Method)) { build->Emit(OP_PARAM, 0, REGT_POINTER, 1); - build->Emit(OP_PARAM, 0, REGT_POINTER, 2); + count += 1; } - else + // and calling an action function from a non-action function. + // This must be blocked because it lacks crucial information. + if (!build->IsActionFunc && (Function->Flags & VARF_Action)) { - 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); + // This case should be eliminated in the analyzing stage. + I_Error("Cannot call action function from non-action functions."); } - count += 2; } + // Emit code to pass explicit parameters if (ArgList != NULL) { diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index 707de30451..3b692391c6 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -100,7 +100,7 @@ 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); + return new FxVMFunctionCall(FindGlobalActionFunction("A_CallSpecial"), args, sc, false); } return NULL; } @@ -582,7 +582,7 @@ FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, B { FArgumentList *args = new FArgumentList; ParseFunctionParameters(sc, bag.Info, *args, afd, statestring, &bag.statedef); - call = new FxVMFunctionCall(afd, args->Size() > 0 ? args : NULL, sc); + call = new FxVMFunctionCall(afd, args->Size() > 0 ? args : NULL, sc, false); if (args->Size() == 0) { delete args; diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index ae03248cc9..7213b4dbc6 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/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; @@ -461,6 +463,7 @@ state_line(X) ::= NWS(A) NWS(B) expr(E) state_opts(C) state_action(D). line->bNoDelay = C.NoDelay; line->bCanRaise = C.CanRaise; line->Offset = C.Offset; + line->Lights = C.Lights; line->Action = D; X = line; } @@ -472,10 +475,28 @@ 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*/ } diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 7e718b42f3..19af0e7c1d 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -46,6 +46,7 @@ #include "v_text.h" #include "p_lnspec.h" #include "gdtoa.h" +#include "thingdef_exp.h" #define DEFINING_CONST ((PSymbolConst *)(void *)1) @@ -109,8 +110,8 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) enumType = nullptr; break; - // todo case AST_States: + cls->States.Push(static_cast(node)); break; case AST_FuncDeclarator: @@ -368,6 +369,7 @@ int ZCCCompiler::Compile() CompileAllFields(); InitDefaults(); InitFunctions(); + CompileStates(); return ErrorCount; } @@ -1856,7 +1858,6 @@ void ZCCCompiler::InitFunctions() { for (auto f : c->Functions) { - Printf("processing function %s\n", FName(f->Name).GetChars()); rets.Clear(); args.Clear(); argflags.Clear(); @@ -1966,3 +1967,277 @@ void ZCCCompiler::InitFunctions() } } +//========================================================================== +// +// 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(PClassActor *cls, ZCC_TreeNode *af) +{ + // We have 3 cases to consider here: + // 1. An action function without parameters. This can be called directly + // 2. An action functon with parameters or a non-action function. This needs to be wrapped into a helper function to set everything up. + // 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); + + PFunction *afd = dyn_cast(cls->Symbols.FindSymbol(id->Identifier, true)); + if (afd != nullptr) + { + if (fc->Parameters == nullptr && (afd->Flags & VARF_Action)) + { + // This is the simple case which doesn't require work on the tree. + return new FxVMFunctionCall(afd, nullptr, *af, true); + } + else + { + // need to generate a function from the information. + } + } + else + { + Error(af, "%s: action function not found in %s", FName(id->Identifier).GetChars(), cls->TypeName.GetChars()); + return nullptr; + } + } + Error(af, "Complex action functions not supported yet."); + return nullptr; + + /* + bool hasfinalret; + tcall->Code = ParseActions(sc, state, statestring, bag, hasfinalret); + if (!hasfinalret && tcall->Code != nullptr) + { + static_cast(tcall->Code)->Add(new FxReturnStatement(nullptr, sc)); + } + */ + +} + +//========================================================================== +// +// Compile the states +// +//========================================================================== + +void ZCCCompiler::CompileStates() +{ + for (auto c : Classes) + { + if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor))) + { + Error(c->cls, "%s: States can only be defined for actors.", c->Type()->TypeName.GetChars()); + continue; + } + FString statename; // The state builder wants the label as one complete string, not separated into tokens. + FStateDefinitions statedef; + for (auto s : c->States) + { + auto st = s->Body; + 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)); + 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 + // and there is little point fixing it because it is essentially useless outside of resolving constants. + if (CheckRandom(sl->Duration)) + { + auto func = static_cast(Simplify(sl->Duration, &c->Type()->Symbols)); + if (func->Parameters == func->Parameters->SiblingNext || func->Parameters != func->Parameters->SiblingNext->SiblingNext) + { + Error(sl, "Random duration requires exactly 2 parameters"); + } + int v1 = GetInt(func->Parameters->Value); + int v2 = GetInt(static_cast(func->Parameters->SiblingNext)->Value); + 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); + 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)); + auto o2 = static_cast(Simplify(static_cast(o1->SiblingNext), &c->Type()->Symbols)); + + 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 + + int count = statedef.AddStates(&state, sl->Frames->GetChars()); + if (count < 0) + { + Error(sl, "Invalid frame character string '%s'", sl->Frames->GetChars()); + count = -count; + } + + if (sl->Action != nullptr) + { + auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); + if (code != nullptr) + { + auto tcall = new FStateTempCall; + tcall->Code = code; + tcall->ActorClass = static_cast(c->Type()); + tcall->FirstState = statedef.GetStateCount() - count; + tcall->NumStates = count; + StateTempCalls.Push(tcall); + } + } + break; + } + case AST_StateGoto: + { + auto sg = static_cast(st); + statename = ""; + if (sg->Qualifier != nullptr) + { + statename << sg->Qualifier->Id << "::"; + } + auto part = sg->Label; + do + { + statename << 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); + 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); + } + } +} diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index e5fb241f35..74d83f529d 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -4,6 +4,7 @@ struct Baggage; struct FPropertyInfo; class AActor; +class FxExpression; struct ZCC_StructWork { @@ -46,6 +47,7 @@ struct ZCC_ClassWork TArray Fields; TArray Defaults; TArray Functions; + TArray States; ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n) { @@ -104,6 +106,8 @@ private: const char *GetString(ZCC_Expression *expr, bool silent = false); void InitFunctions(); + void CompileStates(); + FxExpression *SetupActionFunction(PClassActor *cls, ZCC_TreeNode *sl); TArray Constants; TArray Structs; diff --git a/src/zscript/zcc_parser.cpp b/src/zscript/zcc_parser.cpp index ce2dc98e74..0d69141f08 100644 --- a/src/zscript/zcc_parser.cpp +++ b/src/zscript/zcc_parser.cpp @@ -347,23 +347,6 @@ static void DoParse(int lumpnum) symtable.SetName("Global_Node"); ZCCCompiler cc(state, NULL, symtable, GlobalSymbols); cc.Compile(); - // ... and another one afterward so we can see what the compiler does with the data. -#ifdef _DEBUG - if (f != NULL) - { - fclose(f); - } - FString ast = ZCC_PrintAST(state.TopNode); - FString filename = Wads.GetLumpFullName(lumpnum); - FString astfile = ExtractFileBase(filename, false); - astfile << "-after.ast"; - f = fopen(astfile, "w"); - if (f != NULL) - { - fputs(ast.GetChars(), f); - fclose(f); - } -#endif } void ParseScripts() diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 0cb3f79aed..2a73c86811 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -2,6 +2,7 @@ #define ZCC_PARSER_H #include "memarena.h" +#include "sc_man.h" struct ZCCToken { @@ -176,6 +177,12 @@ struct ZCC_TreeNode SiblingPrev = siblingend; siblingend->SiblingNext = this; } + + operator FScriptPosition() + { + return FScriptPosition(*SourceName, SourceLoc); + } + }; struct ZCC_Identifier : ZCC_TreeNode @@ -276,6 +283,7 @@ struct ZCC_StateLine : ZCC_StatePart FString *Frames; ZCC_Expression *Duration; ZCC_Expression *Offset; + ZCC_ExprConstant *Lights; ZCC_TreeNode *Action; }; From b1a83bfd26450c44aec0ca293dfa2ed9fa90dadc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 12 Oct 2016 19:22:33 +0200 Subject: [PATCH 022/471] - started with cleanup and separation of DECORATE code. * everything related to scripting is now placed in a subdirectory 'scripting', which itself is separated into DECORATE, ZSCRIPT, the VM and code generation. * a few items have been moved to different headers so that the DECORATE parser definitions can mostly be kept local. The only exception at the moment is the flags interface on which 3 source files depend. --- src/CMakeLists.txt | 70 ++++++++++--------- src/d_dehacked.cpp | 3 + src/d_main.cpp | 1 + src/dobjgc.cpp | 1 + src/dobjtype.h | 1 - src/g_doom/a_arachnotron.cpp | 2 +- src/g_doom/a_archvile.cpp | 2 +- src/g_doom/a_bossbrain.cpp | 2 +- src/g_doom/a_cacodemon.cpp | 2 +- src/g_doom/a_cyberdemon.cpp | 2 +- src/g_doom/a_demon.cpp | 2 +- src/g_doom/a_doomimp.cpp | 2 +- src/g_doom/a_doommisc.cpp | 3 +- src/g_doom/a_doomweaps.cpp | 2 +- src/g_doom/a_fatso.cpp | 2 +- src/g_doom/a_keen.cpp | 2 +- src/g_doom/a_lostsoul.cpp | 2 +- src/g_doom/a_painelemental.cpp | 2 +- src/g_doom/a_possessed.cpp | 2 +- src/g_doom/a_revenant.cpp | 2 +- src/g_doom/a_scriptedmarine.cpp | 2 +- src/g_doom/a_spidermaster.cpp | 2 +- src/g_heretic/a_chicken.cpp | 2 +- src/g_heretic/a_dsparil.cpp | 2 +- src/g_heretic/a_hereticartifacts.cpp | 2 +- src/g_heretic/a_hereticimp.cpp | 2 +- src/g_heretic/a_hereticmisc.cpp | 3 +- src/g_heretic/a_hereticweaps.cpp | 2 +- src/g_heretic/a_ironlich.cpp | 2 +- src/g_heretic/a_knight.cpp | 2 +- src/g_heretic/a_wizard.cpp | 2 +- src/g_hexen/a_bats.cpp | 2 +- src/g_hexen/a_bishop.cpp | 2 +- src/g_hexen/a_centaur.cpp | 2 +- src/g_hexen/a_clericflame.cpp | 2 +- src/g_hexen/a_clericholy.cpp | 2 +- src/g_hexen/a_clericmace.cpp | 2 +- src/g_hexen/a_clericstaff.cpp | 2 +- src/g_hexen/a_dragon.cpp | 2 +- src/g_hexen/a_fighteraxe.cpp | 4 +- src/g_hexen/a_fighterhammer.cpp | 2 +- src/g_hexen/a_fighterplayer.cpp | 2 +- src/g_hexen/a_fighterquietus.cpp | 2 +- src/g_hexen/a_firedemon.cpp | 2 +- src/g_hexen/a_flechette.cpp | 2 +- src/g_hexen/a_fog.cpp | 2 +- src/g_hexen/a_heresiarch.cpp | 2 +- src/g_hexen/a_hexenmisc.cpp | 3 +- src/g_hexen/a_hexenspecialdecs.cpp | 2 +- src/g_hexen/a_iceguy.cpp | 2 +- src/g_hexen/a_korax.cpp | 2 +- src/g_hexen/a_magecone.cpp | 2 +- src/g_hexen/a_magelightning.cpp | 2 +- src/g_hexen/a_magestaff.cpp | 2 +- src/g_hexen/a_pig.cpp | 2 +- src/g_hexen/a_serpent.cpp | 2 +- src/g_hexen/a_spike.cpp | 2 +- src/g_hexen/a_summon.cpp | 2 +- src/g_hexen/a_teleportother.cpp | 2 +- src/g_hexen/a_wraith.cpp | 2 +- src/g_raven/a_minotaur.cpp | 3 +- src/g_shared/a_action.cpp | 2 +- src/g_shared/a_bridge.cpp | 2 +- src/g_shared/a_pickups.cpp | 2 +- src/g_shared/a_randomspawner.cpp | 2 +- src/g_shared/a_specialspot.cpp | 2 +- src/g_shared/a_weapons.cpp | 2 +- src/g_shared/sbarinfo.cpp | 1 + src/g_shared/shared_hud.cpp | 1 + src/g_shared/shared_sbar.cpp | 1 + src/g_strife/a_acolyte.cpp | 2 +- src/g_strife/a_alienspectres.cpp | 2 +- src/g_strife/a_crusader.cpp | 2 +- src/g_strife/a_entityboss.cpp | 2 +- src/g_strife/a_inquisitor.cpp | 2 +- src/g_strife/a_loremaster.cpp | 2 +- src/g_strife/a_oracle.cpp | 2 +- src/g_strife/a_programmer.cpp | 2 +- src/g_strife/a_reaver.cpp | 2 +- src/g_strife/a_rebels.cpp | 2 +- src/g_strife/a_sentinel.cpp | 2 +- src/g_strife/a_spectral.cpp | 2 +- src/g_strife/a_stalker.cpp | 2 +- src/g_strife/a_strifeitems.cpp | 2 +- src/g_strife/a_strifestuff.cpp | 3 +- src/g_strife/a_strifeweapons.cpp | 2 +- src/g_strife/a_templar.cpp | 2 +- src/g_strife/a_thingstoblowup.cpp | 4 +- src/g_strife/strife_sbar.cpp | 1 + src/info.cpp | 2 +- src/info.h | 12 ++++ src/menu/menudef.cpp | 1 + src/menu/menuinput.cpp | 1 + src/menu/messagebox.cpp | 1 + src/p_acs.cpp | 1 + src/p_actionfunctions.cpp | 4 +- src/p_enemy.cpp | 3 +- src/p_enemy.h | 3 +- src/p_mobj.cpp | 3 +- src/p_pspr.cpp | 2 +- src/p_pspr.h | 3 +- src/p_states.cpp | 3 +- src/p_user.cpp | 2 +- .../codegeneration}/thingdef_exp.h | 0 .../codegeneration}/thingdef_expression.cpp | 0 .../decorate}/olddecorations.cpp | 2 +- .../decorate}/thingdef_exp.cpp | 2 +- .../decorate}/thingdef_parse.cpp | 2 +- .../decorate}/thingdef_states.cpp | 2 +- src/{thingdef => scripting}/thingdef.cpp | 2 +- src/{thingdef => scripting}/thingdef.h | 67 +----------------- src/{thingdef => scripting}/thingdef_data.cpp | 0 .../thingdef_properties.cpp | 0 src/{zscript => scripting/vm}/vm.h | 60 ++++++++++++++++ src/{zscript => scripting/vm}/vmbuilder.cpp | 0 src/{zscript => scripting/vm}/vmbuilder.h | 0 src/{zscript => scripting/vm}/vmdisasm.cpp | 0 src/{zscript => scripting/vm}/vmexec.cpp | 0 src/{zscript => scripting/vm}/vmexec.h | 0 src/{zscript => scripting/vm}/vmframe.cpp | 0 src/{zscript => scripting/vm}/vmops.h | 0 src/{ => scripting}/zscript/ast.cpp | 0 src/{ => scripting}/zscript/zcc-parse.lemon | 0 src/{ => scripting}/zscript/zcc_compile.cpp | 2 +- src/{ => scripting}/zscript/zcc_compile.h | 0 src/{ => scripting}/zscript/zcc_expr.cpp | 0 src/{ => scripting}/zscript/zcc_exprlist.h | 0 src/{ => scripting}/zscript/zcc_parser.cpp | 0 src/{ => scripting}/zscript/zcc_parser.h | 0 src/serializer.cpp | 1 + src/sound/oalsound.cpp | 1 + src/wi_stuff.cpp | 1 + 132 files changed, 234 insertions(+), 198 deletions(-) rename src/{thingdef => scripting/codegeneration}/thingdef_exp.h (100%) rename src/{thingdef => scripting/codegeneration}/thingdef_expression.cpp (100%) rename src/{thingdef => scripting/decorate}/olddecorations.cpp (99%) rename src/{thingdef => scripting/decorate}/thingdef_exp.cpp (99%) rename src/{thingdef => scripting/decorate}/thingdef_parse.cpp (99%) rename src/{thingdef => scripting/decorate}/thingdef_states.cpp (99%) rename src/{thingdef => scripting}/thingdef.cpp (99%) rename src/{thingdef => scripting}/thingdef.h (76%) rename src/{thingdef => scripting}/thingdef_data.cpp (100%) rename src/{thingdef => scripting}/thingdef_properties.cpp (100%) rename src/{zscript => scripting/vm}/vm.h (90%) rename src/{zscript => scripting/vm}/vmbuilder.cpp (100%) rename src/{zscript => scripting/vm}/vmbuilder.h (100%) rename src/{zscript => scripting/vm}/vmdisasm.cpp (100%) rename src/{zscript => scripting/vm}/vmexec.cpp (100%) rename src/{zscript => scripting/vm}/vmexec.h (100%) rename src/{zscript => scripting/vm}/vmframe.cpp (100%) rename src/{zscript => scripting/vm}/vmops.h (100%) rename src/{ => scripting}/zscript/ast.cpp (100%) rename src/{ => scripting}/zscript/zcc-parse.lemon (100%) rename src/{ => scripting}/zscript/zcc_compile.cpp (99%) rename src/{ => scripting}/zscript/zcc_compile.h (100%) rename src/{ => scripting}/zscript/zcc_expr.cpp (100%) rename src/{ => scripting}/zscript/zcc_exprlist.h (100%) rename src/{ => scripting}/zscript/zcc_parser.cpp (100%) rename src/{ => scripting}/zscript/zcc_parser.h (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ebfac30504..bd01cad424 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -752,8 +752,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 @@ -819,9 +819,9 @@ file( GLOB HEADER_FILES sfmt/*.h sound/*.h textures/*.h - thingdef/*.h + scripting/*.h + scripting/vm/*.h xlat/*.h - zscript/*.h *.h ) @@ -910,7 +910,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 @@ -1226,14 +1226,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 @@ -1248,15 +1240,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/thingdef_expression.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 ) @@ -1316,11 +1316,11 @@ include_directories( . oplsynth sound textures - thingdef timidity wildmidi xlat - zscript + scripting + scripting/vm ../gdtoa ../dumb/include ${CMAKE_BINARY_DIR}/gdtoa @@ -1428,7 +1428,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/.+") @@ -1436,9 +1438,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("Render Core\\Render Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_.+\\.h$") source_group("Render Core\\Render Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_.+\\.cpp$") source_group("Render Data\\Resource Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+\\.h$") @@ -1446,15 +1446,17 @@ 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("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/d_dehacked.cpp b/src/d_dehacked.cpp index d062ce5330..d5150e985e 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -70,6 +70,9 @@ #include "doomerrors.h" #include "p_effect.h" #include "serializer.h" +#include "vm.h" +#include "thingdef.h" +#include "info.h" #include "vmbuilder.h" // [SO] Just the way Randy said to do it :) diff --git a/src/d_main.cpp b/src/d_main.cpp index dad2b86d95..d7757ddf47 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/dobjgc.cpp b/src/dobjgc.cpp index afdc755083..28715a0ecc 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 ------------------------------------------------------------------ diff --git a/src/dobjtype.h b/src/dobjtype.h index 8ccb62acaa..19aeca71b4 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -68,7 +68,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 ------------------------------------------------------------ diff --git a/src/g_doom/a_arachnotron.cpp b/src/g_doom/a_arachnotron.cpp index 62660c7f50..e558b05b26 100644 --- a/src/g_doom/a_arachnotron.cpp +++ b/src/g_doom/a_arachnotron.cpp @@ -4,7 +4,7 @@ #include "p_local.h" #include "p_enemy.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ DEFINE_ACTION_FUNCTION(AActor, A_BspiAttack) diff --git a/src/g_doom/a_archvile.cpp b/src/g_doom/a_archvile.cpp index 84481e5f62..06be5cc0c2 100644 --- a/src/g_doom/a_archvile.cpp +++ b/src/g_doom/a_archvile.cpp @@ -6,7 +6,7 @@ #include "p_enemy.h" #include "gstrings.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ // diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index b0e7259105..8d4163c095 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -7,7 +7,7 @@ #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" */ diff --git a/src/g_doom/a_cacodemon.cpp b/src/g_doom/a_cacodemon.cpp index 3532374cf1..775580c293 100644 --- a/src/g_doom/a_cacodemon.cpp +++ b/src/g_doom/a_cacodemon.cpp @@ -7,7 +7,7 @@ #include "gstrings.h" #include "a_action.h" #include "s_sound.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_headattack ("HeadAttack"); diff --git a/src/g_doom/a_cyberdemon.cpp b/src/g_doom/a_cyberdemon.cpp index 9e0ddd1ddb..55d9181bf2 100644 --- a/src/g_doom/a_cyberdemon.cpp +++ b/src/g_doom/a_cyberdemon.cpp @@ -4,7 +4,7 @@ #include "s_sound.h" #include "p_enemy.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ DEFINE_ACTION_FUNCTION(AActor, A_CyberAttack) diff --git a/src/g_doom/a_demon.cpp b/src/g_doom/a_demon.cpp index 3f8e2f6265..330b02b30b 100644 --- a/src/g_doom/a_demon.cpp +++ b/src/g_doom/a_demon.cpp @@ -6,7 +6,7 @@ #include "p_enemy.h" #include "gstrings.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_sargattack ("SargAttack"); diff --git a/src/g_doom/a_doomimp.cpp b/src/g_doom/a_doomimp.cpp index f00b53a420..6130d39ca8 100644 --- a/src/g_doom/a_doomimp.cpp +++ b/src/g_doom/a_doomimp.cpp @@ -7,7 +7,7 @@ #include "p_enemy.h" #include "gstrings.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_troopattack ("TroopAttack"); diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 129c32f1ed..b68ded59da 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,6 +19,7 @@ #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" diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index a35a31b61f..fd60e85d84 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" */ diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index 872e1982d3..eeef39984c 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -7,7 +7,7 @@ #include "p_enemy.h" #include "gstrings.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ // diff --git a/src/g_doom/a_keen.cpp b/src/g_doom/a_keen.cpp index d0a10da58a..5c57128a3b 100644 --- a/src/g_doom/a_keen.cpp +++ b/src/g_doom/a_keen.cpp @@ -5,7 +5,7 @@ #include "p_spec.h" #include "p_enemy.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ // diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp index 056802fe07..35468ac08d 100644 --- a/src/g_doom/a_lostsoul.cpp +++ b/src/g_doom/a_lostsoul.cpp @@ -9,7 +9,7 @@ #include "gi.h" #include "gstrings.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ FRandom pr_oldsoul ("BetaLostSoul"); diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 3620b88dba..8a0aa41bfb 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" */ diff --git a/src/g_doom/a_possessed.cpp b/src/g_doom/a_possessed.cpp index f6b559c4bb..e665e8f11d 100644 --- a/src/g_doom/a_possessed.cpp +++ b/src/g_doom/a_possessed.cpp @@ -7,7 +7,7 @@ #include "p_enemy.h" #include "gstrings.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_posattack ("PosAttack"); diff --git a/src/g_doom/a_revenant.cpp b/src/g_doom/a_revenant.cpp index 9c8a38602e..adb0ea100a 100644 --- a/src/g_doom/a_revenant.cpp +++ b/src/g_doom/a_revenant.cpp @@ -8,7 +8,7 @@ #include "p_enemy.h" #include "gstrings.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "g_level.h" */ diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 2c293a2deb..76f3e45772 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" */ diff --git a/src/g_doom/a_spidermaster.cpp b/src/g_doom/a_spidermaster.cpp index aaafc4d99f..ab12db4f0a 100644 --- a/src/g_doom/a_spidermaster.cpp +++ b/src/g_doom/a_spidermaster.cpp @@ -6,7 +6,7 @@ #include "p_local.h" #include "p_enemy.h" #include "a_action.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_spidrefire ("SpidRefire"); diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp index 7f62d5f0e1..78eb7ca8d8 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); diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp index f5870f09ec..632260648c 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" */ diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index 518abb44a8..1c4677cb60 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 ------------------------------------------------------------ diff --git a/src/g_heretic/a_hereticimp.cpp b/src/g_heretic/a_hereticimp.cpp index 81185c0c14..41e207ef14 100644 --- a/src/g_heretic/a_hereticimp.cpp +++ b/src/g_heretic/a_hereticimp.cpp @@ -6,7 +6,7 @@ #include "s_sound.h" #include "p_local.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_impmsatk ("ImpMsAttack"); diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 36969f6e7d..d3ffbac238 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,6 +18,7 @@ #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" diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index eb7d49983f..c86cafce7d 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" */ diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index a887484070..c80a7bbed4 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" */ diff --git a/src/g_heretic/a_knight.cpp b/src/g_heretic/a_knight.cpp index 9f42a328ae..9c4ae24732 100644 --- a/src/g_heretic/a_knight.cpp +++ b/src/g_heretic/a_knight.cpp @@ -7,7 +7,7 @@ #include "a_action.h" #include "a_sharedglobal.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_dripblood ("DripBlood"); diff --git a/src/g_heretic/a_wizard.cpp b/src/g_heretic/a_wizard.cpp index 704488f16b..e66bc5531d 100644 --- a/src/g_heretic/a_wizard.cpp +++ b/src/g_heretic/a_wizard.cpp @@ -7,7 +7,7 @@ #include "p_enemy.h" #include "a_action.h" #include "gstrings.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_wizatk3 ("WizAtk3"); diff --git a/src/g_hexen/a_bats.cpp b/src/g_hexen/a_bats.cpp index 56c7ac0247..875910059f 100644 --- a/src/g_hexen/a_bats.cpp +++ b/src/g_hexen/a_bats.cpp @@ -4,7 +4,7 @@ #include "m_random.h" #include "p_local.h" #include "s_sound.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_batspawn ("BatSpawn"); diff --git a/src/g_hexen/a_bishop.cpp b/src/g_hexen/a_bishop.cpp index 5fb95d8bee..a88daa23b2 100644 --- a/src/g_hexen/a_bishop.cpp +++ b/src/g_hexen/a_bishop.cpp @@ -6,7 +6,7 @@ #include "a_action.h" #include "m_random.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_boom ("BishopBoom"); diff --git a/src/g_hexen/a_centaur.cpp b/src/g_hexen/a_centaur.cpp index 692688b63c..75049650d5 100644 --- a/src/g_hexen/a_centaur.cpp +++ b/src/g_hexen/a_centaur.cpp @@ -3,7 +3,7 @@ #include "p_enemy.h" #include "a_action.h" #include "m_random.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_centaurdefend ("CentaurDefend"); diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp index 5b4eba2e85..a9c8b6378c 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; diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index b08ab3e74a..f660b1e7de 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" */ diff --git a/src/g_hexen/a_clericmace.cpp b/src/g_hexen/a_clericmace.cpp index 69f1f729cb..fce979af12 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"); diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index de4e1d75f2..6b54d4de3b 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"); diff --git a/src/g_hexen/a_dragon.cpp b/src/g_hexen/a_dragon.cpp index c94be3988f..ca56525a9c 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"); diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index f47ad6a9d7..a194869f3a 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -10,9 +10,11 @@ #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"); diff --git a/src/g_hexen/a_fighterhammer.cpp b/src/g_hexen/a_fighterhammer.cpp index c33737bfdd..f8fbe33e35 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; diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index 3624ed6250..d946c689c2 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -8,7 +8,7 @@ #include "p_local.h" #include "a_action.h" #include "a_hexenglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ IMPLEMENT_CLASS (AFighterWeapon) diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index 3d04e984af..a86d4911a2 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"); diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp index 712363167b..b60c904e3e 100644 --- a/src/g_hexen/a_firedemon.cpp +++ b/src/g_hexen/a_firedemon.cpp @@ -6,7 +6,7 @@ #include "p_enemy.h" #include "a_action.h" #include "m_random.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ #define FIREDEMON_ATTACK_RANGE (64*8.) diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index ccc2bf1126..3d9555843e 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" */ diff --git a/src/g_hexen/a_fog.cpp b/src/g_hexen/a_fog.cpp index b89f8d38cc..98dbf62b7f 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"); diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index c96c4cc1f2..267320029b 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" */ diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 31a17c3a37..2c91f37b24 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,6 +24,7 @@ #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" diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index 28de8d46a2..61d5780d1a 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" */ diff --git a/src/g_hexen/a_iceguy.cpp b/src/g_hexen/a_iceguy.cpp index d00e860415..d518c7db7b 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"); diff --git a/src/g_hexen/a_korax.cpp b/src/g_hexen/a_korax.cpp index 7f0d3a43cf..01457b91c2 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" */ diff --git a/src/g_hexen/a_magecone.cpp b/src/g_hexen/a_magecone.cpp index f31e57e581..b33f937877 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; diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 896384f4e4..f322d88a68 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" */ diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index d7b06d009e..ca846d794a 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" */ diff --git a/src/g_hexen/a_pig.cpp b/src/g_hexen/a_pig.cpp index ea767dccd0..11bfe3ce83 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"); diff --git a/src/g_hexen/a_serpent.cpp b/src/g_hexen/a_serpent.cpp index 9984660536..1f6d1dd2b8 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"); diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp index 9f73963996..1e81f568f6 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"); diff --git a/src/g_hexen/a_summon.cpp b/src/g_hexen/a_summon.cpp index eb5d825bf2..c9daad6ec1 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" */ diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp index 7333d9d917..a89e62b4b0 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" */ diff --git a/src/g_hexen/a_wraith.cpp b/src/g_hexen/a_wraith.cpp index 460fa65032..f5c1f44f42 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"); diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index 9f58ce4c3f..e3636fe1b8 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) diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index c0ec37d09b..3b11911314 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" diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 178f004caf..3161c2a45c 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"); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 00a6692b25..906be04c45 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" diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index ac162a2417..3ab67425d2 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" diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 1d8d1f72d5..48a8ce1a18 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" diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index edd250debd..36ffbc2715 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" diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 42f28173c8..2e764a4035 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 diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index c4d8ec1ede..4733c6e41b 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 a3bb76b7f4..191b097d2e 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" diff --git a/src/g_strife/a_acolyte.cpp b/src/g_strife/a_acolyte.cpp index e8049da1b8..6f08a84c84 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" */ diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp index a7624785b0..d4103015cf 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" */ diff --git a/src/g_strife/a_crusader.cpp b/src/g_strife/a_crusader.cpp index b54fdd427a..8e340b820d 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) diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp index 72eeaac3a0..b7f60e26ff 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" */ diff --git a/src/g_strife/a_inquisitor.cpp b/src/g_strife/a_inquisitor.cpp index e372d8de1a..16871300a1 100644 --- a/src/g_strife/a_inquisitor.cpp +++ b/src/g_strife/a_inquisitor.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_inq ("Inquisitor"); diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp index ead116c639..2d695ac8df 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) -------------------------------------------------- diff --git a/src/g_strife/a_oracle.cpp b/src/g_strife/a_oracle.cpp index f1f0b0b2bc..139786d893 100644 --- a/src/g_strife/a_oracle.cpp +++ b/src/g_strife/a_oracle.cpp @@ -4,7 +4,7 @@ #include "a_strifeglobal.h" #include "p_enemy.h" #include "r_defs.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp index bed5f838ba..9c8cb6be3a 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" */ diff --git a/src/g_strife/a_reaver.cpp b/src/g_strife/a_reaver.cpp index 372aea794c..09d771a19b 100644 --- a/src/g_strife/a_reaver.cpp +++ b/src/g_strife/a_reaver.cpp @@ -6,7 +6,7 @@ #include "m_random.h" #include "p_local.h" #include "a_strifeglobal.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_reaverattack ("ReaverAttack"); diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index f2031a7a37..c4df1cba11 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" */ diff --git a/src/g_strife/a_sentinel.cpp b/src/g_strife/a_sentinel.cpp index 91adbb01ec..42a7aeb476 100644 --- a/src/g_strife/a_sentinel.cpp +++ b/src/g_strife/a_sentinel.cpp @@ -4,7 +4,7 @@ #include "a_action.h" #include "p_local.h" #include "m_random.h" -#include "thingdef/thingdef.h" +#include "vm.h" */ static FRandom pr_sentinelrefire ("SentinelRefire"); diff --git a/src/g_strife/a_spectral.cpp b/src/g_strife/a_spectral.cpp index 00b19055c6..1b1f13b1af 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 diff --git a/src/g_strife/a_stalker.cpp b/src/g_strife/a_stalker.cpp index 8ee07de8ab..210bd8c22a 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"); diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index 26ac88393b..20de58d4f9 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -13,7 +13,7 @@ #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" */ diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index ad6bbe133d..32ce0e3958 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" diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index be3c3bf2bf..66d635aa53 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" */ diff --git a/src/g_strife/a_templar.cpp b/src/g_strife/a_templar.cpp index 547d4d73e6..5ca2ef862b 100644 --- a/src/g_strife/a_templar.cpp +++ b/src/g_strife/a_templar.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 FRandom pr_templar ("Templar"); diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp index fed1c43371..6d1294b53d 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" */ diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index bcdf624d7b..122846a82b 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) diff --git a/src/info.cpp b/src/info.cpp index ea6701facf..191ed2bd5b 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -52,7 +52,7 @@ #include "cmdlib.h" #include "g_level.h" #include "stats.h" -#include "thingdef/thingdef.h" +#include "vm.h" #include "d_player.h" extern void LoadActors (); diff --git a/src/info.h b/src/info.h index 0e49e1f8fb..5ba7eafd9b 100644 --- a/src/info.h +++ b/src/info.h @@ -54,6 +54,18 @@ class FScanner; struct FActorInfo; class FIntCVar; +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 EStateType { STATE_Actor, diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 618189b4f0..0fcf4e4d5a 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 8921187420..39d7a8c0bf 100644 --- a/src/menu/menuinput.cpp +++ b/src/menu/menuinput.cpp @@ -40,6 +40,7 @@ #include "d_gui.h" #include "v_font.h" #include "v_palette.h" +#include "cmdlib.h" // [TP] New #includes #include "v_text.h" diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index 601c3e7365..a72a377407 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" diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 71ef65f22b..29aee9e126 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" diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index c6bc8215b0..c8e110a68d 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,8 @@ #include "p_maputl.h" #include "p_spec.h" #include "templates.h" +#include "vm.h" +#include "thingdef.h" #include "math/cmath.h" AActor *SingleActorFromTID(int tid, AActor *defactor); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index b7ad540957..5f63ff1e5f 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" diff --git a/src/p_enemy.h b/src/p_enemy.h index 1be77a4eca..7f4424fd6f 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_mobj.cpp b/src/p_mobj.cpp index 1ebec242ed..e443db3686 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,7 @@ #include "p_checkposition.h" #include "serializer.h" #include "r_utility.h" +#include "thingdef.h" // MACROS ------------------------------------------------------------------ diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index e5b076acdc..db2059088d 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -25,7 +25,7 @@ #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" diff --git a/src/p_pspr.h b/src/p_pspr.h index ea03e109f8..568c289d28 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. @@ -120,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_states.cpp b/src/p_states.cpp index 1a8116e53b..007f7f5cee 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -39,7 +39,8 @@ #include "i_system.h" #include "c_dispatch.h" #include "v_text.h" -#include "thingdef/thingdef.h" +#include "vm.h" +#include "thingdef.h" // 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 diff --git a/src/p_user.cpp b/src/p_user.cpp index 0f3b6a516d..c60e4bff67 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" diff --git a/src/thingdef/thingdef_exp.h b/src/scripting/codegeneration/thingdef_exp.h similarity index 100% rename from src/thingdef/thingdef_exp.h rename to src/scripting/codegeneration/thingdef_exp.h diff --git a/src/thingdef/thingdef_expression.cpp b/src/scripting/codegeneration/thingdef_expression.cpp similarity index 100% rename from src/thingdef/thingdef_expression.cpp rename to src/scripting/codegeneration/thingdef_expression.cpp diff --git a/src/thingdef/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp similarity index 99% rename from src/thingdef/olddecorations.cpp rename to src/scripting/decorate/olddecorations.cpp index 9afbfc965a..4bcb2c36c0 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/thingdef_exp.h" #include "r_data/r_translate.h" // TYPES ------------------------------------------------------------------- diff --git a/src/thingdef/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp similarity index 99% rename from src/thingdef/thingdef_exp.cpp rename to src/scripting/decorate/thingdef_exp.cpp index 11baef7226..2f52fb260b 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/thingdef_exp.h" FRandom pr_exrandom ("EX_Random"); diff --git a/src/thingdef/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp similarity index 99% rename from src/thingdef/thingdef_parse.cpp rename to src/scripting/decorate/thingdef_parse.cpp index 6d1077ffe9..5fbe27a9dd 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/thingdef_exp.h" #include "w_wad.h" #include "v_video.h" #include "version.h" diff --git a/src/thingdef/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp similarity index 99% rename from src/thingdef/thingdef_states.cpp rename to src/scripting/decorate/thingdef_states.cpp index 3b692391c6..59d620b2a4 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -54,7 +54,7 @@ #include "s_sound.h" #include "i_system.h" #include "colormatcher.h" -#include "thingdef_exp.h" +#include "codegeneration/thingdef_exp.h" #include "version.h" #include "templates.h" diff --git a/src/thingdef/thingdef.cpp b/src/scripting/thingdef.cpp similarity index 99% rename from src/thingdef/thingdef.cpp rename to src/scripting/thingdef.cpp index 8b174988d4..175aa89904 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -61,7 +61,7 @@ #include "p_conversation.h" #include "v_text.h" #include "thingdef.h" -#include "thingdef_exp.h" +#include "codegeneration/thingdef_exp.h" #include "a_sharedglobal.h" #include "vmbuilder.h" #include "stats.h" diff --git a/src/thingdef/thingdef.h b/src/scripting/thingdef.h similarity index 76% rename from src/thingdef/thingdef.h rename to src/scripting/thingdef.h index 152f324315..84f1f7d068 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; @@ -46,18 +47,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; @@ -171,13 +160,6 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) // //========================================================================== -struct AFuncDesc -{ - const char *Name; - actionf_p Function; - VMNativeFunction **VMPointer; -}; - AFuncDesc *FindFunction(const char * string); @@ -189,8 +171,6 @@ class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestr FName CheckCastKludges(FName in); void SetImplicitArgs(TArray *args, TArray *argflags, PClass *cls, DWORD funcflags); -PFunction *FindGlobalActionFunction(const char *name); - //========================================================================== // // Property parser @@ -232,23 +212,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 @@ -322,39 +292,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 100% rename from src/thingdef/thingdef_data.cpp rename to src/scripting/thingdef_data.cpp diff --git a/src/thingdef/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp similarity index 100% rename from src/thingdef/thingdef_properties.cpp rename to src/scripting/thingdef_properties.cpp diff --git a/src/zscript/vm.h b/src/scripting/vm/vm.h similarity index 90% rename from src/zscript/vm.h rename to src/scripting/vm/vm.h index a000e9533f..28b555e4ef 100644 --- a/src/zscript/vm.h +++ b/src/scripting/vm/vm.h @@ -3,6 +3,7 @@ #include "zstring.h" #include "dobject.h" +#include "autosegs.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 @@ -960,4 +961,63 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_OBJECT_OPT(x,type) ++paramnum; PARAM_OBJECT_OPT_AT(paramnum,x,type) #define PARAM_CLASS_OPT(x,base) ++paramnum; PARAM_CLASS_OPT_AT(paramnum,x,base) +typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ + +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 + +#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) + +class PFunction; + +PFunction *FindGlobalActionFunction(const char *name); + + #endif diff --git a/src/zscript/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp similarity index 100% rename from src/zscript/vmbuilder.cpp rename to src/scripting/vm/vmbuilder.cpp diff --git a/src/zscript/vmbuilder.h b/src/scripting/vm/vmbuilder.h similarity index 100% rename from src/zscript/vmbuilder.h rename to src/scripting/vm/vmbuilder.h diff --git a/src/zscript/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp similarity index 100% rename from src/zscript/vmdisasm.cpp rename to src/scripting/vm/vmdisasm.cpp diff --git a/src/zscript/vmexec.cpp b/src/scripting/vm/vmexec.cpp similarity index 100% rename from src/zscript/vmexec.cpp rename to src/scripting/vm/vmexec.cpp diff --git a/src/zscript/vmexec.h b/src/scripting/vm/vmexec.h similarity index 100% rename from src/zscript/vmexec.h rename to src/scripting/vm/vmexec.h diff --git a/src/zscript/vmframe.cpp b/src/scripting/vm/vmframe.cpp similarity index 100% rename from src/zscript/vmframe.cpp rename to src/scripting/vm/vmframe.cpp diff --git a/src/zscript/vmops.h b/src/scripting/vm/vmops.h similarity index 100% rename from src/zscript/vmops.h rename to src/scripting/vm/vmops.h diff --git a/src/zscript/ast.cpp b/src/scripting/zscript/ast.cpp similarity index 100% rename from src/zscript/ast.cpp rename to src/scripting/zscript/ast.cpp diff --git a/src/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon similarity index 100% rename from src/zscript/zcc-parse.lemon rename to src/scripting/zscript/zcc-parse.lemon diff --git a/src/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp similarity index 99% rename from src/zscript/zcc_compile.cpp rename to src/scripting/zscript/zcc_compile.cpp index 19af0e7c1d..0d9558a527 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -46,7 +46,7 @@ #include "v_text.h" #include "p_lnspec.h" #include "gdtoa.h" -#include "thingdef_exp.h" +#include "codegeneration/thingdef_exp.h" #define DEFINING_CONST ((PSymbolConst *)(void *)1) diff --git a/src/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h similarity index 100% rename from src/zscript/zcc_compile.h rename to src/scripting/zscript/zcc_compile.h diff --git a/src/zscript/zcc_expr.cpp b/src/scripting/zscript/zcc_expr.cpp similarity index 100% rename from src/zscript/zcc_expr.cpp rename to src/scripting/zscript/zcc_expr.cpp diff --git a/src/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h similarity index 100% rename from src/zscript/zcc_exprlist.h rename to src/scripting/zscript/zcc_exprlist.h diff --git a/src/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp similarity index 100% rename from src/zscript/zcc_parser.cpp rename to src/scripting/zscript/zcc_parser.cpp diff --git a/src/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h similarity index 100% rename from src/zscript/zcc_parser.h rename to src/scripting/zscript/zcc_parser.h diff --git a/src/serializer.cpp b/src/serializer.cpp index 7861701c01..5564cdf503 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 21370d082e..42933e5dbd 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -58,6 +58,7 @@ #include "i_music.h" #include "i_musicinterns.h" #include "tempfiles.h" +#include "cmdlib.h" #include "oalload.h" diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 108edff3b6..12ca10e320 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 From 59ed26c0b61a0a3cd63e5b140b98db31973c6f70 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 12 Oct 2016 20:42:41 +0200 Subject: [PATCH 023/471] - resorted some of thingdef.cpp's contents into more appropriate files. - split FinishActor into several functions. While DECORATE can, ZSCRIPT cannot do all this in one go. - split the state finalization into several class-specific virtual functions. --- src/g_shared/a_pickups.cpp | 6 + src/g_shared/a_pickups.h | 2 + src/g_shared/a_weapons.cpp | 32 ++++ src/info.cpp | 71 +++++++ src/info.h | 4 + src/scripting/decorate/thingdef_parse.cpp | 131 ++++++++++++- src/scripting/thingdef.cpp | 215 +--------------------- src/scripting/thingdef.h | 2 - src/scripting/zscript/zcc_compile.cpp | 16 ++ wadsrc/static/zscript/actor.txt | 27 +-- 10 files changed, 286 insertions(+), 220 deletions(-) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 906be04c45..c4daae0241 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -65,6 +65,12 @@ void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass) } } +void PClassInventory::Finalize(FStateDefinitions &statedef) +{ + Super::Finalize(statedef); + ((AActor*)Defaults)->flags |= MF_SPECIAL; +} + IMPLEMENT_CLASS(PClassAmmo) PClassAmmo::PClassAmmo() diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 9dba52639a..45676a214d 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. @@ -274,6 +275,7 @@ protected: public: PClassWeapon(); virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); + void Finalize(FStateDefinitions &statedef); int SlotNumber; int SlotPriority; diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 36ffbc2715..84305b9cdc 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -67,6 +67,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 diff --git a/src/info.cpp b/src/info.cpp index 191ed2bd5b..8089e065b8 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -53,7 +53,9 @@ #include "g_level.h" #include "stats.h" #include "vm.h" +#include "thingdef.h" #include "d_player.h" +#include "doomerrors.h" extern void LoadActors (); extern void InitBotStuff(); @@ -380,6 +382,75 @@ void PClassActor::InitializeNativeDefaults() } } +//========================================================================== +// +// PClassActor :: SetReplacement +// +// Sets as a replacement class for another class. +// +//========================================================================== + +bool PClassActor::SetReplacement(FName replaceName) +{ + // Check for "replaces" + if (replaceName != NAME_None) + { + // Get actor name + PClassActor *replacee = PClass::FindActor(replaceName); + + if (replacee == nullptr) + { + return false; + } + if (replacee != nullptr) + { + replacee->Replacement = this; + Replacee = replacee; + } + } + 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 + { + statedef.FinishStates(this, defaults); + } + catch (CRecoverableError &) + { + statedef.MakeStateDefines(NULL); + throw; + } + statedef.InstallStates(this, defaults); + statedef.MakeStateDefines(NULL); +} + //========================================================================== // // PClassActor :: RegisterIDs diff --git a/src/info.h b/src/info.h index 5ba7eafd9b..0fe479d20e 100644 --- a/src/info.h +++ b/src/info.h @@ -53,6 +53,7 @@ struct Baggage; class FScanner; struct FActorInfo; class FIntCVar; +class FStateDefinitions; enum EStateDefineFlags { @@ -234,6 +235,9 @@ public: 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); diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 5fbe27a9dd..186b269cec 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -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; +} //========================================================================== // @@ -1126,6 +1165,80 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls) ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action); } +//========================================================================== +// +// 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; +} + //========================================================================== // // Starts a new actor definition @@ -1216,7 +1329,10 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag) 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; @@ -1293,7 +1409,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); } diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 175aa89904..5227009e75 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -76,202 +76,6 @@ 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 @@ -426,14 +230,6 @@ static void FinishThingdef() 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); - } } @@ -454,10 +250,11 @@ void LoadActors () timer.Reset(); timer.Clock(); ActorDamageFuncs.Clear(); - FScriptPosition::ResetErrorCounter(); InitThingdef(); lastlump = 0; ParseScripts(); + + FScriptPosition::ResetErrorCounter(); while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1) { FScanner sc(lump); @@ -471,4 +268,12 @@ void LoadActors () timer.Unclock(); if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); // Base time: ~52 ms + + // 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); + } } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 84f1f7d068..714657d24d 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -178,10 +178,8 @@ void SetImplicitArgs(TArray *args, TArray *argflags, PClass *cls //========================================================================== 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); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 0d9558a527..e8ea8a6e73 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -69,6 +69,10 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) name << "nodes - " << FName(cnode->NodeName); cls->TreeNodes.SetName(name); + if (!static_cast(cnode->Type)->SetReplacement(cnode->Replaces->Id)) + { + Warn(cnode, "Replaced type '%s' not found for %s", FName(cnode->Replaces->Id).GetChars(), cnode->Type->TypeName.GetChars()); + } // Need to check if the class actually has a body. if (node != nullptr) do @@ -1836,6 +1840,10 @@ void ZCCCompiler::InitDefaults() content = static_cast(content->SiblingNext); } while (content != d->Content); } + if (bag.DropItemSet) + { + bag.Info->SetDropItems(bag.DropItemList); + } } } } @@ -2239,5 +2247,13 @@ void ZCCCompiler::CompileStates() 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()); + } } } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 34c1271e02..a15ec893a4 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -371,25 +371,30 @@ class Actor : Thinker native 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 + TNT1 A -1; + Stop; Null: - TNT1 A 1 - Stop + TNT1 A 1; + Stop; GenericFreezeDeath: // Generic freeze death frames. Woo! - "####" "#" 5 A_GenericFreezeDeath - "----" A 1 A_FreezeDeathChunks - Wait + #### # 5 A_GenericFreezeDeath; + ---- A 1 A_FreezeDeathChunks; + Wait; GenericCrush: - POL5 A -1 - Stop + POL5 A -1; + Stop; + Test.State: + &&&& A[\] 5 offset(4,4*2); + &&&& A[\] DEFAULT_HEALTH; + abcd efgh random(3, 6); + lght blahblah 5*3 light("furz", "bläh", "rülps"); + lght blahblah 5 light("boing"); + goto Actor::Spawn+1; } -*/ // Internal functions deprecated private native state __decorate_internal_state__(state s); From a72fbb771f1287f08530ca43a103a61656e76bba Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Oct 2016 00:53:59 +0200 Subject: [PATCH 024/471] - separated the code generation from the DECORATE parser and cleaned up the interface to the code generator. Most importantly, the VMScriptFunctions are now preallocated when being added to the list of functions to compile and will be filled in later by the code generator. This allowed the removal of some ugly maintenance code. --- src/CMakeLists.txt | 4 + src/d_dehacked.cpp | 3 +- src/scripting/codegeneration/thingdef_exp.h | 11 +- .../codegeneration/thingdef_expression.cpp | 18 +- src/scripting/decorate/thingdef_parse.cpp | 47 +--- src/scripting/decorate/thingdef_states.cpp | 36 +-- src/scripting/thingdef.cpp | 225 +++++------------- src/scripting/thingdef.h | 19 -- src/scripting/thingdef_properties.cpp | 3 +- src/scripting/vm/vm.h | 1 + src/scripting/vm/vmbuilder.cpp | 120 +++++++++- src/scripting/vm/vmbuilder.h | 32 ++- src/scripting/vm/vmdisasm.cpp | 19 ++ src/scripting/zscript/zcc_compile.cpp | 8 +- src/zstring.cpp | 8 + src/zstring.h | 7 + 16 files changed, 287 insertions(+), 274 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bd01cad424..b612684d5c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -815,11 +815,15 @@ file( GLOB HEADER_FILES posix/cocoa/*.h posix/sdl/*.h r_data/*.h + rapidjson/*.h resourcefiles/*.h sfmt/*.h sound/*.h textures/*.h scripting/*.h + scripting/codegeneration/*.h + scripting/decorate/*.h + scripting/zscript/*.h scripting/vm/*.h xlat/*.h *.h diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index d5150e985e..8e69ecb067 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -820,7 +820,8 @@ void SetDehParams(FState *state, int codepointer) int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2); buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation, ATAG_OBJECT), NAP + argcount, 0); // Attach it to the state. - VMScriptFunction *sfunc = buildit.MakeFunction(); + VMScriptFunction *sfunc = new VMScriptFunction; + buildit.MakeFunction(sfunc); sfunc->NumArgs = NAP; state->SetAction(sfunc); } diff --git a/src/scripting/codegeneration/thingdef_exp.h b/src/scripting/codegeneration/thingdef_exp.h index 65c3ace63f..2e9af65b6d 100644 --- a/src/scripting/codegeneration/thingdef_exp.h +++ b/src/scripting/codegeneration/thingdef_exp.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; @@ -58,14 +61,15 @@ class FxJumpStatement; // // //========================================================================== +struct FScriptPosition; struct FCompileContext { TArray Jumps; PPrototype *ReturnProto; - PClassActor *Class; + PClass *Class; - FCompileContext(PClassActor *cls = nullptr, PPrototype *ret = nullptr); + FCompileContext(PClass *cls = nullptr, PPrototype *ret = nullptr); PSymbol *FindInClass(FName identifier); PSymbol *FindGlobal(FName identifier); @@ -1175,7 +1179,6 @@ public: class FxDamageValue : public FxExpression { FxExpression *val; - VMScriptFunction *MyFunction; public: @@ -1184,8 +1187,6 @@ public: FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); - VMScriptFunction *GetFunction() const { return MyFunction; } - void SetFunction(VMScriptFunction *func) { MyFunction = func; } }; //========================================================================== diff --git a/src/scripting/codegeneration/thingdef_expression.cpp b/src/scripting/codegeneration/thingdef_expression.cpp index ae2639b733..31acc391e6 100644 --- a/src/scripting/codegeneration/thingdef_expression.cpp +++ b/src/scripting/codegeneration/thingdef_expression.cpp @@ -91,7 +91,7 @@ static const FLOP FxFlops[] = // //========================================================================== -FCompileContext::FCompileContext(PClassActor *cls, PPrototype *ret) : Class(cls), ReturnProto(ret) +FCompileContext::FCompileContext(PClass *cls, PPrototype *ret) : Class(cls), ReturnProto(ret) { } @@ -3902,7 +3902,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction() // 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)) + if ((ArgList ? ArgList->Size() : 0) == 0 && (Function->Flags & VARF_Action)) { return Function->Variants[0].Implementation; } @@ -4922,20 +4922,19 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); ABORT(ctx.Class); + auto aclass = dyn_cast(ctx.Class); - if (ctx.Class->NumOwnedStates == 0) - { - // This can't really happen - assert(false); - } - if (ctx.Class->NumOwnedStates <= index) + // This expression type can only be used from DECORATE, so there's no need to consider the possibility of calling it from a non-actor. + 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 NULL; } - FxExpression *x = new FxConstant(ctx.Class->OwnedStates + index, ScriptPosition); + FxExpression *x = new FxConstant(aclass->OwnedStates + index, ScriptPosition); delete this; return x; } @@ -5245,7 +5244,6 @@ FxDamageValue::FxDamageValue(FxExpression *v) { val = v; ValueType = TypeVoid; - MyFunction = NULL; } FxDamageValue::~FxDamageValue() diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 186b269cec..a863c4a4ea 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -441,42 +441,6 @@ static void ParseArgListDef(FScanner &sc, PClassActor *cls, sc.MustGetToken(';'); } -//========================================================================== -// -// SetImplicitArgs -// -// Adds the parameters implied by the function flags. -// -//========================================================================== - -void SetImplicitArgs(TArray *args, TArray *argflags, PClass *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(RUNTIME_CLASS(AActor))); - if (argflags != NULL) argflags->Push(VARF_Implicit); - } - if (funcflags & VARF_Action) - { - // implied stateowner and callingstate pointers - if (args != NULL) - { - args->Push(NewClassPointer(cls)); - args->Push(TypeState); - } - if (argflags != NULL) - { - argflags->Push(VARF_Implicit); - argflags->Push(VARF_Implicit); - } - } -} - //========================================================================== // // ParseFunctionDef @@ -1559,3 +1523,14 @@ void ParseDecorate (FScanner &sc) } } } + +void ParseAllDecorate() +{ + int lastlump, lump; + + while ((lump = Wads.FindLump("DECORATE", &lastlump)) != -1) + { + FScanner sc(lump); + ParseDecorate(sc); + } +} \ No newline at end of file diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 59d620b2a4..143144aa53 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -57,8 +57,7 @@ #include "codegeneration/thingdef_exp.h" #include "version.h" #include "templates.h" - -TDeletingArray StateTempCalls; +#include "vmbuilder.h" //========================================================================== //*** @@ -141,13 +140,14 @@ 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; sc.MustGetStringName ("{"); sc.SetEscape(false); // disable escape sequences in the state parser while (!sc.CheckString ("}") && !sc.End) { + ScriptCode = nullptr; memset(&state,0,sizeof(state)); statestring = ParseStateString(sc); if (!statestring.CompareNoCase("GOTO")) @@ -224,10 +224,6 @@ do_stop: sc.MustGetString(); statestring = sc.String; - if (tcall == NULL) - { - tcall = new FStateTempCall; - } if (sc.CheckString("RANDOM")) { int min, max; @@ -315,35 +311,27 @@ 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: + if (ScriptCode != nullptr) + { + state.ActionFunc = FunctionBuildList.AddFunction(actor, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true); + } int count = bag.statedef.AddStates(&state, statestring); 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; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 5227009e75..1a761b8c25 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -66,174 +66,48 @@ #include "vmbuilder.h" #include "stats.h" -TDeletingArray ActorDamageFuncs; - - // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void InitThingdef(); -void ParseDecorate(FScanner &ctx); // STATIC FUNCTION PROTOTYPES -------------------------------------------- PClassActor *QuestItemClasses[31]; //========================================================================== // -// Do some postprocessing after everything has been defined +// SetImplicitArgs +// +// Adds the parameters implied by the function flags. // //========================================================================== -static void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen) +void SetImplicitArgs(TArray *args, TArray *argflags, PClass *cls, DWORD funcflags) { - 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); + // 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(VARF_Implicit); + } + if (funcflags & VARF_Action) + { + // implied caller and callingstate pointers + if (args != NULL) + { + args->Insert(0, NewClassPointer(RUNTIME_CLASS(AActor))); // the caller must go before self due to an old design mistake. + args->Push(TypeState); + } + if (argflags != NULL) + { + argflags->Push(VARF_Implicit); + argflags->Push(VARF_Implicit); + } + } } -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(); -} - - - //========================================================================== // // LoadActors @@ -242,29 +116,48 @@ static void FinishThingdef() // //========================================================================== void ParseScripts(); +void ParseAllDecorate(); void LoadActors () { - int lastlump, lump; cycle_t timer; timer.Reset(); timer.Clock(); - ActorDamageFuncs.Clear(); - InitThingdef(); - lastlump = 0; - ParseScripts(); - FScriptPosition::ResetErrorCounter(); - while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1) - { - FScanner sc(lump); - ParseDecorate (sc); - } - FinishThingdef(); + + InitThingdef(); + ParseScripts(); + ParseAllDecorate(); + + FunctionBuildList.Build(); + if (FScriptPosition::ErrorCounter > 0) { I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter); } + + int errorcount = 0; + for (auto ti : PClassActor::AllActorClasses) + { + if (ti->Size == TentativeClass) + { + Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); + errorcount++; + continue; + } + + if (GetDefaultByType(ti) == nullptr) + { + Printf(TEXTCOLOR_RED "No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars()); + errorcount++; + continue; + } + } + if (errorcount > 0) + { + I_Error("%d errors during actor postprocessing", errorcount); + } + timer.Unclock(); if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); // Base time: ~52 ms diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 714657d24d..4a984dd5c4 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -101,25 +101,6 @@ public: 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; - //========================================================================== // // Extra info maintained while defining an actor. diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 3c171be7fb..084736c24c 100644 --- a/src/scripting/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" //========================================================================== @@ -656,7 +657,7 @@ DEFINE_PROPERTY(damage, X, Actor) } else { - defaults->DamageFunc = (VMFunction *)(uintptr_t)(ActorDamageFuncs.Push(id) + 1); + defaults->DamageFunc = FunctionBuildList.AddFunction(bag.Info, id, FStringf("%s.DamageFunction", bag.Info->TypeName.GetChars()), false); } } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 28b555e4ef..69e5b81b31 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1020,4 +1020,5 @@ class PFunction; PFunction *FindGlobalActionFunction(const char *name); + #endif diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index fd9a0063ef..4a880cef6b 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -32,6 +32,10 @@ */ #include "vmbuilder.h" +#include "codegeneration/thingdef_exp.h" +#include "info.h" +#include "m_argv.h" +#include "thingdef.h" //========================================================================== // @@ -68,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. @@ -106,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; } //========================================================================== @@ -634,3 +634,113 @@ 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(PClass *cls, FxExpression *code, const FString &name, bool statecall) +{ + auto func = code->GetDirectFunction(); + if (func != nullptr) + { + delete code; + return func; + } + + Printf("Adding %s\n", name.GetChars()); + + Item it; + it.Class = cls; + it.Code = code; + it.DumpName = name; + it.Function = new VMScriptFunction; + it.Proto = nullptr; + it.type = statecall; + 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.Class, nullptr); + item.Code = item.Code->Resolve(ctx); + item.Proto = ctx.ReturnProto; + + // Make sure resolving it didn't obliterate it. + if (item.Code != nullptr) + { + VMFunctionBuilder buildit(true); + + assert(item.Proto != nullptr); + + int numargs; + int flags; + + // Kludge alert. This needs to be done in a more universal fashion. + // Right now there's only action and damage functions, so for the time being + // this will do to get the whole thing started first. + + if (item.type == 1) // anonymous action function + { + numargs = NAP; + flags = VARF_Method | VARF_Action; + } + else + { + numargs = 1; + flags = VARF_Method; + } + + // Generate prototype for this anonymous function + buildit.Registers[REGT_POINTER].Get(numargs); + TArray args(numargs); + SetImplicitArgs(&args, nullptr, item.Class, flags); + + VMScriptFunction *sfunc = item.Function; + item.Function->Proto = NewPrototype(item.Proto->ReturnTypes, args); + + // Emit code + item.Code->Emit(&buildit); + buildit.MakeFunction(item.Function); + item.Function->NumArgs = numargs; + + if (dump != nullptr) + { + char label[64]; + int labellen = mysnprintf(label, countof(label), item.DumpName, + item.Class->TypeName.GetChars()); + DumpFunction(dump, sfunc, label, labellen); + codesize += sfunc->CodeSize; + } + } + delete item.Code; + } + if (dump != nullptr) + { + fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4); + fclose(dump); + } +} \ No newline at end of file diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index ed2516c2ae..59e9fbe79b 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -26,7 +26,7 @@ public: VMFunctionBuilder(bool checkself = false); ~VMFunctionBuilder(); - VMScriptFunction *MakeFunction(); + void MakeFunction(VMScriptFunction *func); // Returns the constant register holding the value. int GetConstantInt(int val); @@ -87,4 +87,34 @@ private: }; +void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen); + + +//========================================================================== +// +// +// +//========================================================================== +class FxExpression; + +class FFunctionBuildList +{ + struct Item + { + PClass *Class = nullptr; + FxExpression *Code = nullptr; + PPrototype *Proto = nullptr; + VMScriptFunction *Function = nullptr; + FString DumpName; + int type; // temporary kludge + }; + + TArray mItems; + +public: + VMFunction *AddFunction(PClass *cls, FxExpression *code, const FString &name, bool statecall = false); + void Build(); +}; + +extern FFunctionBuildList FunctionBuildList; #endif diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 68b92f9f3d..0b84cf8c09 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -33,6 +33,7 @@ #include "vm.h" #include "c_console.h" +#include "templates.h" #define NOP MODE_AUNUSED | MODE_BUNUSED | MODE_CUNUSED @@ -598,3 +599,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/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e8ea8a6e73..d175bd9175 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -47,6 +47,7 @@ #include "p_lnspec.h" #include "gdtoa.h" #include "codegeneration/thingdef_exp.h" +#include "vmbuilder.h" #define DEFINING_CONST ((PSymbolConst *)(void *)1) @@ -2165,12 +2166,7 @@ void ZCCCompiler::CompileStates() auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); if (code != nullptr) { - auto tcall = new FStateTempCall; - tcall->Code = code; - tcall->ActorClass = static_cast(c->Type()); - tcall->FirstState = statedef.GetStateCount() - count; - tcall->NumStates = count; - StateTempCalls.Push(tcall); + state.ActionFunc = FunctionBuildList.AddFunction(c->Type(), code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), true); } } break; diff --git a/src/zstring.cpp b/src/zstring.cpp index f4a3a1fbbf..3794a472aa 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -1192,3 +1192,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 00f373b59a..519b354bfb 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -308,6 +308,13 @@ private: bool operator >= (const FString &illegal) const; }; +class FStringf : public FString +{ +public: + FStringf(const char *fmt, ...); +}; + + namespace StringFormat { enum From 433bf46010f45b178c753c7dddb526ec8a55fc31 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Oct 2016 20:45:52 +0200 Subject: [PATCH 025/471] - removed token 'mode' because it isn't used anywhere and clashed with some actor properties. - fixed uninitialized counter variable in DECORATE parser. - allow dottable_id of xxx.color so that the property parser can parse 'powerup.color'. - fixed crash with actor replacement in script compiler. - add the lump number to tree nodes because parts of the property parser need that to make decisions. - removed test stuff. - converted inventory.txt, player.txt and specialspot.txt to ZSCRIPT. These were the minimal files required to allow actor.txt to parse successfully. - removed the converted files from the DECORATE include list so that these are entirely handled by ZSCRIPT now. --- src/sc_man_scanner.re | 1 - src/sc_man_tokens.h | 1 - src/scripting/decorate/thingdef_parse.cpp | 2 +- src/scripting/vm/vmbuilder.cpp | 2 +- src/scripting/zscript/zcc-parse.lemon | 10 + src/scripting/zscript/zcc_compile.cpp | 12 +- src/scripting/zscript/zcc_parser.cpp | 2 + src/scripting/zscript/zcc_parser.h | 1 + wadsrc/static/actors/actor.txt | 393 --------------- wadsrc/static/actors/shared/inventory.txt | 376 -------------- wadsrc/static/actors/shared/player.txt | 52 -- wadsrc/static/actors/shared/specialspot.txt | 5 - wadsrc/static/decorate.txt | 8 +- wadsrc/static/zscript.txt | 9 + wadsrc/static/zscript/actor.txt | 7 - wadsrc/static/zscript/shared/inventory.txt | 501 +++++++++++++++++++ wadsrc/static/zscript/shared/player.txt | 58 +++ wadsrc/static/zscript/shared/specialspot.txt | 5 + 18 files changed, 601 insertions(+), 844 deletions(-) delete mode 100644 wadsrc/static/actors/actor.txt delete mode 100644 wadsrc/static/actors/shared/inventory.txt delete mode 100644 wadsrc/static/actors/shared/player.txt delete mode 100644 wadsrc/static/actors/shared/specialspot.txt create mode 100644 wadsrc/static/zscript.txt create mode 100644 wadsrc/static/zscript/shared/inventory.txt create mode 100644 wadsrc/static/zscript/shared/player.txt create mode 100644 wadsrc/static/zscript/shared/specialspot.txt diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 92702f9186..ba0e9a8e53 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -118,7 +118,6 @@ 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); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 2464629409..934558d547 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'") diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index a863c4a4ea..f567d91e0e 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -1526,7 +1526,7 @@ void ParseDecorate (FScanner &sc) void ParseAllDecorate() { - int lastlump, lump; + int lastlump = 0, lump; while ((lump = Wads.FindLump("DECORATE", &lastlump)) != -1) { diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 4a880cef6b..f111c45293 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -658,7 +658,7 @@ VMFunction *FFunctionBuildList::AddFunction(PClass *cls, FxExpression *code, con return func; } - Printf("Adding %s\n", name.GetChars()); + //Printf("Adding %s\n", name.GetChars()); Item it; it.Class = cls; diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 7213b4dbc6..51a221af74 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -211,6 +211,16 @@ dottable_id(X) ::= dottable_id(A) DOT IDENTIFIER(B). 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: diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index d175bd9175..6e84476904 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -70,7 +70,7 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) name << "nodes - " << FName(cnode->NodeName); cls->TreeNodes.SetName(name); - if (!static_cast(cnode->Type)->SetReplacement(cnode->Replaces->Id)) + if (cnode->Replaces != nullptr && !static_cast(cnode->Type)->SetReplacement(cnode->Replaces->Id)) { Warn(cnode, "Replaced type '%s' not found for %s", FName(cnode->Replaces->Id).GetChars(), cnode->Type->TypeName.GetChars()); } @@ -1565,7 +1565,9 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper if (exp->NodeType != AST_ExprConstant) { - Error(exp, "%s: non-constant parameter", prop->name); + // 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; @@ -1654,6 +1656,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper if (exp != property->Values) { Error(property, "Too many values for '%s'", prop->name); + return; } break; } @@ -1662,6 +1665,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper if (*p < 'a') { Error(property, "Insufficient parameters for %s", prop->name); + return; } break; } @@ -1816,7 +1820,7 @@ void ZCCCompiler::InitDefaults() bag.StateSet = false; bag.fromZScript = true; bag.CurrentState = 0; - bag.Lumpnum = Wads.CheckNumForFullName(*c->cls->SourceName, true); + bag.Lumpnum = c->cls->SourceLump; bag.DropItemList = nullptr; bag.ScriptPosition.StrictErrors = true; // The actual script position needs to be set per property. @@ -2061,6 +2065,8 @@ void ZCCCompiler::CompileStates() } 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)); + for (auto s : c->States) { auto st = s->Body; diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 0d69141f08..b803b41584 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -399,6 +399,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; @@ -408,5 +409,6 @@ 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->SourceLump = sc->LumpNum; return node; } diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 2a73c86811..5dae72ee0e 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -149,6 +149,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 diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt deleted file mode 100644 index eecc843d39..0000000000 --- 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); - 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/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt deleted file mode 100644 index 43a33f93aa..0000000000 --- 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/player.txt b/wadsrc/static/actors/shared/player.txt deleted file mode 100644 index ac5ceb0a7a..0000000000 --- a/wadsrc/static/actors/shared/player.txt +++ /dev/null @@ -1,52 +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 - 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/specialspot.txt b/wadsrc/static/actors/shared/specialspot.txt deleted file mode 100644 index fc2bd254ac..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index a77a4d5831..e921b55084 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,7 +1,7 @@ -#include "actors/actor.txt" +//#include "actors/actor.txt" -#include "actors/shared/inventory.txt" -#include "actors/shared/player.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" @@ -15,7 +15,7 @@ #include "actors/shared/soundsequence.txt" #include "actors/shared/soundenvironment.txt" #include "actors/shared/bridge.txt" -#include "actors/shared/specialspot.txt" +//#include "actors/shared/specialspot.txt" #include "actors/shared/teleport.txt" #include "actors/shared/camera.txt" #include "actors/shared/movingcamera.txt" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt new file mode 100644 index 0000000000..b0d3ec9256 --- /dev/null +++ b/wadsrc/static/zscript.txt @@ -0,0 +1,9 @@ +zscript/constants.txt +zscript/actor.txt + +zscript/shared/inventory.txt +zscript/shared/player.txt +zscript/shared/specialspot.txt + +//zscript/test1.txt + diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index a15ec893a4..9352028b31 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -387,13 +387,6 @@ class Actor : Thinker native GenericCrush: POL5 A -1; Stop; - Test.State: - &&&& A[\] 5 offset(4,4*2); - &&&& A[\] DEFAULT_HEALTH; - abcd efgh random(3, 6); - lght blahblah 5*3 light("furz", "bläh", "rülps"); - lght blahblah 5 light("boing"); - goto Actor::Spawn+1; } // Internal functions diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt new file mode 100644 index 0000000000..fe60fdc1a0 --- /dev/null +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -0,0 +1,501 @@ +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"; + } + + // functions that can be used from weapons and CustomInventory. These require that 'self' is of type class and be treated as such in the scripts. + /*inventory*/ action native state A_JumpIfNoAmmo(state label); + /*inventory*/ action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = ""); + /*inventory*/ action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); + /*inventory*/ 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); + /*inventory*/ action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + /*inventory*/ action native void A_Light(int extralight); + /*inventory*/ action native void A_Light0(); + /*inventory*/ action native void A_Light1(); + /*inventory*/ action native void A_Light2(); + /*inventory*/ action native void A_LightInverse(); + /*inventory*/ action native void A_WeaponReady(int flags = 0); + /*inventory*/ action native void A_Lower(); + /*inventory*/ action native void A_Raise(); + /*inventory*/ action native void A_FirePistol(); + /*inventory*/ action native void A_FireShotgun(); + /*inventory*/ action native void A_FireShotgun2(); + /*inventory*/ action native void A_OpenShotgun2(); + /*inventory*/ action native void A_LoadShotgun2(); + /*inventory*/ action native void A_CloseShotgun2(); + /*inventory*/ action native void A_FireCGun(); + /*inventory*/ action native void A_FireSTGrenade(class grenadetype = "Grenade"); + /*inventory*/ action native void A_FireMissile(); + /*inventory*/ action native void A_FirePlasma(); + /*inventory*/ action native void A_FireRailgun(); + /*inventory*/ action native void A_FireRailgunLeft(); + /*inventory*/ action native void A_FireRailgunRight(); + /*inventory*/ action native void A_RailWait(); + /*inventory*/ action native void A_BFGsound(); + /*inventory*/ action native void A_FireBFG(); + /*inventory*/ action native void A_FireOldBFG(); + /*inventory*/ action native void A_ReFire(state flash = ""); + /*inventory*/ action native void A_ClearReFire(); + /*inventory*/ action native void A_CheckReload(); + /*inventory*/ action native void A_GunFlash(state flash = "", int flags = 0); + /*inventory*/ 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"); + /*inventory*/ action native state A_CheckForReload(int counter, state label, bool dontincrement = false); + /*inventory*/ action native void A_ResetReloadCounter(); + + // These are regular functions for the item itself. + action native void A_RestoreSpecialPosition(); + action native void A_RestoreSpecialDoomThing(); + action native void A_RestoreSpecialThing1(); + action native void 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; + } +} + +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 : Inventory native {} + +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 : Inventory native +{ + Default + { + 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; + } + + /*inventory*/ action native void A_ZoomFactor(float scale = 1, int flags = 0); + const ZOOM_INSTANT = 1; + const ZOOM_NOSCALETURNING = 2; + + /*inventory*/ action 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/player.txt b/wadsrc/static/zscript/shared/player.txt new file mode 100644 index 0000000000..b205a2a37a --- /dev/null +++ b/wadsrc/static/zscript/shared/player.txt @@ -0,0 +1,58 @@ +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; + 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/specialspot.txt b/wadsrc/static/zscript/shared/specialspot.txt new file mode 100644 index 0000000000..a06d41c279 --- /dev/null +++ b/wadsrc/static/zscript/shared/specialspot.txt @@ -0,0 +1,5 @@ + +class SpecialSpot : Actor native +{ + action native void A_SpawnSingleItem(class type, int fail_sp = 0, int fail_co = 0, int fail_dm = 0); +} From 7e8d7eb2ecc74c07f61fdb753bf820b2f540e8e8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Oct 2016 22:52:31 +0200 Subject: [PATCH 026/471] - fixed parsing of 'damage' default property. - fixed processing of goto labels. --- src/scripting/zscript/zcc_compile.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6e84476904..5e0e648564 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1575,8 +1575,13 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper switch ((*p) & 223) { - case 'I': 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); @@ -2188,7 +2193,7 @@ void ZCCCompiler::CompileStates() auto part = sg->Label; do { - statename << part->Id << '.'; + 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 From 7de683f9f52b86d89ef91d08f149bba7c81fd80c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 00:40:20 +0200 Subject: [PATCH 027/471] - converted a few more DECORATE files. - started with the AST converter. So far it only deals with direct function calls with simple constants as parameters. - added an error condition for the defaults block to get rid of some asserts. --- .../codegeneration/thingdef_expression.cpp | 9 +- src/scripting/zscript/zcc-parse.lemon | 1 + src/scripting/zscript/zcc_compile.cpp | 91 ++++- src/scripting/zscript/zcc_compile.h | 6 + wadsrc/static/actors/shared/action.txt | 56 --- wadsrc/static/actors/shared/blood.txt | 69 ---- wadsrc/static/actors/shared/botstuff.txt | 19 - wadsrc/static/actors/shared/debris.txt | 331 ---------------- wadsrc/static/actors/shared/morph.txt | 15 - wadsrc/static/actors/shared/sharedmisc.txt | 178 --------- wadsrc/static/decorate.txt | 12 +- wadsrc/static/zscript.txt | 6 + wadsrc/static/zscript/shared/blood.txt | 78 ++++ wadsrc/static/zscript/shared/botstuff.txt | 25 ++ wadsrc/static/zscript/shared/debris.txt | 364 ++++++++++++++++++ wadsrc/static/zscript/shared/ice.txt | 61 +++ wadsrc/static/zscript/shared/morph.txt | 21 + wadsrc/static/zscript/shared/sharedmisc.txt | 220 +++++++++++ 18 files changed, 881 insertions(+), 681 deletions(-) delete mode 100644 wadsrc/static/actors/shared/action.txt delete mode 100644 wadsrc/static/actors/shared/blood.txt delete mode 100644 wadsrc/static/actors/shared/botstuff.txt delete mode 100644 wadsrc/static/actors/shared/debris.txt delete mode 100644 wadsrc/static/actors/shared/morph.txt delete mode 100644 wadsrc/static/actors/shared/sharedmisc.txt create mode 100644 wadsrc/static/zscript/shared/blood.txt create mode 100644 wadsrc/static/zscript/shared/botstuff.txt create mode 100644 wadsrc/static/zscript/shared/debris.txt create mode 100644 wadsrc/static/zscript/shared/ice.txt create mode 100644 wadsrc/static/zscript/shared/morph.txt create mode 100644 wadsrc/static/zscript/shared/sharedmisc.txt diff --git a/src/scripting/codegeneration/thingdef_expression.cpp b/src/scripting/codegeneration/thingdef_expression.cpp index 31acc391e6..77b062ed65 100644 --- a/src/scripting/codegeneration/thingdef_expression.cpp +++ b/src/scripting/codegeneration/thingdef_expression.cpp @@ -3622,12 +3622,19 @@ FxFunctionCall::~FxFunctionCall() //========================================================================== // -// +// Note: This currently only deals with the simple cases and needs some changes. // //========================================================================== FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { + // This part is mostly a kludge, it really needs to get the class type from Self. + PFunction *afd = dyn_cast(ctx.Class->Symbols.FindSymbol(MethodName, true)); + if (afd != nullptr) + { + return new FxVMFunctionCall(afd, ArgList, ScriptPosition, false); + } + for (size_t i = 0; i < countof(FxFlops); ++i) { if (MethodName == FxFlops[i].Name) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 51a221af74..96b4b66c15 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -565,6 +565,7 @@ default_statement_list(X) ::= default_statement_list(X) default_statement(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*/ } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 5e0e648564..904f938ca8 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -45,6 +45,7 @@ #include "zcc_compile.h" #include "v_text.h" #include "p_lnspec.h" +#include "i_system.h" #include "gdtoa.h" #include "codegeneration/thingdef_exp.h" #include "vmbuilder.h" @@ -2028,10 +2029,6 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a // This is the simple case which doesn't require work on the tree. return new FxVMFunctionCall(afd, nullptr, *af, true); } - else - { - // need to generate a function from the information. - } } else { @@ -2039,8 +2036,10 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a return nullptr; } } - Error(af, "Complex action functions not supported yet."); - return nullptr; + return ConvertAST(af); + + //Error(af, "Complex action functions not supported yet."); + //return nullptr; /* bool hasfinalret; @@ -2264,3 +2263,83 @@ void ZCCCompiler::CompileStates() } } } + +//========================================================================== +// +// Convert the AST data for the code generator. +// +//========================================================================== + +FxExpression *ZCCCompiler::ConvertAST(ZCC_TreeNode *ast) +{ + // FxReturnStatement will have to be done more intelligently, of course. + return new FxReturnStatement(ConvertNode(ast), *ast); +} + +FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) +{ + // 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); + assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. + auto fname = static_cast(fcall->Function)->Identifier; + return new FxFunctionCall(nullptr, fname, ConvertNodeList(fcall->Parameters), *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_ExprConstant: + { + auto cnst = static_cast(ast); + if (cnst->Type->IsKindOf(RUNTIME_CLASS(PInt))) + { + return new FxConstant(cnst->IntVal, *ast); + } + else if (cnst->Type->IsKindOf(RUNTIME_CLASS(PFloat))) + { + return new FxConstant(cnst->DoubleVal, *ast); + } + else if (cnst->Type->IsKindOf(RUNTIME_CLASS(PString))) + { + return new FxConstant(*cnst->StringVal, *ast); + } + else if (cnst->Type->IsKindOf(RUNTIME_CLASS(PName))) + { + return new FxConstant(ENamedName(cnst->IntVal), *ast); + } + else + { + // can there be other types? + Error(cnst, "Unknown constant type"); + return new FxConstant(0, *ast); + } + } + + default: + // 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(ZCC_TreeNode *head) +{ + FArgumentList *list = new FArgumentList; + auto node = head; + do + { + list->Push(ConvertNode(node)); + node = node->SiblingNext; + } while (node != head); + return list; +} \ No newline at end of file diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 74d83f529d..2ca00459aa 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -5,6 +5,8 @@ struct Baggage; struct FPropertyInfo; class AActor; class FxExpression; +typedef TDeletingArray FArgumentList; + struct ZCC_StructWork { @@ -136,6 +138,10 @@ private: void Error(ZCC_TreeNode *node, const char *msg, ...); void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr); + FxExpression *ConvertAST(ZCC_TreeNode *ast); + FxExpression *ConvertNode(ZCC_TreeNode *node); + FArgumentList *ConvertNodeList(ZCC_TreeNode *head); + DObject *Outer; PSymbolTable *GlobalTreeNodes; PSymbolTable *OutputSymbols; diff --git a/wadsrc/static/actors/shared/action.txt b/wadsrc/static/actors/shared/action.txt deleted file mode 100644 index fc0e713130..0000000000 --- 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 ab33fee75c..0000000000 --- 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 4b1992bde4..0000000000 --- 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/debris.txt b/wadsrc/static/actors/shared/debris.txt deleted file mode 100644 index 5d14a48fad..0000000000 --- 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/morph.txt b/wadsrc/static/actors/shared/morph.txt deleted file mode 100644 index f5aac48d21..0000000000 --- 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/sharedmisc.txt b/wadsrc/static/actors/shared/sharedmisc.txt deleted file mode 100644 index fe5ac72d80..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index e921b55084..4fe719c629 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -2,11 +2,11 @@ //#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/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" @@ -26,7 +26,7 @@ #include "actors/shared/secrettrigger.txt" #include "actors/shared/setcolor.txt" #include "actors/shared/sectoraction.txt" -#include "actors/shared/action.txt" +//#include "actors/shared/action.txt" #include "actors/shared/dog.txt" #include "actors/shared/damagetypes.txt" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index b0d3ec9256..9604812aaf 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -3,6 +3,12 @@ zscript/actor.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/ice.txt +zscript/shared/debris.txt zscript/shared/specialspot.txt //zscript/test1.txt diff --git a/wadsrc/static/zscript/shared/blood.txt b/wadsrc/static/zscript/shared/blood.txt new file mode 100644 index 0000000000..e5f05de05b --- /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 0000000000..cf671ea8be --- /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/debris.txt b/wadsrc/static/zscript/shared/debris.txt new file mode 100644 index 0000000000..24eae25be5 --- /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/ice.txt b/wadsrc/static/zscript/shared/ice.txt new file mode 100644 index 0000000000..9668466cbe --- /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 + } + action 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/morph.txt b/wadsrc/static/zscript/shared/morph.txt new file mode 100644 index 0000000000..ff58d897b1 --- /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/sharedmisc.txt b/wadsrc/static/zscript/shared/sharedmisc.txt new file mode 100644 index 0000000000..bebf285492 --- /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; + } +} From 905e44713faa63e3efd4f22eb837851f5081c8d4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 09:32:45 +0200 Subject: [PATCH 028/471] - deprecated A_SetUserVar family for ZSCRIPT due to its muddled semantics. Better use direct variable access which is a lot safer and also provides better error checking. --- wadsrc/static/zscript/actor.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 9352028b31..4c09e86640 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -297,10 +297,10 @@ class Actor : Thinker native native void A_ScaleVelocity(float scale, int ptr = AAPTR_DEFAULT); action native void 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); + 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_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); From 9e2830a3db663b83d47dcbc421de217cf52bbd78 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 10:46:15 +0200 Subject: [PATCH 029/471] - converted the rest of actors/shared. - moved damagetype definitions to MAPINFO. These were in DECORATE which is not correct. The old code is left for compatibility. --- src/g_level.h | 1 + src/g_mapinfo.cpp | 12 + src/info.cpp | 40 +++ src/p_states.cpp | 5 + wadsrc/static/actors/shared/bridge.txt | 105 ------- wadsrc/static/actors/shared/camera.txt | 23 -- wadsrc/static/actors/shared/damagetypes.txt | 4 - wadsrc/static/actors/shared/decal.txt | 3 - wadsrc/static/actors/shared/dog.txt | 44 --- wadsrc/static/actors/shared/fountain.txt | 42 --- wadsrc/static/actors/shared/hatetarget.txt | 19 -- wadsrc/static/actors/shared/mapmarker.txt | 15 - wadsrc/static/actors/shared/movingcamera.txt | 34 --- wadsrc/static/actors/shared/secrettrigger.txt | 9 - wadsrc/static/actors/shared/setcolor.txt | 16 - wadsrc/static/actors/shared/skies.txt | 40 --- .../static/actors/shared/soundenvironment.txt | 9 - wadsrc/static/actors/shared/soundsequence.txt | 79 ----- wadsrc/static/actors/shared/spark.txt | 8 - wadsrc/static/actors/shared/splashes.txt | 237 --------------- wadsrc/static/actors/shared/teleport.txt | 42 --- wadsrc/static/actors/shared/waterzone.txt | 7 - wadsrc/static/decorate.txt | 32 -- wadsrc/static/mapinfo/common.txt | 5 + wadsrc/static/zscript.txt | 20 ++ wadsrc/static/zscript/shared/bridge.txt | 129 +++++++++ wadsrc/static/zscript/shared/camera.txt | 29 ++ wadsrc/static/zscript/shared/decal.txt | 3 + wadsrc/static/zscript/shared/dog.txt | 47 +++ wadsrc/static/zscript/shared/fountain.txt | 66 +++++ wadsrc/static/zscript/shared/hatetarget.txt | 22 ++ wadsrc/static/zscript/shared/mapmarker.txt | 18 ++ wadsrc/static/zscript/shared/movingcamera.txt | 46 +++ .../{actors => zscript}/shared/pickups.txt | 24 +- .../static/zscript/shared/secrettrigger.txt | 12 + .../shared/sectoraction.txt | 37 +-- wadsrc/static/zscript/shared/setcolor.txt | 22 ++ wadsrc/static/zscript/shared/skies.txt | 49 ++++ .../zscript/shared/soundenvironment.txt | 12 + .../static/zscript/shared/soundsequence.txt | 121 ++++++++ wadsrc/static/zscript/shared/spark.txt | 11 + wadsrc/static/zscript/shared/splashes.txt | 273 ++++++++++++++++++ wadsrc/static/zscript/shared/teleport.txt | 54 ++++ wadsrc/static/zscript/shared/waterzone.txt | 10 + 44 files changed, 1042 insertions(+), 794 deletions(-) delete mode 100644 wadsrc/static/actors/shared/bridge.txt delete mode 100644 wadsrc/static/actors/shared/camera.txt delete mode 100644 wadsrc/static/actors/shared/damagetypes.txt delete mode 100644 wadsrc/static/actors/shared/decal.txt delete mode 100644 wadsrc/static/actors/shared/dog.txt delete mode 100644 wadsrc/static/actors/shared/fountain.txt delete mode 100644 wadsrc/static/actors/shared/hatetarget.txt delete mode 100644 wadsrc/static/actors/shared/mapmarker.txt delete mode 100644 wadsrc/static/actors/shared/movingcamera.txt delete mode 100644 wadsrc/static/actors/shared/secrettrigger.txt delete mode 100644 wadsrc/static/actors/shared/setcolor.txt delete mode 100644 wadsrc/static/actors/shared/skies.txt delete mode 100644 wadsrc/static/actors/shared/soundenvironment.txt delete mode 100644 wadsrc/static/actors/shared/soundsequence.txt delete mode 100644 wadsrc/static/actors/shared/spark.txt delete mode 100644 wadsrc/static/actors/shared/splashes.txt delete mode 100644 wadsrc/static/actors/shared/teleport.txt delete mode 100644 wadsrc/static/actors/shared/waterzone.txt create mode 100644 wadsrc/static/zscript/shared/bridge.txt create mode 100644 wadsrc/static/zscript/shared/camera.txt create mode 100644 wadsrc/static/zscript/shared/decal.txt create mode 100644 wadsrc/static/zscript/shared/dog.txt create mode 100644 wadsrc/static/zscript/shared/fountain.txt create mode 100644 wadsrc/static/zscript/shared/hatetarget.txt create mode 100644 wadsrc/static/zscript/shared/mapmarker.txt create mode 100644 wadsrc/static/zscript/shared/movingcamera.txt rename wadsrc/static/{actors => zscript}/shared/pickups.txt (65%) create mode 100644 wadsrc/static/zscript/shared/secrettrigger.txt rename wadsrc/static/{actors => zscript}/shared/sectoraction.txt (61%) create mode 100644 wadsrc/static/zscript/shared/setcolor.txt create mode 100644 wadsrc/static/zscript/shared/skies.txt create mode 100644 wadsrc/static/zscript/shared/soundenvironment.txt create mode 100644 wadsrc/static/zscript/shared/soundsequence.txt create mode 100644 wadsrc/static/zscript/shared/spark.txt create mode 100644 wadsrc/static/zscript/shared/splashes.txt create mode 100644 wadsrc/static/zscript/shared/teleport.txt create mode 100644 wadsrc/static/zscript/shared/waterzone.txt diff --git a/src/g_level.h b/src/g_level.h index 9f8c5efd52..2b0de7b687 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) \ diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index bc04704740..814a364352 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/info.cpp b/src/info.cpp index 8089e065b8..44f485e6ce 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -817,3 +817,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/p_states.cpp b/src/p_states.cpp index 007f7f5cee..00b011e3d8 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -433,6 +433,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"); diff --git a/wadsrc/static/actors/shared/bridge.txt b/wadsrc/static/actors/shared/bridge.txt deleted file mode 100644 index 97d4c22ad1..0000000000 --- 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 46816f9eab..0000000000 --- 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 9e5f1e2540..0000000000 --- a/wadsrc/static/actors/shared/damagetypes.txt +++ /dev/null @@ -1,4 +0,0 @@ -damagetype Drowning -{ - NoArmor -} diff --git a/wadsrc/static/actors/shared/decal.txt b/wadsrc/static/actors/shared/decal.txt deleted file mode 100644 index 25e7062c8e..0000000000 --- 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 1004fba204..0000000000 --- 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 d9c31e88e5..0000000000 --- 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 75442c65c3..0000000000 --- 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/mapmarker.txt b/wadsrc/static/actors/shared/mapmarker.txt deleted file mode 100644 index 9c5e36b44f..0000000000 --- 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/movingcamera.txt b/wadsrc/static/actors/shared/movingcamera.txt deleted file mode 100644 index 4ba2291541..0000000000 --- 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/secrettrigger.txt b/wadsrc/static/actors/shared/secrettrigger.txt deleted file mode 100644 index 8db3239936..0000000000 --- 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 136b0bbf4c..0000000000 --- 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/skies.txt b/wadsrc/static/actors/shared/skies.txt deleted file mode 100644 index 89f742573c..0000000000 --- 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 822a723f81..0000000000 --- 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 5fe34b3265..0000000000 --- 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 240d98152e..0000000000 --- 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/splashes.txt b/wadsrc/static/actors/shared/splashes.txt deleted file mode 100644 index 4c71b45653..0000000000 --- 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 0bce22ea36..0000000000 --- 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 b6cf4bd297..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 4fe719c629..079d8fa6a5 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,35 +1,3 @@ -//#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/doom/doomplayer.txt" #include "actors/doom/possessed.txt" #include "actors/doom/doomimp.txt" diff --git a/wadsrc/static/mapinfo/common.txt b/wadsrc/static/mapinfo/common.txt index 347f424f93..986b8e48c4 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 index 9604812aaf..9ba69ceef1 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -10,6 +10,26 @@ zscript/shared/blood.txt zscript/shared/ice.txt zscript/shared/debris.txt zscript/shared/specialspot.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/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/dog.txt + //zscript/test1.txt diff --git a/wadsrc/static/zscript/shared/bridge.txt b/wadsrc/static/zscript/shared/bridge.txt new file mode 100644 index 0000000000..08c788f8e3 --- /dev/null +++ b/wadsrc/static/zscript/shared/bridge.txt @@ -0,0 +1,129 @@ +// Bridge ball ------------------------------------------------------------- + +class BridgeBall : Actor +{ + default + { + +NOBLOCKMAP + +NOTELEPORT + +NOGRAVITY + } + + action 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"; + } + + action 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 0000000000..9420c98d5a --- /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/decal.txt b/wadsrc/static/zscript/shared/decal.txt new file mode 100644 index 0000000000..0614f6235c --- /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 0000000000..663dd6b980 --- /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 0000000000..60129a8c59 --- /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 0000000000..6d2263f61b --- /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/mapmarker.txt b/wadsrc/static/zscript/shared/mapmarker.txt new file mode 100644 index 0000000000..1afa00459d --- /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/movingcamera.txt b/wadsrc/static/zscript/shared/movingcamera.txt new file mode 100644 index 0000000000..c5b8534db4 --- /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 a9ee0b2d7f..8e1e88233d 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/secrettrigger.txt b/wadsrc/static/zscript/shared/secrettrigger.txt new file mode 100644 index 0000000000..48c93686ea --- /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 f8db34323f..03278f2d30 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 0000000000..8689e5fd10 --- /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/skies.txt b/wadsrc/static/zscript/shared/skies.txt new file mode 100644 index 0000000000..35077ee5c6 --- /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 0000000000..2a4d66adb5 --- /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 0000000000..97ff8e9aa8 --- /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 0000000000..5adffdfe1c --- /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/splashes.txt b/wadsrc/static/zscript/shared/splashes.txt new file mode 100644 index 0000000000..8b16d85b86 --- /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 0000000000..55308415fe --- /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 0000000000..975c8a473b --- /dev/null +++ b/wadsrc/static/zscript/shared/waterzone.txt @@ -0,0 +1,10 @@ +class WaterZone : Actor native +{ + default + { + +NOSECTOR + +NOBLOCKMAP + +NOGRAVITY + +DONTSPLASH + } +} From 784f7ed67180af87e188ae658307fd48dee22060 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 20:08:41 +0200 Subject: [PATCH 030/471] - converted all of Doom's actors. - fixed a few problems that were encountered during conversion: * action specials as action functions were not recognized by the parser. * Player.StartItem could not be parsed. * disabled the naming hack for PowerupType. ZScript, unlike DECORATE will never prepend 'Power' to the power's name, it always needs to specified by its full name. * states and defaults were not checked for empty bodies. * the scope qualifier for goto labels was not properly converted to a string, because it is an ENamedName, not an FName. --- src/scripting/thingdef_properties.cpp | 2 +- src/scripting/zscript/zcc-parse.lemon | 12 + src/scripting/zscript/zcc_compile.cpp | 19 +- wadsrc/static/actors/doom/arachnotron.txt | 85 -- wadsrc/static/actors/doom/archvile.txt | 83 -- wadsrc/static/actors/doom/bossbrain.txt | 120 --- wadsrc/static/actors/doom/bruiser.txt | 131 --- wadsrc/static/actors/doom/cacodemon.txt | 82 -- wadsrc/static/actors/doom/cyberdemon.txt | 61 -- wadsrc/static/actors/doom/demon.txt | 71 -- wadsrc/static/actors/doom/doomammo.txt | 142 --- wadsrc/static/actors/doom/doomarmor.txt | 60 -- wadsrc/static/actors/doom/doomartifacts.txt | 171 ---- wadsrc/static/actors/doom/doomdecorations.txt | 753 --------------- wadsrc/static/actors/doom/doomhealth.txt | 45 - wadsrc/static/actors/doom/doomimp.txt | 87 -- wadsrc/static/actors/doom/doomkeys.txt | 98 -- wadsrc/static/actors/doom/doommisc.txt | 104 -- wadsrc/static/actors/doom/doomplayer.txt | 90 -- wadsrc/static/actors/doom/doomweapons.txt | 574 ----------- wadsrc/static/actors/doom/fatso.txt | 89 -- wadsrc/static/actors/doom/keen.txt | 41 - wadsrc/static/actors/doom/lostsoul.txt | 80 -- wadsrc/static/actors/doom/painelemental.txt | 50 - wadsrc/static/actors/doom/possessed.txt | 241 ----- wadsrc/static/actors/doom/revenant.txt | 113 --- wadsrc/static/actors/doom/scriptedmarine.txt | 306 ------ wadsrc/static/actors/doom/spidermaster.txt | 59 -- wadsrc/static/actors/doom/stealthmonsters.txt | 103 -- wadsrc/static/decorate.txt | 29 - wadsrc/static/zscript.txt | 28 + wadsrc/static/zscript/doom/arachnotron.txt | 91 ++ wadsrc/static/zscript/doom/archvile.txt | 89 ++ wadsrc/static/zscript/doom/bossbrain.txt | 135 +++ wadsrc/static/zscript/doom/bruiser.txt | 140 +++ wadsrc/static/zscript/doom/cacodemon.txt | 88 ++ wadsrc/static/zscript/doom/cyberdemon.txt | 64 ++ .../{actors => zscript}/doom/deadthings.txt | 72 +- wadsrc/static/zscript/doom/demon.txt | 77 ++ wadsrc/static/zscript/doom/doomammo.txt | 169 ++++ wadsrc/static/zscript/doom/doomarmor.txt | 69 ++ wadsrc/static/zscript/doom/doomartifacts.txt | 201 ++++ .../static/zscript/doom/doomdecorations.txt | 900 ++++++++++++++++++ wadsrc/static/zscript/doom/doomhealth.txt | 54 ++ wadsrc/static/zscript/doom/doomimp.txt | 93 ++ wadsrc/static/zscript/doom/doomkeys.txt | 119 +++ wadsrc/static/zscript/doom/doommisc.txt | 116 +++ wadsrc/static/zscript/doom/doomplayer.txt | 93 ++ wadsrc/static/zscript/doom/doomweapons.txt | 621 ++++++++++++ wadsrc/static/zscript/doom/fatso.txt | 95 ++ wadsrc/static/zscript/doom/keen.txt | 44 + wadsrc/static/zscript/doom/lostsoul.txt | 83 ++ wadsrc/static/zscript/doom/painelemental.txt | 53 ++ wadsrc/static/zscript/doom/possessed.txt | 253 +++++ wadsrc/static/zscript/doom/revenant.txt | 122 +++ wadsrc/static/zscript/doom/scriptedmarine.txt | 309 ++++++ wadsrc/static/zscript/doom/spidermaster.txt | 62 ++ .../static/zscript/doom/stealthmonsters.txt | 139 +++ 58 files changed, 4377 insertions(+), 3903 deletions(-) delete mode 100644 wadsrc/static/actors/doom/arachnotron.txt delete mode 100644 wadsrc/static/actors/doom/archvile.txt delete mode 100644 wadsrc/static/actors/doom/bossbrain.txt delete mode 100644 wadsrc/static/actors/doom/bruiser.txt delete mode 100644 wadsrc/static/actors/doom/cacodemon.txt delete mode 100644 wadsrc/static/actors/doom/cyberdemon.txt delete mode 100644 wadsrc/static/actors/doom/demon.txt delete mode 100644 wadsrc/static/actors/doom/doomammo.txt delete mode 100644 wadsrc/static/actors/doom/doomarmor.txt delete mode 100644 wadsrc/static/actors/doom/doomartifacts.txt delete mode 100644 wadsrc/static/actors/doom/doomdecorations.txt delete mode 100644 wadsrc/static/actors/doom/doomhealth.txt delete mode 100644 wadsrc/static/actors/doom/doomimp.txt delete mode 100644 wadsrc/static/actors/doom/doomkeys.txt delete mode 100644 wadsrc/static/actors/doom/doommisc.txt delete mode 100644 wadsrc/static/actors/doom/doomplayer.txt delete mode 100644 wadsrc/static/actors/doom/doomweapons.txt delete mode 100644 wadsrc/static/actors/doom/fatso.txt delete mode 100644 wadsrc/static/actors/doom/keen.txt delete mode 100644 wadsrc/static/actors/doom/lostsoul.txt delete mode 100644 wadsrc/static/actors/doom/painelemental.txt delete mode 100644 wadsrc/static/actors/doom/possessed.txt delete mode 100644 wadsrc/static/actors/doom/revenant.txt delete mode 100644 wadsrc/static/actors/doom/scriptedmarine.txt delete mode 100644 wadsrc/static/actors/doom/spidermaster.txt delete mode 100644 wadsrc/static/actors/doom/stealthmonsters.txt create mode 100644 wadsrc/static/zscript/doom/arachnotron.txt create mode 100644 wadsrc/static/zscript/doom/archvile.txt create mode 100644 wadsrc/static/zscript/doom/bossbrain.txt create mode 100644 wadsrc/static/zscript/doom/bruiser.txt create mode 100644 wadsrc/static/zscript/doom/cacodemon.txt create mode 100644 wadsrc/static/zscript/doom/cyberdemon.txt rename wadsrc/static/{actors => zscript}/doom/deadthings.txt (67%) create mode 100644 wadsrc/static/zscript/doom/demon.txt create mode 100644 wadsrc/static/zscript/doom/doomammo.txt create mode 100644 wadsrc/static/zscript/doom/doomarmor.txt create mode 100644 wadsrc/static/zscript/doom/doomartifacts.txt create mode 100644 wadsrc/static/zscript/doom/doomdecorations.txt create mode 100644 wadsrc/static/zscript/doom/doomhealth.txt create mode 100644 wadsrc/static/zscript/doom/doomimp.txt create mode 100644 wadsrc/static/zscript/doom/doomkeys.txt create mode 100644 wadsrc/static/zscript/doom/doommisc.txt create mode 100644 wadsrc/static/zscript/doom/doomplayer.txt create mode 100644 wadsrc/static/zscript/doom/doomweapons.txt create mode 100644 wadsrc/static/zscript/doom/fatso.txt create mode 100644 wadsrc/static/zscript/doom/keen.txt create mode 100644 wadsrc/static/zscript/doom/lostsoul.txt create mode 100644 wadsrc/static/zscript/doom/painelemental.txt create mode 100644 wadsrc/static/zscript/doom/possessed.txt create mode 100644 wadsrc/static/zscript/doom/revenant.txt create mode 100644 wadsrc/static/zscript/doom/scriptedmarine.txt create mode 100644 wadsrc/static/zscript/doom/spidermaster.txt create mode 100644 wadsrc/static/zscript/doom/stealthmonsters.txt diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 084736c24c..833a2d381e 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -2431,7 +2431,7 @@ 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 == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(APowerup)) && !bag.fromZScript) { FString st; st.Format("%s%s", strnicmp(str, "power", 5)? "Power" : "", str); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index dba30af5ff..cd1cbce14b 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -458,6 +458,18 @@ state_flow_type(X) ::= GOTO(T) IDENTIFIER(C) SCOPE dottable_id(A) state_goto_off 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) ::= ADD expr(A). { X = A; /*X-overwrites-A*/ } /* Must evaluate to a non-negative integer constant. */ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 904f938ca8..f24bce20cf 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1657,7 +1657,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper // Skip the DECORATE 'no comma' marker if (*p == '_') p++; - else if (*p == 0) + if (*p == 0) { if (exp != property->Values) { @@ -1834,7 +1834,7 @@ void ZCCCompiler::InitDefaults() for (auto d : c->Defaults) { auto content = d->Content; - do + if (content != nullptr) do { switch (content->NodeType) { @@ -1870,7 +1870,7 @@ void ZCCCompiler::InitFunctions() { TArray rets(1); TArray args; - TArray argflags; + TArray argflags; TArray argnames; for (auto c : Classes) @@ -2032,8 +2032,13 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a } else { - Error(af, "%s: action function not found in %s", FName(id->Identifier).GetChars(), cls->TypeName.GetChars()); - return nullptr; + // 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(af); @@ -2074,7 +2079,7 @@ void ZCCCompiler::CompileStates() for (auto s : c->States) { auto st = s->Body; - do + if (st != nullptr) do { switch (st->NodeType) { @@ -2187,7 +2192,7 @@ void ZCCCompiler::CompileStates() statename = ""; if (sg->Qualifier != nullptr) { - statename << sg->Qualifier->Id << "::"; + statename << FName(sg->Qualifier->Id) << "::"; } auto part = sg->Label; do diff --git a/wadsrc/static/actors/doom/arachnotron.txt b/wadsrc/static/actors/doom/arachnotron.txt deleted file mode 100644 index 1a70a11d13..0000000000 --- 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 f2c5d6ab47..0000000000 --- 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 67b6da7d61..0000000000 --- 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 0a2bdcff64..0000000000 --- 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 db2ee76571..0000000000 --- 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 9f9c986f4a..0000000000 --- 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 3680b24e96..0000000000 --- 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 bc931c08fb..0000000000 --- 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 c676f91318..0000000000 --- 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 "ARM1A0" - 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 e9caa5f113..0000000000 --- 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 4206c09ed7..0000000000 --- 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 c1a8d96ffa..0000000000 --- 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 a5725e7240..0000000000 --- a/wadsrc/static/actors/doom/doomimp.txt +++ /dev/null @@ -1,87 +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 MLKJI 8 - 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 d243925599..0000000000 --- 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 cb22474b93..0000000000 --- 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 e31c10ea77..0000000000 --- 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 16369572bd..0000000000 --- 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 9b3a7d26a2..0000000000 --- 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 7ad41d2cee..0000000000 --- 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 bd6212cf27..0000000000 --- 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 bba4756502..0000000000 --- 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 6961cc8a50..0000000000 --- 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 4062647f48..0000000000 --- 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 73de9a49d2..0000000000 --- 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 e087b3fb38..0000000000 --- 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 2755374858..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 079d8fa6a5..1ae7d73288 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,32 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 9ba69ceef1..73bb467d82 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -30,6 +30,34 @@ zscript/shared/setcolor.txt zscript/shared/sectoraction.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/test1.txt diff --git a/wadsrc/static/zscript/doom/arachnotron.txt b/wadsrc/static/zscript/doom/arachnotron.txt new file mode 100644 index 0000000000..e3aa17d484 --- /dev/null +++ b/wadsrc/static/zscript/doom/arachnotron.txt @@ -0,0 +1,91 @@ +//=========================================================================== +// +// 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; + } +} + + diff --git a/wadsrc/static/zscript/doom/archvile.txt b/wadsrc/static/zscript/doom/archvile.txt new file mode 100644 index 0000000000..bdca2b05f6 --- /dev/null +++ b/wadsrc/static/zscript/doom/archvile.txt @@ -0,0 +1,89 @@ +//=========================================================================== +// +// 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; + } +} + diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt new file mode 100644 index 0000000000..533d0fa01c --- /dev/null +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -0,0 +1,135 @@ + +//=========================================================================== +// +// Boss Brain +// +//=========================================================================== + +class BossBrain : Actor +{ + Default + { + 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 +// +//=========================================================================== + +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; + } +} diff --git a/wadsrc/static/zscript/doom/bruiser.txt b/wadsrc/static/zscript/doom/bruiser.txt new file mode 100644 index 0000000000..bbeb319f61 --- /dev/null +++ b/wadsrc/static/zscript/doom/bruiser.txt @@ -0,0 +1,140 @@ +//=========================================================================== +// +// 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; + } +} + diff --git a/wadsrc/static/zscript/doom/cacodemon.txt b/wadsrc/static/zscript/doom/cacodemon.txt new file mode 100644 index 0000000000..6a07feb705 --- /dev/null +++ b/wadsrc/static/zscript/doom/cacodemon.txt @@ -0,0 +1,88 @@ +//=========================================================================== +// +// 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; + } +} diff --git a/wadsrc/static/zscript/doom/cyberdemon.txt b/wadsrc/static/zscript/doom/cyberdemon.txt new file mode 100644 index 0000000000..75f4fd211a --- /dev/null +++ b/wadsrc/static/zscript/doom/cyberdemon.txt @@ -0,0 +1,64 @@ + +//=========================================================================== +// +// 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; + } +} + 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 f90d35eefd..3a7e47610b 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 0000000000..398888e456 --- /dev/null +++ b/wadsrc/static/zscript/doom/demon.txt @@ -0,0 +1,77 @@ +//=========================================================================== +// +// 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"; + } +} + + diff --git a/wadsrc/static/zscript/doom/doomammo.txt b/wadsrc/static/zscript/doom/doomammo.txt new file mode 100644 index 0000000000..394f13e94f --- /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 0000000000..8c3d52cc9f --- /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 "ARM1A0"; + 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 0000000000..ad5e304c66 --- /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 0000000000..8eec812f6b --- /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 0000000000..c0ecf2dc01 --- /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 0000000000..244ae70eaa --- /dev/null +++ b/wadsrc/static/zscript/doom/doomimp.txt @@ -0,0 +1,93 @@ +//=========================================================================== +// +// 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 MLKJI 8; + 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; + } +} diff --git a/wadsrc/static/zscript/doom/doomkeys.txt b/wadsrc/static/zscript/doom/doomkeys.txt new file mode 100644 index 0000000000..9ae88dade6 --- /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 0000000000..80e330a68e --- /dev/null +++ b/wadsrc/static/zscript/doom/doommisc.txt @@ -0,0 +1,116 @@ +// 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; + } +} + +// 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 0000000000..6ec0d5f903 --- /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 0000000000..41f2c434fa --- /dev/null +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -0,0 +1,621 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + +// -------------------------------------------------------------------------- +// +// 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 0000000000..46d013d7f2 --- /dev/null +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -0,0 +1,95 @@ +//=========================================================================== +// +// 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; + } +} + + diff --git a/wadsrc/static/zscript/doom/keen.txt b/wadsrc/static/zscript/doom/keen.txt new file mode 100644 index 0000000000..a60e924eff --- /dev/null +++ b/wadsrc/static/zscript/doom/keen.txt @@ -0,0 +1,44 @@ +//=========================================================================== +// +// 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; + } +} diff --git a/wadsrc/static/zscript/doom/lostsoul.txt b/wadsrc/static/zscript/doom/lostsoul.txt new file mode 100644 index 0000000000..69574e5c7c --- /dev/null +++ b/wadsrc/static/zscript/doom/lostsoul.txt @@ -0,0 +1,83 @@ +//=========================================================================== +// +// 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; + } +} diff --git a/wadsrc/static/zscript/doom/painelemental.txt b/wadsrc/static/zscript/doom/painelemental.txt new file mode 100644 index 0000000000..ce30bbfd30 --- /dev/null +++ b/wadsrc/static/zscript/doom/painelemental.txt @@ -0,0 +1,53 @@ +//=========================================================================== +// +// 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; + } +} diff --git a/wadsrc/static/zscript/doom/possessed.txt b/wadsrc/static/zscript/doom/possessed.txt new file mode 100644 index 0000000000..de1e50ff2b --- /dev/null +++ b/wadsrc/static/zscript/doom/possessed.txt @@ -0,0 +1,253 @@ + +//=========================================================================== +// +// 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 ; + } +} diff --git a/wadsrc/static/zscript/doom/revenant.txt b/wadsrc/static/zscript/doom/revenant.txt new file mode 100644 index 0000000000..7fc8b8e0df --- /dev/null +++ b/wadsrc/static/zscript/doom/revenant.txt @@ -0,0 +1,122 @@ +//=========================================================================== +// +// 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; + } +} diff --git a/wadsrc/static/zscript/doom/scriptedmarine.txt b/wadsrc/static/zscript/doom/scriptedmarine.txt new file mode 100644 index 0000000000..358bf4ea45 --- /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"; + } + + action native void A_M_Refire (bool ignoremissile=false); + action native void A_M_CheckAttack (); + action native void A_MarineChase (); + action native void A_MarineLook (); + action native void A_MarineNoise (); + action native void A_M_Punch (int force); + action native void A_M_SawRefire (); + action native void A_M_FirePistol (bool accurate); + action native void A_M_FireShotgun (); + action native void A_M_FireShotgun2 (); + action native void A_M_FireCGun(bool accurate); + action native void A_M_FireMissile (); + action native void A_M_FirePlasma (); + action native void A_M_FireRailgun (); + action native void A_M_BFGsound (); + action 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 0000000000..b9f0600688 --- /dev/null +++ b/wadsrc/static/zscript/doom/spidermaster.txt @@ -0,0 +1,62 @@ +//=========================================================================== +// +// 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; + } +} diff --git a/wadsrc/static/zscript/doom/stealthmonsters.txt b/wadsrc/static/zscript/doom/stealthmonsters.txt new file mode 100644 index 0000000000..785261fbba --- /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"; + } +} + From 52005214c1ecd93e81cc6feabee2656314e839d4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 21:15:46 +0200 Subject: [PATCH 031/471] - Added some fudging so that A_PlayerSkinCheck creates proper code until I can rewrite the FunctionCall expression to match what the script compiler needs. The current version of this class is too much geared toward DECORATE. --- src/namedef.h | 4 +-- .../codegeneration/thingdef_expression.cpp | 33 ++++++++++++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index 8d883d5666..8d60c97ee0 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -672,8 +672,8 @@ xx(DecoRandom) xx(DecoFRandom) xx(DecoCallLineSpecial) xx(DecoNameToClass) -xx(DecoFindMultiNameState) -xx(DecoFindSingleNameState) +xx(BuiltinFindMultiNameState) +xx(BuiltinFindSingleNameState) xx(DecoHandleRuntimeState) xx(Damage) diff --git a/src/scripting/codegeneration/thingdef_expression.cpp b/src/scripting/codegeneration/thingdef_expression.cpp index 77b062ed65..a352c7b87f 100644 --- a/src/scripting/codegeneration/thingdef_expression.cpp +++ b/src/scripting/codegeneration/thingdef_expression.cpp @@ -3632,7 +3632,10 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) PFunction *afd = dyn_cast(ctx.Class->Symbols.FindSymbol(MethodName, true)); if (afd != nullptr) { - return new FxVMFunctionCall(afd, ArgList, ScriptPosition, false); + auto x = new FxVMFunctionCall(afd, ArgList, ScriptPosition, false); + ArgList = nullptr; + delete this; + return x->Resolve(ctx); } for (size_t i = 0; i < countof(FxFlops); ++i) @@ -3927,11 +3930,25 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); bool failed = false; + auto proto = Function->Variants[0].Implementation->Proto; + auto argtypes = proto->ArgumentTypes; + + int implicit; + if (Function->Flags & VARF_Action) implicit = 3; + else if (Function->Flags & VARF_Method) implicit = 1; + else implicit = 0; if (ArgList != NULL) { for (unsigned i = 0; i < ArgList->Size(); i++) { + // temporary hack to let strings get compiled as state. This will have to be done more intelligently. + if (i+implicit < argtypes.Size() && argtypes[i+implicit] == TypeState && (*ArgList)[i]->isConstant() && static_cast((*ArgList)[i])->ValueType == TypeString) + { + auto statenode = new FxMultiNameState(static_cast((*ArgList)[i])->GetValue().GetString(), ScriptPosition); + delete (*ArgList)[i]; + (*ArgList)[i] = statenode; + } (*ArgList)[i] = (*ArgList)[i]->Resolve(ctx); if ((*ArgList)[i] == NULL) failed = true; } @@ -3941,7 +3958,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) delete this; return NULL; } - TArray &rets = Function->Variants[0].Implementation->Proto->ReturnTypes; + TArray &rets = proto->ReturnTypes; if (rets.Size() > 0) { ValueType = rets[0]; @@ -5175,7 +5192,7 @@ static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMRetu } // Find a state with any number of dots in its name. -int DecoFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) { assert(numparam > 1); assert(numret == 1); @@ -5191,7 +5208,7 @@ int DecoFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VM } // Find a state without any dots in its name. -int DecoFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) { assert(numparam == 2); assert(numret == 1); @@ -5217,18 +5234,18 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) build->EmitParamInt(names[i]); } - // For one name, use the DecoFindSingleNameState function. For more than - // one name, use the DecoFindMultiNameState function. + // For one name, use the BuiltinFindSingleNameState function. For more than + // one name, use the BuiltinFindMultiNameState function. VMFunction *callfunc; PSymbol *sym; if (names.Size() == 1) { - sym = FindDecorateBuiltinFunction(NAME_DecoFindSingleNameState, DecoFindSingleNameState); + sym = FindDecorateBuiltinFunction(NAME_BuiltinFindSingleNameState, BuiltinFindSingleNameState); } else { - sym = FindDecorateBuiltinFunction(NAME_DecoFindMultiNameState, DecoFindMultiNameState); + sym = FindDecorateBuiltinFunction(NAME_BuiltinFindMultiNameState, BuiltinFindMultiNameState); } assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); From d00e93bdab779548413f49385bb13d1908d6f7e9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 21:56:45 +0200 Subject: [PATCH 032/471] - fixed order of state setup. It looks like the setup of the action function and the adding of the states got inverted by something I tried, leaving the ActionFunc member empty on the real states. --- src/scripting/zscript/zcc_compile.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f24bce20cf..d034c51cc6 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2169,13 +2169,6 @@ void ZCCCompiler::CompileStates() } #endif - int count = statedef.AddStates(&state, sl->Frames->GetChars()); - if (count < 0) - { - Error(sl, "Invalid frame character string '%s'", sl->Frames->GetChars()); - count = -count; - } - if (sl->Action != nullptr) { auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); @@ -2184,6 +2177,13 @@ void ZCCCompiler::CompileStates() state.ActionFunc = FunctionBuildList.AddFunction(c->Type(), code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), true); } } + + int count = statedef.AddStates(&state, sl->Frames->GetChars()); + if (count < 0) + { + Error(sl, "Invalid frame character string '%s'", sl->Frames->GetChars()); + count = -count; + } break; } case AST_StateGoto: From 9def9ec095864dbcc71792adafe6d5b4cdfb31e1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 22:54:22 +0200 Subject: [PATCH 033/471] - added more casting kludges so that I can run some tests with Heretic's definitions. --- src/dobjtype.h | 11 ----- .../codegeneration/thingdef_expression.cpp | 40 ++++++++++++++++--- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index 19aeca71b4..b41ffe0e6b 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -824,17 +824,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 diff --git a/src/scripting/codegeneration/thingdef_expression.cpp b/src/scripting/codegeneration/thingdef_expression.cpp index a352c7b87f..323ca083ed 100644 --- a/src/scripting/codegeneration/thingdef_expression.cpp +++ b/src/scripting/codegeneration/thingdef_expression.cpp @@ -3942,13 +3942,43 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { for (unsigned i = 0; i < ArgList->Size(); i++) { - // temporary hack to let strings get compiled as state. This will have to be done more intelligently. - if (i+implicit < argtypes.Size() && argtypes[i+implicit] == TypeState && (*ArgList)[i]->isConstant() && static_cast((*ArgList)[i])->ValueType == TypeString) + if ((*ArgList)[i]->isConstant()) { - auto statenode = new FxMultiNameState(static_cast((*ArgList)[i])->GetValue().GetString(), ScriptPosition); - delete (*ArgList)[i]; - (*ArgList)[i] = statenode; + if (i + implicit < argtypes.Size()) + { + auto type = static_cast((*ArgList)[i])->ValueType; + // temporary hack to add the casts which get used by the internal definitions + if (argtypes[i + implicit] == TypeState && type == TypeString) + { + ScriptPosition.Message(MSG_WARNING, "Converting %s to state", static_cast((*ArgList)[i])->GetValue().GetString()); + auto statenode = new FxMultiNameState(static_cast((*ArgList)[i])->GetValue().GetString(), ScriptPosition); + delete (*ArgList)[i]; + (*ArgList)[i] = statenode; + } + if (argtypes[i + implicit] == TypeSound && type == TypeString) + { + ScriptPosition.Message(MSG_WARNING, "Converting %s to sound", static_cast((*ArgList)[i])->GetValue().GetString()); + auto statenode = new FxConstant(FSoundID(static_cast((*ArgList)[i])->GetValue().GetString()), ScriptPosition); + delete (*ArgList)[i]; + (*ArgList)[i] = statenode; + } + if (argtypes[i + implicit] == TypeSInt32 && type == TypeFloat64) + { + ScriptPosition.Message(MSG_WARNING, "Converting %f to int", static_cast((*ArgList)[i])->GetValue().GetFloat()); + auto statenode = new FxConstant(static_cast((*ArgList)[i])->GetValue().GetInt(), ScriptPosition); + delete (*ArgList)[i]; + (*ArgList)[i] = statenode; + } + if (argtypes[i + implicit] == TypeFloat64 && type == TypeSInt32) + { + ScriptPosition.Message(MSG_WARNING, "Converting %d to float", static_cast((*ArgList)[i])->GetValue().GetInt()); + auto statenode = new FxConstant(static_cast((*ArgList)[i])->GetValue().GetFloat(), ScriptPosition); + delete (*ArgList)[i]; + (*ArgList)[i] = statenode; + } + } } + (*ArgList)[i] = (*ArgList)[i]->Resolve(ctx); if ((*ArgList)[i] == NULL) failed = true; } From 7bdd320f13ec6362d97b1147a5286c4eee77ca85 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 23:51:38 +0200 Subject: [PATCH 034/471] - forgot to save this. --- src/dobjtype.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index b41ffe0e6b..aee2d0ae25 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -852,7 +852,6 @@ PArray *NewArray(PType *type, unsigned int count); PDynArray *NewDynArray(PType *type); PPointer *NewPointer(PType *type); 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); From d8a8b590061c839f90774ca98018658d941b5b78 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 10:34:26 +0200 Subject: [PATCH 035/471] - cleaned up the loop statement nodes in the code generator, which put some handling in FCompileContext and some of their data into the base FxExpression class instead of having an intermediate base class for all loops which is responsible for the relevant data. All this is now encapsulated in a new FxLoopStatement class which serves as base for the actual loop statements. --- src/scripting/codegeneration/thingdef_exp.h | 34 ++++++--- .../codegeneration/thingdef_expression.cpp | 72 +++++++++++-------- 2 files changed, 65 insertions(+), 41 deletions(-) diff --git a/src/scripting/codegeneration/thingdef_exp.h b/src/scripting/codegeneration/thingdef_exp.h index 2e9af65b6d..3c52547c50 100644 --- a/src/scripting/codegeneration/thingdef_exp.h +++ b/src/scripting/codegeneration/thingdef_exp.h @@ -198,9 +198,6 @@ protected: FxExpression(const FScriptPosition &pos) : ScriptPosition(pos) { - isresolved = false; - ScriptPosition = pos; - ValueType = NULL; } public: virtual ~FxExpression() {} @@ -215,12 +212,10 @@ public: virtual ExpEmit Emit(VMFunctionBuilder *build); - TArray JumpAddresses; - FScriptPosition ScriptPosition; - PType *ValueType; + PType *ValueType = nullptr; - bool isresolved; + bool isresolved = false; }; //========================================================================== @@ -1003,13 +998,32 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// Base class for loops +// +//========================================================================== + +class FxLoopStatement : public FxExpression +{ +protected: + FxLoopStatement(const FScriptPosition &pos) + : FxExpression(pos) + { + } + + void HandleJumps(int token, FCompileContext &ctx); + + TArray JumpAddresses; +}; + //========================================================================== // // FxWhileLoop // //========================================================================== -class FxWhileLoop : public FxExpression +class FxWhileLoop : public FxLoopStatement { FxExpression *Condition; FxExpression *Code; @@ -1027,7 +1041,7 @@ public: // //========================================================================== -class FxDoWhileLoop : public FxExpression +class FxDoWhileLoop : public FxLoopStatement { FxExpression *Condition; FxExpression *Code; @@ -1045,7 +1059,7 @@ public: // //========================================================================== -class FxForLoop : public FxExpression +class FxForLoop : public FxLoopStatement { FxExpression *Init; FxExpression *Condition; diff --git a/src/scripting/codegeneration/thingdef_expression.cpp b/src/scripting/codegeneration/thingdef_expression.cpp index 323ca083ed..2a6cf51aa2 100644 --- a/src/scripting/codegeneration/thingdef_expression.cpp +++ b/src/scripting/codegeneration/thingdef_expression.cpp @@ -104,20 +104,6 @@ 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); @@ -4398,6 +4384,27 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) return ExpEmit(); } + +//========================================================================== +// +// FxLoopStatement +// +//========================================================================== + +void FxLoopStatement::HandleJumps(int token, FCompileContext &ctx) +{ + for (unsigned int i = 0; i < ctx.Jumps.Size(); i++) + { + if (ctx.Jumps[i]->Token == token) + { + ctx.Jumps[i]->AddressResolver = this; + JumpAddresses.Push(ctx.Jumps[i]); + ctx.Jumps.Delete(i); + i--; + } + } +} + //========================================================================== // // FxWhileLoop @@ -4405,7 +4412,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) //========================================================================== FxWhileLoop::FxWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) -: FxExpression(pos), Condition(condition), Code(code) +: FxLoopStatement(pos), Condition(condition), Code(code) { ValueType = TypeVoid; } @@ -4422,8 +4429,8 @@ FxExpression *FxWhileLoop::Resolve(FCompileContext &ctx) SAFE_RESOLVE(Condition, ctx); SAFE_RESOLVE_OPT(Code, ctx); - ctx.HandleJumps(TK_Break, this); - ctx.HandleJumps(TK_Continue, this); + HandleJumps(TK_Break, ctx); + HandleJumps(TK_Continue, ctx); if (Condition->ValueType != TypeBool) { @@ -4506,7 +4513,7 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) //========================================================================== FxDoWhileLoop::FxDoWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) -: FxExpression(pos), Condition(condition), Code(code) +: FxLoopStatement(pos), Condition(condition), Code(code) { ValueType = TypeVoid; } @@ -4523,8 +4530,8 @@ FxExpression *FxDoWhileLoop::Resolve(FCompileContext &ctx) SAFE_RESOLVE(Condition, ctx); SAFE_RESOLVE_OPT(Code, ctx); - ctx.HandleJumps(TK_Break, this); - ctx.HandleJumps(TK_Continue, this); + HandleJumps(TK_Break, ctx); + HandleJumps(TK_Continue, ctx); if (Condition->ValueType != TypeBool) { @@ -4608,7 +4615,7 @@ ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) //========================================================================== FxForLoop::FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos) -: FxExpression(pos), Init(init), Condition(condition), Iteration(iteration), Code(code) +: FxLoopStatement(pos), Init(init), Condition(condition), Iteration(iteration), Code(code) { ValueType = TypeVoid; } @@ -4629,8 +4636,8 @@ FxExpression *FxForLoop::Resolve(FCompileContext &ctx) SAFE_RESOLVE_OPT(Iteration, ctx); SAFE_RESOLVE_OPT(Code, ctx); - ctx.HandleJumps(TK_Break, this); - ctx.HandleJumps(TK_Continue, this); + HandleJumps(TK_Break, ctx); + HandleJumps(TK_Continue, ctx); if (Condition != nullptr) { @@ -5041,17 +5048,20 @@ static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int { PClassActor *cls = stateowner->GetClass(); - while (cls != RUNTIME_CLASS(AActor)) + if (stateinfo->mCallingState != nullptr) { - // both calling and target state need to belong to the same class. - if (cls->OwnsState(stateinfo->mCallingState)) + while (cls != RUNTIME_CLASS(AActor)) { - return cls->OwnsState(stateinfo->mCallingState + index); - } + // 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); + // 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; } From f86e64e712ab1af01467f7c324c7ba834b44754f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 10:39:58 +0200 Subject: [PATCH 036/471] - renamed thingdef_expression to codegen. Eventually this needs to be split up into smaller units because the file is already quite large and there's still a lot to add here. --- src/CMakeLists.txt | 2 +- .../codegeneration/{thingdef_expression.cpp => codegen.cpp} | 0 src/scripting/codegeneration/{thingdef_exp.h => codegen.h} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename src/scripting/codegeneration/{thingdef_expression.cpp => codegen.cpp} (100%) rename src/scripting/codegeneration/{thingdef_exp.h => codegen.h} (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b612684d5c..ab9306447f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1247,7 +1247,7 @@ set (PCH_SOURCES scripting/thingdef.cpp scripting/thingdef_data.cpp scripting/thingdef_properties.cpp - scripting/codegeneration/thingdef_expression.cpp + scripting/codegeneration/codegen.cpp scripting/decorate/olddecorations.cpp scripting/decorate/thingdef_exp.cpp scripting/decorate/thingdef_parse.cpp diff --git a/src/scripting/codegeneration/thingdef_expression.cpp b/src/scripting/codegeneration/codegen.cpp similarity index 100% rename from src/scripting/codegeneration/thingdef_expression.cpp rename to src/scripting/codegeneration/codegen.cpp diff --git a/src/scripting/codegeneration/thingdef_exp.h b/src/scripting/codegeneration/codegen.h similarity index 100% rename from src/scripting/codegeneration/thingdef_exp.h rename to src/scripting/codegeneration/codegen.h From 3b0d687b22b8e04ae13b348af389097882d2df44 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 10:43:02 +0200 Subject: [PATCH 037/471] - committed from the wrong subdirectory and missed all files that just changed the #include line. --- src/scripting/decorate/olddecorations.cpp | 2 +- src/scripting/decorate/thingdef_exp.cpp | 2 +- src/scripting/decorate/thingdef_parse.cpp | 2 +- src/scripting/decorate/thingdef_states.cpp | 2 +- src/scripting/thingdef.cpp | 2 +- src/scripting/vm/vmbuilder.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 3 ++- 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 4bcb2c36c0..75e49dbaa8 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -48,7 +48,7 @@ #include "decallib.h" #include "i_system.h" #include "thingdef.h" -#include "codegeneration/thingdef_exp.h" +#include "codegeneration/codegen.h" #include "r_data/r_translate.h" // TYPES ------------------------------------------------------------------- diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 2f52fb260b..5dc909cd07 100644 --- a/src/scripting/decorate/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 "codegeneration/thingdef_exp.h" +#include "codegeneration/codegen.h" FRandom pr_exrandom ("EX_Random"); diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index f567d91e0e..e48d4d8564 100644 --- a/src/scripting/decorate/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 "codegeneration/thingdef_exp.h" +#include "codegeneration/codegen.h" #include "w_wad.h" #include "v_video.h" #include "version.h" diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 143144aa53..f2dda5548e 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -54,7 +54,7 @@ #include "s_sound.h" #include "i_system.h" #include "colormatcher.h" -#include "codegeneration/thingdef_exp.h" +#include "codegeneration/codegen.h" #include "version.h" #include "templates.h" #include "vmbuilder.h" diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 1a761b8c25..1ed0ea9103 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -61,7 +61,7 @@ #include "p_conversation.h" #include "v_text.h" #include "thingdef.h" -#include "codegeneration/thingdef_exp.h" +#include "codegeneration/codegen.h" #include "a_sharedglobal.h" #include "vmbuilder.h" #include "stats.h" diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index f111c45293..4351723f86 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -32,7 +32,7 @@ */ #include "vmbuilder.h" -#include "codegeneration/thingdef_exp.h" +#include "codegeneration/codegen.h" #include "info.h" #include "m_argv.h" #include "thingdef.h" diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index d034c51cc6..2016659fad 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -47,7 +47,7 @@ #include "p_lnspec.h" #include "i_system.h" #include "gdtoa.h" -#include "codegeneration/thingdef_exp.h" +#include "codegeneration/codegen.h" #include "vmbuilder.h" #define DEFINING_CONST ((PSymbolConst *)(void *)1) @@ -2290,6 +2290,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_ExprFuncCall: { auto fcall = static_cast(ast); + //return ConvertFunctionCall(fcall); assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. auto fname = static_cast(fcall->Function)->Identifier; return new FxFunctionCall(nullptr, fname, ConvertNodeList(fcall->Parameters), *ast); From 2cb5839c1133a44378ff277e0bc2d6d340aa2abf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 12:15:25 +0200 Subject: [PATCH 038/471] - count errors in the parser and abort afterward if there were some. - use FScriptPosition's error counter throughout the compiler so that there is only one counter for everything, not two. Parts of the compiler use FScriptPosition, so this is easier to handle than having a separate counter in the compiler class. It also avoids having to pass the compiler object to any function where an error may be output. The TreeNodes contain sufficient data to be converted to an FScriptPosition and using that for error message formatting. --- src/CMakeLists.txt | 1 + src/sc_man.cpp | 2 ++ src/sc_man.h | 2 ++ src/scripting/thingdef.cpp | 1 + src/scripting/zscript/zcc-parse.lemon | 1 + src/scripting/zscript/zcc_compile.cpp | 11 +++++------ src/scripting/zscript/zcc_compile.h | 2 -- src/scripting/zscript/zcc_parser.cpp | 20 ++++++++++++++++++++ 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ab9306447f..545400b1c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1248,6 +1248,7 @@ set (PCH_SOURCES scripting/thingdef_data.cpp scripting/thingdef_properties.cpp scripting/codegeneration/codegen.cpp + scripting/codegeneration/functioncalls.cpp scripting/decorate/olddecorations.cpp scripting/decorate/thingdef_exp.cpp scripting/decorate/thingdef_parse.cpp diff --git a/src/sc_man.cpp b/src/sc_man.cpp index 97f384f3df..f48d6b4612 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -1006,6 +1006,7 @@ void FScanner::CheckOpen() // //========================================================================== int FScriptPosition::ErrorCounter; +int FScriptPosition::WarnCounter; bool FScriptPosition::StrictErrors; // makes all OPTERRPR messages real errors. FScriptPosition::FScriptPosition(const FScriptPosition &other) @@ -1072,6 +1073,7 @@ void FScriptPosition::Message (int severity, const char *message, ...) const return; case MSG_WARNING: + WarnCounter++; type = "warning"; color = TEXTCOLOR_YELLOW; break; diff --git a/src/sc_man.h b/src/sc_man.h index c319a7a2f6..5eeacd8924 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -139,6 +139,7 @@ enum struct FScriptPosition { + static int WarnCounter; static int ErrorCounter; static bool StrictErrors; FString FileName; @@ -155,6 +156,7 @@ struct FScriptPosition void Message(int severity, const char *message,...) const; static void ResetErrorCounter() { + WarnCounter = 0; ErrorCounter = 0; } }; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 1ed0ea9103..f62997816f 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -127,6 +127,7 @@ void LoadActors () InitThingdef(); ParseScripts(); + ParseAllDecorate(); FunctionBuildList.Build(); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index cd1cbce14b..78a4d29ea0 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -99,6 +99,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) } } stat->sc->ScriptMessage("%s\n%s\n", unexpected.GetChars(), expecting.GetChars()); + FScriptPosition::ErrorCounter++; } %parse_accept { DPrintf(DMSG_SPAMMY, "Input accepted\n"); } %parse_failure { /**failed = true;*/ } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 2016659fad..f2f7b4d4b9 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -203,8 +203,9 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC //========================================================================== ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PSymbolTable &_outsymbols) - : Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), ErrorCount(0), WarnCount(0) + : Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast) { + FScriptPosition::ResetErrorCounter(); // Group top-level nodes by type if (ast.TopNode != NULL) { @@ -320,7 +321,7 @@ void ZCCCompiler::Warn(ZCC_TreeNode *node, const char *msg, ...) MessageV(node, TEXTCOLOR_ORANGE, msg, argptr); va_end(argptr); - WarnCount++; + FScriptPosition::WarnCounter++; } //========================================================================== @@ -338,7 +339,7 @@ void ZCCCompiler::Error(ZCC_TreeNode *node, const char *msg, ...) MessageV(node, TEXTCOLOR_RED, msg, argptr); va_end(argptr); - ErrorCount++; + FScriptPosition::ErrorCounter++; } //========================================================================== @@ -376,7 +377,7 @@ int ZCCCompiler::Compile() InitDefaults(); InitFunctions(); CompileStates(); - return ErrorCount; + return FScriptPosition::ErrorCounter; } //========================================================================== @@ -1678,7 +1679,6 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper } } // call the handler - FScriptPosition::ErrorCounter = 0; try { prop->Handler(defaults, bag.Info, bag, ¶ms[0]); @@ -1687,7 +1687,6 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper { Error(property, "%s", error.GetMessage()); } - ErrorCount += FScriptPosition::ErrorCounter; } //========================================================================== diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 2ca00459aa..12e5703302 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -146,8 +146,6 @@ private: PSymbolTable *GlobalTreeNodes; PSymbolTable *OutputSymbols; ZCC_AST &AST; - int ErrorCount; - int WarnCount; }; void ZCC_InitConversions(); diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index b803b41584..c3f75b2b0a 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -39,6 +39,7 @@ #include "cmdlib.h" #include "m_alloc.h" #include "i_system.h" +#include "v_text.h" #include "zcc_parser.h" #include "zcc_compile.h" @@ -323,6 +324,12 @@ static void DoParse(int lumpnum) ZCCParse(parser, 0, value, &state); ZCCParseFree(parser, free); + // 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) + { + I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum)); + } + { // Make a dump of the AST before running the compiler for diagnostic purposes. #ifdef _DEBUG @@ -347,11 +354,24 @@ static void DoParse(int lumpnum) symtable.SetName("Global_Node"); ZCCCompiler cc(state, NULL, symtable, GlobalSymbols); 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)); + } + 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)); + } + } void ParseScripts() { int lump, lastlump = 0; + FScriptPosition::ResetErrorCounter(); while ((lump = Wads.FindLump("ZSCRIPT", &lastlump)) != -1) { DoParse(lump); From 32a3f57a5474244702f1b2084fce83a0142635cb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 14:36:08 +0200 Subject: [PATCH 039/471] - more preparations to compile functions: * Allow PFunction to work without a VMFunction being attached. * The Variant for a function must store the prototype itself instead of relying on the VMFunction it points to. Otherwise it would not be possible to reference a prototype during compilation of the function because it does not exist yet. * Give the variant a list of the function's argument's names, because these are also needed to compile the function. * create an anonymous function symbol when the function gets registered to the builder. At this point we have all the needed information to set it up correctly, but later this is no longer the case. This is the most convenient info to have here because it contains everything that's needed to compile the function in the proper context, so it has to be present when starting compilation. * added some preparations to implement special handling for weapons and custom inventory items, which can run action functions in another actor's context. This part is not active yet but the basics are present in SetImplicitArgs. --- src/dobjtype.cpp | 6 +-- src/dobjtype.h | 5 +- src/namedef.h | 2 +- src/scripting/codegeneration/codegen.cpp | 4 +- src/scripting/decorate/thingdef_parse.cpp | 6 ++- src/scripting/decorate/thingdef_states.cpp | 5 +- src/scripting/thingdef.cpp | 58 ++++++++++++++++++---- src/scripting/thingdef.h | 3 +- src/scripting/thingdef_properties.cpp | 3 +- src/scripting/vm/vmbuilder.cpp | 36 ++++---------- src/scripting/vm/vmbuilder.h | 4 +- src/scripting/zscript/zcc_compile.cpp | 27 +++------- src/scripting/zscript/zcc_compile.h | 1 + 13 files changed, 91 insertions(+), 69 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 7709bfa8f0..4dcb904d5b 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2490,14 +2490,14 @@ size_t PFunction::PropagateMark() // //========================================================================== -unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, VMFunction *impl) +unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl) { Variant variant; - //variant.Proto = proto; + variant.Proto = proto; variant.ArgFlags = argflags; variant.Implementation = impl; - impl->Proto = proto; + if (impl != nullptr) impl->Proto = proto; return Variants.Push(variant); } diff --git a/src/dobjtype.h b/src/dobjtype.h index aee2d0ae25..9a51fa88a5 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -692,14 +692,15 @@ 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. }; TArray Variants; DWORD Flags; - unsigned AddVariant(PPrototype *proto, TArray &argflags, VMFunction *impl); + unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl); size_t PropagateMark(); diff --git a/src/namedef.h b/src/namedef.h index eedbaf899e..43856aad16 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -717,7 +717,7 @@ xx(Max_10_Exp) // implicit function parameters xx(self) -xx(caller) +xx(invoker) xx(stateinfo) xx(__decorate_internal_int__) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 2a6cf51aa2..0034de8a40 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3883,7 +3883,7 @@ FxVMFunctionCall::~FxVMFunctionCall() PPrototype *FxVMFunctionCall::ReturnProto() { EmitTail = true; - return Function->Variants[0].Implementation->Proto; + return Function->Variants[0].Proto; } //========================================================================== @@ -3916,7 +3916,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); bool failed = false; - auto proto = Function->Variants[0].Implementation->Proto; + auto proto = Function->Variants[0].Proto; auto argtypes = proto->ArgumentTypes; int implicit; diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index e48d4d8564..f547956dd9 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -458,6 +458,7 @@ void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname, const AFuncDesc *afd; TArray args; TArray argflags; + TArray argnames; afd = FindFunction(funcname); if (afd == NULL) @@ -467,13 +468,14 @@ void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname, } sc.MustGetToken('('); - SetImplicitArgs(&args, &argflags, cls, funcflags); + SetImplicitArgs(&args, &argflags, &argnames, cls, funcflags); + // This function will be removed once all internal classes have been ported so don't bother filling in the function's argument names, because for anything going through here they'll never be used. ParseArgListDef(sc, cls, args, argflags); if (afd != NULL) { PFunction *sym = new PFunction(funcname); - sym->AddVariant(NewPrototype(rets, args), argflags, *(afd->VMPointer)); + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, *(afd->VMPointer)); sym->Flags = funcflags; if (cls->Symbols.AddSymbol(sym) == NULL) { diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index f2dda5548e..ada9462e04 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -322,7 +322,8 @@ do_stop: endofstate: if (ScriptCode != nullptr) { - state.ActionFunc = FunctionBuildList.AddFunction(actor, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true); + auto funcsym = CreateAnonymousFunction(actor, nullptr, VARF_Method | VARF_Action); + state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true); } int count = bag.statedef.AddStates(&state, statestring); if (count < 0) @@ -595,7 +596,7 @@ 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; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index f62997816f..182bfbd12a 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -80,34 +80,74 @@ PClassActor *QuestItemClasses[31]; // //========================================================================== -void SetImplicitArgs(TArray *args, TArray *argflags, PClass *cls, DWORD funcflags) +void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags) { // Must be called before adding any other arguments. - assert(args == NULL || args->Size() == 0); - assert(argflags == NULL || argflags->Size() == 0); + assert(args == nullptr || args->Size() == 0); + assert(argflags == nullptr || argflags->Size() == 0); if (funcflags & VARF_Method) { // implied self pointer - if (args != NULL) args->Push(NewClassPointer(cls)); - if (argflags != NULL) argflags->Push(VARF_Implicit); + if (args != nullptr) args->Push(cls); + if (argflags != nullptr) argflags->Push(VARF_Implicit); + if (argnames != nullptr) argnames->Push(NAME_self); } if (funcflags & VARF_Action) { // implied caller and callingstate pointers - if (args != NULL) + if (args != nullptr) { - args->Insert(0, NewClassPointer(RUNTIME_CLASS(AActor))); // the caller must go before self due to an old design mistake. - args->Push(TypeState); + // Special treatment for weapons and CustomInventorys: 'self' is not the defining class but the actual user of the item, so this pointer must be of type 'Actor' + /* if (cls->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) + { + args->Insert(0, RUNTIME_CLASS(AActor)); // this must go in before the real pointer to the containing class. + } + else*/ + { + args->Push(cls); + } + args->Push(TypeState/*Info*/); // fixme: TypeState is not the correct type here!!! } - if (argflags != NULL) + if (argflags != nullptr) { argflags->Push(VARF_Implicit); argflags->Push(VARF_Implicit); } + 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; + + rets[0] = returntype != nullptr? returntype : TypeError; // Use TypeError as placeholder if we do not know the return type yet. + SetImplicitArgs(&args, &argflags, &argnames, containingclass, flags); + + PFunction *sym = new PFunction(NAME_None); // anonymous functions do not have names. + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr); + sym->Flags = VARF_Action; + return sym; +} + //========================================================================== // // LoadActors diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 4a984dd5c4..d5b189d47b 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -150,7 +150,8 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray *args, TArray *argflags, PClass *cls, DWORD funcflags); +void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags); +PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); //========================================================================== // diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 833a2d381e..34f424ab4c 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -657,7 +657,8 @@ DEFINE_PROPERTY(damage, X, Actor) } else { - defaults->DamageFunc = FunctionBuildList.AddFunction(bag.Info, id, FStringf("%s.DamageFunction", bag.Info->TypeName.GetChars()), false); + auto funcsym = CreateAnonymousFunction(bag.Info, TypeSInt32, VARF_Method); + defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, id, FStringf("%s.DamageFunction", bag.Info->TypeName.GetChars()), false); } } diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 4351723f86..76fd840724 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -649,7 +649,7 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc) //========================================================================== FFunctionBuildList FunctionBuildList; -VMFunction *FFunctionBuildList::AddFunction(PClass *cls, FxExpression *code, const FString &name, bool statecall) +VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool statecall) { auto func = code->GetDirectFunction(); if (func != nullptr) @@ -661,7 +661,7 @@ VMFunction *FFunctionBuildList::AddFunction(PClass *cls, FxExpression *code, con //Printf("Adding %s\n", name.GetChars()); Item it; - it.Class = cls; + it.Func = functype; it.Code = code; it.DumpName = name; it.Function = new VMScriptFunction; @@ -684,8 +684,11 @@ void FFunctionBuildList::Build() { assert(item.Code != NULL); + // This needs to be fixed, so that the compile context receives the entire function symbol, including the containing class, the prototype and argument names, which will be needed to run the code generator + // As a first step this just needs to get working so fetch the class type from the prototype's argument list. + auto cls = static_cast(item.Func->Variants[0].Proto->ArgumentTypes[!!(item.Func->Flags & VARF_Action)]); // We don't know the return type in advance for anonymous functions. - FCompileContext ctx(item.Class, nullptr); + FCompileContext ctx(cls, nullptr); item.Code = item.Code->Resolve(ctx); item.Proto = ctx.ReturnProto; @@ -695,32 +698,15 @@ void FFunctionBuildList::Build() VMFunctionBuilder buildit(true); assert(item.Proto != nullptr); - - int numargs; - int flags; - - // Kludge alert. This needs to be done in a more universal fashion. - // Right now there's only action and damage functions, so for the time being - // this will do to get the whole thing started first. - - if (item.type == 1) // anonymous action function - { - numargs = NAP; - flags = VARF_Method | VARF_Action; - } - else - { - numargs = 1; - flags = VARF_Method; - } + auto numargs = item.Func->Variants[0].Proto->ArgumentTypes.Size(); // Generate prototype for this anonymous function + // Fixme: This later needs to do proper allocation for the function's entire argument list, once non-anonymous functions can be done. buildit.Registers[REGT_POINTER].Get(numargs); - TArray args(numargs); - SetImplicitArgs(&args, nullptr, item.Class, flags); VMScriptFunction *sfunc = item.Function; - item.Function->Proto = NewPrototype(item.Proto->ReturnTypes, args); + // create a new prototype from the now known return type and the argument list of the function's template prototype. + item.Function->Proto = NewPrototype(item.Proto->ReturnTypes, item.Func->Variants[0].Proto->ArgumentTypes); // Emit code item.Code->Emit(&buildit); @@ -731,7 +717,7 @@ void FFunctionBuildList::Build() { char label[64]; int labellen = mysnprintf(label, countof(label), item.DumpName, - item.Class->TypeName.GetChars()); + cls->TypeName.GetChars()); DumpFunction(dump, sfunc, label, labellen); codesize += sfunc->CodeSize; } diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 59e9fbe79b..6b9a0aa682 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -101,7 +101,7 @@ class FFunctionBuildList { struct Item { - PClass *Class = nullptr; + PFunction *Func = nullptr; FxExpression *Code = nullptr; PPrototype *Proto = nullptr; VMScriptFunction *Function = nullptr; @@ -112,7 +112,7 @@ class FFunctionBuildList TArray mItems; public: - VMFunction *AddFunction(PClass *cls, FxExpression *code, const FString &name, bool statecall = false); + VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool statecall = false); void Build(); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f2f7b4d4b9..23bdce3b52 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1870,7 +1870,7 @@ void ZCCCompiler::InitFunctions() TArray rets(1); TArray args; TArray argflags; - TArray argnames; + TArray argnames; for (auto c : Classes) { @@ -1925,20 +1925,7 @@ void ZCCCompiler::InitFunctions() Error(f, "The function '%s' has not been exported from the executable.", FName(f->Name).GetChars()); } } - SetImplicitArgs(&args, &argflags, c->Type(), varflags); - // Give names to the implicit parameters. - // Note that 'self' is the second argument on action functions, because this is the one referring to the owning class. - if (varflags & VARF_Action) - { - argnames.Push(NAME_caller); - argnames.Push(NAME_self); - argnames.Push(NAME_stateinfo); - } - else if (varflags & VARF_Method) - { - argnames.Push(NAME_self); - } - + SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags); auto p = f->Params; if (p != nullptr) { @@ -1974,7 +1961,7 @@ void ZCCCompiler::InitFunctions() } PFunction *sym = new PFunction(f->Name); - sym->AddVariant(NewPrototype(rets, args), argflags, afd == nullptr? nullptr : *(afd->VMPointer)); + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr? nullptr : *(afd->VMPointer)); sym->Flags = varflags; c->Type()->Symbols.ReplaceSymbol(sym); @@ -2025,7 +2012,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a { if (fc->Parameters == nullptr && (afd->Flags & VARF_Action)) { - // This is the simple case which doesn't require work on the tree. + // We can use this function directly without wrapping it in a caller. return new FxVMFunctionCall(afd, nullptr, *af, true); } } @@ -2040,6 +2027,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a // Action specials fall through to the code generator. } } + ConvertClass = cls; return ConvertAST(af); //Error(af, "Complex action functions not supported yet."); @@ -2173,7 +2161,8 @@ void ZCCCompiler::CompileStates() auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); if (code != nullptr) { - state.ActionFunc = FunctionBuildList.AddFunction(c->Type(), code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), true); + auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action); + state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), true); } } @@ -2289,10 +2278,10 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_ExprFuncCall: { auto fcall = static_cast(ast); - //return ConvertFunctionCall(fcall); assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. auto fname = static_cast(fcall->Function)->Identifier; return new FxFunctionCall(nullptr, fname, ConvertNodeList(fcall->Parameters), *ast); + //return ConvertFunctionCall(fcall->Function, ConvertNodeList(fcall->Parameters), ConvertClass, *ast); } case AST_FuncParm: diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 12e5703302..4ecd632275 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -143,6 +143,7 @@ private: FArgumentList *ConvertNodeList(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; From 091da92819fed1559fba584ba4840fdbf60169b1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 15:10:48 +0200 Subject: [PATCH 040/471] - Added AStateProvider class which is used to define the special action function behavior of weapons and custom inventorys. The class itself does not do anything, but the compiler will use it to set up the action function prototypes differently which in turn will be used to do type checking during code generation. --- src/CMakeLists.txt | 1 + src/g_shared/a_pickups.cpp | 1 + src/g_shared/a_pickups.h | 15 ++-- src/scripting/thingdef.cpp | 4 +- wadsrc/static/zscript/shared/inventory.txt | 95 +++++++++++----------- 5 files changed, 63 insertions(+), 53 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 545400b1c4..ae2f19960d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1461,6 +1461,7 @@ source_group("Scripting\\Decorate" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_D 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("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index c4daae0241..38f0a51300 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1642,6 +1642,7 @@ void AInventory::DetachFromOwner () { } +IMPLEMENT_CLASS(AStateProvider) IMPLEMENT_CLASS (ACustomInventory) //=========================================================================== diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 45676a214d..6dc2d0bc59 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -226,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. @@ -281,9 +286,9 @@ public: 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/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 182bfbd12a..21f690f6ca 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -99,11 +99,11 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArrayIsDescendantOf(RUNTIME_CLASS(AStateProvider))) + if (cls->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) { args->Insert(0, RUNTIME_CLASS(AActor)); // this must go in before the real pointer to the containing class. } - else*/ + else { args->Push(cls); } diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index fe60fdc1a0..bf2f7e188c 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -10,50 +10,49 @@ class Inventory : Actor native Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"; } - // functions that can be used from weapons and CustomInventory. These require that 'self' is of type class and be treated as such in the scripts. - /*inventory*/ action native state A_JumpIfNoAmmo(state label); - /*inventory*/ action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = ""); - /*inventory*/ action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); - /*inventory*/ 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); - /*inventory*/ action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); - /*inventory*/ action native void A_Light(int extralight); - /*inventory*/ action native void A_Light0(); - /*inventory*/ action native void A_Light1(); - /*inventory*/ action native void A_Light2(); - /*inventory*/ action native void A_LightInverse(); - /*inventory*/ action native void A_WeaponReady(int flags = 0); - /*inventory*/ action native void A_Lower(); - /*inventory*/ action native void A_Raise(); - /*inventory*/ action native void A_FirePistol(); - /*inventory*/ action native void A_FireShotgun(); - /*inventory*/ action native void A_FireShotgun2(); - /*inventory*/ action native void A_OpenShotgun2(); - /*inventory*/ action native void A_LoadShotgun2(); - /*inventory*/ action native void A_CloseShotgun2(); - /*inventory*/ action native void A_FireCGun(); - /*inventory*/ action native void A_FireSTGrenade(class grenadetype = "Grenade"); - /*inventory*/ action native void A_FireMissile(); - /*inventory*/ action native void A_FirePlasma(); - /*inventory*/ action native void A_FireRailgun(); - /*inventory*/ action native void A_FireRailgunLeft(); - /*inventory*/ action native void A_FireRailgunRight(); - /*inventory*/ action native void A_RailWait(); - /*inventory*/ action native void A_BFGsound(); - /*inventory*/ action native void A_FireBFG(); - /*inventory*/ action native void A_FireOldBFG(); - /*inventory*/ action native void A_ReFire(state flash = ""); - /*inventory*/ action native void A_ClearReFire(); - /*inventory*/ action native void A_CheckReload(); - /*inventory*/ action native void A_GunFlash(state flash = "", int flags = 0); - /*inventory*/ 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"); - /*inventory*/ action native state A_CheckForReload(int counter, state label, bool dontincrement = false); - /*inventory*/ action native void A_ResetReloadCounter(); + action native state A_JumpIfNoAmmo(state label); + action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = ""); + action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); + action native void A_FireCustomMissile(class missiletype, float angle = 0, bool useammo = true, float spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0); + action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + action native void A_Light(int extralight); + action native void A_Light0(); + action native void A_Light1(); + action native void A_Light2(); + 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 native void A_OpenShotgun2(); + action native void A_LoadShotgun2(); + action native void A_CloseShotgun2(); + 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 native void A_RailWait(); + action native void A_BFGsound(); + action native void A_FireBFG(); + action native void A_FireOldBFG(); + action native void A_ReFire(state flash = ""); + action native void A_ClearReFire(); + action native void A_CheckReload(); + action native void A_GunFlash(state flash = "", int flags = 0); + action native void A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff", int flags = 0, float range = 0, float spread_xy = 2.8125, float spread_z = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus"); + action native state A_CheckForReload(int counter, state label, bool dontincrement = false); + action native void A_ResetReloadCounter(); // These are regular functions for the item itself. - action native void A_RestoreSpecialPosition(); - action native void A_RestoreSpecialDoomThing(); - action native void A_RestoreSpecialThing1(); - action native void A_RestoreSpecialThing2(); + private action native void A_RestoreSpecialPosition(); + private action native void A_RestoreSpecialDoomThing(); + private action native void A_RestoreSpecialThing1(); + private action native void A_RestoreSpecialThing2(); States { @@ -78,6 +77,10 @@ class Inventory : Actor native } } +class StateProvider : Inventory native +{ +} + class ScoreItem : Inventory native { Default @@ -151,7 +154,7 @@ class DehackedPickup : Inventory native {} class FakeInventory : Inventory native {} -class CustomInventory : Inventory native {} +class CustomInventory : StateProvider native {} class Health : Inventory native { @@ -448,7 +451,7 @@ class PuzzleItem : Inventory native } } -class Weapon : Inventory native +class Weapon : StateProvider native { Default { @@ -466,11 +469,11 @@ class Weapon : Inventory native Stop; } - /*inventory*/ action native void A_ZoomFactor(float scale = 1, int flags = 0); + action native void A_ZoomFactor(float scale = 1, int flags = 0); const ZOOM_INSTANT = 1; const ZOOM_NOSCALETURNING = 2; - /*inventory*/ action native void A_SetCrosshair(int xhair); + action native void A_SetCrosshair(int xhair); } class WeaponGiver : Weapon native From db8ab1bc4ac269606bdb50743c4a8f2b896cf8c5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 15:50:45 +0200 Subject: [PATCH 041/471] - give PFunction a bit more information: * explicitly require passing the owning class when creating it. * extract self pointer class when adding a variant. * put the flags on the single variants, we can not fully rule out that they will be 100% identical, if variants ever get allowed. --- src/d_dehacked.cpp | 4 +- src/dobjtype.cpp | 19 ++- src/dobjtype.h | 9 +- src/scripting/codegeneration/codegen.cpp | 21 ++- .../codegeneration/functioncalls.cpp | 153 ++++++++++++++++++ src/scripting/decorate/thingdef_parse.cpp | 5 +- src/scripting/decorate/thingdef_states.cpp | 4 +- src/scripting/thingdef.cpp | 5 +- src/scripting/vm/vmbuilder.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 7 +- 10 files changed, 196 insertions(+), 33 deletions(-) create mode 100644 src/scripting/codegeneration/functioncalls.cpp diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 8e69ecb067..81ee907f47 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2119,7 +2119,7 @@ static int PatchCodePtrs (int dummy) 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))) + if ((sym->Variants[0].Flags & (VARF_Method | VARF_Action)) != (VARF_Method | VARF_Action) || (args.Size() > NAP && !(args[NAP] & VARF_Optional))) { Printf("Frame %d: Incompatible code pointer '%s'\n", frame, Line2); sym = NULL; @@ -2731,7 +2731,7 @@ 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))) + if ((sym->Variants[0].Flags & (VARF_Method|VARF_Action)) != (VARF_Method | VARF_Action) || (args.Size() > NAP && !(args[NAP] & VARF_Optional))) { sc.ScriptMessage("Incompatible code pointer '%s'", sc.String); } diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 4dcb904d5b..c43abf9a76 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2475,7 +2475,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(); @@ -2490,14 +2490,29 @@ size_t PFunction::PropagateMark() // //========================================================================== -unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl) +unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags) { Variant variant; + // I do not think we really want to deal with overloading here... + assert(Variants.Size() == 0); + + variant.Flags = flags; variant.Proto = proto; variant.ArgFlags = argflags; variant.Implementation = impl; 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); + variant.SelfClass = dyn_cast(proto->ArgumentTypes[0]); + assert(variant.SelfClass != nullptr); + } + return Variants.Push(variant); } diff --git a/src/dobjtype.h b/src/dobjtype.h index 9a51fa88a5..07d7ae10f2 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -696,16 +696,17 @@ public: 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, TArray &argnames, VMFunction *impl); + unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags); 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 --------------------------- diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 0034de8a40..801df8c652 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3898,7 +3898,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction() // 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 ? ArgList->Size() : 0) == 0 && (Function->Flags & VARF_Action)) + if ((ArgList ? ArgList->Size() : 0) == 0 && (Function->Variants[0].Flags & VARF_Action)) { return Function->Variants[0].Implementation; } @@ -3920,8 +3920,8 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) auto argtypes = proto->ArgumentTypes; int implicit; - if (Function->Flags & VARF_Action) implicit = 3; - else if (Function->Flags & VARF_Method) implicit = 1; + if (Function->Variants[0].Flags & VARF_Action) implicit = 3; + else if (Function->Variants[0].Flags & VARF_Method) implicit = 1; else implicit = 0; if (ArgList != NULL) @@ -4014,15 +4014,15 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) // For ZSCRIPT 'self' is properly used for the state's owning actor, meaning we have to pass the second argument here. // If both functions are non-action or both are action, there is no need for special treatment. - if (!OwnerIsSelf || (!!(Function->Flags & VARF_Action) == build->IsActionFunc)) + if (!OwnerIsSelf || (!!(Function->Variants[0].Flags & VARF_Action) == build->IsActionFunc)) { // Emit code to pass implied parameters - if (Function->Flags & VARF_Method) + if (Function->Variants[0].Flags & VARF_Method) { build->Emit(OP_PARAM, 0, REGT_POINTER, 0); count += 1; } - if (Function->Flags & VARF_Action) + if (Function->Variants[0].Flags & VARF_Action) { static_assert(NAP == 3, "This code needs to be updated if NAP changes"); if (build->IsActionFunc) @@ -4041,17 +4041,14 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } else { - // There are two possibilities here: - // Calling a non-action function from an action function. - // In that case the 'stateowner' pointer needs to be used as self. - if (build->IsActionFunc && (Function->Flags & VARF_Method)) + if (build->IsActionFunc && (Function->Variants[0].Flags & VARF_Method)) { - build->Emit(OP_PARAM, 0, REGT_POINTER, 1); + build->Emit(OP_PARAM, 0, REGT_POINTER, 0); count += 1; } // and calling an action function from a non-action function. // This must be blocked because it lacks crucial information. - if (!build->IsActionFunc && (Function->Flags & VARF_Action)) + if (!build->IsActionFunc && (Function->Variants[0].Flags & VARF_Action)) { // This case should be eliminated in the analyzing stage. I_Error("Cannot call action function from non-action functions."); diff --git a/src/scripting/codegeneration/functioncalls.cpp b/src/scripting/codegeneration/functioncalls.cpp new file mode 100644 index 0000000000..d085635cd6 --- /dev/null +++ b/src/scripting/codegeneration/functioncalls.cpp @@ -0,0 +1,153 @@ +#if 0 +/* +** cg_functioncall.cpp +** +**--------------------------------------------------------------------------- +** 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 "doomtype.h" +#include "codegen.h" +#include "thingdef.h" +#include "zscript/zcc_parser.h" + +// just some rough concepts for now... + +//========================================================================== +// +// FindClassMemberFunction +// +// Looks for a name in a class's +// +//========================================================================== + +PFunction *FindClassMemberFunction(PClass *cls, FName name, FScriptPosition &sc) +{ + PSymbolTable *symtable; + auto symbol = cls->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(), cls->TypeName.GetChars()); + } + else if (funcsym->Flags & VARF_Private && symtable != &cls->Symbols) + { + sc.Message(MSG_ERROR, "%s is declared private and not accessible", symbol->SymbolName.GetChars()); + } + else if (funcsym->Flags & VARF_Deprecated) + { + sc.Message(MSG_WARNING, "Call to deprecated function %s", symbol->SymbolName.GetChars()); + } + } + return funcsym; +} + + +//========================================================================== +// +// let's save some work down the line by analyzing the type of function +// that's being called right here and create appropriate nodes. +// A simple function call expression must be immediately resolvable in +// the context it gets compiled in, if the function name cannot be +// resolved here, it will never. +// +//========================================================================== + +FxExpression *ConvertSimpleFunctionCall(ZCC_ExprID *function, FArgumentList *args, PClass *cls, FScriptPosition &sc) +{ + // Priority is as follows: + //1. member functions of the containing class. + //2. action specials. + //3. floating point operations + //4. global builtins + + if (cls != nullptr) + { + // There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work. + if (function->Identifier != NAME_ACS_NamedExecuteWithResult) + { + { + args = ConvertNodeList(fcall->Parameters); + if (args->Size() == 0) + { + delete args; + args = nullptr; + } + + return new FxMemberunctionCall(new FxSelf(), new FxInvoker(), func, args, sc, false); + } + } + +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *ConvertFunctionCall(ZCC_Expression *function, FArgumentList *args, PClass *cls, FScriptPosition &sc) +{ + // function names can either be + // - plain identifiers + // - class members + // - array syntax for random() calls. + + switch(function->NodeType) + { + case AST_ExprID: + return ConvertSimpleFunctionCall(static_cast(function), args, cls, sc); + + case AST_ExprMemberAccess: + return ConvertMemberCall(fcall); + + case AST_ExprBinary: + // Array access syntax is wrapped into a ZCC_ExprBinary object. + if (fcall->Function->Operation == PEX_ArrayAccess) + { + return ConvertArrayFunctionCall(fcall); + } + break; + + default: + break; + } + Error(fcall, "Invalid function identifier"); + return new FxNop(*fcall); // return something so that we can continue +} + + + assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. + auto fname = static_cast(fcall->Function)->Identifier; + return new FxFunctionCall(nullptr, fname, ConvertNodeList(fcall->Parameters), *ast); + +#endif \ No newline at end of file diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index f547956dd9..b2f1cac071 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -474,9 +474,8 @@ void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname, if (afd != NULL) { - PFunction *sym = new PFunction(funcname); - sym->AddVariant(NewPrototype(rets, args), argflags, argnames, *(afd->VMPointer)); - sym->Flags = funcflags; + PFunction *sym = new PFunction(cls, funcname); + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, *(afd->VMPointer), funcflags); if (cls->Symbols.AddSymbol(sym) == NULL) { delete sym; diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index ada9462e04..d5a3395d73 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -602,12 +602,12 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArrayFlags & VARF_Method) + if (afd->Variants[0].Flags & VARF_Method) { numparams--; pnum++; } - if (afd->Flags & VARF_Action) + if (afd->Variants[0].Flags & VARF_Action) { numparams -= 2; pnum += 2; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 21f690f6ca..f80a8f87a0 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -142,9 +142,8 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i rets[0] = returntype != nullptr? returntype : TypeError; // Use TypeError as placeholder if we do not know the return type yet. SetImplicitArgs(&args, &argflags, &argnames, containingclass, flags); - PFunction *sym = new PFunction(NAME_None); // anonymous functions do not have names. - sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr); - sym->Flags = VARF_Action; + PFunction *sym = new PFunction(containingclass, NAME_None); // anonymous functions do not have names. + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, VARF_Action|VARF_Method); return sym; } diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 76fd840724..f366ec6505 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -686,7 +686,7 @@ void FFunctionBuildList::Build() // This needs to be fixed, so that the compile context receives the entire function symbol, including the containing class, the prototype and argument names, which will be needed to run the code generator // As a first step this just needs to get working so fetch the class type from the prototype's argument list. - auto cls = static_cast(item.Func->Variants[0].Proto->ArgumentTypes[!!(item.Func->Flags & VARF_Action)]); + auto cls = static_cast(item.Func->Variants[0].Proto->ArgumentTypes[!!(item.Func->Variants[0].Flags & VARF_Action)]); // We don't know the return type in advance for anonymous functions. FCompileContext ctx(cls, nullptr); item.Code = item.Code->Resolve(ctx); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 23bdce3b52..ee40868d37 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1960,9 +1960,8 @@ void ZCCCompiler::InitFunctions() } while (p != f->Params); } - PFunction *sym = new PFunction(f->Name); - sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr? nullptr : *(afd->VMPointer)); - sym->Flags = varflags; + 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); // todo: Check inheritance. @@ -2010,7 +2009,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a PFunction *afd = dyn_cast(cls->Symbols.FindSymbol(id->Identifier, true)); if (afd != nullptr) { - if (fc->Parameters == nullptr && (afd->Flags & VARF_Action)) + if (fc->Parameters == nullptr && (afd->Variants[0].Flags & VARF_Action)) { // We can use this function directly without wrapping it in a caller. return new FxVMFunctionCall(afd, nullptr, *af, true); From cbb990a79e625357dee848bbc98d653f6fc9e09b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 17:40:27 +0200 Subject: [PATCH 042/471] - pass the current function to the compile context instead of just the containing class. --- src/dobjtype.cpp | 4 +- src/dobjtype.h | 1 + src/scripting/codegeneration/codegen.cpp | 116 ++++++++++++++++------- src/scripting/codegeneration/codegen.h | 9 +- src/scripting/thingdef.cpp | 6 +- src/scripting/vm/vmbuilder.cpp | 8 +- src/scripting/zscript/zcc_compile.cpp | 5 + 7 files changed, 101 insertions(+), 48 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index c43abf9a76..966663f129 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2509,7 +2509,9 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra if (flags & VARF_Method) { assert(proto->ArgumentTypes.Size() > 0); - variant.SelfClass = dyn_cast(proto->ArgumentTypes[0]); + auto selftypeptr = dyn_cast(proto->ArgumentTypes[0]); + assert(selftypeptr != nullptr); + variant.SelfClass = dyn_cast(selftypeptr->PointedType); assert(variant.SelfClass != nullptr); } diff --git a/src/dobjtype.h b/src/dobjtype.h index 07d7ae10f2..a5da177a4f 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -29,6 +29,7 @@ enum VARF_In = (1<<10), VARF_Out = (1<<11), VARF_Implicit = (1<<12), // implicitly created parameters (i.e. do not compare when checking function signatures) + VARF_Static = (1<<13), // static class data (by necessity read only.) }; // Symbol information ------------------------------------------------------- diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 801df8c652..4ed7128346 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -49,7 +49,7 @@ #include "thingdef.h" #include "p_lnspec.h" #include "doomstat.h" -#include "thingdef_exp.h" +#include "codegen.h" #include "m_fixed.h" #include "vmbuilder.h" #include "v_text.h" @@ -91,13 +91,25 @@ static const FLOP FxFlops[] = // //========================================================================== -FCompileContext::FCompileContext(PClass *cls, PPrototype *ret) : Class(cls), ReturnProto(ret) +FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret) : ReturnProto(ret), Function(fnc), Class(nullptr) +{ + if (fnc != nullptr) Class = fnc->OwningClass; +} + +FCompileContext::FCompileContext(PClass *cls) : ReturnProto(nullptr), Function(nullptr), Class(cls) { } -PSymbol *FCompileContext::FindInClass(FName identifier) +PSymbol *FCompileContext::FindInClass(FName identifier, PSymbolTable *&symt) { - return Class ? Class->Symbols.FindSymbol(identifier, true) : nullptr; + 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) { @@ -3178,15 +3190,16 @@ FxIdentifier::FxIdentifier(FName name, const FScriptPosition &pos) FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) { PSymbol * sym; - FxExpression *newex = NULL; - //FBaseCVar * cv = NULL; - //FString s; + FxExpression *newex = nullptr; int num; - //const PClass *Class; CHECKRESOLVED(); + + // 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. - if ((sym = ctx.FindInClass(Identifier)) != NULL) + PSymbolTable *symtbl; + if ((sym = ctx.FindInClass(Identifier, symtbl)) != nullptr) { if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) { @@ -3195,15 +3208,64 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else if (sym->IsKindOf(RUNTIME_CLASS(PField))) { + ABORT(ctx.Function); // only valid when resolving a function. 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); + + // 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) + { + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); + } + if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols) + { + ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars()); + delete this; + return nullptr; + } + + if (vsym->Flags & VARF_Static) + { + // todo. For now these cannot be defined so let's just exit. + delete this; + return nullptr; + } + + if (ctx.Function->Variants[0].SelfClass == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Unable to access class member from static function"); + delete this; + return nullptr; + } + else + { + if (ctx.Function->Variants[0].SelfClass != ctx.Class) + { + // Check if the restricted class can access it. + PSymbol *sym2; + if ((sym2 = ctx.FindInSelfClass(Identifier, symtbl)) != nullptr) + { + if (sym != sym2) + { + ScriptPosition.Message(MSG_ERROR, "Member variable of %s not accessible through restricted self pointer", ctx.Class->TypeName.GetChars()); + delete this; + return nullptr; + } + } + } + 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) { @@ -3217,23 +3279,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) 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))) { @@ -3270,15 +3316,13 @@ FxSelf::FxSelf(const FScriptPosition &pos) FxExpression *FxSelf::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ctx.Class) + if (ctx.Function == nullptr || ctx.Function->Variants[0].SelfClass == nullptr) { - // can't really happen with DECORATE's expression evaluator. ScriptPosition.Message(MSG_ERROR, "self used outside of a member function"); delete this; - return NULL; + return nullptr; } - ValueType = ctx.Class; - ValueType = NewPointer(RUNTIME_CLASS(DObject)); + ValueType = NewPointer(ctx.Function->Variants[0].SelfClass); return this; } @@ -3614,8 +3658,10 @@ FxFunctionCall::~FxFunctionCall() FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { - // This part is mostly a kludge, it really needs to get the class type from Self. + ABORT(ctx.Class); + PFunction *afd = dyn_cast(ctx.Class->Symbols.FindSymbol(MethodName, true)); + // Todo: More checks are needed here to make it work as expected. if (afd != nullptr) { auto x = new FxVMFunctionCall(afd, ArgList, ScriptPosition, false); @@ -5172,9 +5218,9 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) delete this; return NULL; } - else if (!scope->IsDescendantOf(ctx.Class)) + else if (!scope->IsAncestorOf(ctx.Class)) { - ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(),ctx.Class->TypeName.GetChars()); + ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars()); delete this; return NULL; } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 3c52547c50..d69323ce0b 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -67,11 +67,14 @@ struct FCompileContext { TArray Jumps; PPrototype *ReturnProto; - PClass *Class; + PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) + PClass *Class; // The type of the owning class. - FCompileContext(PClass *cls = nullptr, PPrototype *ret = nullptr); + FCompileContext(PFunction *func = nullptr, PPrototype *ret = nullptr); + FCompileContext(PClass *cls); // 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); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index f80a8f87a0..413999ddc2 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -89,7 +89,7 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArrayPush(cls); + if (args != nullptr) args->Push(NewPointer(cls)); if (argflags != nullptr) argflags->Push(VARF_Implicit); if (argnames != nullptr) argnames->Push(NAME_self); } @@ -101,11 +101,11 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArrayIsDescendantOf(RUNTIME_CLASS(AStateProvider))) { - args->Insert(0, RUNTIME_CLASS(AActor)); // this must go in before the real pointer to the containing class. + args->Insert(0, NewPointer(RUNTIME_CLASS(AActor))); // this must go in before the real pointer to the containing class. } else { - args->Push(cls); + args->Push(NewPointer(cls)); } args->Push(TypeState/*Info*/); // fixme: TypeState is not the correct type here!!! } diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index f366ec6505..7c51184670 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -686,9 +686,8 @@ void FFunctionBuildList::Build() // This needs to be fixed, so that the compile context receives the entire function symbol, including the containing class, the prototype and argument names, which will be needed to run the code generator // As a first step this just needs to get working so fetch the class type from the prototype's argument list. - auto cls = static_cast(item.Func->Variants[0].Proto->ArgumentTypes[!!(item.Func->Variants[0].Flags & VARF_Action)]); // We don't know the return type in advance for anonymous functions. - FCompileContext ctx(cls, nullptr); + FCompileContext ctx(item.Func, nullptr); item.Code = item.Code->Resolve(ctx); item.Proto = ctx.ReturnProto; @@ -715,10 +714,7 @@ void FFunctionBuildList::Build() if (dump != nullptr) { - char label[64]; - int labellen = mysnprintf(label, countof(label), item.DumpName, - cls->TypeName.GetChars()); - DumpFunction(dump, sfunc, label, labellen); + DumpFunction(dump, sfunc, item.DumpName.GetChars(), (int)item.DumpName.Len()); codesize += sfunc->CodeSize; } } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index ee40868d37..aee7e8b763 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1888,6 +1888,11 @@ void ZCCCompiler::InitFunctions() do { auto type = DetermineType(c->Type(), f, f->Name, t, false); + if (type->IsKindOf(RUNTIME_CLASS(PStruct))) + { + // 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); From c3e693b507619c66728cae43a9f2f66b8098ff18 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 20:16:44 +0200 Subject: [PATCH 043/471] - added FindClassMemberFunction which retrieves a function symbol and performs some verification. - removed Self parameter from FxFunctionCall. Actual member function calls through an object require quite different handling so lumping these two together makes no sense. - added a workaround to deal with ACS_NamedExecuteWithResult to both the compiler and FindClassMemberFunction. The way the ZScript compiler sets this up means that it will call the builtin, not the actual action function, so the parser needs to do some explicit check to get past the same-named action function. - pass a proper self pointer to FxActionSpecial. Although it's still not being used, propagating design shortcuts through several function levels is a very, very bad idea. --- src/scripting/codegeneration/codegen.cpp | 35 ++++----- src/scripting/codegeneration/codegen.h | 3 +- .../codegeneration/functioncalls.cpp | 71 +------------------ src/scripting/decorate/thingdef_exp.cpp | 2 +- src/scripting/thingdef.cpp | 37 ++++++++++ src/scripting/thingdef.h | 1 + src/scripting/zscript/zcc_compile.cpp | 48 +++++++------ 7 files changed, 83 insertions(+), 114 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4ed7128346..9cdd9c1f29 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3630,10 +3630,9 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) // //========================================================================== -FxFunctionCall::FxFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos) +FxFunctionCall::FxFunctionCall(FName methodname, FArgumentList *args, const FScriptPosition &pos) : FxExpression(pos) { - Self = self; MethodName = methodname; ArgList = args; } @@ -3646,7 +3645,6 @@ FxFunctionCall::FxFunctionCall(FxExpression *self, FName methodname, FArgumentLi FxFunctionCall::~FxFunctionCall() { - SAFE_DELETE(Self); SAFE_DELETE(ArgList); } @@ -3659,9 +3657,9 @@ FxFunctionCall::~FxFunctionCall() FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { ABORT(ctx.Class); - - PFunction *afd = dyn_cast(ctx.Class->Symbols.FindSymbol(MethodName, true)); - // Todo: More checks are needed here to make it work as expected. + + PFunction *afd = FindClassMemberFunction(ctx.Class, ctx.Class, MethodName, ScriptPosition); + if (afd != nullptr) { auto x = new FxVMFunctionCall(afd, ArgList, ScriptPosition, false); @@ -3674,14 +3672,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { 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; + ArgList = nullptr; delete this; return x->Resolve(ctx); } @@ -3706,24 +3698,25 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) ScriptPosition.Message(MSG_ERROR, "Not enough parameters for '%s' (expected %d, got %d)", MethodName.GetChars(), min, paramcount); delete this; - return NULL; + 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 NULL; + return nullptr; } - FxExpression *x = new FxActionSpecialCall(Self, special, ArgList, ScriptPosition); - ArgList = NULL; + FxExpression *self = (ctx.Function && ctx.Function->Variants[0].Flags & VARF_Method) ? new FxSelf(ScriptPosition) : nullptr; + FxExpression *x = new FxActionSpecialCall(self, special, ArgList, ScriptPosition); + ArgList = nullptr; delete this; return x->Resolve(ctx); } ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); delete this; - return NULL; + return nullptr; } @@ -3780,6 +3773,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) CHECKRESOLVED(); bool failed = false; + SAFE_RESOLVE_OPT(Self, ctx); if (ArgList != NULL) { for (unsigned i = 0; i < ArgList->Size(); i++) @@ -3840,11 +3834,12 @@ int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, int numparam, VMRet 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 + // fixme: This really should use the Self pointer that got passed to this class instead of just using the first argument from the function. + // Once static functions are possible, or specials can be called through a member access operator this won't work anymore. + build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self if (ArgList != NULL) { for (; i < ArgList->Size(); ++i) diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index d69323ce0b..7f00020c12 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -888,13 +888,12 @@ typedef TDeletingArray FArgumentList; class FxFunctionCall : public FxExpression { - FxExpression *Self; FName MethodName; FArgumentList *ArgList; public: - FxFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos); + FxFunctionCall(FName methodname, FArgumentList *args, const FScriptPosition &pos); ~FxFunctionCall(); FxExpression *Resolve(FCompileContext&); }; diff --git a/src/scripting/codegeneration/functioncalls.cpp b/src/scripting/codegeneration/functioncalls.cpp index d085635cd6..1c8dfb3f5e 100644 --- a/src/scripting/codegeneration/functioncalls.cpp +++ b/src/scripting/codegeneration/functioncalls.cpp @@ -39,75 +39,6 @@ // just some rough concepts for now... -//========================================================================== -// -// FindClassMemberFunction -// -// Looks for a name in a class's -// -//========================================================================== - -PFunction *FindClassMemberFunction(PClass *cls, FName name, FScriptPosition &sc) -{ - PSymbolTable *symtable; - auto symbol = cls->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(), cls->TypeName.GetChars()); - } - else if (funcsym->Flags & VARF_Private && symtable != &cls->Symbols) - { - sc.Message(MSG_ERROR, "%s is declared private and not accessible", symbol->SymbolName.GetChars()); - } - else if (funcsym->Flags & VARF_Deprecated) - { - sc.Message(MSG_WARNING, "Call to deprecated function %s", symbol->SymbolName.GetChars()); - } - } - return funcsym; -} - - -//========================================================================== -// -// let's save some work down the line by analyzing the type of function -// that's being called right here and create appropriate nodes. -// A simple function call expression must be immediately resolvable in -// the context it gets compiled in, if the function name cannot be -// resolved here, it will never. -// -//========================================================================== - -FxExpression *ConvertSimpleFunctionCall(ZCC_ExprID *function, FArgumentList *args, PClass *cls, FScriptPosition &sc) -{ - // Priority is as follows: - //1. member functions of the containing class. - //2. action specials. - //3. floating point operations - //4. global builtins - - if (cls != nullptr) - { - // There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work. - if (function->Identifier != NAME_ACS_NamedExecuteWithResult) - { - { - args = ConvertNodeList(fcall->Parameters); - if (args->Size() == 0) - { - delete args; - args = nullptr; - } - - return new FxMemberunctionCall(new FxSelf(), new FxInvoker(), func, args, sc, false); - } - } - -} //========================================================================== // @@ -125,7 +56,7 @@ FxExpression *ConvertFunctionCall(ZCC_Expression *function, FArgumentList *args, switch(function->NodeType) { case AST_ExprID: - return ConvertSimpleFunctionCall(static_cast(function), args, cls, sc); + return new FxFunctionCall( ConvertSimpleFunctionCall(static_cast(function), args, cls, sc); case AST_ExprMemberAccess: return ConvertMemberCall(fcall); diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 5dc909cd07..8b12e1c1e0 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -548,7 +548,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) while (sc.CheckToken(',')); sc.MustGetToken(')'); } - return new FxFunctionCall(NULL, identifier, args, sc); + return new FxFunctionCall(identifier, args, sc); } catch (...) { diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 413999ddc2..fc281e8e8a 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -147,6 +147,43 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i 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) +{ + // 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; +} + //========================================================================== // // LoadActors diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index d5b189d47b..7c2b90e506 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -152,6 +152,7 @@ class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestr FName CheckCastKludges(FName in); void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags); PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); +PFunction *FindClassMemberFunction(PClass *cls, PClass *funccls, FName name, FScriptPosition &sc); //========================================================================== // diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index aee7e8b763..1561bc0967 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2011,24 +2011,30 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a assert(fc->Function->NodeType == AST_ExprID); auto id = static_cast(fc->Function); - PFunction *afd = dyn_cast(cls->Symbols.FindSymbol(id->Identifier, true)); - if (afd != nullptr) + // 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) { - if (fc->Parameters == nullptr && (afd->Variants[0].Flags & VARF_Action)) + PFunction *afd = dyn_cast(cls->Symbols.FindSymbol(id->Identifier, true)); + if (afd != nullptr) { - // We can use this function directly without wrapping it in a caller. - return new FxVMFunctionCall(afd, nullptr, *af, true); + if (fc->Parameters == nullptr && (afd->Variants[0].Flags & VARF_Action)) + { + // We can use this function directly without wrapping it in a caller. + return new FxVMFunctionCall(afd, nullptr, *af, true); + } } - } - else - { - // it may also be an action special so check that first before printing an error. - if (!P_FindLineSpecial(FName(id->Identifier).GetChars())) + else { - Error(af, "%s: action function not found in %s", FName(id->Identifier).GetChars(), cls->TypeName.GetChars()); - return nullptr; + // 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. } - // Action specials fall through to the code generator. } } ConvertClass = cls; @@ -2284,7 +2290,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) auto fcall = static_cast(ast); assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. auto fname = static_cast(fcall->Function)->Identifier; - return new FxFunctionCall(nullptr, fname, ConvertNodeList(fcall->Parameters), *ast); + return new FxFunctionCall(fname, ConvertNodeList(fcall->Parameters), *ast); //return ConvertFunctionCall(fcall->Function, ConvertNodeList(fcall->Parameters), ConvertClass, *ast); } @@ -2298,22 +2304,22 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_ExprConstant: { auto cnst = static_cast(ast); - if (cnst->Type->IsKindOf(RUNTIME_CLASS(PInt))) + 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->IsKindOf(RUNTIME_CLASS(PFloat))) + else if (cnst->Type->IsA(RUNTIME_CLASS(PFloat))) { return new FxConstant(cnst->DoubleVal, *ast); } - else if (cnst->Type->IsKindOf(RUNTIME_CLASS(PString))) + else if (cnst->Type->IsA(RUNTIME_CLASS(PString))) { return new FxConstant(*cnst->StringVal, *ast); } - else if (cnst->Type->IsKindOf(RUNTIME_CLASS(PName))) - { - return new FxConstant(ENamedName(cnst->IntVal), *ast); - } else { // can there be other types? From b299b64e47736227a098aa42bd5c5292c165dfd3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 21:35:31 +0200 Subject: [PATCH 044/471] - the compile context now knows if it is invoked by ZScript or DECORATE, so that it can be more strict with ZScript if needed. - added a truncation warning to FxIntCast, which only occurs with ZScript, not with DECORATE. FxBoolCast is intentionally left out because it would defeat the reason for this cast type. --- src/scripting/codegeneration/codegen.cpp | 49 ++++++++++++++-------- src/scripting/codegeneration/codegen.h | 12 +++--- src/scripting/decorate/thingdef_exp.cpp | 8 ++-- src/scripting/decorate/thingdef_parse.cpp | 4 +- src/scripting/decorate/thingdef_states.cpp | 2 +- src/scripting/thingdef_properties.cpp | 2 +- src/scripting/vm/vmbuilder.cpp | 6 +-- src/scripting/vm/vmbuilder.h | 4 +- src/scripting/zscript/zcc_compile.cpp | 2 +- 9 files changed, 52 insertions(+), 37 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9cdd9c1f29..c66c96f326 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -91,12 +91,12 @@ static const FLOP FxFlops[] = // //========================================================================== -FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret) : ReturnProto(ret), Function(fnc), Class(nullptr) +FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecorate) : ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate) { if (fnc != nullptr) Class = fnc->OwningClass; } -FCompileContext::FCompileContext(PClass *cls) : ReturnProto(nullptr), Function(nullptr), Class(cls) +FCompileContext::FCompileContext(PClass *cls) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(true) // only used by DECORATE constants. { } @@ -495,11 +495,12 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) // //========================================================================== -FxIntCast::FxIntCast(FxExpression *x) +FxIntCast::FxIntCast(FxExpression *x, bool nowarn) : FxExpression(x->ScriptPosition) { basex=x; ValueType = TypeSInt32; + NoWarn = nowarn; } //========================================================================== @@ -536,6 +537,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) 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, ScriptPosition); @@ -549,9 +551,19 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) { 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"); @@ -634,6 +646,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) 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); @@ -837,7 +850,7 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) if (Operand->ValueType->GetRegType() == REGT_FLOAT /* lax */) { // DECORATE allows floats here so cast them to int. - Operand = new FxIntCast(Operand); + Operand = new FxIntCast(Operand, ctx.FromDecorate); Operand = Operand->Resolve(ctx); if (Operand == NULL) { @@ -1165,7 +1178,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) } else if (ValueType->GetRegType() == REGT_INT) { - Right = new FxIntCast(Right); + Right = new FxIntCast(Right, ctx.FromDecorate); } else { @@ -1840,12 +1853,12 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) // For DECORATE which allows floats here. if (left->ValueType->GetRegType() != REGT_INT) { - left = new FxIntCast(left); + left = new FxIntCast(left, ctx.FromDecorate); left = left->Resolve(ctx); } if (right->ValueType->GetRegType() != REGT_INT) { - right = new FxIntCast(right); + right = new FxIntCast(right, ctx.FromDecorate); right = right->Resolve(ctx); } if (left == NULL || right == NULL) @@ -2710,14 +2723,14 @@ ExpEmit FxMinMax::Emit(VMFunctionBuilder *build) // // //========================================================================== -FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) +FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos, bool nowarn) : FxExpression(pos) { EmitTail = false; if (mi != NULL && ma != NULL) { - min = new FxIntCast(mi); - max = new FxIntCast(ma); + min = new FxIntCast(mi, nowarn); + max = new FxIntCast(ma, nowarn); } else min = max = NULL; rng = r; @@ -2843,7 +2856,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build) // // //========================================================================== -FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, const FScriptPosition &pos) +FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, const FScriptPosition &pos, bool nowarn) : FxExpression(pos) { assert(expr.Size() > 0); @@ -2856,7 +2869,7 @@ FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, } else { - choices[index] = new FxIntCast(expr[index]); + choices[index] = new FxIntCast(expr[index], nowarn); } } @@ -3008,7 +3021,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) // //========================================================================== FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) -: FxRandom(r, NULL, NULL, pos) +: FxRandom(r, NULL, NULL, pos, true) { if (mi != NULL && ma != NULL) { @@ -3089,12 +3102,12 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) // //========================================================================== -FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos) +FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos, bool nowarn) : FxExpression(pos) { EmitTail = false; rng = r; - if (m) mask = new FxIntCast(m); + if (m) mask = new FxIntCast(m, nowarn); else mask = new FxConstant(-1, pos); ValueType = TypeSInt32; } @@ -3505,7 +3518,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) if (index->ValueType->GetRegType() == REGT_FLOAT /* lax */) { // DECORATE allows floats here so cast them to int. - index = new FxIntCast(index); + index = new FxIntCast(index, ctx.FromDecorate); index = index->Resolve(ctx); if (index == NULL) { @@ -3792,7 +3805,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) { if ((*ArgList)[i]->ValueType->GetRegType() == REGT_FLOAT /* lax */) { - (*ArgList)[i] = new FxIntCast((*ArgList)[i]); + (*ArgList)[i] = new FxIntCast((*ArgList)[i], ctx.FromDecorate); } else { @@ -5075,7 +5088,7 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) } else if (Index->ValueType->GetRegType() != REGT_INT) { // Float. - Index = new FxIntCast(Index); + Index = new FxIntCast(Index, ctx.FromDecorate); SAFE_RESOLVE(Index, ctx); } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 7f00020c12..9ee8704cc9 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -69,8 +69,9 @@ struct FCompileContext PPrototype *ReturnProto; PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) PClass *Class; // The type of the owning class. + bool FromDecorate; - FCompileContext(PFunction *func = nullptr, PPrototype *ret = nullptr); + FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate); FCompileContext(PClass *cls); // only to be used to resolve constants! PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); @@ -383,10 +384,11 @@ public: class FxIntCast : public FxExpression { FxExpression *basex; + bool NoWarn; public: - FxIntCast(FxExpression *x); + FxIntCast(FxExpression *x, bool nowarn); ~FxIntCast(); FxExpression *Resolve(FCompileContext&); @@ -759,7 +761,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(); @@ -780,7 +782,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&); @@ -814,7 +816,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(); diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 8b12e1c1e0..c10ef9ad8e 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -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)) { @@ -600,7 +600,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 +627,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 +642,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/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index b2f1cac071..534c74d18e 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -131,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 { @@ -871,7 +871,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 = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info), true)); sc.MustGetStringName(")"); conv.exp = x; params.Push(conv); diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index d5a3395d73..59ec3e39d4 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -84,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; } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 34f424ab4c..8fc6609130 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -658,7 +658,7 @@ DEFINE_PROPERTY(damage, X, Actor) else { auto funcsym = CreateAnonymousFunction(bag.Info, TypeSInt32, VARF_Method); - defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, id, FStringf("%s.DamageFunction", bag.Info->TypeName.GetChars()), false); + defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, id, FStringf("%s.DamageFunction", bag.Info->TypeName.GetChars()), !bag.fromZScript); } } diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 7c51184670..7e946a17c3 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -649,7 +649,7 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc) //========================================================================== FFunctionBuildList FunctionBuildList; -VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool statecall) +VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate) { auto func = code->GetDirectFunction(); if (func != nullptr) @@ -666,7 +666,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c it.DumpName = name; it.Function = new VMScriptFunction; it.Proto = nullptr; - it.type = statecall; + it.FromDecorate = fromdecorate; mItems.Push(it); return it.Function; } @@ -687,7 +687,7 @@ void FFunctionBuildList::Build() // This needs to be fixed, so that the compile context receives the entire function symbol, including the containing class, the prototype and argument names, which will be needed to run the code generator // As a first step this just needs to get working so fetch the class type from the prototype's argument list. // We don't know the return type in advance for anonymous functions. - FCompileContext ctx(item.Func, nullptr); + FCompileContext ctx(item.Func, nullptr, item.FromDecorate); item.Code = item.Code->Resolve(ctx); item.Proto = ctx.ReturnProto; diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 6b9a0aa682..c5ca868e08 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -106,13 +106,13 @@ class FFunctionBuildList PPrototype *Proto = nullptr; VMScriptFunction *Function = nullptr; FString DumpName; - int type; // temporary kludge + bool FromDecorate; }; TArray mItems; public: - VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool statecall = false); + VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate); void Build(); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 1561bc0967..cbf6b08c17 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2172,7 +2172,7 @@ void ZCCCompiler::CompileStates() if (code != nullptr) { auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action); - state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), true); + state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false); } } From 55f6661c87d0d54353e3f695541ff3354ec0f43c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 00:12:33 +0200 Subject: [PATCH 045/471] - added handling for all the builtins supported by DECORATE to FxFunctionCall. For the random functions this class only handles the default-RNG version. The one with an explicit RNG needs to be done separately because the parser produces different output for them. --- src/scripting/codegeneration/codegen.cpp | 114 ++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 5 +- src/scripting/zscript/zcc_compile.cpp | 6 ++ 3 files changed, 122 insertions(+), 3 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c66c96f326..8d2fa10a2c 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2541,7 +2541,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx) { floatcount++; } - else if (choices[i]->ValueType->GetRegType() == REGT_INT) + else if (choices[i]->ValueType->GetRegType() == REGT_INT && choices[i]->ValueType != TypeName) { intcount++; } @@ -3663,7 +3663,29 @@ FxFunctionCall::~FxFunctionCall() //========================================================================== // -// Note: This currently only deals with the simple cases and needs some changes. +// Check function that gets called +// +//========================================================================== + +static bool CheckArgSize(FName fname, FArgumentList *args, int min, int max, FScriptPosition &sc) +{ + int s = args ? args->Size() : 0; + 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; +} + +//========================================================================== +// +// // //========================================================================== @@ -3727,6 +3749,94 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) return x->Resolve(ctx); } + // Last but not least: Check builtins. The random functions will have to be duplicated for the case where an RNG is 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; + + Printf("Resolving %s with %d args\n", MethodName.GetChars(), ArgList->Size()); + switch (MethodName) + { + case NAME_Random: + if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) + { + func = new FxRandom(nullptr, (*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(nullptr, (*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(nullptr, *ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); + for (auto &i : *ArgList) i = nullptr; // Ownership of items is transferred to FxMinMax but not ownership of the array itself, so Clear cannot be called here. + } + break; + + case NAME_Random2: + if (CheckArgSize(NAME_Random2, ArgList, 1, 1, ScriptPosition)) + { + func = new FxRandom2(nullptr, (*ArgList)[0], ScriptPosition, ctx.FromDecorate); + (*ArgList)[0] = nullptr; + } + break; + + case NAME_Min: + case NAME_Max: + if (CheckArgSize(MethodName, ArgList, 2, -1, ScriptPosition)) + { + func = new FxMinMax(*ArgList, MethodName, ScriptPosition); + for (auto &i : *ArgList) i = nullptr; // Ownership of items is transferred to FxMinMax but not ownership of the array itself, so Clear cannot be called here. + } + 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(*ArgList, 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: + break; + } + if (func != nullptr) + { + delete this; + return func->Resolve(ctx); + } ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); delete this; return nullptr; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 9ee8704cc9..6645d8c8a0 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -203,7 +203,10 @@ protected: : ScriptPosition(pos) { } -public: + +public: + FxExpression *CheckIntForName(); + virtual ~FxExpression() {} virtual FxExpression *Resolve(FCompileContext &ctx); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index cbf6b08c17..26964381bc 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2301,6 +2301,12 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) 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); From d6ce60f63a517a11f645d6876a47805d6fd80b2d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 01:08:02 +0200 Subject: [PATCH 046/471] - added named RNG support to FxFunctionCall. This looks simpler than duplicating all that stuff and avoids a lot code duplication. --- src/scripting/codegeneration/codegen.cpp | 31 +++++++++++++++++++----- src/scripting/codegeneration/codegen.h | 3 ++- src/scripting/decorate/thingdef_exp.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 2 +- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8d2fa10a2c..7eaecb82d6 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3643,11 +3643,30 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) // //========================================================================== -FxFunctionCall::FxFunctionCall(FName methodname, FArgumentList *args, const FScriptPosition &pos) +FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos) : FxExpression(pos) { MethodName = methodname; + RNG = nullptr; ArgList = 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; + + } + } } //========================================================================== @@ -3749,7 +3768,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) return x->Resolve(ctx); } - // Last but not least: Check builtins. The random functions will have to be duplicated for the case where an RNG is specified. + // Last but not least: Check builtins. 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; @@ -3759,7 +3778,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Random: if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) { - func = new FxRandom(nullptr, (*ArgList)[0], (*ArgList)[1], ScriptPosition, ctx.FromDecorate); + func = new FxRandom(RNG, (*ArgList)[0], (*ArgList)[1], ScriptPosition, ctx.FromDecorate); (*ArgList)[0] = (*ArgList)[1] = nullptr; } break; @@ -3767,7 +3786,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_FRandom: if (CheckArgSize(NAME_FRandom, ArgList, 2, 2, ScriptPosition)) { - func = new FxFRandom(nullptr, (*ArgList)[0], (*ArgList)[1], ScriptPosition); + func = new FxFRandom(RNG, (*ArgList)[0], (*ArgList)[1], ScriptPosition); (*ArgList)[0] = (*ArgList)[1] = nullptr; } break; @@ -3776,7 +3795,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_FRandomPick: if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition)) { - func = new FxRandomPick(nullptr, *ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); + func = new FxRandomPick(RNG, *ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); for (auto &i : *ArgList) i = nullptr; // Ownership of items is transferred to FxMinMax but not ownership of the array itself, so Clear cannot be called here. } break; @@ -3784,7 +3803,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Random2: if (CheckArgSize(NAME_Random2, ArgList, 1, 1, ScriptPosition)) { - func = new FxRandom2(nullptr, (*ArgList)[0], ScriptPosition, ctx.FromDecorate); + func = new FxRandom2(RNG, (*ArgList)[0], ScriptPosition, ctx.FromDecorate); (*ArgList)[0] = nullptr; } break; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 6645d8c8a0..213fe388a7 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -894,11 +894,12 @@ typedef TDeletingArray FArgumentList; class FxFunctionCall : public FxExpression { FName MethodName; + FRandom *RNG; FArgumentList *ArgList; public: - FxFunctionCall(FName methodname, FArgumentList *args, const FScriptPosition &pos); + FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos); ~FxFunctionCall(); FxExpression *Resolve(FCompileContext&); }; diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index c10ef9ad8e..5be69390e7 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -548,7 +548,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) while (sc.CheckToken(',')); sc.MustGetToken(')'); } - return new FxFunctionCall(identifier, args, sc); + return new FxFunctionCall(identifier, NAME_None, args, sc); } catch (...) { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 26964381bc..e9e8069079 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2290,7 +2290,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) auto fcall = static_cast(ast); assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. auto fname = static_cast(fcall->Function)->Identifier; - return new FxFunctionCall(fname, ConvertNodeList(fcall->Parameters), *ast); + return new FxFunctionCall(fname, NAME_None, ConvertNodeList(fcall->Parameters), *ast); //return ConvertFunctionCall(fcall->Function, ConvertNodeList(fcall->Parameters), ConvertClass, *ast); } From 847b8c45efac8d98922fef6e981352a516c5e265 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 01:33:36 +0200 Subject: [PATCH 047/471] - Changed ZCCCompiler::Simplify to allow running in constant and non-constant mode. The difference is that non-constant mode does not attempt to simplify function name expressions because these cannot be processed without destroying them, if some identifier in there is not referencing a symbol, which is quite common. --- src/scripting/zscript/zcc_compile.cpp | 52 ++++++++++++++++----------- src/scripting/zscript/zcc_compile.h | 4 ++- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e9e8069079..6d02956964 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -685,7 +685,7 @@ bool ZCCCompiler::CompileConstant(ZCC_ConstantDef *def, PSymbolTable *sym) assert(def->Symbol == nullptr); def->Symbol = DEFINING_CONST; // avoid recursion - ZCC_Expression *val = Simplify(def->Value, sym); + ZCC_Expression *val = Simplify(def->Value, sym, true); def->Value = val; if (def->Symbol == DEFINING_CONST) def->Symbol = nullptr; return (val->NodeType == AST_ExprConstant); @@ -705,7 +705,13 @@ bool ZCCCompiler::CompileConstant(ZCC_ConstantDef *def, PSymbolTable *sym) // //========================================================================== -ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root, PSymbolTable *sym) +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) { @@ -738,7 +744,7 @@ ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root, PSymbolTable *sym) ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *sym) { - unary->Operand = Simplify(unary->Operand, sym); + unary->Operand = DoSimplify(unary->Operand, sym); if (unary->Operand->Type == nullptr) { return unary; @@ -763,8 +769,8 @@ ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *s ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary, PSymbolTable *sym) { - binary->Left = Simplify(binary->Left, sym); - binary->Right = Simplify(binary->Right, 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.) @@ -794,7 +800,8 @@ ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop, P { PSymbolTable *symtable; - dotop->Left = Simplify(dotop->Left, symt); + // 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. @@ -842,7 +849,6 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSym ZCC_FuncParm *parm; int parmcount = 0; - callop->Function = Simplify(callop->Function, sym); parm = callop->Parameters; if (parm != NULL) { @@ -850,11 +856,18 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSym { parmcount++; assert(parm->NodeType == AST_FuncParm); - parm->Value = Simplify(parm->Value, sym); + 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) @@ -1440,11 +1453,11 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) 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); + arraysize = Simplify(arraysize, sym, true); ZCC_Expression *val; do { - val = Simplify(arraysize, sym); + 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"); @@ -1556,7 +1569,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper Error(property, "%s: arguments missing", prop->name); return; } - property->Values = Simplify(property->Values, &bag.Info->Symbols); // need to do this before the loop so that we can find the head node again. + 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; @@ -1634,7 +1647,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper params.Push(conv); params[0].i++; } - exp = Simplify(static_cast(exp->SiblingNext), &bag.Info->Symbols); + exp = Simplify(static_cast(exp->SiblingNext), &bag.Info->Symbols, true); } while (exp != property->Values); goto endofparm; } @@ -1652,7 +1665,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper } params.Push(conv); params[0].i++; - exp = Simplify(static_cast(exp->SiblingNext), &bag.Info->Symbols); + exp = Simplify(static_cast(exp->SiblingNext), &bag.Info->Symbols, true); endofparm: p++; // Skip the DECORATE 'no comma' marker @@ -1944,7 +1957,7 @@ void ZCCCompiler::InitFunctions() if (p->Flags & ZCC_Out) flags |= VARF_Out; if (p->Default != nullptr) { - auto val = Simplify(p->Default, &c->Type()->Symbols); + auto val = Simplify(p->Default, &c->Type()->Symbols, true); flags |= VARF_Optional; if (val->Operation != PEX_ConstValue) { @@ -2101,10 +2114,9 @@ void ZCCCompiler::CompileStates() state.sprite = GetSpriteIndex(sl->Sprite->GetChars()); } // It is important to call CheckRandom before Simplify, because Simplify will resolve the function's name to nonsense - // and there is little point fixing it because it is essentially useless outside of resolving constants. if (CheckRandom(sl->Duration)) { - auto func = static_cast(Simplify(sl->Duration, &c->Type()->Symbols)); + auto func = static_cast(Simplify(sl->Duration, &c->Type()->Symbols, true)); if (func->Parameters == func->Parameters->SiblingNext || func->Parameters != func->Parameters->SiblingNext->SiblingNext) { Error(sl, "Random duration requires exactly 2 parameters"); @@ -2117,7 +2129,7 @@ void ZCCCompiler::CompileStates() } else { - auto duration = Simplify(sl->Duration, &c->Type()->Symbols); + auto duration = Simplify(sl->Duration, &c->Type()->Symbols, true); if (duration->Operation == PEX_ConstValue) { state.Tics = (int16_t)clamp(GetInt(duration), -1, INT16_MAX); @@ -2141,8 +2153,8 @@ void ZCCCompiler::CompileStates() } if (sl->Offset != nullptr) { - auto o1 = static_cast(Simplify(sl->Offset, &c->Type()->Symbols)); - auto o2 = static_cast(Simplify(static_cast(o1->SiblingNext), &c->Type()->Symbols)); + 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) { @@ -2201,7 +2213,7 @@ void ZCCCompiler::CompileStates() 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); + auto ofs = Simplify(sg->Offset, &c->Type()->Symbols, true); if (ofs->Operation != PEX_ConstValue) { Error(sg, "Constant offset expected for GOTO"); diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 4ecd632275..7a0246ea15 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -111,13 +111,15 @@ private: void CompileStates(); FxExpression *SetupActionFunction(PClassActor *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); + 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); From 2c7c04e803aef5c7dd186a287efc37c9961544b2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 09:31:03 +0200 Subject: [PATCH 048/471] - when simplifying a non-constant expression, leave any identifier that cannot be trivially simplified to a constant alone. It is better to defer resolution to more context-aware code for those. --- src/scripting/zscript/zcc_compile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6d02956964..e184ccaa14 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1009,7 +1009,7 @@ ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable return node; } } - else + 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. From 59ab8b7ccdc86291d4ec17963798f533667c1d7b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 10:59:12 +0200 Subject: [PATCH 049/471] - implemented array-style syntax for Random calls. - implemented handling of the basic math operators so that heretic/beast.txt can be processed. This is working, aside from still needing the type casts to properly transform the strings to class pointers. --- src/scripting/codegeneration/codegen.cpp | 10 +-- .../codegeneration/functioncalls.cpp | 8 -- src/scripting/zscript/zcc_compile.cpp | 81 ++++++++++++++++--- 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7eaecb82d6..91153f3acf 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3796,15 +3796,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition)) { func = new FxRandomPick(RNG, *ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); - for (auto &i : *ArgList) i = nullptr; // Ownership of items is transferred to FxMinMax but not ownership of the array itself, so Clear cannot be called here. + for (auto &i : *ArgList) i = nullptr; } break; case NAME_Random2: - if (CheckArgSize(NAME_Random2, ArgList, 1, 1, ScriptPosition)) + if (CheckArgSize(NAME_Random2, ArgList, 0, 1, ScriptPosition)) { - func = new FxRandom2(RNG, (*ArgList)[0], ScriptPosition, ctx.FromDecorate); - (*ArgList)[0] = nullptr; + func = new FxRandom2(RNG, ArgList->Size() == 0? nullptr : (*ArgList)[0], ScriptPosition, ctx.FromDecorate); + if (ArgList->Size() > 0) (*ArgList)[0] = nullptr; } break; @@ -3813,7 +3813,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) if (CheckArgSize(MethodName, ArgList, 2, -1, ScriptPosition)) { func = new FxMinMax(*ArgList, MethodName, ScriptPosition); - for (auto &i : *ArgList) i = nullptr; // Ownership of items is transferred to FxMinMax but not ownership of the array itself, so Clear cannot be called here. + for (auto &i : *ArgList) i = nullptr; } break; diff --git a/src/scripting/codegeneration/functioncalls.cpp b/src/scripting/codegeneration/functioncalls.cpp index 1c8dfb3f5e..ca2b437e70 100644 --- a/src/scripting/codegeneration/functioncalls.cpp +++ b/src/scripting/codegeneration/functioncalls.cpp @@ -48,10 +48,6 @@ FxExpression *ConvertFunctionCall(ZCC_Expression *function, FArgumentList *args, PClass *cls, FScriptPosition &sc) { - // function names can either be - // - plain identifiers - // - class members - // - array syntax for random() calls. switch(function->NodeType) { @@ -63,10 +59,6 @@ FxExpression *ConvertFunctionCall(ZCC_Expression *function, FArgumentList *args, case AST_ExprBinary: // Array access syntax is wrapped into a ZCC_ExprBinary object. - if (fcall->Function->Operation == PEX_ArrayAccess) - { - return ConvertArrayFunctionCall(fcall); - } break; default: diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e184ccaa14..b2f22555f0 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2300,10 +2300,40 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_ExprFuncCall: { auto fcall = static_cast(ast); - assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. - auto fname = static_cast(fcall->Function)->Identifier; - return new FxFunctionCall(fname, NAME_None, ConvertNodeList(fcall->Parameters), *ast); - //return ConvertFunctionCall(fcall->Function, ConvertNodeList(fcall->Parameters), ConvertClass, *ast); + + // function names can either be + // - plain identifiers + // - class members + // - array syntax for random() calls. + // Everything else coming here is a syntax error. + 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(fcall->Parameters), *ast); + + case AST_ExprMemberAccess: + // calling a class member through its pointer + // todo. + break; + + 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(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_FuncParm: @@ -2346,22 +2376,47 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } } - default: - // 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; + case AST_ExprBinary: + { + auto binary = static_cast(ast); + auto left = ConvertNode(binary->Left); + auto right = ConvertNode(binary->Right); + auto op = binary->Operation; + switch (op) + { + case PEX_Add: + case PEX_Sub: + return new FxAddSub(op == PEX_Add ? '+' : '-', left, right); + + case PEX_Mul: + case PEX_Div: + case PEX_Mod: + return new FxMulDiv(op == PEX_Mul ? '*' : op == PEX_Div ? '/' : '%', left, right); + + default: + I_Error("Binary operator %d not implemented yet", op); + } + break; } + } + + // 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(ZCC_TreeNode *head) { FArgumentList *list = new FArgumentList; - auto node = head; - do + if (head != nullptr) { - list->Push(ConvertNode(node)); - node = node->SiblingNext; - } while (node != head); + auto node = head; + do + { + list->Push(ConvertNode(node)); + node = node->SiblingNext; + } while (node != head); + } return list; } \ No newline at end of file From 2da52cedc960babe42ab17a04023b3265782e988 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 12:47:26 +0200 Subject: [PATCH 050/471] - restrict 8 and 16 bit integer types to struct and class members - and I am not really sure if they should even be allowed there, aside from legacy readonly properties. For 32 bit floats the same would hold, but those are already mapped to 64 bit doubles silently. ZDoom only uses these types in a very few isolated places, and even those can be removed without problems, so it's very doubtful that having support for these types is of any benefit - on the other hand, having them will most likely introduce more code than is saved in the data by using them... --- src/dobjtype.cpp | 2 + src/dobjtype.h | 1 + src/scripting/zscript/zcc_compile.cpp | 75 ++++++++++++++++++--------- src/scripting/zscript/zcc_compile.h | 2 +- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 966663f129..b023a26932 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -727,6 +727,7 @@ PInt::PInt() PInt::PInt(unsigned int size, bool unsign) : PBasicType(size, size), Unsigned(unsign) { + MemberOnly = (size < 4); if (!unsign) { int maxval = (1 << ((8 * size) - 1)) - 1; @@ -1018,6 +1019,7 @@ PFloat::PFloat(unsigned int size) else { assert(size == 4); + MemberOnly = true; SetSingleSymbols(); } } diff --git a/src/dobjtype.h b/src/dobjtype.h index a5da177a4f..885e1ea0ed 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -221,6 +221,7 @@ 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. PType(); PType(unsigned int size, unsigned int align); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index b2f22555f0..f6d23a99b3 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1205,7 +1205,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel { auto field = Fields[0]; - PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, true); + 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; @@ -1290,8 +1290,9 @@ FString ZCCCompiler::FlagsToString(uint32_t flags) // //========================================================================== -PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes) +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()); @@ -1305,26 +1306,33 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n switch (btype->Type) { case ZCC_SInt8: - return TypeSInt8; + retval = TypeSInt8; + break; case ZCC_UInt8: - return TypeUInt8; + retval = TypeUInt8; + break; case ZCC_SInt16: - return TypeSInt16; + retval = TypeSInt16; + break; case ZCC_UInt16: - return TypeUInt16; + retval = TypeUInt16; + break; case ZCC_SInt32: case ZCC_IntAuto: // todo: for enums, autoselect appropriately sized int - return TypeSInt32; + retval = TypeSInt32; + break; case ZCC_UInt32: - return TypeUInt32; + retval = TypeUInt32; + break; case ZCC_Bool: - return TypeBool; + 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 @@ -1332,19 +1340,24 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n case ZCC_FloatAuto: //return TypeFloat32; case ZCC_Float64: - return TypeFloat64; + retval = TypeFloat64; + return; case ZCC_String: - return TypeString; + retval = TypeString; + break; case ZCC_Name: - return TypeName; + retval = TypeName; + break; case ZCC_Vector2: - return TypeVector2; + retval = TypeVector2; + break; case ZCC_Vector3: - return TypeVector3; + retval = TypeVector3; + break; case ZCC_Vector4: // This has almost no use, so we really shouldn't bother. @@ -1352,18 +1365,22 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n return TypeError; case ZCC_State: - return TypeState; + retval = TypeState; + break; case ZCC_Color: - return TypeColor; + retval = TypeColor; + break; case ZCC_Sound: - return TypeSound; + retval = TypeSound; + break; case ZCC_UserType: - return ResolveUserType(btype, &outertype->Symbols); + retval = ResolveUserType(btype, &outertype->Symbols); break; } + break; } case AST_MapType: @@ -1372,7 +1389,8 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n 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); - return NewMap(DetermineType(outertype, field, name, mtype->KeyType, false), DetermineType(outertype, field, name, mtype->ValueType, false)); + retval = NewMap(DetermineType(outertype, field, name, mtype->KeyType, false, false), DetermineType(outertype, field, name, mtype->ValueType, false, false)); + break; } break; @@ -1381,7 +1399,8 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n { Error(field, "%s: Dynamic array types not implemented yet", name.GetChars()); auto atype = static_cast(ztype); - return NewDynArray(DetermineType(outertype, field, name, atype->ElementType, false)); + retval = NewDynArray(DetermineType(outertype, field, name, atype->ElementType, false, false)); + break; } break; @@ -1390,7 +1409,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n auto ctype = static_cast(ztype); if (ctype->Restriction == nullptr) { - return NewClassPointer(RUNTIME_CLASS(DObject)); + retval = NewClassPointer(RUNTIME_CLASS(DObject)); } else { @@ -1407,11 +1426,17 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars()); return TypeError; } - return NewClassPointer(static_cast(typesym->Type)); + retval = NewClassPointer(static_cast(typesym->Type)); } + break; } } - return TypeError; + if (retval != TypeError && retval->MemberOnly && !formember) + { + Error(field, "Invalid type"); // fixme: Types need a descriptive name that can be output here. + return TypeError; + } + return retval; } //========================================================================== @@ -1900,7 +1925,7 @@ void ZCCCompiler::InitFunctions() { do { - auto type = DetermineType(c->Type(), f, f->Name, t, false); + auto type = DetermineType(c->Type(), f, f->Name, t, false, false); if (type->IsKindOf(RUNTIME_CLASS(PStruct))) { // structs and classes only get passed by pointer. @@ -1951,7 +1976,7 @@ void ZCCCompiler::InitFunctions() { if (p->Type != nullptr) { - auto type = DetermineType(c->Type(), p, f->Name, p->Type, false); + auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); int flags; if (p->Flags & ZCC_In) flags |= VARF_In; if (p->Flags & ZCC_Out) flags |= VARF_Out; diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 7a0246ea15..cf27758349 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -95,7 +95,7 @@ private: 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); + 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); From afd9347087eb62e5c996247ab2da8291d7449ed3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 19:42:22 +0200 Subject: [PATCH 051/471] - changed order of script files to match the old DECORATE list for easy comparison of the disassembly. - added a descriptive name to all types for error messages. - added a generic type cast node to the code generator. - added a few more cast operations to the 'cast' VM instruction. - extended FxClassTypeCast to handle all possible input that can be cast to a class pointer, not just names. --- src/dobjtype.cpp | 47 ++ src/dobjtype.h | 11 +- src/scripting/codegeneration/codegen.cpp | 545 +++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 74 ++- src/scripting/decorate/thingdef_parse.cpp | 2 +- src/scripting/vm/vm.h | 6 + src/scripting/vm/vmdisasm.cpp | 6 + src/scripting/vm/vmexec.cpp | 2 + src/scripting/vm/vmexec.h | 33 ++ src/scripting/zscript/zcc_compile.cpp | 6 +- wadsrc/static/zscript.txt | 6 +- 11 files changed, 723 insertions(+), 15 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index b023a26932..3d42059ca2 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -199,6 +199,7 @@ END_POINTERS PType::PType() : Size(0), Align(1), HashNext(NULL) { + mDescriptiveName = "Type"; } //========================================================================== @@ -210,6 +211,7 @@ PType::PType() PType::PType(unsigned int size, unsigned int align) : Size(size), Align(align), HashNext(NULL) { + mDescriptiveName = "Type"; } //========================================================================== @@ -533,6 +535,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 @@ -649,6 +662,7 @@ PBasicType::PBasicType() PBasicType::PBasicType(unsigned int size, unsigned int align) : PType(size, align) { + mDescriptiveName = "BasicType"; } /* PCompoundType **********************************************************/ @@ -714,6 +728,7 @@ IMPLEMENT_CLASS(PInt) PInt::PInt() : PBasicType(4, 4), Unsigned(false) { + mDescriptiveName = "SInt32"; Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, -0x7FFFFFFF - 1)); Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, 0x7FFFFFFF)); } @@ -727,6 +742,8 @@ PInt::PInt() PInt::PInt(unsigned int size, bool unsign) : PBasicType(size, size), Unsigned(unsign) { + mDescriptiveName.Format("%cInt%d", unsign? 'U':'S', size); + MemberOnly = (size < 4); if (!unsign) { @@ -981,6 +998,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))); @@ -1000,6 +1019,7 @@ IMPLEMENT_CLASS(PFloat) PFloat::PFloat() : PBasicType(8, 8) { + mDescriptiveName = "Float"; SetDoubleSymbols(); } @@ -1012,6 +1032,7 @@ PFloat::PFloat() PFloat::PFloat(unsigned int size) : PBasicType(size, size) { + mDescriptiveName.Format("Float%d", size); if (size == 8) { SetDoubleSymbols(); @@ -1274,6 +1295,7 @@ IMPLEMENT_CLASS(PString) PString::PString() : PBasicType(sizeof(FString), __alignof(FString)) { + mDescriptiveName = "String"; } //========================================================================== @@ -1376,6 +1398,7 @@ IMPLEMENT_CLASS(PName) PName::PName() : PInt(sizeof(FName), true) { + mDescriptiveName = "Name"; assert(sizeof(FName) == __alignof(FName)); } @@ -1425,6 +1448,7 @@ IMPLEMENT_CLASS(PSound) PSound::PSound() : PInt(sizeof(FSoundID), true) { + mDescriptiveName = "Sound"; assert(sizeof(FSoundID) == __alignof(FSoundID)); } @@ -1474,6 +1498,7 @@ IMPLEMENT_CLASS(PColor) PColor::PColor() : PInt(sizeof(PalEntry), true) { + mDescriptiveName = "Color"; assert(sizeof(PalEntry) == __alignof(PalEntry)); } @@ -1490,6 +1515,7 @@ IMPLEMENT_CLASS(PStatePointer) PStatePointer::PStatePointer() : PBasicType(sizeof(FState *), __alignof(FState *)) { + mDescriptiveName = "State"; } //========================================================================== @@ -1564,6 +1590,7 @@ END_POINTERS PPointer::PPointer() : PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL) { + mDescriptiveName = "Pointer"; } //========================================================================== @@ -1575,6 +1602,7 @@ PPointer::PPointer() PPointer::PPointer(PType *pointsat) : PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat) { + mDescriptiveName.Format("Pointer<%s>", pointsat->DescriptiveName()); } //========================================================================== @@ -1708,6 +1736,7 @@ END_POINTERS PClassPointer::PClassPointer() : PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(NULL) { + mDescriptiveName = "ClassPointer"; } //========================================================================== @@ -1719,6 +1748,7 @@ PClassPointer::PClassPointer() PClassPointer::PClassPointer(PClass *restrict) : PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(restrict) { + mDescriptiveName.Format("ClassPointer<%s>", restrict->TypeName.GetChars()); } //========================================================================== @@ -1784,6 +1814,7 @@ END_POINTERS PEnum::PEnum() : ValueType(NULL) { + mDescriptiveName = "Enum"; } //========================================================================== @@ -1795,6 +1826,7 @@ PEnum::PEnum() PEnum::PEnum(FName name, PTypeBase *outer) : PNamedType(name, outer), ValueType(NULL) { + mDescriptiveName.Format("Enum<%s>", name.GetChars()); } //========================================================================== @@ -1833,6 +1865,7 @@ END_POINTERS PArray::PArray() : ElementType(NULL), ElementCount(0) { + mDescriptiveName = "Array"; } //========================================================================== @@ -1844,6 +1877,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. @@ -1975,6 +2010,7 @@ IMPLEMENT_CLASS(PVector) PVector::PVector() : PArray(TypeFloat32, 3) { + mDescriptiveName = "Vector"; } //========================================================================== @@ -1986,6 +2022,7 @@ PVector::PVector() PVector::PVector(unsigned int size) : PArray(TypeFloat32, size) { + mDescriptiveName.Format("Vector<%d>", size); assert(size >= 2 && size <= 4); } @@ -2025,6 +2062,7 @@ END_POINTERS PDynArray::PDynArray() : ElementType(NULL) { + mDescriptiveName = "DynArray"; Size = sizeof(FArray); Align = __alignof(FArray); } @@ -2038,6 +2076,7 @@ PDynArray::PDynArray() PDynArray::PDynArray(PType *etype) : ElementType(etype) { + mDescriptiveName.Format("DynArray<%s>", etype->DescriptiveName()); Size = sizeof(FArray); Align = __alignof(FArray); } @@ -2105,6 +2144,7 @@ END_POINTERS PMap::PMap() : KeyType(NULL), ValueType(NULL) { + mDescriptiveName = "Map"; Size = sizeof(FMap); Align = __alignof(FMap); } @@ -2118,6 +2158,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); } @@ -2181,6 +2222,7 @@ IMPLEMENT_CLASS(PStruct) PStruct::PStruct() { + mDescriptiveName = "Struct"; } //========================================================================== @@ -2192,6 +2234,7 @@ PStruct::PStruct() PStruct::PStruct(FName name, PTypeBase *outer) : PNamedType(name, outer) { + mDescriptiveName.Format("Struct<%s>", name.GetChars()); } //========================================================================== @@ -2804,6 +2847,7 @@ PClass::PClass() Defaults = NULL; bRuntimeClass = false; ConstructNative = NULL; + mDescriptiveName = "Class"; PClass::AllClasses.Push(this); } @@ -2896,6 +2940,7 @@ void ClassReg::SetupClass(PClass *cls) cls->Size = SizeOf; cls->Pointers = Pointers; cls->ConstructNative = ConstructNative; + cls->mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars()); } //========================================================================== @@ -3108,6 +3153,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) type->TypeName = name; type->Size = size; type->bRuntimeClass = true; + type->mDescriptiveName.Format("Class<%s>", name.GetChars()); Derive(type); DeriveData(type); if (!notnew) @@ -3185,6 +3231,7 @@ PClass *PClass::FindClassTentative(FName name, bool fatal) type->ConstructNative = ConstructNative; type->Size = TentativeClass; type->bRuntimeClass = true; + type->mDescriptiveName.Format("Class<%s>", name.GetChars()); type->Symbols.SetParentTable(&Symbols); TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket); return type; diff --git a/src/dobjtype.h b/src/dobjtype.h index 885e1ea0ed..fd6e078eab 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -222,6 +222,7 @@ public: 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; PType(); PType(unsigned int size, unsigned int align); @@ -285,6 +286,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(); @@ -377,8 +380,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; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 91153f3acf..9b8a87eedb 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -595,9 +595,9 @@ ExpEmit FxIntCast::Emit(VMFunctionBuilder *build) //========================================================================== FxFloatCast::FxFloatCast(FxExpression *x) -: FxExpression(x->ScriptPosition) + : FxExpression(x->ScriptPosition) { - basex=x; + basex = x; ValueType = TypeFloat64; } @@ -685,6 +685,519 @@ ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build) // //========================================================================== +FxNameCast::FxNameCast(FxExpression *x) + : FxExpression(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 = NULL; + 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 NULL; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +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(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 = NULL; + 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 NULL; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxStringCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit from = basex->Emit(build); + assert(!from.Konst); + + from.Free(build); + ExpEmit to(build, REGT_STRING); + if (ValueType == TypeName) + { + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_N2S); + } + else if (ValueType == TypeSound) + { + build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_So2S); + } + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxColorCast::FxColorCast(FxExpression *x) + : FxExpression(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 = NULL; + delete this; + return x; + } + else if (basex->ValueType == TypeString) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + 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 NULL; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +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(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 = NULL; + 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 NULL; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +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) + : FxExpression(x->ScriptPosition) +{ + basex = x; + ValueType = type; +} + +//========================================================================== +// +// +// +//========================================================================== + +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) + { + 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 (ValueType->GetRegType() == REGT_FLOAT) + { + 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); + 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->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 (ValueType->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. + if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + { + auto fromtype = static_cast(basex->ValueType); + auto totype = static_cast(ValueType); + 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); + if (fromcls->IsDescendantOf(tocls)) 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; + 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(operand->ScriptPosition) { @@ -5030,10 +5543,11 @@ VMFunction *FxReturnStatement::GetDirectFunction() // //========================================================================== -FxClassTypeCast::FxClassTypeCast(PClass *dtype, FxExpression *x) +FxClassTypeCast::FxClassTypeCast(PClassPointer *dtype, FxExpression *x) : FxExpression(x->ScriptPosition) { - desttype = dtype; + ValueType = dtype; + desttype = dtype->ClassRestriction; basex=x; } @@ -5058,8 +5572,25 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer)) + { + auto to = static_cast(ValueType); + 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) + if (basex->ValueType != TypeName && basex->ValueType != TypeString) { ScriptPosition.Message(MSG_ERROR, "Cannot convert to class type"); delete this; @@ -5097,6 +5628,10 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + if (basex->ValueType == TypeString) + { + basex = new FxNameCast(basex); + } return this; } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 213fe388a7..7d6465e75d 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -411,6 +411,78 @@ 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; + +public: + + FxTypeCast(FxExpression *x, PType *type, bool nowarn); + ~FxTypeCast(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxSign @@ -1130,7 +1202,7 @@ class FxClassTypeCast : public FxExpression public: - FxClassTypeCast(PClass *dtype, FxExpression *x); + FxClassTypeCast(PClassPointer *dtype, FxExpression *x); ~FxClassTypeCast(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 534c74d18e..f416d6103b 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -207,7 +207,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 { diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 69e5b81b31..425eba531f 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -116,6 +116,12 @@ enum CAST_P2S, CAST_S2I, CAST_S2F, + CAST_S2N, + CAST_N2S, + CAST_S2Co, + CAST_S2So, + CAST_Co2S, + CAST_So2S, }; // Register types for VMParam diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 0b84cf8c09..563f89f280 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -379,6 +379,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; @@ -391,6 +394,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; diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 651090c6ba..b1393382a2 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -32,6 +32,8 @@ */ #include +#include +#include #include "vm.h" #include "xs_Float.h" #include "math/cmath.h" diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index adf2986c50..1d1764c6ea 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1466,6 +1466,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] = 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); } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f6d23a99b3..1992587c8f 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -885,7 +885,7 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSym if (routelen < 0) { ///FIXME: Need real type names - Error(callop, "Cannot convert type 1 to type 2"); + Error(callop, "Cannot convert %s to %s", parm->Value->Type->DescriptiveName(), dest->DescriptiveName()); callop->ToErrorNode(); } else @@ -1341,7 +1341,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n //return TypeFloat32; case ZCC_Float64: retval = TypeFloat64; - return; + break; case ZCC_String: retval = TypeString; @@ -1433,7 +1433,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n } if (retval != TypeError && retval->MemberOnly && !formember) { - Error(field, "Invalid type"); // fixme: Types need a descriptive name that can be output here. + Error(field, "Invalid type %s", retval->DescriptiveName()); // fixme: Types need a descriptive name that can be output here. return TypeError; } return retval; diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 73bb467d82..a349d7ed5b 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -7,9 +7,7 @@ zscript/shared/morph.txt zscript/shared/botstuff.txt zscript/shared/sharedmisc.txt zscript/shared/blood.txt -zscript/shared/ice.txt zscript/shared/debris.txt -zscript/shared/specialspot.txt zscript/shared/decal.txt zscript/shared/splashes.txt zscript/shared/pickups.txt @@ -18,6 +16,7 @@ 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 @@ -28,6 +27,7 @@ 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 @@ -59,5 +59,5 @@ zscript/doom/doomweapons.txt zscript/doom/stealthmonsters.txt zscript/doom/scriptedmarine.txt -//zscript/test1.txt +zscript/heretic/beast.txt From 6650e2bbfb9ff35e11b95d0caa47e3ac075ce4ed Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 22:32:52 +0200 Subject: [PATCH 052/471] - converted some Heretic stuff to ZScript for testing. - added type casts to the arguments of function calls. - added string constant to state conversion to FxTypeCast. --- src/dobjtype.cpp | 3 +- src/scripting/codegeneration/codegen.cpp | 59 ++-- src/scripting/codegeneration/codegen.h | 6 +- wadsrc/static/actors/heretic/hereticammo.txt | 204 ------------ wadsrc/static/actors/heretic/hereticarmor.txt | 35 -- .../actors/heretic/hereticartifacts.txt | 103 ------ .../actors/heretic/hereticdecorations.txt | 248 -------------- wadsrc/static/actors/heretic/heretickeys.txt | 144 --------- wadsrc/static/actors/heretic/hereticmisc.txt | 229 ------------- .../static/actors/heretic/hereticplayer.txt | 129 -------- wadsrc/static/decorate.txt | 14 +- wadsrc/static/zscript.txt | 19 ++ wadsrc/static/zscript/doom/doomimp.txt | 3 +- wadsrc/static/zscript/heretic/beast.txt | 118 +++++++ wadsrc/static/zscript/heretic/hereticammo.txt | 243 ++++++++++++++ .../static/zscript/heretic/hereticarmor.txt | 41 +++ .../zscript/heretic/hereticartifacts.txt | 118 +++++++ .../zscript/heretic/hereticdecorations.txt | 302 ++++++++++++++++++ wadsrc/static/zscript/heretic/heretickeys.txt | 174 ++++++++++ wadsrc/static/zscript/heretic/hereticmisc.txt | 255 +++++++++++++++ .../static/zscript/heretic/hereticplayer.txt | 135 ++++++++ 21 files changed, 1438 insertions(+), 1144 deletions(-) delete mode 100644 wadsrc/static/actors/heretic/hereticammo.txt delete mode 100644 wadsrc/static/actors/heretic/hereticarmor.txt delete mode 100644 wadsrc/static/actors/heretic/hereticartifacts.txt delete mode 100644 wadsrc/static/actors/heretic/hereticdecorations.txt delete mode 100644 wadsrc/static/actors/heretic/heretickeys.txt delete mode 100644 wadsrc/static/actors/heretic/hereticmisc.txt delete mode 100644 wadsrc/static/actors/heretic/hereticplayer.txt create mode 100644 wadsrc/static/zscript/heretic/beast.txt create mode 100644 wadsrc/static/zscript/heretic/hereticammo.txt create mode 100644 wadsrc/static/zscript/heretic/hereticarmor.txt create mode 100644 wadsrc/static/zscript/heretic/hereticartifacts.txt create mode 100644 wadsrc/static/zscript/heretic/hereticdecorations.txt create mode 100644 wadsrc/static/zscript/heretic/heretickeys.txt create mode 100644 wadsrc/static/zscript/heretic/hereticmisc.txt create mode 100644 wadsrc/static/zscript/heretic/hereticplayer.txt diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 3d42059ca2..317694e206 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1748,7 +1748,8 @@ PClassPointer::PClassPointer() PClassPointer::PClassPointer(PClass *restrict) : PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(restrict) { - mDescriptiveName.Format("ClassPointer<%s>", restrict->TypeName.GetChars()); + if (restrict) mDescriptiveName.Format("ClassPointer<%s>", restrict->TypeName.GetChars()); + else mDescriptiveName = "ClassPointer"; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9b8a87eedb..d7a3a56b0d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1123,6 +1123,18 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + else if (ValueType == TypeState) + { + // 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)) + { + FxExpression *x = new FxMultiNameState(static_cast(basex)->GetValue().GetString(), basex->ScriptPosition); + 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); @@ -4624,45 +4636,10 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { for (unsigned i = 0; i < ArgList->Size(); i++) { - if ((*ArgList)[i]->isConstant()) - { - if (i + implicit < argtypes.Size()) - { - auto type = static_cast((*ArgList)[i])->ValueType; - // temporary hack to add the casts which get used by the internal definitions - if (argtypes[i + implicit] == TypeState && type == TypeString) - { - ScriptPosition.Message(MSG_WARNING, "Converting %s to state", static_cast((*ArgList)[i])->GetValue().GetString()); - auto statenode = new FxMultiNameState(static_cast((*ArgList)[i])->GetValue().GetString(), ScriptPosition); - delete (*ArgList)[i]; - (*ArgList)[i] = statenode; - } - if (argtypes[i + implicit] == TypeSound && type == TypeString) - { - ScriptPosition.Message(MSG_WARNING, "Converting %s to sound", static_cast((*ArgList)[i])->GetValue().GetString()); - auto statenode = new FxConstant(FSoundID(static_cast((*ArgList)[i])->GetValue().GetString()), ScriptPosition); - delete (*ArgList)[i]; - (*ArgList)[i] = statenode; - } - if (argtypes[i + implicit] == TypeSInt32 && type == TypeFloat64) - { - ScriptPosition.Message(MSG_WARNING, "Converting %f to int", static_cast((*ArgList)[i])->GetValue().GetFloat()); - auto statenode = new FxConstant(static_cast((*ArgList)[i])->GetValue().GetInt(), ScriptPosition); - delete (*ArgList)[i]; - (*ArgList)[i] = statenode; - } - if (argtypes[i + implicit] == TypeFloat64 && type == TypeSInt32) - { - ScriptPosition.Message(MSG_WARNING, "Converting %d to float", static_cast((*ArgList)[i])->GetValue().GetInt()); - auto statenode = new FxConstant(static_cast((*ArgList)[i])->GetValue().GetFloat(), ScriptPosition); - delete (*ArgList)[i]; - (*ArgList)[i] = statenode; - } - } - } - - (*ArgList)[i] = (*ArgList)[i]->Resolve(ctx); - if ((*ArgList)[i] == NULL) failed = true; + FxExpression *x = new FxTypeCast((*ArgList)[i], argtypes[i + implicit], false); + x = x->Resolve(ctx); + failed |= (x == nullptr); + (*ArgList)[i] = x; } } if (failed) @@ -5592,7 +5569,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) if (basex->ValueType != TypeName && basex->ValueType != TypeString) { - ScriptPosition.Message(MSG_ERROR, "Cannot convert to class type"); + ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to class type", basex->ValueType->DescriptiveName()); delete this; return NULL; } @@ -5855,7 +5832,7 @@ FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPositi } else { - scopename = NULL; + scopename = NAME_None; } names = MakeStateNameList(statestring); names.Insert(0, scopename); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 7d6465e75d..ce4f11bb13 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -174,6 +174,7 @@ struct ExpVal FName GetName() const { + if (Type == TypeString) return FName(*(FString *)&pointer); return Type == TypeName ? ENamedName(Int) : NAME_None; } }; @@ -338,8 +339,9 @@ public: FxConstant(PClass *val, const FScriptPosition &pos) : FxExpression(pos) { value.pointer = (void*)val; - ValueType = val; - value.Type = NewClassPointer(RUNTIME_CLASS(AActor)); + if (val != nullptr) ValueType = NewClassPointer(val); + else ValueType = NewClassPointer(RUNTIME_CLASS(DObject)); + value.Type = NewClassPointer(RUNTIME_CLASS(DObject)); isresolved = true; } diff --git a/wadsrc/static/actors/heretic/hereticammo.txt b/wadsrc/static/actors/heretic/hereticammo.txt deleted file mode 100644 index 35f404274e..0000000000 --- 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 91684cc0e4..0000000000 --- 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 9555415fda..0000000000 --- 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 032ee33a1d..0000000000 --- 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/heretickeys.txt b/wadsrc/static/actors/heretic/heretickeys.txt deleted file mode 100644 index 1bda24dcc5..0000000000 --- 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 9b000ede32..0000000000 --- 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 5a3e437729..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 1ae7d73288..960b28558d 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -5,13 +5,13 @@ #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/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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index a349d7ed5b..decf9241c5 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -59,5 +59,24 @@ zscript/doom/doomweapons.txt zscript/doom/stealthmonsters.txt zscript/doom/scriptedmarine.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 +*/ diff --git a/wadsrc/static/zscript/doom/doomimp.txt b/wadsrc/static/zscript/doom/doomimp.txt index 244ae70eaa..318e81471a 100644 --- a/wadsrc/static/zscript/doom/doomimp.txt +++ b/wadsrc/static/zscript/doom/doomimp.txt @@ -55,7 +55,8 @@ class DoomImp : Actor TROO U -1; Stop; Raise: - TROO MLKJI 8; + TROO ML 8; + TROO KJI 6; Goto See; } } diff --git a/wadsrc/static/zscript/heretic/beast.txt b/wadsrc/static/zscript/heretic/beast.txt new file mode 100644 index 0000000000..209b2da565 --- /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/hereticammo.txt b/wadsrc/static/zscript/heretic/hereticammo.txt new file mode 100644 index 0000000000..cf1e50a3d7 --- /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 0000000000..8cbcb9fbcf --- /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 0000000000..e04426f053 --- /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 "Ghost"; + 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 "Weaponlevel2"; + 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"; + } + + action 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 0000000000..d38f47a394 --- /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/heretickeys.txt b/wadsrc/static/zscript/heretic/heretickeys.txt new file mode 100644 index 0000000000..d5532ce016 --- /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 0000000000..0b90208b9f --- /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; + } + action native void A_PodPain (class podtype = "PodGoo"); + action 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"; + } + + action 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; + } + + action 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 + } + + action native void A_VolcanoSet (); + action 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"; + } + + action 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 0000000000..26ff684f33 --- /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; + } +} + From 76f1b9d3f8407a1bd6f752884832b37cc4598c77 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 00:21:52 +0200 Subject: [PATCH 053/471] - converted the raven actors. --- wadsrc/static/actors/raven/artiegg.txt | 102 -------- wadsrc/static/actors/raven/artitele.txt | 24 -- wadsrc/static/actors/raven/minotaur.txt | 218 ---------------- wadsrc/static/actors/raven/ravenambient.txt | 36 --- wadsrc/static/actors/raven/ravenartifacts.txt | 125 ---------- wadsrc/static/actors/raven/ravenhealth.txt | 13 - wadsrc/static/decorate.txt | 14 -- wadsrc/static/zscript.txt | 7 + .../zscript/heretic/hereticartifacts.txt | 2 +- wadsrc/static/zscript/raven/artiegg.txt | 114 +++++++++ wadsrc/static/zscript/raven/artitele.txt | 27 ++ wadsrc/static/zscript/raven/minotaur.txt | 236 ++++++++++++++++++ wadsrc/static/zscript/raven/ravenambient.txt | 42 ++++ .../static/zscript/raven/ravenartifacts.txt | 143 +++++++++++ wadsrc/static/zscript/raven/ravenhealth.txt | 16 ++ 15 files changed, 586 insertions(+), 533 deletions(-) delete mode 100644 wadsrc/static/actors/raven/artiegg.txt delete mode 100644 wadsrc/static/actors/raven/artitele.txt delete mode 100644 wadsrc/static/actors/raven/minotaur.txt delete mode 100644 wadsrc/static/actors/raven/ravenambient.txt delete mode 100644 wadsrc/static/actors/raven/ravenartifacts.txt delete mode 100644 wadsrc/static/actors/raven/ravenhealth.txt create mode 100644 wadsrc/static/zscript/raven/artiegg.txt create mode 100644 wadsrc/static/zscript/raven/artitele.txt create mode 100644 wadsrc/static/zscript/raven/minotaur.txt create mode 100644 wadsrc/static/zscript/raven/ravenambient.txt create mode 100644 wadsrc/static/zscript/raven/ravenartifacts.txt create mode 100644 wadsrc/static/zscript/raven/ravenhealth.txt diff --git a/wadsrc/static/actors/raven/artiegg.txt b/wadsrc/static/actors/raven/artiegg.txt deleted file mode 100644 index 1c4a8f190b..0000000000 --- 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 569926d16d..0000000000 --- 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 134bf9d52f..0000000000 --- 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 f7312de022..0000000000 --- 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 43a5e87fcc..0000000000 --- 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 99e6692bac..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 960b28558d..52906258c1 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,17 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index decf9241c5..bd7b914b5c 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -59,6 +59,13 @@ 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 diff --git a/wadsrc/static/zscript/heretic/hereticartifacts.txt b/wadsrc/static/zscript/heretic/hereticartifacts.txt index e04426f053..154f48ad3b 100644 --- a/wadsrc/static/zscript/heretic/hereticartifacts.txt +++ b/wadsrc/static/zscript/heretic/hereticartifacts.txt @@ -32,7 +32,7 @@ Class ArtiInvisibility : PowerupGiver Alpha 0.4; Inventory.RespawnTics 4230; Inventory.Icon "ARTIINVS"; - Powerup.Type "Ghost"; + Powerup.Type "PowerGhost"; Inventory.PickupMessage "$TXT_ARTIINVISIBILITY"; Tag "$TAG_ARTIINVISIBILITY"; } diff --git a/wadsrc/static/zscript/raven/artiegg.txt b/wadsrc/static/zscript/raven/artiegg.txt new file mode 100644 index 0000000000..ef3c6e2be8 --- /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 0000000000..9f21bd7337 --- /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 0000000000..9bc02fced2 --- /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; + } + + action native void A_MinotaurDecide(); + action native void A_MinotaurAtk1(); + action native void A_MinotaurAtk2(); + action native void A_MinotaurAtk3(); + action native void A_MinotaurCharge(); + action native void A_MinotaurLook(); + action native void A_MinotaurRoam(); + action native void A_MinotaurChase(); + action 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"; + } + + action 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 0000000000..3495dc4e04 --- /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 0000000000..443816788e --- /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 0000000000..cf7c79d0a7 --- /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; + } +} + From c13916ea1801388b840f83b0f14e3e6e1e688940 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 10:07:12 +0200 Subject: [PATCH 054/471] - converted more Heretic actors. --- src/scripting/codegeneration/codegen.cpp | 1 - wadsrc/static/actors/heretic/beast.txt | 109 -- wadsrc/static/actors/heretic/clink.txt | 46 - wadsrc/static/actors/heretic/hereticimp.txt | 156 -- wadsrc/static/actors/heretic/hereticweaps.txt | 1133 --------------- wadsrc/static/actors/heretic/mummy.txt | 133 -- wadsrc/static/actors/heretic/snake.txt | 95 -- wadsrc/static/decorate.txt | 6 - wadsrc/static/zscript.txt | 2 +- wadsrc/static/zscript/heretic/clink.txt | 48 + wadsrc/static/zscript/heretic/hereticimp.txt | 171 +++ .../static/zscript/heretic/hereticweaps.txt | 1286 +++++++++++++++++ wadsrc/static/zscript/heretic/mummy.txt | 151 ++ wadsrc/static/zscript/heretic/snake.txt | 104 ++ 14 files changed, 1761 insertions(+), 1680 deletions(-) delete mode 100644 wadsrc/static/actors/heretic/beast.txt delete mode 100644 wadsrc/static/actors/heretic/clink.txt delete mode 100644 wadsrc/static/actors/heretic/hereticimp.txt delete mode 100644 wadsrc/static/actors/heretic/hereticweaps.txt delete mode 100644 wadsrc/static/actors/heretic/mummy.txt delete mode 100644 wadsrc/static/actors/heretic/snake.txt create mode 100644 wadsrc/static/zscript/heretic/clink.txt create mode 100644 wadsrc/static/zscript/heretic/hereticimp.txt create mode 100644 wadsrc/static/zscript/heretic/hereticweaps.txt create mode 100644 wadsrc/static/zscript/heretic/mummy.txt create mode 100644 wadsrc/static/zscript/heretic/snake.txt diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d7a3a56b0d..f567357976 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4297,7 +4297,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) // 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; - Printf("Resolving %s with %d args\n", MethodName.GetChars(), ArgList->Size()); switch (MethodName) { case NAME_Random: diff --git a/wadsrc/static/actors/heretic/beast.txt b/wadsrc/static/actors/heretic/beast.txt deleted file mode 100644 index 73eb630ec2..0000000000 --- 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/clink.txt b/wadsrc/static/actors/heretic/clink.txt deleted file mode 100644 index 7f3e4370d3..0000000000 --- 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/hereticimp.txt b/wadsrc/static/actors/heretic/hereticimp.txt deleted file mode 100644 index fdbdeb9b7d..0000000000 --- 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/hereticweaps.txt b/wadsrc/static/actors/heretic/hereticweaps.txt deleted file mode 100644 index 41461379af..0000000000 --- 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/mummy.txt b/wadsrc/static/actors/heretic/mummy.txt deleted file mode 100644 index 331f315cd5..0000000000 --- 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 bb9beb3dd0..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 52906258c1..69b2fbb55f 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,9 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index bd7b914b5c..e65e49fea7 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -73,13 +73,13 @@ 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 diff --git a/wadsrc/static/zscript/heretic/clink.txt b/wadsrc/static/zscript/heretic/clink.txt new file mode 100644 index 0000000000..7549ff097a --- /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/hereticimp.txt b/wadsrc/static/zscript/heretic/hereticimp.txt new file mode 100644 index 0000000000..9f5c0a23e1 --- /dev/null +++ b/wadsrc/static/zscript/heretic/hereticimp.txt @@ -0,0 +1,171 @@ + +// Heretic imp (as opposed to the Doom variety) ----------------------------- + +class HereticImp : Actor +{ + 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"; + } + + action native void A_ImpMsAttack(); + action native void A_ImpDeath(); + action native void A_ImpXDeath1(); + action native void 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 ------------------------------------------------------- + +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/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt new file mode 100644 index 0000000000..eabecd9d86 --- /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_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; + } +} + + +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_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 ---------------------------------------------------------- + +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"; + } + + action native void A_MacePL1Check(); + action 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 ""; + } + + action 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"; + } + + action 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"; + } + + action 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"; + } + + action native void A_AddPlayerRain(); + action native void A_HideInCeiling(); + action 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"; + } + + action 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"; + } + + action 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"; + } + + action native void A_FlameEnd(); + action 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/mummy.txt b/wadsrc/static/zscript/heretic/mummy.txt new file mode 100644 index 0000000000..6d01fcea42 --- /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 0000000000..613559a86c --- /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; + } +} From 552f094ec15bb0d5ed2348da50f8171565df182c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 12:58:23 +0200 Subject: [PATCH 055/471] - converted the rest of Heretic's actors. - fixed: Boolean constants were not properly handled. --- src/scripting/zscript/zcc_compile.cpp | 6 +- wadsrc/static/actors/heretic/chicken.txt | 181 ------------- wadsrc/static/actors/heretic/dsparil.txt | 270 ------------------- wadsrc/static/actors/heretic/ironlich.txt | 175 ------------ wadsrc/static/actors/heretic/knight.txt | 118 -------- wadsrc/static/actors/heretic/wizard.txt | 96 ------- wadsrc/static/decorate.txt | 6 - wadsrc/static/zscript.txt | 3 - wadsrc/static/zscript/heretic/chicken.txt | 201 ++++++++++++++ wadsrc/static/zscript/heretic/dsparil.txt | 297 +++++++++++++++++++++ wadsrc/static/zscript/heretic/ironlich.txt | 191 +++++++++++++ wadsrc/static/zscript/heretic/knight.txt | 131 +++++++++ wadsrc/static/zscript/heretic/wizard.txt | 103 +++++++ 13 files changed, 928 insertions(+), 850 deletions(-) delete mode 100644 wadsrc/static/actors/heretic/chicken.txt delete mode 100644 wadsrc/static/actors/heretic/dsparil.txt delete mode 100644 wadsrc/static/actors/heretic/ironlich.txt delete mode 100644 wadsrc/static/actors/heretic/knight.txt delete mode 100644 wadsrc/static/actors/heretic/wizard.txt create mode 100644 wadsrc/static/zscript/heretic/chicken.txt create mode 100644 wadsrc/static/zscript/heretic/dsparil.txt create mode 100644 wadsrc/static/zscript/heretic/ironlich.txt create mode 100644 wadsrc/static/zscript/heretic/knight.txt create mode 100644 wadsrc/static/zscript/heretic/wizard.txt diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 1992587c8f..5511898f7a 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2385,6 +2385,10 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) { 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); @@ -2396,7 +2400,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) else { // can there be other types? - Error(cnst, "Unknown constant type"); + Error(cnst, "Unknown constant type %s", cnst->Type->DescriptiveName()); return new FxConstant(0, *ast); } } diff --git a/wadsrc/static/actors/heretic/chicken.txt b/wadsrc/static/actors/heretic/chicken.txt deleted file mode 100644 index 8d3b1e71d8..0000000000 --- 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/dsparil.txt b/wadsrc/static/actors/heretic/dsparil.txt deleted file mode 100644 index 8b2f4dc5c1..0000000000 --- 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/ironlich.txt b/wadsrc/static/actors/heretic/ironlich.txt deleted file mode 100644 index 43d7c16c58..0000000000 --- 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 863c67b75d..0000000000 --- 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/wizard.txt b/wadsrc/static/actors/heretic/wizard.txt deleted file mode 100644 index 11ef0ad675..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 69b2fbb55f..b8586d3ee7 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,9 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index e65e49fea7..8fef6819a1 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -79,11 +79,8 @@ 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 -*/ - diff --git a/wadsrc/static/zscript/heretic/chicken.txt b/wadsrc/static/zscript/heretic/chicken.txt new file mode 100644 index 0000000000..2e5ada81c8 --- /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/dsparil.txt b/wadsrc/static/zscript/heretic/dsparil.txt new file mode 100644 index 0000000000..ebf60eb47b --- /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"; + } + + action native void A_Sor1Pain (); + action native void A_Sor1Chase (); + action native void A_Srcr1Attack (); + action 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"; + } + + action native void A_Srcr2Decide (); + action native void A_Srcr2Attack (); + action native void A_Sor2DthInit (); + action 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"; + } + + action 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"; + } + + action 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/ironlich.txt b/wadsrc/static/zscript/heretic/ironlich.txt new file mode 100644 index 0000000000..9b66bcb0d7 --- /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; + } + + action 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"; + } + + action 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"; + } + + action 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; + } + + action 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 0000000000..f8b84b9aad --- /dev/null +++ b/wadsrc/static/zscript/heretic/knight.txt @@ -0,0 +1,131 @@ + +// 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; + } + + action native void 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 ------------------------------------------------------------- + +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; + } + + action native void A_DripBlood (); + + States + { + Spawn: + RAXE AB 5 BRIGHT A_DripBlood; + Loop; + Death: + RAXE CDE 6 BRIGHT; + Stop; + } +} + diff --git a/wadsrc/static/zscript/heretic/wizard.txt b/wadsrc/static/zscript/heretic/wizard.txt new file mode 100644 index 0000000000..3599354ad9 --- /dev/null +++ b/wadsrc/static/zscript/heretic/wizard.txt @@ -0,0 +1,103 @@ + +// 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; + } + + action native void A_GhostOff (); + action native void A_WizAtk1 (); + action native void A_WizAtk2 (); + action native void 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 -------------------------------------------------------- + +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; + } +} + + From d0a8960f61b727bdade1c385c7720931a8497bac Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 14:38:51 +0200 Subject: [PATCH 056/471] - added genuine PEX_GT, PEX_GTEQ and PEX_NEQ operations to the parser. These were previously faked with the inverse plus a boolean not. Although this works, it either leads to sub-optimal code generation or some fudging to avoid the inefficient handling. Just adding proper handling to the parser seems the easiest and most straightforward way to get around this. The code generator already can deal with these operations properly so there's no good reason to do it differently. --- src/scripting/zscript/zcc-parse.lemon | 15 ++++++--------- src/scripting/zscript/zcc_expr.cpp | 12 ++++++++++++ src/scripting/zscript/zcc_exprlist.h | 3 +++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 78a4d29ea0..215670c825 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -1161,9 +1161,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 */ { @@ -1172,9 +1171,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 */ { @@ -1194,9 +1192,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 */ { diff --git a/src/scripting/zscript/zcc_expr.cpp b/src/scripting/zscript/zcc_expr.cpp index 6f640d8f16..b342510619 100644 --- a/src/scripting/zscript/zcc_expr.cpp +++ b/src/scripting/zscript/zcc_expr.cpp @@ -365,6 +365,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 index e36aedea63..2df687798a 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -36,10 +36,13 @@ xx(Concat, ) xx(LT, ) xx(LTEQ, ) +xx(GT, ) +xx(GTEQ, ) xx(LTGTEQ, ) xx(Is, ) xx(EQEQ, ) +xx(NEQ, ) xx(APREQ, ) xx(BitAnd, ) From 938ab4ca706c278d34f03ce37eda262bbde100ca Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 15:17:48 +0200 Subject: [PATCH 057/471] - implemented '**' (power) operator. To ensure reliability, acustom 'pow' function will be used to calculate it. - fixed: FxBinary::ResolveLR' check for numeric operations was incomplete. Like far too many other places it just assumed that everything with ValueType->GetRegType() == REGT_INT is a numeric type, but for names this is not the case. --- src/CMakeLists.txt | 2 + src/fragglescript/t_func.cpp | 2 +- src/math/cmath.h | 3 + src/math/pow.c | 756 +++++++++++++++++++++++ src/math/powi.c | 186 ++++++ src/scripting/codegeneration/codegen.cpp | 67 +- src/scripting/codegeneration/codegen.h | 15 + src/scripting/vm/vmexec.h | 6 +- src/scripting/zscript/zcc_compile.cpp | 3 + src/scripting/zscript/zcc_expr.cpp | 3 +- 10 files changed, 1033 insertions(+), 10 deletions(-) create mode 100644 src/math/pow.c create mode 100644 src/math/powi.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ae2f19960d..ddd027c802 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1287,6 +1287,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 diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index a02ec947f3..4897d8fdb6 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -3636,7 +3636,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/math/cmath.h b/src/math/cmath.h index 9fd0b570d1..5c02c4e87e 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 0000000000..c55fa81fd3 --- /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 0000000000..ec80dc1d5f --- /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/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f567357976..fceee42c05 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1824,13 +1824,16 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) { ValueType = TypeBool; } - if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) - { - ValueType = TypeSInt32; - } else if (left->IsNumeric() && right->IsNumeric()) { - ValueType = TypeFloat64; + if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) + { + ValueType = TypeSInt32; + } + else + { + ValueType = TypeFloat64; + } } else if (left->ValueType->GetRegType() == REGT_POINTER && left->ValueType == right->ValueType) { @@ -2137,6 +2140,60 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) // //========================================================================== +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 NULL; + + 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) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index ce4f11bb13..8d49361857 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -686,6 +686,21 @@ public: // //========================================================================== +class FxPow : public FxBinary +{ +public: + + FxPow(FxExpression*, FxExpression*); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// FxBinary +// +//========================================================================== + class FxCompareRel : public FxBinary { public: diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 1d1764c6ea..8f8a212955 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1055,15 +1055,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): diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 5511898f7a..6ec463490f 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2422,6 +2422,9 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_Mod: return new FxMulDiv(op == PEX_Mul ? '*' : op == PEX_Div ? '/' : '%', left, right); + case PEX_Pow: + return new FxPow(left, right); + default: I_Error("Binary operator %d not implemented yet", op); } diff --git a/src/scripting/zscript/zcc_expr.cpp b/src/scripting/zscript/zcc_expr.cpp index b342510619..0c2c6baee5 100644 --- a/src/scripting/zscript/zcc_expr.cpp +++ b/src/scripting/zscript/zcc_expr.cpp @@ -41,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)) @@ -332,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 }, From 23a2a19a784d52b9f0a4efe43cc737c8db34fc39 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 15:52:29 +0200 Subject: [PATCH 058/471] - added handling for shift and bit operators. - added the '>>>' (unsigned shift) operator. Although, with unsigned numbers available, this is technically not really needed, DECORATE supports this so ZScript should, too, if only for the benefit of making conversion tools easier to handle. --- src/scripting/codegeneration/codegen.cpp | 4 ++-- src/scripting/zscript/zcc-parse.lemon | 7 ++++++- src/scripting/zscript/zcc_compile.cpp | 8 ++++++++ src/scripting/zscript/zcc_exprlist.h | 3 ++- src/scripting/zscript/zcc_parser.cpp | 1 + 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index fceee42c05..c68fc3723a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2430,9 +2430,9 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) CHECKRESOLVED(); if (!ResolveLR(ctx, false)) return NULL; - if (ValueType->GetRegType() == REGT_FLOAT /* lax */) + if (ValueType->GetRegType() == REGT_FLOAT && ctx.FromDecorate) { - // For DECORATE which allows floats here. + // For DECORATE which allows floats here. ZScript does not. if (left->ValueType->GetRegType() != REGT_INT) { left = new FxIntCast(left, ctx.FromDecorate); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 215670c825..1e10103a06 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -114,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. @@ -1148,6 +1148,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); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6ec463490f..9d0ff5428d 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2425,6 +2425,14 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) 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(op == PEX_LeftShift ? TK_LShift : op == PEX_RightShift ? TK_RShift : op == PEX_URightShift? TK_URShift : op == PEX_BitAnd ? '&' : op == PEX_BitOr ? '|' : '^', left, right); + default: I_Error("Binary operator %d not implemented yet", op); } diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index 2df687798a..46a1b9c690 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -32,6 +32,7 @@ xx(CrossProduct, ) xx(DotProduct, ) xx(LeftShift, ) xx(RightShift, ) +xx(URightShift, ) xx(Concat, ) xx(LT, ) @@ -42,7 +43,7 @@ xx(LTGTEQ, ) xx(Is, ) xx(EQEQ, ) -xx(NEQ, ) +xx(NEQ, ) xx(APREQ, ) xx(BitAnd, ) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index c3f75b2b0a..cc8d187d31 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -95,6 +95,7 @@ static void InitTokenMap() 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); From a6a0c4b93c9b163cc185d59495720d9831efbacb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 20:33:35 +0200 Subject: [PATCH 059/471] - handle all unary operators. - handle all binary operators which are already implemented in the code generator. - implemented sizeof/alignof operators in code generator. - rewrote RequestAddress so that its return value is not the writability of an address but the mere existence. Also changed it to not output errors itself because those cannot be dealt with by the calling function. --- src/scripting/codegeneration/codegen.cpp | 101 +++++++++++++++++++---- src/scripting/codegeneration/codegen.h | 28 +++++-- src/scripting/zscript/zcc_compile.cpp | 65 +++++++++++++++ 3 files changed, 174 insertions(+), 20 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c68fc3723a..14f1627d98 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -264,9 +264,9 @@ FxExpression *FxExpression::Resolve(FCompileContext &ctx) // //========================================================================== -bool FxExpression::RequestAddress() +bool FxExpression::RequestAddress(bool *writable) { - ScriptPosition.Message(MSG_ERROR, "invalid dereference\n"); + if (writable != nullptr) *writable = false; return false; } @@ -1488,6 +1488,67 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) return from; } +//========================================================================== +// +// +// +//========================================================================== + +FxSizeAlign::FxSizeAlign(FxExpression *operand, int which) + : FxExpression(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 == 'a'? "alignment" : "size"); + delete this; + return NULL; + } + else if (!Operand->RequestAddress(nullptr)) + { + ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == 'a' ? "alignment" : "size"); + delete this; + return NULL; + } + else + { + FxExpression *x = new FxConstant(Which == 'a' ? int(type->Align) : int(type->Size), Operand->ScriptPosition); + delete this; + return x->Resolve(ctx); + } +} + +ExpEmit FxSizeAlign::Emit(VMFunctionBuilder *build) +{ + return ExpEmit(); +} + //========================================================================== // // FxPreIncrDecr @@ -1506,10 +1567,11 @@ FxPreIncrDecr::~FxPreIncrDecr() SAFE_DELETE(Base); } -bool FxPreIncrDecr::RequestAddress() +bool FxPreIncrDecr::RequestAddress(bool *writable) { AddressRequested = true; - return AddressWritable; + if (writable != nullptr) *writable = AddressWritable; + return true; } FxExpression *FxPreIncrDecr::Resolve(FCompileContext &ctx) @@ -1531,7 +1593,7 @@ FxExpression *FxPreIncrDecr::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (!(AddressWritable = Base->RequestAddress())) + if (!Base->RequestAddress(&AddressWritable) || !AddressWritable ) { ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); delete this; @@ -1594,6 +1656,7 @@ FxExpression *FxPostIncrDecr::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); SAFE_RESOLVE(Base, ctx); + bool AddressWritable; ValueType = Base->ValueType; @@ -1609,7 +1672,7 @@ FxExpression *FxPostIncrDecr::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (!Base->RequestAddress()) + if (!Base->RequestAddress(&AddressWritable) || !AddressWritable) { ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); delete this; @@ -1667,10 +1730,11 @@ FxAssign::~FxAssign() SAFE_DELETE(Right); } -bool FxAssign::RequestAddress() +bool FxAssign::RequestAddress(bool *writable) { AddressRequested = true; - return AddressWritable; + if (writable != nullptr) *writable = AddressWritable; + return true; } FxExpression *FxAssign::Resolve(FCompileContext &ctx) @@ -1688,7 +1752,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (!(AddressWritable = Base->RequestAddress())) + if (!Base->RequestAddress(&AddressWritable) || !AddressWritable) { ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); delete this; @@ -3968,10 +4032,11 @@ FxClassMember::~FxClassMember() // //========================================================================== -bool FxClassMember::RequestAddress() +bool FxClassMember::RequestAddress(bool *writable) { AddressRequested = true; - return !!(~membervar->Flags & VARF_ReadOnly); + if (writable != nullptr) *writable = !(membervar->Flags & VARF_ReadOnly); + return true; } //========================================================================== @@ -4079,10 +4144,11 @@ FxArrayElement::~FxArrayElement() // //========================================================================== -bool FxArrayElement::RequestAddress() +bool FxArrayElement::RequestAddress(bool *writable) { AddressRequested = true; - return AddressWritable; + if (writable != nullptr) *writable = AddressWritable; + return true; } //========================================================================== @@ -4108,7 +4174,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) return NULL; } } - if (index->ValueType->GetRegType() != REGT_INT) + if (index->ValueType->GetRegType() != REGT_INT && index->ValueType != TypeName) { ScriptPosition.Message(MSG_ERROR, "Array index must be integer"); delete this; @@ -4141,7 +4207,12 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) delete this; return NULL; } - AddressWritable = Array->RequestAddress(); + if (!Array->RequestAddress(&AddressWritable)) + { + ScriptPosition.Message(MSG_ERROR, "Unable to dereference array."); + delete this; + return NULL; + } return this; } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 8d49361857..1a2d2045d1 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -212,7 +212,7 @@ public: virtual FxExpression *Resolve(FCompileContext &ctx); virtual bool isConstant() const; - virtual bool RequestAddress(); + virtual bool RequestAddress(bool *writable); virtual PPrototype *ReturnProto(); virtual VMFunction *GetDirectFunction(); bool IsNumeric() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } @@ -553,6 +553,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 @@ -570,7 +588,7 @@ public: FxPreIncrDecr(FxExpression *base, int token); ~FxPreIncrDecr(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(); + bool RequestAddress(bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -609,7 +627,7 @@ public: FxAssign(FxExpression *base, FxExpression *right); ~FxAssign(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(); + bool RequestAddress(bool *writable); ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Address; @@ -932,7 +950,7 @@ public: FxClassMember(FxExpression*, PField*, const FScriptPosition&); ~FxClassMember(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(); + bool RequestAddress(bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -967,7 +985,7 @@ public: FxArrayElement(FxExpression*, FxExpression*); ~FxArrayElement(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(); + bool RequestAddress(bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 9d0ff5428d..c55d6994ae 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2405,6 +2405,46 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *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, op == PEX_PostDec ? TK_Decr : TK_Incr); + + case PEX_PreDec: + case PEX_PreInc: + return new FxPreIncrDecr(operand, op == PEX_PostDec ? TK_Decr : TK_Incr); + + 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, op == PEX_AlignOf ? 'a' : 's'); + + 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); @@ -2433,6 +2473,31 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_BitXor: return new FxBinaryInt(op == PEX_LeftShift ? TK_LShift : op == PEX_RightShift ? TK_RShift : op == PEX_URightShift? TK_URShift : op == PEX_BitAnd ? '&' : op == PEX_BitOr ? '|' : '^', left, right); + case PEX_BoolOr: + case PEX_BoolAnd: + return new FxBinaryLogical(op == PEX_BoolAnd ? TK_AndAnd : TK_OrOr, left, right); + + case PEX_LT: + case PEX_LTEQ: + case PEX_GT: + case PEX_GTEQ: + return new FxCompareRel(op == PEX_LT ? '<' : op == PEX_RightShift ? '>' : op == PEX_LTEQ ? TK_Leq : TK_Geq, left, right); + + case PEX_EQEQ: + case PEX_NEQ: + return new FxCompareEq(op == PEX_NEQ ? TK_Neq : TK_Eq, left, right); + + + // todo: These do not have representations in DECORATE and no implementation exists yet. + case PEX_LTGTEQ: + case PEX_Concat: + case PEX_Is: + // more esoteric operators + case PEX_APREQ: + + // vector operations will be done later. + case PEX_CrossProduct: + case PEX_DotProduct: default: I_Error("Binary operator %d not implemented yet", op); } From 1c21dbc44cc21d0f44cc4f819ff971f94793fdf3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 21:43:14 +0200 Subject: [PATCH 060/471] - handle trinary conditional statement. --- src/scripting/zscript/zcc_compile.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index c55d6994ae..39597c5130 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2471,7 +2471,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_BitAnd: case PEX_BitOr: case PEX_BitXor: - return new FxBinaryInt(op == PEX_LeftShift ? TK_LShift : op == PEX_RightShift ? TK_RShift : op == PEX_URightShift? TK_URShift : op == PEX_BitAnd ? '&' : op == PEX_BitOr ? '|' : '^', left, right); + return new FxBinaryInt(op == PEX_LeftShift ? TK_LShift : op == PEX_RightShift ? TK_RShift : op == PEX_URightShift ? TK_URShift : op == PEX_BitAnd ? '&' : op == PEX_BitOr ? '|' : '^', left, right); case PEX_BoolOr: case PEX_BoolAnd: @@ -2485,17 +2485,17 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_EQEQ: case PEX_NEQ: - return new FxCompareEq(op == PEX_NEQ ? TK_Neq : TK_Eq, left, right); + return new FxCompareEq(op == PEX_NEQ ? TK_Neq : TK_Eq, left, right); - // todo: These do not have representations in DECORATE and no implementation exists yet. + // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_LTGTEQ: case PEX_Concat: case PEX_Is: // more esoteric operators case PEX_APREQ: - // vector operations will be done later. + // vector operations will be done later. case PEX_CrossProduct: case PEX_DotProduct: default: @@ -2503,6 +2503,16 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } 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); + } } // only for development. I_Error is more convenient here than a normal error. From d66631478a47e7047d1e2e79d9ffaebe678f1b59 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 23:27:34 +0200 Subject: [PATCH 061/471] - converted some Hexen stuff. --- wadsrc/static/actors/hexen/baseweapons.txt | 20 --- wadsrc/static/actors/hexen/clericplayer.txt | 103 ----------- wadsrc/static/actors/hexen/fighterplayer.txt | 126 ------------- wadsrc/static/actors/hexen/flame.txt | 106 ----------- wadsrc/static/actors/hexen/flies.txt | 27 --- wadsrc/static/actors/hexen/korax.txt | 124 ------------- wadsrc/static/actors/hexen/mageplayer.txt | 104 ----------- wadsrc/static/actors/hexen/pig.txt | 155 ---------------- wadsrc/static/decorate.txt | 8 - wadsrc/static/zscript.txt | 53 ++++++ wadsrc/static/zscript/hexen/baseweapons.txt | 29 +++ wadsrc/static/zscript/hexen/clericplayer.txt | 106 +++++++++++ wadsrc/static/zscript/hexen/fighterplayer.txt | 133 ++++++++++++++ wadsrc/static/zscript/hexen/flame.txt | 122 +++++++++++++ wadsrc/static/zscript/hexen/flies.txt | 30 ++++ wadsrc/static/zscript/hexen/korax.txt | 133 ++++++++++++++ wadsrc/static/zscript/hexen/mageplayer.txt | 107 +++++++++++ wadsrc/static/zscript/hexen/pig.txt | 170 ++++++++++++++++++ 18 files changed, 883 insertions(+), 773 deletions(-) delete mode 100644 wadsrc/static/actors/hexen/baseweapons.txt delete mode 100644 wadsrc/static/actors/hexen/clericplayer.txt delete mode 100644 wadsrc/static/actors/hexen/fighterplayer.txt delete mode 100644 wadsrc/static/actors/hexen/flame.txt delete mode 100644 wadsrc/static/actors/hexen/flies.txt delete mode 100644 wadsrc/static/actors/hexen/korax.txt delete mode 100644 wadsrc/static/actors/hexen/mageplayer.txt delete mode 100644 wadsrc/static/actors/hexen/pig.txt create mode 100644 wadsrc/static/zscript/hexen/baseweapons.txt create mode 100644 wadsrc/static/zscript/hexen/clericplayer.txt create mode 100644 wadsrc/static/zscript/hexen/fighterplayer.txt create mode 100644 wadsrc/static/zscript/hexen/flame.txt create mode 100644 wadsrc/static/zscript/hexen/flies.txt create mode 100644 wadsrc/static/zscript/hexen/korax.txt create mode 100644 wadsrc/static/zscript/hexen/mageplayer.txt create mode 100644 wadsrc/static/zscript/hexen/pig.txt diff --git a/wadsrc/static/actors/hexen/baseweapons.txt b/wadsrc/static/actors/hexen/baseweapons.txt deleted file mode 100644 index d40536316f..0000000000 --- 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/clericplayer.txt b/wadsrc/static/actors/hexen/clericplayer.txt deleted file mode 100644 index 4b762af5da..0000000000 --- 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/fighterplayer.txt b/wadsrc/static/actors/hexen/fighterplayer.txt deleted file mode 100644 index 29de1f3a3d..0000000000 --- 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/flame.txt b/wadsrc/static/actors/hexen/flame.txt deleted file mode 100644 index b3e369a2e1..0000000000 --- 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/flies.txt b/wadsrc/static/actors/hexen/flies.txt deleted file mode 100644 index e297cc2890..0000000000 --- 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/korax.txt b/wadsrc/static/actors/hexen/korax.txt deleted file mode 100644 index a35183ad6b..0000000000 --- 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/mageplayer.txt b/wadsrc/static/actors/hexen/mageplayer.txt deleted file mode 100644 index 9cf4117a5e..0000000000 --- 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/pig.txt b/wadsrc/static/actors/hexen/pig.txt deleted file mode 100644 index 9d986e7eb1..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index b8586d3ee7..450cc37a77 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,11 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 8fef6819a1..787cb661f9 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -84,3 +84,56 @@ 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 +*/ \ No newline at end of file diff --git a/wadsrc/static/zscript/hexen/baseweapons.txt b/wadsrc/static/zscript/hexen/baseweapons.txt new file mode 100644 index 0000000000..eb685a873c --- /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/clericplayer.txt b/wadsrc/static/zscript/hexen/clericplayer.txt new file mode 100644 index 0000000000..1b47ad3f56 --- /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/fighterplayer.txt b/wadsrc/static/zscript/hexen/fighterplayer.txt new file mode 100644 index 0000000000..3aa5607d33 --- /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/flame.txt b/wadsrc/static/zscript/hexen/flame.txt new file mode 100644 index 0000000000..4eab6c6d3f --- /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/flies.txt b/wadsrc/static/zscript/hexen/flies.txt new file mode 100644 index 0000000000..35c52a124e --- /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"; + } + + action native void A_FlySearch(); + action 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/korax.txt b/wadsrc/static/zscript/hexen/korax.txt new file mode 100644 index 0000000000..3928de8840 --- /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"; + } + + action native void A_KoraxChase(); + action native void A_KoraxDecide(); + action native void A_KoraxBonePop(); + action native void A_KoraxMissile(); + action 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; + } + + action 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"; + } + + action native void A_KBolt(); + action 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/mageplayer.txt b/wadsrc/static/zscript/hexen/mageplayer.txt new file mode 100644 index 0000000000..33b34633ea --- /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/pig.txt b/wadsrc/static/zscript/hexen/pig.txt new file mode 100644 index 0000000000..8fa4468827 --- /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; + } +} + From 4aecc4f5657e5e5bc7be31c653078ba61ed07771 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 18 Oct 2016 00:49:13 +0200 Subject: [PATCH 062/471] - more Hexen conversions. --- wadsrc/static/actors/hexen/hexenarmor.txt | 65 - .../static/actors/hexen/hexendecorations.txt | 1396 -------------- wadsrc/static/actors/hexen/hexenkeys.txt | 139 -- .../static/actors/hexen/hexenspecialdecs.txt | 684 ------- wadsrc/static/decorate.txt | 4 - wadsrc/static/zscript.txt | 2 +- wadsrc/static/zscript/hexen/hexenarmor.txt | 77 + .../static/zscript/hexen/hexendecorations.txt | 1705 +++++++++++++++++ wadsrc/static/zscript/hexen/hexenkeys.txt | 175 ++ .../static/zscript/hexen/hexenspecialdecs.txt | 756 ++++++++ 10 files changed, 2714 insertions(+), 2289 deletions(-) delete mode 100644 wadsrc/static/actors/hexen/hexenarmor.txt delete mode 100644 wadsrc/static/actors/hexen/hexendecorations.txt delete mode 100644 wadsrc/static/actors/hexen/hexenkeys.txt delete mode 100644 wadsrc/static/actors/hexen/hexenspecialdecs.txt create mode 100644 wadsrc/static/zscript/hexen/hexenarmor.txt create mode 100644 wadsrc/static/zscript/hexen/hexendecorations.txt create mode 100644 wadsrc/static/zscript/hexen/hexenkeys.txt create mode 100644 wadsrc/static/zscript/hexen/hexenspecialdecs.txt diff --git a/wadsrc/static/actors/hexen/hexenarmor.txt b/wadsrc/static/actors/hexen/hexenarmor.txt deleted file mode 100644 index 53be60fe0d..0000000000 --- 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 87af4eff5a..0000000000 --- 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 b65d59e164..0000000000 --- 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 cd50633858..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 450cc37a77..146600f34c 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,7 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 787cb661f9..50ecf62120 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -93,11 +93,11 @@ 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 diff --git a/wadsrc/static/zscript/hexen/hexenarmor.txt b/wadsrc/static/zscript/hexen/hexenarmor.txt new file mode 100644 index 0000000000..13b674fbf2 --- /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 0000000000..937034bd88 --- /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 0000000000..9bf9f426c7 --- /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 0000000000..97c6ea41ea --- /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 + } + + action 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 + } + + action native void A_PotteryChooseBit(); + action 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 + } + + action 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"; + } + + action 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 + } + + action 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 + } + + action native void A_LeafThrust(); + action 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"; + } + + action 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"; + } + + action native void A_BellReset1(); + action 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; + } +} + From 1652c02a08337fec5281ddbbbce6b1bf1ae5fd8b Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Mon, 17 Oct 2016 22:37:49 -0500 Subject: [PATCH 063/471] Add unsigned division opcodes to the VM --- src/scripting/vm/vmexec.h | 50 +++++++++++++++++++++++++++++++++++++++ src/scripting/vm/vmops.h | 10 ++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 8f8a212955..9dbea7c51b 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -813,6 +813,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) @@ -838,6 +863,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]; diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 39d224f5c9..1b34dcc0fc 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -115,12 +115,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 From 61cc7dbb2907e148c04b4bc24da48976425c773d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 18 Oct 2016 10:09:02 +0200 Subject: [PATCH 064/471] - another batch of Hexen items converted. - fixed parsing of named damage types and pain chances. --- src/scripting/zscript/zcc_compile.cpp | 9 +- wadsrc/static/actors/hexen/centaur.txt | 186 -------- wadsrc/static/actors/hexen/demons.txt | 385 ----------------- wadsrc/static/actors/hexen/ettin.txt | 106 ----- wadsrc/static/actors/hexen/mana.txt | 87 ---- wadsrc/static/actors/hexen/puzzleitems.txt | 287 ------------ .../static/actors/hexen/scriptprojectiles.txt | 123 ------ wadsrc/static/actors/hexen/speedboots.txt | 18 - wadsrc/static/decorate.txt | 7 - wadsrc/static/zscript.txt | 2 +- wadsrc/static/zscript/hexen/centaur.txt | 204 +++++++++ wadsrc/static/zscript/hexen/demons.txt | 408 ++++++++++++++++++ wadsrc/static/zscript/hexen/ettin.txt | 115 +++++ wadsrc/static/zscript/hexen/mana.txt | 99 +++++ wadsrc/static/zscript/hexen/puzzleitems.txt | 338 +++++++++++++++ .../zscript/hexen/scriptprojectiles.txt | 141 ++++++ wadsrc/static/zscript/hexen/speedboots.txt | 21 + 17 files changed, 1332 insertions(+), 1204 deletions(-) delete mode 100644 wadsrc/static/actors/hexen/centaur.txt delete mode 100644 wadsrc/static/actors/hexen/demons.txt delete mode 100644 wadsrc/static/actors/hexen/ettin.txt delete mode 100644 wadsrc/static/actors/hexen/mana.txt delete mode 100644 wadsrc/static/actors/hexen/puzzleitems.txt delete mode 100644 wadsrc/static/actors/hexen/scriptprojectiles.txt delete mode 100644 wadsrc/static/actors/hexen/speedboots.txt create mode 100644 wadsrc/static/zscript/hexen/centaur.txt create mode 100644 wadsrc/static/zscript/hexen/demons.txt create mode 100644 wadsrc/static/zscript/hexen/ettin.txt create mode 100644 wadsrc/static/zscript/hexen/mana.txt create mode 100644 wadsrc/static/zscript/hexen/puzzleitems.txt create mode 100644 wadsrc/static/zscript/hexen/scriptprojectiles.txt create mode 100644 wadsrc/static/zscript/hexen/speedboots.txt diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 39597c5130..43219acb1e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1554,7 +1554,7 @@ const char *ZCCCompiler::GetString(ZCC_Expression *expr, bool silent) { if (expr->Type == TypeError) { - return 0; + return nullptr; } else if (expr->Type->IsKindOf(RUNTIME_CLASS(PString))) { @@ -1568,7 +1568,7 @@ const char *ZCCCompiler::GetString(ZCC_Expression *expr, bool silent) else { if (!silent) Error(expr, "Cannot convert to string"); - return 0; + return nullptr; } } @@ -1631,7 +1631,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper conv.d = GetDouble(exp); break; - case 'Z': // an optional string. Does not allow any numerical value. + 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. @@ -1640,7 +1640,8 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper p++; continue; } - // fall through + conv.s = GetString(exp); + break; case 'C': // this parser accepts colors only in string form. pref.i = 1; diff --git a/wadsrc/static/actors/hexen/centaur.txt b/wadsrc/static/actors/hexen/centaur.txt deleted file mode 100644 index d036566bd6..0000000000 --- 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/demons.txt b/wadsrc/static/actors/hexen/demons.txt deleted file mode 100644 index 39da26e1de..0000000000 --- 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/ettin.txt b/wadsrc/static/actors/hexen/ettin.txt deleted file mode 100644 index 4ce13406c4..0000000000 --- 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/mana.txt b/wadsrc/static/actors/hexen/mana.txt deleted file mode 100644 index 4a50e368a1..0000000000 --- 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/puzzleitems.txt b/wadsrc/static/actors/hexen/puzzleitems.txt deleted file mode 100644 index ad1187da01..0000000000 --- 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 d031be3ee6..0000000000 --- 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/speedboots.txt b/wadsrc/static/actors/hexen/speedboots.txt deleted file mode 100644 index 2ae4dcd019..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 146600f34c..92802dc7e5 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,10 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 50ecf62120..531c353f59 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -97,7 +97,6 @@ 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 @@ -105,6 +104,7 @@ 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 diff --git a/wadsrc/static/zscript/hexen/centaur.txt b/wadsrc/static/zscript/hexen/centaur.txt new file mode 100644 index 0000000000..37a8d6b11d --- /dev/null +++ b/wadsrc/static/zscript/hexen/centaur.txt @@ -0,0 +1,204 @@ +// 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 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 ----------------------------------------------------------- + +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/demons.txt b/wadsrc/static/zscript/hexen/demons.txt new file mode 100644 index 0000000000..56b4f3bdac --- /dev/null +++ b/wadsrc/static/zscript/hexen/demons.txt @@ -0,0 +1,408 @@ + +// 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 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 ---------------------------------------------------- + +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 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 ---------------------------------------------------- + +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/ettin.txt b/wadsrc/static/zscript/hexen/ettin.txt new file mode 100644 index 0000000000..8ddf9e7d2c --- /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/mana.txt b/wadsrc/static/zscript/hexen/mana.txt new file mode 100644 index 0000000000..0a43a21ddd --- /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/puzzleitems.txt b/wadsrc/static/zscript/hexen/puzzleitems.txt new file mode 100644 index 0000000000..f502664d75 --- /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 0000000000..5bf3f254ff --- /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/speedboots.txt b/wadsrc/static/zscript/hexen/speedboots.txt new file mode 100644 index 0000000000..e5a0364eca --- /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; + } +} From bef71f29e27421fd9850baf04a91aeb6759d6fea Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 18 Oct 2016 10:17:09 +0200 Subject: [PATCH 065/471] - make generation of the AST dump a command line parameter instead of having it depend on running a debug build. - disable generation of the parser's trace file in debug builds. This increases parsing time by a factor of 15 and is only needed when debugging a problem in the grammar. --- src/scripting/zscript/zcc_parser.cpp | 31 +++++++++++++++------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index cc8d187d31..9fefa537d0 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -39,6 +39,7 @@ #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" @@ -297,7 +298,7 @@ static void DoParse(int lumpnum) parser = ZCCParseAlloc(malloc); ZCCParseState state; -#ifdef _DEBUG +#if 0 // 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); @@ -331,24 +332,26 @@ static void DoParse(int lumpnum) I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum)); } - { - // Make a dump of the AST before running the compiler for diagnostic purposes. -#ifdef _DEBUG +#if 0 if (f != NULL) { fclose(f); } - FString ast = ZCC_PrintAST(state.TopNode); - FString filename = Wads.GetLumpFullName(lumpnum); - FString astfile = ExtractFileBase(filename, false); - astfile << "-before.ast"; - f = fopen(astfile, "w"); - 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.GetLumpFullName(lumpnum); + FString astfile = ExtractFileBase(filename, false); + astfile << ".ast"; + FILE *ff = fopen(astfile, "w"); + if (ff != NULL) + { + fputs(ast.GetChars(), ff); + fclose(ff); + } } PSymbolTable symtable; From 2c1d9a7a960269b590ea40d98caf86d269dee824 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 18 Oct 2016 15:15:06 +0200 Subject: [PATCH 066/471] - another bunch of Hexen actors converted. --- wadsrc/static/actors/hexen/bats.txt | 47 ---- wadsrc/static/actors/hexen/bishop.txt | 151 ------------ wadsrc/static/actors/hexen/blastradius.txt | 36 --- wadsrc/static/actors/hexen/boostarmor.txt | 21 -- wadsrc/static/actors/hexen/clericboss.txt | 79 ------ wadsrc/static/actors/hexen/clericmace.txt | 46 ---- wadsrc/static/actors/hexen/fighterboss.txt | 80 ------ wadsrc/static/actors/hexen/firedemon.txt | 227 ----------------- wadsrc/static/actors/hexen/flechette.txt | 222 ----------------- wadsrc/static/actors/hexen/fog.txt | 72 ------ wadsrc/static/actors/hexen/mageboss.txt | 83 ------- wadsrc/static/actors/hexen/summon.txt | 61 ----- wadsrc/static/decorate.txt | 12 - wadsrc/static/zscript.txt | 2 +- wadsrc/static/zscript/hexen/bats.txt | 53 ++++ wadsrc/static/zscript/hexen/bishop.txt | 166 +++++++++++++ wadsrc/static/zscript/hexen/blastradius.txt | 42 ++++ wadsrc/static/zscript/hexen/boostarmor.txt | 24 ++ wadsrc/static/zscript/hexen/clericboss.txt | 82 +++++++ wadsrc/static/zscript/hexen/clericmace.txt | 49 ++++ wadsrc/static/zscript/hexen/fighterboss.txt | 83 +++++++ wadsrc/static/zscript/hexen/firedemon.txt | 236 ++++++++++++++++++ wadsrc/static/zscript/hexen/flechette.txt | 254 ++++++++++++++++++++ wadsrc/static/zscript/hexen/fog.txt | 78 ++++++ wadsrc/static/zscript/hexen/mageboss.txt | 86 +++++++ wadsrc/static/zscript/hexen/summon.txt | 71 ++++++ 26 files changed, 1225 insertions(+), 1138 deletions(-) delete mode 100644 wadsrc/static/actors/hexen/bats.txt delete mode 100644 wadsrc/static/actors/hexen/bishop.txt delete mode 100644 wadsrc/static/actors/hexen/blastradius.txt delete mode 100644 wadsrc/static/actors/hexen/boostarmor.txt delete mode 100644 wadsrc/static/actors/hexen/clericboss.txt delete mode 100644 wadsrc/static/actors/hexen/clericmace.txt delete mode 100644 wadsrc/static/actors/hexen/fighterboss.txt delete mode 100644 wadsrc/static/actors/hexen/firedemon.txt delete mode 100644 wadsrc/static/actors/hexen/flechette.txt delete mode 100644 wadsrc/static/actors/hexen/fog.txt delete mode 100644 wadsrc/static/actors/hexen/mageboss.txt delete mode 100644 wadsrc/static/actors/hexen/summon.txt create mode 100644 wadsrc/static/zscript/hexen/bats.txt create mode 100644 wadsrc/static/zscript/hexen/bishop.txt create mode 100644 wadsrc/static/zscript/hexen/blastradius.txt create mode 100644 wadsrc/static/zscript/hexen/boostarmor.txt create mode 100644 wadsrc/static/zscript/hexen/clericboss.txt create mode 100644 wadsrc/static/zscript/hexen/clericmace.txt create mode 100644 wadsrc/static/zscript/hexen/fighterboss.txt create mode 100644 wadsrc/static/zscript/hexen/firedemon.txt create mode 100644 wadsrc/static/zscript/hexen/flechette.txt create mode 100644 wadsrc/static/zscript/hexen/fog.txt create mode 100644 wadsrc/static/zscript/hexen/mageboss.txt create mode 100644 wadsrc/static/zscript/hexen/summon.txt diff --git a/wadsrc/static/actors/hexen/bats.txt b/wadsrc/static/actors/hexen/bats.txt deleted file mode 100644 index 521d46e6ef..0000000000 --- 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 435420ddd8..0000000000 --- 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 5612404380..0000000000 --- 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 b55c29f881..0000000000 --- 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/clericboss.txt b/wadsrc/static/actors/hexen/clericboss.txt deleted file mode 100644 index dac0f741cd..0000000000 --- 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/clericmace.txt b/wadsrc/static/actors/hexen/clericmace.txt deleted file mode 100644 index dfb06d9585..0000000000 --- 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/fighterboss.txt b/wadsrc/static/actors/hexen/fighterboss.txt deleted file mode 100644 index 195c0a1a3a..0000000000 --- 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/firedemon.txt b/wadsrc/static/actors/hexen/firedemon.txt deleted file mode 100644 index 3f96d22acd..0000000000 --- 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/flechette.txt b/wadsrc/static/actors/hexen/flechette.txt deleted file mode 100644 index 2c7fbdc2b4..0000000000 --- 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/fog.txt b/wadsrc/static/actors/hexen/fog.txt deleted file mode 100644 index 18effbb779..0000000000 --- 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/mageboss.txt b/wadsrc/static/actors/hexen/mageboss.txt deleted file mode 100644 index 95f36954ba..0000000000 --- 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/summon.txt b/wadsrc/static/actors/hexen/summon.txt deleted file mode 100644 index 7a2971562c..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt index 92802dc7e5..88ce6a2c78 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,15 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 531c353f59..570d6eee32 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -104,7 +104,6 @@ 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 @@ -117,6 +116,7 @@ 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 diff --git a/wadsrc/static/zscript/hexen/bats.txt b/wadsrc/static/zscript/hexen/bats.txt new file mode 100644 index 0000000000..f96f932729 --- /dev/null +++ b/wadsrc/static/zscript/hexen/bats.txt @@ -0,0 +1,53 @@ + +// Bat Spawner -------------------------------------------------------------- + +class BatSpawner : SwitchableDecoration +{ + Default + { + +NOBLOCKMAP +NOSECTOR +NOGRAVITY + RenderStyle "None"; + } + + action native void A_BatSpawnInit(); + action native void 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 ---------------------------------------------------------------------- + +class Bat : Actor +{ + Default + { + Speed 5; + Radius 3; + Height 3; + +NOBLOCKMAP +NOGRAVITY +MISSILE + +NOTELEPORT +CANPASS + } + + action native void A_BatMove(); + + States + { + Spawn: + ABAT ABC 2 A_BatMove; + Loop; + Death: + ABAT A 2; + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/bishop.txt b/wadsrc/static/zscript/hexen/bishop.txt new file mode 100644 index 0000000000..4dbb0d2262 --- /dev/null +++ b/wadsrc/static/zscript/hexen/bishop.txt @@ -0,0 +1,166 @@ + +// Bishop ------------------------------------------------------------------- + +class Bishop : Actor +{ + 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"; + } + + action native void A_BishopChase(); + action native void A_BishopDecide(); + action native void A_BishopDoBlur(); + action native void A_BishopSpawnBlur(); + action native void A_BishopPainBlur(); + action native void A_BishopAttack(); + action native void 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 -------------------------------------------------------------- + +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 0000000000..17ac75dc32 --- /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 0000000000..4c14b69bc9 --- /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/clericboss.txt b/wadsrc/static/zscript/hexen/clericboss.txt new file mode 100644 index 0000000000..6493cde89c --- /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"; + } + + action 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/clericmace.txt b/wadsrc/static/zscript/hexen/clericmace.txt new file mode 100644 index 0000000000..5e00b9c3b7 --- /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/fighterboss.txt b/wadsrc/static/zscript/hexen/fighterboss.txt new file mode 100644 index 0000000000..aa3e28ce77 --- /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"; + } + + action 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/firedemon.txt b/wadsrc/static/zscript/hexen/firedemon.txt new file mode 100644 index 0000000000..f793034006 --- /dev/null +++ b/wadsrc/static/zscript/hexen/firedemon.txt @@ -0,0 +1,236 @@ + +// FireDemon ---------------------------------------------------------------- + +class FireDemon : Actor +{ + 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"; + } + + action native void A_FiredRocks(); + action native void A_FiredChase(); + action native void A_FiredAttack(); + action native void 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 ------------------------------------------------------- + +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 + } + + action native void A_SmBounce(); + + States + { + Spawn: + FDMN S 4; + Loop; + Death: + FDMN S 5 A_SmBounce; + XDeath: + FDMN S 200; + Stop; + } +} + +// 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/flechette.txt b/wadsrc/static/zscript/hexen/flechette.txt new file mode 100644 index 0000000000..4b3cd914c5 --- /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 + } + + action 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"; + } + + action 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"; + } + + action native void A_CheckThrowBomb(); + action 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"; + } + + action native void A_PoisonBagDamage(); + action 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"; + } + + action 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/fog.txt b/wadsrc/static/zscript/hexen/fog.txt new file mode 100644 index 0000000000..84cc6c03eb --- /dev/null +++ b/wadsrc/static/zscript/hexen/fog.txt @@ -0,0 +1,78 @@ + +// Fog Spawner -------------------------------------------------------------- + +class FogSpawner : Actor +{ + Default + { + +NOSECTOR +NOBLOCKMAP + +FLOATBOB + +NOGRAVITY + +INVISIBLE + } + + action 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; + } + + action 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/mageboss.txt b/wadsrc/static/zscript/hexen/mageboss.txt new file mode 100644 index 0000000000..083d210162 --- /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"; + } + + action 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/summon.txt b/wadsrc/static/zscript/hexen/summon.txt new file mode 100644 index 0000000000..395d4760d5 --- /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 + } + + action 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; + } +} From 1bdc1ccb6c8832be1558271fcd81d9365861b794 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 18 Oct 2016 18:11:13 +0200 Subject: [PATCH 067/471] - converted the remaining Hexen actors. --- wadsrc/static/actors/hexen/clericflame.txt | 196 ---------- wadsrc/static/actors/hexen/clericholy.txt | 237 ------------ wadsrc/static/actors/hexen/clericstaff.txt | 96 ----- wadsrc/static/actors/hexen/dragon.txt | 117 ------ wadsrc/static/actors/hexen/fighteraxe.txt | 113 ------ wadsrc/static/actors/hexen/fighterfist.txt | 64 ---- wadsrc/static/actors/hexen/fighterhammer.txt | 101 ----- wadsrc/static/actors/hexen/fighterquietus.txt | 164 -------- wadsrc/static/actors/hexen/healingradius.txt | 23 -- wadsrc/static/actors/hexen/heresiarch.txt | 335 ---------------- wadsrc/static/actors/hexen/iceguy.txt | 167 -------- wadsrc/static/actors/hexen/magecone.txt | 89 ----- wadsrc/static/actors/hexen/magelightning.txt | 154 -------- wadsrc/static/actors/hexen/magestaff.txt | 142 ------- wadsrc/static/actors/hexen/magewand.txt | 73 ---- wadsrc/static/actors/hexen/serpent.txt | 224 ----------- wadsrc/static/actors/hexen/spike.txt | 104 ----- wadsrc/static/actors/hexen/teleportother.txt | 112 ------ wadsrc/static/actors/hexen/wraith.txt | 218 ----------- wadsrc/static/actors/strife/strifestuff.txt | 4 +- wadsrc/static/decorate.txt | 20 - wadsrc/static/zscript.txt | 2 - wadsrc/static/zscript/hexen/clericflame.txt | 211 ++++++++++ wadsrc/static/zscript/hexen/clericholy.txt | 267 +++++++++++++ wadsrc/static/zscript/hexen/clericstaff.txt | 105 +++++ wadsrc/static/zscript/hexen/dragon.txt | 126 ++++++ wadsrc/static/zscript/hexen/fighteraxe.txt | 122 ++++++ wadsrc/static/zscript/hexen/fighterfist.txt | 70 ++++ wadsrc/static/zscript/hexen/fighterhammer.txt | 110 ++++++ .../static/zscript/hexen/fighterquietus.txt | 185 +++++++++ wadsrc/static/zscript/hexen/healingradius.txt | 26 ++ wadsrc/static/zscript/hexen/heresiarch.txt | 362 ++++++++++++++++++ wadsrc/static/zscript/hexen/iceguy.txt | 185 +++++++++ wadsrc/static/zscript/hexen/magecone.txt | 98 +++++ wadsrc/static/zscript/hexen/magelightning.txt | 169 ++++++++ wadsrc/static/zscript/hexen/magestaff.txt | 160 ++++++++ wadsrc/static/zscript/hexen/magewand.txt | 81 ++++ wadsrc/static/zscript/hexen/serpent.txt | 238 ++++++++++++ wadsrc/static/zscript/hexen/spike.txt | 116 ++++++ wadsrc/static/zscript/hexen/teleportother.txt | 130 +++++++ wadsrc/static/zscript/hexen/wraith.txt | 236 ++++++++++++ 41 files changed, 2999 insertions(+), 2753 deletions(-) delete mode 100644 wadsrc/static/actors/hexen/clericflame.txt delete mode 100644 wadsrc/static/actors/hexen/clericholy.txt delete mode 100644 wadsrc/static/actors/hexen/clericstaff.txt delete mode 100644 wadsrc/static/actors/hexen/dragon.txt delete mode 100644 wadsrc/static/actors/hexen/fighteraxe.txt delete mode 100644 wadsrc/static/actors/hexen/fighterfist.txt delete mode 100644 wadsrc/static/actors/hexen/fighterhammer.txt delete mode 100644 wadsrc/static/actors/hexen/fighterquietus.txt delete mode 100644 wadsrc/static/actors/hexen/healingradius.txt delete mode 100644 wadsrc/static/actors/hexen/heresiarch.txt delete mode 100644 wadsrc/static/actors/hexen/iceguy.txt delete mode 100644 wadsrc/static/actors/hexen/magecone.txt delete mode 100644 wadsrc/static/actors/hexen/magelightning.txt delete mode 100644 wadsrc/static/actors/hexen/magestaff.txt delete mode 100644 wadsrc/static/actors/hexen/magewand.txt delete mode 100644 wadsrc/static/actors/hexen/serpent.txt delete mode 100644 wadsrc/static/actors/hexen/spike.txt delete mode 100644 wadsrc/static/actors/hexen/teleportother.txt delete mode 100644 wadsrc/static/actors/hexen/wraith.txt create mode 100644 wadsrc/static/zscript/hexen/clericflame.txt create mode 100644 wadsrc/static/zscript/hexen/clericholy.txt create mode 100644 wadsrc/static/zscript/hexen/clericstaff.txt create mode 100644 wadsrc/static/zscript/hexen/dragon.txt create mode 100644 wadsrc/static/zscript/hexen/fighteraxe.txt create mode 100644 wadsrc/static/zscript/hexen/fighterfist.txt create mode 100644 wadsrc/static/zscript/hexen/fighterhammer.txt create mode 100644 wadsrc/static/zscript/hexen/fighterquietus.txt create mode 100644 wadsrc/static/zscript/hexen/healingradius.txt create mode 100644 wadsrc/static/zscript/hexen/heresiarch.txt create mode 100644 wadsrc/static/zscript/hexen/iceguy.txt create mode 100644 wadsrc/static/zscript/hexen/magecone.txt create mode 100644 wadsrc/static/zscript/hexen/magelightning.txt create mode 100644 wadsrc/static/zscript/hexen/magestaff.txt create mode 100644 wadsrc/static/zscript/hexen/magewand.txt create mode 100644 wadsrc/static/zscript/hexen/serpent.txt create mode 100644 wadsrc/static/zscript/hexen/spike.txt create mode 100644 wadsrc/static/zscript/hexen/teleportother.txt create mode 100644 wadsrc/static/zscript/hexen/wraith.txt diff --git a/wadsrc/static/actors/hexen/clericflame.txt b/wadsrc/static/actors/hexen/clericflame.txt deleted file mode 100644 index b6688a6edd..0000000000 --- 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 f24a846b39..0000000000 --- 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/clericstaff.txt b/wadsrc/static/actors/hexen/clericstaff.txt deleted file mode 100644 index bd848b5c6a..0000000000 --- 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/dragon.txt b/wadsrc/static/actors/hexen/dragon.txt deleted file mode 100644 index f6c3746f28..0000000000 --- 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/fighteraxe.txt b/wadsrc/static/actors/hexen/fighteraxe.txt deleted file mode 100644 index 28642c7d1b..0000000000 --- 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/fighterfist.txt b/wadsrc/static/actors/hexen/fighterfist.txt deleted file mode 100644 index b6a27332d5..0000000000 --- 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 d9932ae5f6..0000000000 --- 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/fighterquietus.txt b/wadsrc/static/actors/hexen/fighterquietus.txt deleted file mode 100644 index 8d784ebf53..0000000000 --- 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/healingradius.txt b/wadsrc/static/actors/hexen/healingradius.txt deleted file mode 100644 index cc921f59cd..0000000000 --- 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 4d32f701eb..0000000000 --- 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/iceguy.txt b/wadsrc/static/actors/hexen/iceguy.txt deleted file mode 100644 index 235be474fa..0000000000 --- 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/magecone.txt b/wadsrc/static/actors/hexen/magecone.txt deleted file mode 100644 index 72c37c38cd..0000000000 --- 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 d12b7d389d..0000000000 --- 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/magestaff.txt b/wadsrc/static/actors/hexen/magestaff.txt deleted file mode 100644 index 381588ce50..0000000000 --- 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 e9a1f339bc..0000000000 --- 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/serpent.txt b/wadsrc/static/actors/hexen/serpent.txt deleted file mode 100644 index 50d81bf8ac..0000000000 --- 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/spike.txt b/wadsrc/static/actors/hexen/spike.txt deleted file mode 100644 index eaadfe012d..0000000000 --- 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/teleportother.txt b/wadsrc/static/actors/hexen/teleportother.txt deleted file mode 100644 index 7ef86636d7..0000000000 --- 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 8d25bc74a8..0000000000 --- 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/strife/strifestuff.txt b/wadsrc/static/actors/strife/strifestuff.txt index 95d6d93cd5..3bbc1fb904 100644 --- a/wadsrc/static/actors/strife/strifestuff.txt +++ b/wadsrc/static/actors/strife/strifestuff.txt @@ -1675,8 +1675,8 @@ ACTOR Meat native ACTOR Junk : Meat { -states -{ + States + { Spawn: JUNK A 700 Stop diff --git a/wadsrc/static/decorate.txt b/wadsrc/static/decorate.txt index 88ce6a2c78..6ecac49c6b 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,23 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 570d6eee32..c4dac2b95a 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -116,7 +116,6 @@ 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 @@ -136,4 +135,3 @@ zscript/hexen/serpent.txt zscript/hexen/spike.txt zscript/hexen/wraith.txt zscript/hexen/heresiarch.txt -*/ \ No newline at end of file diff --git a/wadsrc/static/zscript/hexen/clericflame.txt b/wadsrc/static/zscript/hexen/clericflame.txt new file mode 100644 index 0000000000..ae5ecaac3e --- /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"; + } + + action 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"; + } + + action native void A_CFlamePuff(); + action 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 0000000000..b238ce09be --- /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 + } + + action 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"; + } + + action native void A_CHolySeek(); + action 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; + } + + action 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/clericstaff.txt b/wadsrc/static/zscript/hexen/clericstaff.txt new file mode 100644 index 0000000000..7ae0e9da37 --- /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/dragon.txt b/wadsrc/static/zscript/hexen/dragon.txt new file mode 100644 index 0000000000..bfc037e713 --- /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"; + } + + action native void A_DragonInitFlight(); + action native void A_DragonFlap(); + action native void A_DragonFlight(); + action native void A_DragonPain(); + action native void A_DragonAttack(); + action 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"; + } + + action 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/fighteraxe.txt b/wadsrc/static/zscript/hexen/fighteraxe.txt new file mode 100644 index 0000000000..30b235192d --- /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/fighterfist.txt b/wadsrc/static/zscript/hexen/fighterfist.txt new file mode 100644 index 0000000000..8428ebe7da --- /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 0000000000..f415cbb722 --- /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/fighterquietus.txt b/wadsrc/static/zscript/hexen/fighterquietus.txt new file mode 100644 index 0000000000..5fe132237a --- /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"; + } + + action 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/healingradius.txt b/wadsrc/static/zscript/hexen/healingradius.txt new file mode 100644 index 0000000000..94d8e2dd5c --- /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 0000000000..076bc01cac --- /dev/null +++ b/wadsrc/static/zscript/hexen/heresiarch.txt @@ -0,0 +1,362 @@ + +// 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"; + } + + action native void A_SorcSpinBalls(); + action native void A_SpeedBalls(); + action native void A_SorcBossAttack(); + action 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"; + } + + action native void A_SorcBallOrbit(); + action native void A_SorcBallPop(); + action native void A_BounceCheck (); +} + +// 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 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 -------------------------------- + +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: + 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 ------------------------------------- + +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: + 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) ---------------------- + +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"; + } + + action 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 + } + + action native void A_SorcFX2Split(); + action 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"; + } + + action native void A_SpawnBishop(); + action 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"; + } + + action 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/iceguy.txt b/wadsrc/static/zscript/hexen/iceguy.txt new file mode 100644 index 0000000000..635aea07f1 --- /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"; + } + + action native void A_IceGuyLook(); + action native void A_IceGuyChase(); + action 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"; + } + + action 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/magecone.txt b/wadsrc/static/zscript/hexen/magecone.txt new file mode 100644 index 0000000000..94452985cf --- /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"; + } + + action 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 0000000000..2c35a41e5a --- /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"; + } + + action native void A_LightningZap(); + action native void A_LightningClip(); + action 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"; + } + + action 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"; + } + + action 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/magestaff.txt b/wadsrc/static/zscript/hexen/magestaff.txt new file mode 100644 index 0000000000..b71c1e3dc7 --- /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"; + } + + action 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 0000000000..3feb96ae16 --- /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/serpent.txt b/wadsrc/static/zscript/hexen/serpent.txt new file mode 100644 index 0000000000..516d0c703b --- /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"; + } + + action native void A_SerpentHumpDecide(); + action native void A_SerpentHide(); + action native void A_SerpentCheckForAttack(); + action native void A_SerpentSpawnGibs(); + action native void A_SerpentUnHide(); + action native void A_SerpentRaiseHump(); + action native void A_SerpentLowerHump(); + action native void A_SerpentChooseAttack(); + action native void 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_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", "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 ----------------------------------------------------------- + +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 + } + + action 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 + } + + action native void A_FloatGib(); + action native void A_DelayGib(); + action 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/spike.txt b/wadsrc/static/zscript/hexen/spike.txt new file mode 100644 index 0000000000..2c8b4e80a3 --- /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; + } + + action native void A_ThrustRaise(); + action native void A_ThrustImpale(); + action native void A_ThrustLower(); + action native void A_ThrustInitDn(); + action 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/teleportother.txt b/wadsrc/static/zscript/hexen/teleportother.txt new file mode 100644 index 0000000000..90015b2075 --- /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; + } + + action native void A_TeloSpawnA(); + action native void A_TeloSpawnB(); + action native void A_TeloSpawnC(); + action native void A_TeloSpawnD(); + action 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 0000000000..a8b648a727 --- /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"; + } + + action native void A_WraithInit(); + action native void A_WraithChase(); + action native void A_WraithFX3(); + action 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", 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 ------------------------------------------------------------ + +class WraithBuried : Wraith +{ + Default + { + Height 68; + -SHOOTABLE + -SOLID + +DONTMORPH + +DONTBLAST + +SPECIALFLOORCLIP + +STAYMORPHED + +INVISIBLE + PainChance 0; + } + + action native void A_WraithRaiseInit(); + action 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"; + } + + action 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; + } +} From 5643831ccc320e530312909b163e322ccf4eb601 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 18 Oct 2016 23:05:58 +0200 Subject: [PATCH 068/471] - converted all Strife actors. --- wadsrc/static/actors/strife/acolyte.txt | 185 -- wadsrc/static/actors/strife/alienspectres.txt | 202 -- wadsrc/static/actors/strife/beggars.txt | 87 - wadsrc/static/actors/strife/coin.txt | 84 - wadsrc/static/actors/strife/crusader.txt | 122 - wadsrc/static/actors/strife/entityboss.txt | 199 -- wadsrc/static/actors/strife/inquisitor.txt | 141 -- wadsrc/static/actors/strife/loremaster.txt | 114 - wadsrc/static/actors/strife/macil.txt | 89 - wadsrc/static/actors/strife/merchants.txt | 93 - wadsrc/static/actors/strife/oracle.txt | 35 - wadsrc/static/actors/strife/peasants.txt | 182 -- wadsrc/static/actors/strife/programmer.txt | 107 - wadsrc/static/actors/strife/ratbuddy.txt | 34 - wadsrc/static/actors/strife/reaver.txt | 64 - wadsrc/static/actors/strife/rebels.txt | 131 -- wadsrc/static/actors/strife/sentinel.txt | 95 - wadsrc/static/actors/strife/sigil.txt | 161 -- wadsrc/static/actors/strife/spectral.txt | 262 --- wadsrc/static/actors/strife/stalker.txt | 76 - wadsrc/static/actors/strife/strifeammo.txt | 202 -- wadsrc/static/actors/strife/strifearmor.txt | 43 - wadsrc/static/actors/strife/strifebishop.txt | 94 - .../static/actors/strife/strifehumanoid.txt | 53 - wadsrc/static/actors/strife/strifeitems.txt | 519 ----- wadsrc/static/actors/strife/strifekeys.txt | 460 ---- wadsrc/static/actors/strife/strifeplayer.txt | 102 - wadsrc/static/actors/strife/strifestuff.txt | 1723 -------------- wadsrc/static/actors/strife/strifeweapons.txt | 813 ------- wadsrc/static/actors/strife/templar.txt | 66 - .../static/actors/strife/thingstoblowup.txt | 141 -- wadsrc/static/actors/strife/zombie.txt | 58 - wadsrc/static/decorate.txt | 33 - wadsrc/static/zscript.txt | 34 + wadsrc/static/zscript/strife/acolyte.txt | 218 ++ .../static/zscript/strife/alienspectres.txt | 223 ++ wadsrc/static/zscript/strife/beggars.txt | 90 + wadsrc/static/zscript/strife/coin.txt | 99 + wadsrc/static/zscript/strife/crusader.txt | 131 ++ wadsrc/static/zscript/strife/entityboss.txt | 211 ++ wadsrc/static/zscript/strife/inquisitor.txt | 150 ++ wadsrc/static/zscript/strife/loremaster.txt | 123 + wadsrc/static/zscript/strife/macil.txt | 95 + wadsrc/static/zscript/strife/merchants.txt | 108 + wadsrc/static/zscript/strife/oracle.txt | 38 + wadsrc/static/zscript/strife/peasants.txt | 251 +++ wadsrc/static/zscript/strife/programmer.txt | 116 + .../{actors => zscript}/strife/questitems.txt | 93 +- wadsrc/static/zscript/strife/ratbuddy.txt | 37 + wadsrc/static/zscript/strife/reaver.txt | 67 + wadsrc/static/zscript/strife/rebels.txt | 140 ++ wadsrc/static/zscript/strife/sentinel.txt | 104 + wadsrc/static/zscript/strife/sigil.txt | 178 ++ wadsrc/static/zscript/strife/spectral.txt | 307 +++ wadsrc/static/zscript/strife/stalker.txt | 79 + wadsrc/static/zscript/strife/strifeammo.txt | 235 ++ wadsrc/static/zscript/strife/strifearmor.txt | 49 + wadsrc/static/zscript/strife/strifebishop.txt | 99 + .../static/zscript/strife/strifehumanoid.txt | 58 + wadsrc/static/zscript/strife/strifeitems.txt | 597 +++++ wadsrc/static/zscript/strife/strifekeys.txt | 547 +++++ wadsrc/static/zscript/strife/strifeplayer.txt | 105 + wadsrc/static/zscript/strife/strifestuff.txt | 2002 +++++++++++++++++ .../static/zscript/strife/strifeweapons.txt | 891 ++++++++ wadsrc/static/zscript/strife/templar.txt | 68 + .../static/zscript/strife/thingstoblowup.txt | 153 ++ wadsrc/static/zscript/strife/zombie.txt | 64 + 67 files changed, 7718 insertions(+), 6812 deletions(-) delete mode 100644 wadsrc/static/actors/strife/acolyte.txt delete mode 100644 wadsrc/static/actors/strife/alienspectres.txt delete mode 100644 wadsrc/static/actors/strife/beggars.txt delete mode 100644 wadsrc/static/actors/strife/coin.txt delete mode 100644 wadsrc/static/actors/strife/crusader.txt delete mode 100644 wadsrc/static/actors/strife/entityboss.txt delete mode 100644 wadsrc/static/actors/strife/inquisitor.txt delete mode 100644 wadsrc/static/actors/strife/loremaster.txt delete mode 100644 wadsrc/static/actors/strife/macil.txt delete mode 100644 wadsrc/static/actors/strife/merchants.txt delete mode 100644 wadsrc/static/actors/strife/oracle.txt delete mode 100644 wadsrc/static/actors/strife/peasants.txt delete mode 100644 wadsrc/static/actors/strife/programmer.txt delete mode 100644 wadsrc/static/actors/strife/ratbuddy.txt delete mode 100644 wadsrc/static/actors/strife/reaver.txt delete mode 100644 wadsrc/static/actors/strife/rebels.txt delete mode 100644 wadsrc/static/actors/strife/sentinel.txt delete mode 100644 wadsrc/static/actors/strife/sigil.txt delete mode 100644 wadsrc/static/actors/strife/spectral.txt delete mode 100644 wadsrc/static/actors/strife/stalker.txt delete mode 100644 wadsrc/static/actors/strife/strifeammo.txt delete mode 100644 wadsrc/static/actors/strife/strifearmor.txt delete mode 100644 wadsrc/static/actors/strife/strifebishop.txt delete mode 100644 wadsrc/static/actors/strife/strifehumanoid.txt delete mode 100644 wadsrc/static/actors/strife/strifeitems.txt delete mode 100644 wadsrc/static/actors/strife/strifekeys.txt delete mode 100644 wadsrc/static/actors/strife/strifeplayer.txt delete mode 100644 wadsrc/static/actors/strife/strifestuff.txt delete mode 100644 wadsrc/static/actors/strife/strifeweapons.txt delete mode 100644 wadsrc/static/actors/strife/templar.txt delete mode 100644 wadsrc/static/actors/strife/thingstoblowup.txt delete mode 100644 wadsrc/static/actors/strife/zombie.txt create mode 100644 wadsrc/static/zscript/strife/acolyte.txt create mode 100644 wadsrc/static/zscript/strife/alienspectres.txt create mode 100644 wadsrc/static/zscript/strife/beggars.txt create mode 100644 wadsrc/static/zscript/strife/coin.txt create mode 100644 wadsrc/static/zscript/strife/crusader.txt create mode 100644 wadsrc/static/zscript/strife/entityboss.txt create mode 100644 wadsrc/static/zscript/strife/inquisitor.txt create mode 100644 wadsrc/static/zscript/strife/loremaster.txt create mode 100644 wadsrc/static/zscript/strife/macil.txt create mode 100644 wadsrc/static/zscript/strife/merchants.txt create mode 100644 wadsrc/static/zscript/strife/oracle.txt create mode 100644 wadsrc/static/zscript/strife/peasants.txt create mode 100644 wadsrc/static/zscript/strife/programmer.txt rename wadsrc/static/{actors => zscript}/strife/questitems.txt (51%) create mode 100644 wadsrc/static/zscript/strife/ratbuddy.txt create mode 100644 wadsrc/static/zscript/strife/reaver.txt create mode 100644 wadsrc/static/zscript/strife/rebels.txt create mode 100644 wadsrc/static/zscript/strife/sentinel.txt create mode 100644 wadsrc/static/zscript/strife/sigil.txt create mode 100644 wadsrc/static/zscript/strife/spectral.txt create mode 100644 wadsrc/static/zscript/strife/stalker.txt create mode 100644 wadsrc/static/zscript/strife/strifeammo.txt create mode 100644 wadsrc/static/zscript/strife/strifearmor.txt create mode 100644 wadsrc/static/zscript/strife/strifebishop.txt create mode 100644 wadsrc/static/zscript/strife/strifehumanoid.txt create mode 100644 wadsrc/static/zscript/strife/strifeitems.txt create mode 100644 wadsrc/static/zscript/strife/strifekeys.txt create mode 100644 wadsrc/static/zscript/strife/strifeplayer.txt create mode 100644 wadsrc/static/zscript/strife/strifestuff.txt create mode 100644 wadsrc/static/zscript/strife/strifeweapons.txt create mode 100644 wadsrc/static/zscript/strife/templar.txt create mode 100644 wadsrc/static/zscript/strife/thingstoblowup.txt create mode 100644 wadsrc/static/zscript/strife/zombie.txt diff --git a/wadsrc/static/actors/strife/acolyte.txt b/wadsrc/static/actors/strife/acolyte.txt deleted file mode 100644 index f190fb928f..0000000000 --- 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 0476fdfdf1..0000000000 --- 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 eca6e67f44..0000000000 --- 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 b410d25a17..0000000000 --- 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 c397474716..0000000000 --- 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 ddd19d9efb..0000000000 --- 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 5b9495d40f..0000000000 --- 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 fd2b400cb8..0000000000 --- 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 7c03d1f24b..0000000000 --- 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 1a843f47a3..0000000000 --- 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 8502bae96b..0000000000 --- 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 b5ec89258c..0000000000 --- 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 d9544af9c2..0000000000 --- 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 c6a1baf9c6..0000000000 --- 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 816070d475..0000000000 --- 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 2dcb5ac1ad..0000000000 --- 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 ca61f2bf80..0000000000 --- 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 4c5f552d5f..0000000000 --- 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 6f9c87c0c0..0000000000 --- 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 7f469e6103..0000000000 --- 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 e432a71448..0000000000 --- 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 3722d9338d..0000000000 --- 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 e64b247b17..0000000000 --- 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 7168065644..0000000000 --- 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 357d64ad5a..0000000000 --- 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 1a58505bb2..0000000000 --- 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 77135dcbf9..0000000000 --- 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 3bbc1fb904..0000000000 --- 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 b807f110a1..0000000000 --- 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 f15195c3d8..0000000000 --- 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 8f81488095..0000000000 --- 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 54683b824c..0000000000 --- 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 index 6ecac49c6b..2fc515af0c 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -1,36 +1,3 @@ -#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" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index c4dac2b95a..f65ae55550 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -135,3 +135,37 @@ 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 diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt new file mode 100644 index 0000000000..2f01cb836e --- /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"; + } + + action native void A_BeShadowyFoe (); + action native void A_AcolyteBits (); + action 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 + } + + action 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 0000000000..42c8293d0f --- /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 + } + + action 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 0000000000..e70a3a8e76 --- /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 0000000000..a930cb0ba9 --- /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 0000000000..334e9d803d --- /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"; + } + + action native void A_CrusaderChoose (); + action native void A_CrusaderSweepLeft (); + action native void A_CrusaderSweepRight (); + action native void A_CrusaderRefire (); + action 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 0000000000..d54a95a76e --- /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"; + } + + action 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"; + } + + action native void A_EntityAttack(); + action 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"; + } + + action 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 0000000000..5a053c74f3 --- /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"; + } + + action native void A_InquisitorWalk (); + action native void A_InquisitorDecide (); + action native void A_InquisitorAttack (); + action native void A_InquisitorJump (); + action native void A_InquisitorCheckLand (); + action native void A_TossArm (); + action 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 0000000000..d3b437bbdd --- /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"; + } + + action 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 0000000000..870f0db359 --- /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 0000000000..71b7976391 --- /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 0000000000..206dee1641 --- /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"; + } + + action 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 0000000000..6645c69fa6 --- /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 0000000000..cd577ff13c --- /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"; + } + + action native void A_ProgrammerMelee (); + action native void A_SpawnProgrammerBase (); + action native void A_ProgrammerDeath (); + action 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 11da7c90f1..4946f0414f 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 0000000000..fc0c9c63e0 --- /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 0000000000..0ce15fab81 --- /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"; + } + + action 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 0000000000..3ee0200dcc --- /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"; + } + + action 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 0000000000..8108265cb5 --- /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"; + } + + action 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 0000000000..d8b1f80f8a --- /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 0000000000..df23f3663e --- /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 + } + + action native void A_SpectreChunkSmall (); + action native void A_SpectreChunkLarge (); + action native void A_Spectre3Attack (); + action 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 + } + + action 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 + } + + action 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; + } + + action 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 0000000000..b22e432c68 --- /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"; + } + + action native void A_StalkerLookInit (); + action native void A_StalkerChaseDecide (); + action native void A_StalkerWalk (); + action native void A_StalkerDrop (); + action 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 0000000000..dcc31b2c71 --- /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 0000000000..8d2c7fad52 --- /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 0000000000..98b09eceed --- /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 0000000000..7ac776026c --- /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 0000000000..3d8b4af544 --- /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 "Shadow"; + 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 "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 ------------------------------------------------------------ + +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 "Targeter"; + 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 "Scanner"; + 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 0000000000..0241443847 --- /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 0000000000..311bf308af --- /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; + } + + action native void A_ItBurnsItBurns(); + action native void A_CrispyPlayer(); + action 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 0000000000..e72e8d9243 --- /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 0000000000..4ae358bfa6 --- /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"; + } + + action 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"; + } + + action 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"; + } + + action native void A_Burnarea (); + action 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, 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 --------------------------------------- + +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 0000000000..4c640fd541 --- /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"; + } + action 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 0000000000..659c13f56f --- /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"; + } + + action native void A_ExtraLightOff (); + action native void A_Explode512 (); + action 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 0000000000..c7a7cea593 --- /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; + } +} + From f6b3cdc23d6f40773baefa54b66892713ad7beb8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 18 Oct 2016 23:22:41 +0200 Subject: [PATCH 069/471] - converted the Chex Quest actors, completing the DECORATE conversion. --- wadsrc/static/actors/chex/chexammo.txt | 77 -------- wadsrc/static/actors/chex/chexdecorations.txt | 120 ------------ wadsrc/static/actors/chex/chexitems.txt | 59 ------ wadsrc/static/actors/chex/chexkeys.txt | 16 -- wadsrc/static/actors/chex/chexplayer.txt | 29 --- wadsrc/static/actors/chex/chexweapons.txt | 124 ------------ wadsrc/static/decorate.txt | 8 - wadsrc/static/zscript.txt | 8 + wadsrc/static/zscript/chex/chexammo.txt | 101 ++++++++++ .../static/zscript/chex/chexdecorations.txt | 180 ++++++++++++++++++ wadsrc/static/zscript/chex/chexitems.txt | 89 +++++++++ wadsrc/static/zscript/chex/chexkeys.txt | 25 +++ .../{actors => zscript}/chex/chexmonsters.txt | 68 ++++--- wadsrc/static/zscript/chex/chexplayer.txt | 32 ++++ wadsrc/static/zscript/chex/chexweapons.txt | 160 ++++++++++++++++ 15 files changed, 638 insertions(+), 458 deletions(-) delete mode 100644 wadsrc/static/actors/chex/chexammo.txt delete mode 100644 wadsrc/static/actors/chex/chexdecorations.txt delete mode 100644 wadsrc/static/actors/chex/chexitems.txt delete mode 100644 wadsrc/static/actors/chex/chexkeys.txt delete mode 100644 wadsrc/static/actors/chex/chexplayer.txt delete mode 100644 wadsrc/static/actors/chex/chexweapons.txt delete mode 100644 wadsrc/static/decorate.txt create mode 100644 wadsrc/static/zscript/chex/chexammo.txt create mode 100644 wadsrc/static/zscript/chex/chexdecorations.txt create mode 100644 wadsrc/static/zscript/chex/chexitems.txt create mode 100644 wadsrc/static/zscript/chex/chexkeys.txt rename wadsrc/static/{actors => zscript}/chex/chexmonsters.txt (62%) create mode 100644 wadsrc/static/zscript/chex/chexplayer.txt create mode 100644 wadsrc/static/zscript/chex/chexweapons.txt diff --git a/wadsrc/static/actors/chex/chexammo.txt b/wadsrc/static/actors/chex/chexammo.txt deleted file mode 100644 index 27c5d419b4..0000000000 --- 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 6515061c5f..0000000000 --- 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 431728e073..0000000000 --- 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 0d5156392e..0000000000 --- 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 210a684707..0000000000 --- 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 0cdb968491..0000000000 --- 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/decorate.txt b/wadsrc/static/decorate.txt deleted file mode 100644 index 2fc515af0c..0000000000 --- a/wadsrc/static/decorate.txt +++ /dev/null @@ -1,8 +0,0 @@ - -#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/zscript.txt b/wadsrc/static/zscript.txt index f65ae55550..6de64d07e5 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -169,3 +169,11 @@ 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/chex/chexammo.txt b/wadsrc/static/zscript/chex/chexammo.txt new file mode 100644 index 0000000000..23c3cccd5f --- /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 0000000000..2db19181dd --- /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 0000000000..fc5d4c8174 --- /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 0000000000..5ac28330eb --- /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 0ee3c34c57..22e3977027 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 0000000000..43f7fc1eee --- /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 0000000000..a4c862d64c --- /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; + } +} From 665d7526867f52b12d62d861643c0042e797e165 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Oct 2016 00:35:34 +0200 Subject: [PATCH 070/471] - added 'null' token to the ZScript parser which is needed for null pointers. - removed function declaration parser from DECORATE because it is not needed anymore. - fixed: comparison operators could not handle names. --- src/sc_man_scanner.re | 1 + src/sc_man_tokens.h | 1 + src/scripting/codegeneration/codegen.cpp | 20 +- src/scripting/decorate/thingdef_parse.cpp | 264 ---------------------- src/scripting/zscript/zcc-parse.lemon | 7 + src/scripting/zscript/zcc_exprlist.h | 1 + src/scripting/zscript/zcc_parser.cpp | 1 + 7 files changed, 23 insertions(+), 272 deletions(-) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index ba0e9a8e53..caeb18f8cc 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -171,6 +171,7 @@ std2: '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 934558d547..69927883cb 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -106,6 +106,7 @@ xx(TK_Optional, "'optional'") xx(TK_Export, "'expert'") xx(TK_Virtual, "'virtual'") xx(TK_Super, "'super'") +xx(TK_Null, "'null'") xx(TK_Global, "'global'") xx(TK_Self, "'self'") xx(TK_Stop, "'stop'") diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index bc503d8324..7687be371d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1888,16 +1888,20 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) { ValueType = TypeBool; } + else if (left->ValueType == TypeName && right->ValueType == TypeName) + { + ValueType = TypeName; + } else if (left->IsNumeric() && right->IsNumeric()) { - if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) - { - ValueType = TypeSInt32; - } + if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) + { + ValueType = TypeSInt32; + } else - { - ValueType = TypeFloat64; - } + { + ValueType = TypeFloat64; + } } else if (left->ValueType->GetRegType() == REGT_POINTER && left->ValueType == right->ValueType) { @@ -2395,7 +2399,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) return NULL; } - if (!IsNumeric() && !IsPointer()) + if (!IsNumeric() && !IsPointer() && ValueType != TypeName) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index f416d6103b..bd4885c87b 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -334,213 +334,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(';'); -} - -//========================================================================== -// -// 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; - TArray argnames; - - 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, &argnames, cls, funcflags); - // This function will be removed once all internal classes have been ported so don't bother filling in the function's argument names, because for anything going through here they'll never be used. - ParseArgListDef(sc, cls, args, argflags); - - if (afd != NULL) - { - PFunction *sym = new PFunction(cls, funcname); - sym->AddVariant(NewPrototype(rets, args), argflags, argnames, *(afd->VMPointer), 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 @@ -1081,55 +874,6 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) } } -//========================================================================== -// -// ActorActionDef -// -// Parses an action function definition. A lot of this is essentially -// documentation in the declaration for when I have a proper language -// ready. -// -//========================================================================== - -static void ParseActionDef (FScanner &sc, PClassActor *cls) -{ - 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++; - } - - sc.MustGetToken(TK_Native); - // check for a return value - do - { - if (sc.CheckToken(TK_Bool)) - { - rets.Push(TypeBool); - } - else if (sc.CheckToken(TK_Int)) - { - rets.Push(TypeSInt32); - } - else if (sc.CheckToken(TK_State)) - { - rets.Push(TypeState); - } - else if (sc.CheckToken(TK_Float)) - { - rets.Push(TypeFloat64); - } - } - while (sc.CheckToken(',')); - sc.MustGetToken(TK_Identifier); - funcname = sc.String; - ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action); -} - //========================================================================== // // Starts a new actor definition @@ -1330,10 +1074,6 @@ static void ParseActor(FScanner &sc) { switch (sc.TokenType) { - case TK_Action: - ParseActionDef (sc, info); - break; - case TK_Const: ParseConstant (sc, &info->Symbols, info); break; @@ -1342,10 +1082,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; diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 1e10103a06..595f2a3182 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -956,6 +956,13 @@ primary(X) ::= IDENTIFIER(A). expr->Type = NULL; X = expr; } +primary(X) ::= NULL(T). +{ + NEW_AST_NODE(Expression, expr, T); + expr->Operation = PEX_Null; + expr->Type = NULL; + X = expr; +} primary(X) ::= SUPER(T). { NEW_AST_NODE(Expression, expr, T); diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index 46a1b9c690..eeabb10e5d 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -3,6 +3,7 @@ xx(Nil, ) xx(ID, ) xx(Super, ) +xx(Null, ) xx(Self, ) xx(ConstValue, ) xx(FuncCall, ) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 9fefa537d0..48fd28f453 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -153,6 +153,7 @@ static void InitTokenMap() TOKENDEF (TK_Out, ZCC_OUT); TOKENDEF (TK_Optional, ZCC_OPTIONAL); TOKENDEF (TK_Super, ZCC_SUPER); + TOKENDEF (TK_Null, ZCC_NULL); TOKENDEF (TK_Self, ZCC_SELF); TOKENDEF ('~', ZCC_TILDE); TOKENDEF ('!', ZCC_BANG); From 33567741f5c3b0bc80dd7d208db5857989ac0e5d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Oct 2016 10:38:25 +0200 Subject: [PATCH 071/471] - fixed: The parser was not generating a compound statement node for anonymous action functions. --- src/scripting/zscript/zcc-parse.lemon | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 595f2a3182..45b7a99ffe 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -522,7 +522,12 @@ light_list(X) ::= light_list(A) COMMA STRCONST(B). } /* 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 error scanner_mode RBRACE. { X = NULL; } state_action(X) ::= state_call(A) scanner_mode SEMICOLON. { X = A; /*X-overwrites-A*/ } From cfbcfc440d134f6ed6642b45456bce449b6c0864 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Oct 2016 13:07:44 +0200 Subject: [PATCH 072/471] - 'fixed' local variable declrations to work like C, not like some Lua-inspired nightmare. Also added proper initialization syntax for arrays. --- src/scripting/zscript/ast.cpp | 13 ++++- src/scripting/zscript/zcc-parse.lemon | 70 +++++++++++++++++++++++++-- src/scripting/zscript/zcc_parser.h | 10 +++- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index 45b8053ba6..2f15c019e4 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -437,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; @@ -762,7 +773,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(); } @@ -859,6 +869,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintStateGoto, PrintStateLine, PrintVarName, + PrintVarInit, PrintType, PrintBasicType, PrintMapType, diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 45b7a99ffe..43d7d02ab4 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -1637,15 +1637,75 @@ assign_op(X) ::= XOREQ(T). { X.Int = ZCC_XOREQ; X.SourceLoc = T.SourceLoc; } %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_parser.h b/src/scripting/zscript/zcc_parser.h index 5dae72ee0e..503ef7e9e3 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -62,6 +62,7 @@ enum EZCCTreeNodeType AST_StateGoto, AST_StateLine, AST_VarName, + AST_VarInit, AST_Type, AST_BasicType, AST_MapType, @@ -294,6 +295,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 @@ -446,8 +453,7 @@ 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 From 458c68775f4adee9df0f57081296c6d1c0d4e67e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Oct 2016 14:36:54 +0200 Subject: [PATCH 073/471] - fixed handling of loop statements. All break and continue statements were collected in one list, and each loop statement taking hold of that entire list, including the breaks and continues from previous outer loops. Changed it so that loop statements contain the jump addresses themselves and set a pointer in FCompileContext, so that the jump point can be set directly in the loop statement - and an error printed if there is none in the resolving stage, not the emitting one. Consolidated the identical backpatching code of the three loop statement nodes into a subfunction. --- src/scripting/codegeneration/codegen.cpp | 112 +++++++++-------------- src/scripting/codegeneration/codegen.h | 17 ++-- 2 files changed, 52 insertions(+), 77 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7687be371d..d5c70f493d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5185,23 +5185,36 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) return ExpEmit(); } - //========================================================================== // -// FxLoopStatement +// 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. // //========================================================================== -void FxLoopStatement::HandleJumps(int token, FCompileContext &ctx) +FxExpression *FxLoopStatement::Resolve(FCompileContext &ctx) { - for (unsigned int i = 0; i < ctx.Jumps.Size(); i++) + 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 (ctx.Jumps[i]->Token == token) + if (Jumps[i]->Token == TK_Break) { - ctx.Jumps[i]->AddressResolver = this; - JumpAddresses.Push(ctx.Jumps[i]); - ctx.Jumps.Delete(i); - i--; + build->Backpatch(Jumps[i]->Address, loopend); + } + else + { // Continue statement. + build->Backpatch(Jumps[i]->Address, loopstart); } } } @@ -5224,15 +5237,12 @@ FxWhileLoop::~FxWhileLoop() SAFE_DELETE(Code); } -FxExpression *FxWhileLoop::Resolve(FCompileContext &ctx) +FxExpression *FxWhileLoop::DoResolve(FCompileContext &ctx) { CHECKRESOLVED(); SAFE_RESOLVE(Condition, ctx); SAFE_RESOLVE_OPT(Code, ctx); - HandleJumps(TK_Break, ctx); - HandleJumps(TK_Continue, ctx); - if (Condition->ValueType != TypeBool) { Condition = new FxBoolCast(Condition); @@ -5291,19 +5301,7 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) 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); - } - } - + Backpatch(build, loopstart, loopend); return ExpEmit(); } @@ -5325,15 +5323,12 @@ FxDoWhileLoop::~FxDoWhileLoop() SAFE_DELETE(Code); } -FxExpression *FxDoWhileLoop::Resolve(FCompileContext &ctx) +FxExpression *FxDoWhileLoop::DoResolve(FCompileContext &ctx) { CHECKRESOLVED(); SAFE_RESOLVE(Condition, ctx); SAFE_RESOLVE_OPT(Code, ctx); - HandleJumps(TK_Break, ctx); - HandleJumps(TK_Continue, ctx); - if (Condition->ValueType != TypeBool) { Condition = new FxBoolCast(Condition); @@ -5344,7 +5339,7 @@ FxExpression *FxDoWhileLoop::Resolve(FCompileContext &ctx) { if (static_cast(Condition)->GetValue().GetBool() == false) { // The code executes once, if any. - if (JumpAddresses.Size() == 0) + if (Jumps.Size() == 0) { // We would still have to handle the jumps however. FxExpression *e = Code; if (e == nullptr) e = new FxNop(ScriptPosition); @@ -5393,18 +5388,7 @@ ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) } 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); - } - } + Backpatch(build, loopstart, loopend); return ExpEmit(); } @@ -5429,7 +5413,7 @@ FxForLoop::~FxForLoop() SAFE_DELETE(Code); } -FxExpression *FxForLoop::Resolve(FCompileContext &ctx) +FxExpression *FxForLoop::DoResolve(FCompileContext &ctx) { CHECKRESOLVED(); SAFE_RESOLVE_OPT(Init, ctx); @@ -5437,9 +5421,6 @@ FxExpression *FxForLoop::Resolve(FCompileContext &ctx) SAFE_RESOLVE_OPT(Iteration, ctx); SAFE_RESOLVE_OPT(Code, ctx); - HandleJumps(TK_Break, ctx); - HandleJumps(TK_Continue, ctx); - if (Condition != nullptr) { if (Condition->ValueType != TypeBool) @@ -5480,7 +5461,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) size_t codestart; size_t jumpspot; - // Init statement. + // 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); @@ -5520,19 +5501,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) 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); - } - } - + Backpatch(build, loopstart, loopend); return ExpEmit(); } @@ -5543,7 +5512,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) //========================================================================== FxJumpStatement::FxJumpStatement(int token, const FScriptPosition &pos) -: FxExpression(pos), Token(token), AddressResolver(nullptr) +: FxExpression(pos), Token(token) { ValueType = TypeVoid; } @@ -5552,18 +5521,21 @@ FxExpression *FxJumpStatement::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); - ctx.Jumps.Push(this); - - return this; + 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) { - 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(); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 1a2d2045d1..c4e1753bd5 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -62,10 +62,11 @@ class FxJumpStatement; // //========================================================================== struct FScriptPosition; +class FxLoopStatement; struct FCompileContext { - TArray Jumps; + FxLoopStatement *Loop; PPrototype *ReturnProto; PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) PClass *Class; // The type of the owning class. @@ -1127,9 +1128,12 @@ protected: { } - void HandleJumps(int token, FCompileContext &ctx); + void Backpatch(VMFunctionBuilder *build, size_t loopstart, size_t loopend); + FxExpression *Resolve(FCompileContext&) final; + virtual FxExpression *DoResolve(FCompileContext&) = 0; - TArray JumpAddresses; +public: + TArray Jumps; }; //========================================================================== @@ -1146,7 +1150,7 @@ class FxWhileLoop : public FxLoopStatement public: FxWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos); ~FxWhileLoop(); - FxExpression *Resolve(FCompileContext&); + FxExpression *DoResolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1164,7 +1168,7 @@ class FxDoWhileLoop : public FxLoopStatement public: FxDoWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos); ~FxDoWhileLoop(); - FxExpression *Resolve(FCompileContext&); + FxExpression *DoResolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1184,7 +1188,7 @@ class FxForLoop : public FxLoopStatement public: FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos); ~FxForLoop(); - FxExpression *Resolve(FCompileContext&); + FxExpression *DoResolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1203,7 +1207,6 @@ public: int Token; size_t Address; - FxExpression *AddressResolver; }; //========================================================================== From 8a6230d64a23a8c51e5dc519322ceddc0ca51032 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Oct 2016 16:15:02 +0200 Subject: [PATCH 074/471] - Renamed FxSequence to FxCompoundStatement. - fixed: The state parser was unable to accept empty anonymous functions, which should be treated as if there is none at all. --- src/scripting/codegeneration/codegen.cpp | 12 ++++++------ src/scripting/codegeneration/codegen.h | 6 +++--- src/scripting/decorate/thingdef_states.cpp | 6 +++--- src/scripting/zscript/zcc-parse.lemon | 4 ++++ src/scripting/zscript/zcc_compile.cpp | 2 +- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d5c70f493d..7a7ff7f130 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5016,11 +5016,11 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) //========================================================================== // -// FxSequence :: Resolve +// FxCompoundStatement :: Resolve // //========================================================================== -FxExpression *FxSequence::Resolve(FCompileContext &ctx) +FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); for (unsigned i = 0; i < Expressions.Size(); ++i) @@ -5036,11 +5036,11 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx) //========================================================================== // -// FxSequence :: Emit +// FxCompoundStatement :: Emit // //========================================================================== -ExpEmit FxSequence::Emit(VMFunctionBuilder *build) +ExpEmit FxCompoundStatement::Emit(VMFunctionBuilder *build) { for (unsigned i = 0; i < Expressions.Size(); ++i) { @@ -5053,11 +5053,11 @@ ExpEmit FxSequence::Emit(VMFunctionBuilder *build) //========================================================================== // -// FxSequence :: GetDirectFunction +// FxCompoundStatement :: GetDirectFunction // //========================================================================== -VMFunction *FxSequence::GetDirectFunction() +VMFunction *FxCompoundStatement::GetDirectFunction() { if (Expressions.Size() == 1) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index c4e1753bd5..57a6d42579 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -1079,16 +1079,16 @@ public: //========================================================================== // -// FxSequence +// FxCompoundStatement // //========================================================================== -class FxSequence : public FxExpression +class FxCompoundStatement : public FxExpression { TDeletingArray Expressions; public: - FxSequence(const FScriptPosition &pos) : FxExpression(pos) {} + FxCompoundStatement(const FScriptPosition &pos) : FxExpression(pos) {} FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); } diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 59ec3e39d4..11db1504d5 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -314,7 +314,7 @@ do_stop: ScriptCode = ParseActions(sc, state, statestring, bag, hasfinalret); if (!hasfinalret && ScriptCode != nullptr) { - static_cast(ScriptCode)->Add(new FxReturnStatement(nullptr, sc)); + static_cast(ScriptCode)->Add(new FxReturnStatement(nullptr, sc)); } goto endofstate; } @@ -474,7 +474,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(); @@ -536,7 +536,7 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg { if (seq == NULL) { - seq = new FxSequence(pos); + seq = new FxCompoundStatement(pos); } seq->Add(add); } diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 43d7d02ab4..0c493d54aa 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -528,6 +528,10 @@ state_action(X) ::= LBRACE(T) statement_list(A) scanner_mode RBRACE. 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*/ } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 43219acb1e..e86a7c959e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2087,7 +2087,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a tcall->Code = ParseActions(sc, state, statestring, bag, hasfinalret); if (!hasfinalret && tcall->Code != nullptr) { - static_cast(tcall->Code)->Add(new FxReturnStatement(nullptr, sc)); + static_cast(tcall->Code)->Add(new FxReturnStatement(nullptr, sc)); } */ From 2d85efce2ad0ae4150223979e26997f8d11e3f87 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Oct 2016 19:05:48 +0200 Subject: [PATCH 075/471] - added processing of compound statements to the compiler. This means that anonymous functions without control statements are generating code now. - added local variable declarations to the code generator. This is not tested yet, that will come with the next commit. --- src/scripting/codegeneration/codegen.cpp | 141 ++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 38 +++++- src/scripting/thingdef.h | 1 + src/scripting/zscript/zcc_compile.cpp | 57 ++++++++- 4 files changed, 232 insertions(+), 5 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7a7ff7f130..d115cbbd80 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5023,14 +5023,18 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + Outer = ctx.Block; + ctx.Block = this; for (unsigned i = 0; i < Expressions.Size(); ++i) { if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx))) { + ctx.Block = Outer; delete this; - return NULL; + return nullptr; } } + ctx.Block = Outer; return this; } @@ -5048,6 +5052,11 @@ ExpEmit FxCompoundStatement::Emit(VMFunctionBuilder *build) // Throw away any result. We don't care about it. v.Free(build); } + // Release all local variables in this block. + for (auto l : LocalVars) + { + l->Release(build); + } return ExpEmit(); } @@ -5066,6 +5075,52 @@ VMFunction *FxCompoundStatement::GetDirectFunction() return NULL; } +//========================================================================== +// +// FxCompoundStatement :: FindLocalVariable +// +// Looks for a variable name in any of the containing compound statements +// +//========================================================================== + +FxLocalVariableDeclaration *FxCompoundStatement::FindLocalVariable(FName name) +{ + auto block = this; + while (block != nullptr) + { + for (auto l : block->LocalVars) + { + if (l->Name == name) + { + return l; + } + } + block = block->Outer; + } + 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; +} + //========================================================================== // // FxIfStatement @@ -6142,3 +6197,87 @@ ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build) return ExpEmit(); } + +//========================================================================== +// +// declares a single local variable (no arrays) +// +//========================================================================== + +FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p) + :FxExpression(p) +{ + ValueType = type; + Name = name; + Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false); +} + +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(1); + } + 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, build->GetConstantInt(constval->GetValue().GetInt()), RegNum); + break; + + case REGT_FLOAT: + build->Emit(OP_LKF, build->GetConstantFloat(constval->GetValue().GetFloat()), RegNum); + break; + + case REGT_POINTER: + build->Emit(OP_LKP, build->GetConstantAddress(constval->GetValue().GetPointer(), ATAG_GENERIC), RegNum); + break; + + case REGT_STRING: + build->Emit(OP_LKS, build->GetConstantString(constval->GetValue().GetString()), RegNum); + } + emitval.Free(build); + } + else + { + // take over the register that got allocated while emitting the Init expression. + RegNum = emitval.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, 1); +} diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 57a6d42579..75cdadf8d3 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -63,10 +63,12 @@ class FxJumpStatement; //========================================================================== struct FScriptPosition; class FxLoopStatement; +class FxCompoundStatement; struct FCompileContext { - FxLoopStatement *Loop; + FxLoopStatement *Loop = nullptr; + FxCompoundStatement *Block = nullptr; PPrototype *ReturnProto; PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) PClass *Class; // The type of the owning class. @@ -162,6 +164,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()) : ""; @@ -1082,10 +1090,15 @@ public: // FxCompoundStatement // //========================================================================== +class FxLocalVariableDeclaration; class FxCompoundStatement : public FxExpression { + TArray LocalVars; TDeletingArray Expressions; + FxCompoundStatement *Outer = nullptr; + + friend class FxLocalVariableDeclaration; public: FxCompoundStatement(const FScriptPosition &pos) : FxExpression(pos) {} @@ -1093,6 +1106,8 @@ public: ExpEmit Emit(VMFunctionBuilder *build); void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); } VMFunction *GetDirectFunction(); + FxLocalVariableDeclaration *FindLocalVariable(FName name); + bool CheckLocalVariable(FName name); }; //========================================================================== @@ -1341,7 +1356,26 @@ public: } }; -FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve = false); +//========================================================================== +// +// +// +//========================================================================== +class FxLocalVariableDeclaration : public FxExpression +{ + friend class FxCompoundStatement; + + FName Name; + FxExpression *Init; + int RegNum = -1; + +public: + FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); + void Release(VMFunctionBuilder *build); + +}; #endif diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 7c2b90e506..bdee476ee4 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -144,6 +144,7 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) 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); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e86a7c959e..e641524afc 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2313,8 +2313,27 @@ void ZCCCompiler::CompileStates() FxExpression *ZCCCompiler::ConvertAST(ZCC_TreeNode *ast) { - // FxReturnStatement will have to be done more intelligently, of course. - return new FxReturnStatement(ConvertNode(ast), *ast); + // 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) + { + return new FxReturnStatement(ConvertNode(ast), *ast); + } + 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; + } } FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) @@ -2514,8 +2533,42 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) return new FxConditional(condition, left, right); } + + case AST_ExpressionStmt: + return ConvertNode(static_cast(ast)->Expression); + + case AST_ReturnStmt: + { + auto ret = static_cast(ast); + FArgumentList *args = ConvertNodeList(ret->Values); + if (args->Size() == 0) + { + return new FxReturnStatement(nullptr, *ast); + } + else if (args->Size() == 1) + { + return new FxReturnStatement((*args)[0], *ast); + } + else + { + Error(ast, "Return with multiple values not implemented yet."); + return new FxReturnStatement(nullptr, *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; From ffc38d422ea1ee7f8bbebc7238a6672288bc0c47 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 20 Oct 2016 01:09:35 +0200 Subject: [PATCH 076/471] - split up FxCompoundStatement into the old FxSequence and a new subclass. FxSequence is just a sequence of expressions, while FxCompoundStatement is the one that actually implements handling of local variables. The split was done so that ZCCCompiler::ConvertNode can return multiple statements as one object and for that FxCompoundStatement is not suitable. - added conversion of local variable declarations. This is still untested --- src/scripting/codegeneration/codegen.cpp | 89 +++++++++++++++--------- src/scripting/codegeneration/codegen.h | 28 ++++++-- src/scripting/zscript/zcc_compile.cpp | 33 +++++++++ 3 files changed, 112 insertions(+), 38 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d115cbbd80..4554a830b3 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5014,6 +5014,58 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) 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 nullptr; + } + } + 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; +} + //========================================================================== // // FxCompoundStatement :: Resolve @@ -5023,18 +5075,11 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + auto outer = ctx.Block; Outer = ctx.Block; ctx.Block = this; - for (unsigned i = 0; i < Expressions.Size(); ++i) - { - if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx))) - { - ctx.Block = Outer; - delete this; - return nullptr; - } - } - ctx.Block = Outer; + auto x = FxSequence::Resolve(ctx); + ctx.Block = outer; return this; } @@ -5046,33 +5091,13 @@ FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx) ExpEmit FxCompoundStatement::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); - } + auto e = FxSequence::Emit(build); // Release all local variables in this block. for (auto l : LocalVars) { l->Release(build); } - return ExpEmit(); -} - -//========================================================================== -// -// FxCompoundStatement :: GetDirectFunction -// -//========================================================================== - -VMFunction *FxCompoundStatement::GetDirectFunction() -{ - if (Expressions.Size() == 1) - { - return Expressions[0]->GetDirectFunction(); - } - return NULL; + return e; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 75cdadf8d3..eeabf891e1 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -1087,25 +1087,41 @@ public: //========================================================================== // -// FxCompoundStatement +// FxSequence (a list of statements with no semantics attached - used to return multiple nodes as one) // //========================================================================== class FxLocalVariableDeclaration; -class FxCompoundStatement : public FxExpression +class FxSequence : public FxExpression +{ + TDeletingArray Expressions; + +public: + FxSequence(const FScriptPosition &pos) : FxExpression(pos) {} + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); + void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); } + VMFunction *GetDirectFunction(); +}; + +//========================================================================== +// +// FxCompoundStatement (like a list but implements maintenance of local variables) +// +//========================================================================== +class FxLocalVariableDeclaration; + +class FxCompoundStatement : public FxSequence { TArray LocalVars; - TDeletingArray Expressions; FxCompoundStatement *Outer = nullptr; friend class FxLocalVariableDeclaration; public: - FxCompoundStatement(const FScriptPosition &pos) : FxExpression(pos) {} + FxCompoundStatement(const FScriptPosition &pos) : FxSequence(pos) {} FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); - void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); } - VMFunction *GetDirectFunction(); FxLocalVariableDeclaration *FindLocalVariable(FName name); bool CheckLocalVariable(FName name); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e641524afc..33830d1352 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2534,6 +2534,39 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) return new FxConditional(condition, left, right); } + 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, *node)); + } + + node = static_cast(node->SiblingNext); + } while (node != loc->Vars); + return list; + } + case AST_ExpressionStmt: return ConvertNode(static_cast(ast)->Expression); From 24394dfc924b17abc0581e2d6c022be42d1a6c0d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 20 Oct 2016 16:55:12 +0200 Subject: [PATCH 077/471] - tested and fixed FxLocalVariableDeclaration. - create proper variable data from the function prototype instead of assuming that there's just 3 pointers. - added a printable name to VMScriptFunction for error output during gameplay in case something goes wrong. --- src/dobjtype.cpp | 3 ++- src/scripting/codegeneration/codegen.cpp | 13 +++++++-- src/scripting/codegeneration/codegen.h | 9 ++++--- src/scripting/vm/vm.h | 1 + src/scripting/vm/vmbuilder.cpp | 34 ++++++++++++++---------- src/scripting/vm/vmbuilder.h | 2 +- src/scripting/zscript/zcc_compile.cpp | 13 --------- 7 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 317694e206..f25e592f2f 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2545,7 +2545,8 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra variant.Flags = flags; variant.Proto = proto; - variant.ArgFlags = argflags; + variant.ArgFlags = std::move(argflags); + variant.ArgNames = std::move(argnames); variant.Implementation = impl; if (impl != nullptr) impl->Proto = proto; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4554a830b3..9b6248c88e 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5074,7 +5074,6 @@ VMFunction *FxSequence::GetDirectFunction() FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx) { - CHECKRESOLVED(); auto outer = ctx.Block; Outer = ctx.Block; ctx.Block = this; @@ -5105,10 +5104,12 @@ ExpEmit FxCompoundStatement::Emit(VMFunctionBuilder *build) // 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) +FxLocalVariableDeclaration *FxCompoundStatement::FindLocalVariable(FName name, FCompileContext &ctx) { auto block = this; while (block != nullptr) @@ -5122,6 +5123,14 @@ FxLocalVariableDeclaration *FxCompoundStatement::FindLocalVariable(FName name) } block = block->Outer; } + // finally check the context for function arguments + for (auto arg : ctx.FunctionArgs) + { + if (arg->Name == name) + { + return arg; + } + } return nullptr; } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index eeabf891e1..c16c45f42e 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -64,6 +64,7 @@ class FxJumpStatement; struct FScriptPosition; class FxLoopStatement; class FxCompoundStatement; +class FxLocalVariableDeclaration; struct FCompileContext { @@ -73,6 +74,7 @@ struct FCompileContext PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) PClass *Class; // The type of the owning class. bool FromDecorate; + TDeletingArray FunctionArgs; FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate); FCompileContext(PClass *cls); // only to be used to resolve constants! @@ -191,8 +193,7 @@ struct ExpVal 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(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), Konst(konst), Fixed(fixed), Final(false) {} ExpEmit(VMFunctionBuilder *build, int type); void Free(VMFunctionBuilder *build); void Reuse(VMFunctionBuilder *build); @@ -1122,7 +1123,7 @@ public: FxCompoundStatement(const FScriptPosition &pos) : FxSequence(pos) {} FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); - FxLocalVariableDeclaration *FindLocalVariable(FName name); + FxLocalVariableDeclaration *FindLocalVariable(FName name, FCompileContext &ctx); bool CheckLocalVariable(FName name); }; @@ -1384,9 +1385,9 @@ class FxLocalVariableDeclaration : public FxExpression FName Name; FxExpression *Init; +public: int RegNum = -1; -public: FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 425eba531f..8cd63f3e51 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -789,6 +789,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 diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 7e946a17c3..5e5ce85db1 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -663,7 +663,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c Item it; it.Func = functype; it.Code = code; - it.DumpName = name; + it.PrintableName = name; it.Function = new VMScriptFunction; it.Proto = nullptr; it.FromDecorate = fromdecorate; @@ -684,39 +684,45 @@ void FFunctionBuildList::Build() { assert(item.Code != NULL); - // This needs to be fixed, so that the compile context receives the entire function symbol, including the containing class, the prototype and argument names, which will be needed to run the code generator - // As a first step this just needs to get working so fetch the class type from the prototype's argument list. // We don't know the return type in advance for anonymous functions. - FCompileContext ctx(item.Func, nullptr, item.FromDecorate); + FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate); + + // Allocate registers for the function's arguments and create local variable nodes before starting to resolve it. + VMFunctionBuilder buildit(true); + 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]; + // this won't get resolved and won't get emitted. This is only needed so that the code generator can retrieve the necessary info to do its work. + auto local = new FxLocalVariableDeclaration(type, name, nullptr, FScriptPosition()); + local->RegNum = buildit.Registers[type->GetRegType()].Get(1); + ctx.FunctionArgs.Push(local); + } + item.Code = item.Code->Resolve(ctx); item.Proto = ctx.ReturnProto; // Make sure resolving it didn't obliterate it. if (item.Code != nullptr) { - VMFunctionBuilder buildit(true); - assert(item.Proto != nullptr); - auto numargs = item.Func->Variants[0].Proto->ArgumentTypes.Size(); // Generate prototype for this anonymous function - // Fixme: This later needs to do proper allocation for the function's entire argument list, once non-anonymous functions can be done. - buildit.Registers[REGT_POINTER].Get(numargs); - VMScriptFunction *sfunc = item.Function; // create a new prototype from the now known return type and the argument list of the function's template prototype. - item.Function->Proto = NewPrototype(item.Proto->ReturnTypes, item.Func->Variants[0].Proto->ArgumentTypes); + sfunc->Proto = NewPrototype(item.Proto->ReturnTypes, item.Func->Variants[0].Proto->ArgumentTypes); // Emit code item.Code->Emit(&buildit); - buildit.MakeFunction(item.Function); - item.Function->NumArgs = numargs; + buildit.MakeFunction(sfunc); + sfunc->NumArgs = item.Func->Variants[0].Proto->ArgumentTypes.Size(); if (dump != nullptr) { - DumpFunction(dump, sfunc, item.DumpName.GetChars(), (int)item.DumpName.Len()); + DumpFunction(dump, sfunc, item.PrintableName.GetChars(), (int)item.PrintableName.Len()); codesize += sfunc->CodeSize; } + sfunc->PrintableName = item.PrintableName; } delete item.Code; } diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index c5ca868e08..dcaae72518 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -105,7 +105,7 @@ class FFunctionBuildList FxExpression *Code = nullptr; PPrototype *Proto = nullptr; VMScriptFunction *Function = nullptr; - FString DumpName; + FString PrintableName; bool FromDecorate; }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 33830d1352..88486d9c35 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2078,19 +2078,6 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a } ConvertClass = cls; return ConvertAST(af); - - //Error(af, "Complex action functions not supported yet."); - //return nullptr; - - /* - bool hasfinalret; - tcall->Code = ParseActions(sc, state, statestring, bag, hasfinalret); - if (!hasfinalret && tcall->Code != nullptr) - { - static_cast(tcall->Code)->Add(new FxReturnStatement(nullptr, sc)); - } - */ - } //========================================================================== From 9f99ca478890b1b50698233a84888b8dcdb5de27 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 21 Oct 2016 01:12:54 +0200 Subject: [PATCH 078/471] - process most of the remaining statement types. - extend assignment operations to handle local variables (untested.) - make the implicit function arguments read only. --- src/dobjtype.cpp | 56 ++++++++++ src/dobjtype.h | 9 +- src/scripting/codegeneration/codegen.cpp | 135 +++++++++++++++++++---- src/scripting/codegeneration/codegen.h | 25 ++++- src/scripting/thingdef.cpp | 6 +- src/scripting/vm/vmbuilder.cpp | 5 +- src/scripting/vm/vmexec.h | 20 ++-- src/scripting/zscript/zcc_compile.cpp | 63 ++++++++++- 8 files changed, 277 insertions(+), 42 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index f25e592f2f..ded832f2df 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -500,6 +500,18 @@ int PType::GetLoadOp() const return OP_NOP; } +//========================================================================== +// +// PType :: GetMoveOp +// +//========================================================================== + +int PType::GetMoveOp() const +{ + assert(0 && "Cannot move this type"); + return OP_NOP; +} + //========================================================================== // // PType :: GetRegType @@ -974,6 +986,17 @@ int PInt::GetLoadOp() const } } +//========================================================================== +// +// PInt :: GetLoadOp +// +//========================================================================== + +int PInt::GetMoveOp() const +{ + return OP_MOVE; +} + //========================================================================== // // PInt :: GetRegType @@ -1271,6 +1294,17 @@ int PFloat::GetLoadOp() const return OP_NOP; } +//========================================================================== +// +// PFloat :: GetMoveOp +// +//========================================================================== + +int PFloat::GetMoveOp() const +{ + return OP_MOVEF; +} + //========================================================================== // // PFloat :: GetRegType @@ -1540,6 +1574,17 @@ int PStatePointer::GetLoadOp() const return OP_LP; } +//========================================================================== +// +// PStatePointer :: GetMoveOp +// +//========================================================================== + +int PStatePointer::GetMoveOp() const +{ + return OP_MOVEA; +} + //========================================================================== // // PStatePointer :: GetRegType @@ -1627,6 +1672,17 @@ int PPointer::GetLoadOp() const return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP; } +//========================================================================== +// +// PPointer :: GetMoveOp +// +//========================================================================== + +int PPointer::GetMoveOp() const +{ + return OP_MOVEA; +} + //========================================================================== // // PPointer :: GetRegType diff --git a/src/dobjtype.h b/src/dobjtype.h index fd6e078eab..4a15078fd2 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -28,7 +28,7 @@ enum 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 when checking function signatures) + 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.) }; @@ -272,6 +272,9 @@ public: // Gets the opcode to load from memory to a register virtual int GetLoadOp() const; + // Gets the opcode to move from register to another register + virtual int GetMoveOp() const; + // Gets the register type for this type virtual int GetRegType() const; @@ -409,6 +412,7 @@ public: virtual double GetValueFloat(void *addr) const; virtual int GetStoreOp() const; virtual int GetLoadOp() const; + virtual int GetMoveOp() const; virtual int GetRegType() const; bool Unsigned; @@ -438,6 +442,7 @@ public: virtual double GetValueFloat(void *addr) const; virtual int GetStoreOp() const; virtual int GetLoadOp() const; + virtual int GetMoveOp() const; virtual int GetRegType() const; protected: PFloat(); @@ -516,6 +521,7 @@ public: virtual int GetStoreOp() const; virtual int GetLoadOp() const; + virtual int GetMoveOp() const; virtual int GetRegType() const; }; @@ -530,6 +536,7 @@ public: virtual int GetStoreOp() const; virtual int GetLoadOp() const; + virtual int GetMoveOp() const; virtual int GetRegType() const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9b6248c88e..d3e7ef0299 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -160,6 +160,18 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) } } +FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name) +{ + if (Block == nullptr) + { + return nullptr; + } + else + { + return Block->FindLocalVariable(name, *this); + } +} + //========================================================================== // // ExpEmit @@ -1611,9 +1623,13 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) int zero = build->GetConstantInt(0); int regtype = ValueType->GetRegType(); ExpEmit pointer = Base->Emit(build); + ExpEmit value = pointer; - ExpEmit value(build, regtype); - build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero); + if (!pointer.Target) + { + value = ExpEmit(build, regtype); + build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero); + } if (regtype == REGT_INT) { @@ -1624,7 +1640,10 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) 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 (!pointer.Target) + { + build->Emit(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero); + } if (AddressRequested) { @@ -1690,9 +1709,13 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) int zero = build->GetConstantInt(0); int regtype = ValueType->GetRegType(); ExpEmit pointer = Base->Emit(build); + ExpEmit out = pointer; - ExpEmit out(build, regtype); - build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero); + if (!pointer.Target) + { + out = ExpEmit(build, regtype); + build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero); + } ExpEmit assign(build, regtype); if (regtype == REGT_INT) @@ -1704,7 +1727,10 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) 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); + if (!pointer.Target) + { + build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero); + } pointer.Free(build); assign.Free(build); @@ -1781,6 +1807,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) ExpEmit FxAssign::Emit(VMFunctionBuilder *build) { + static const BYTE loadops[] = { OP_NOP, OP_LK, OP_LKF, OP_LKS, OP_LKP }; assert(ValueType == Base->ValueType && IsNumeric()); assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); @@ -1788,16 +1815,31 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *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; - } + assert(result.RegType <= REGT_TYPE); - build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); + 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; + } + + build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); + } if (AddressRequested) { @@ -1837,9 +1879,16 @@ 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; + if (!pointer.Target) + { + ExpEmit out(build, ValueType->GetRegType()); + build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0)); + return out; + } + else + { + return pointer; + } } //========================================================================== @@ -3858,8 +3907,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) 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); + } // 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; if ((sym = ctx.FindInClass(Identifier, symtbl)) != nullptr) @@ -3959,6 +4015,40 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } +//========================================================================== +// +// +// +//========================================================================== + +FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptPosition &sc) + : FxExpression(sc) +{ + Variable = var; + AddressRequested = false; +} + +FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + return this; +} + +bool FxLocalVariable::RequestAddress(bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = !(Variable->VarFlags & VARF_ReadOnly); + return true; +} + +ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) +{ + ExpEmit ret(Variable->RegNum, Variable->ValueType->GetRegType(), false, true); + if (AddressRequested) ret.Target = true; + return ret; +} + + //========================================================================== // // @@ -3998,9 +4088,7 @@ FxExpression *FxSelf::Resolve(FCompileContext& ctx) 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; + return ExpEmit(0, REGT_POINTER, false, true); } @@ -6238,10 +6326,11 @@ ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build) // //========================================================================== -FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p) +FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p) :FxExpression(p) { ValueType = type; + VarFlags = varflags; Name = name; Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false); } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index c16c45f42e..7a69f39896 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -85,6 +85,7 @@ struct FCompileContext void HandleJumps(int token, FxExpression *handler); void CheckReturn(PPrototype *proto, FScriptPosition &pos); + FxLocalVariableDeclaration *FindLocalVariable(FName name); }; //========================================================================== @@ -198,7 +199,7 @@ struct ExpEmit void Free(VMFunctionBuilder *build); void Reuse(VMFunctionBuilder *build); - BYTE RegNum, RegType, Konst:1, Fixed:1, Final:1; + BYTE RegNum, RegType, Konst:1, Fixed:1, Final:1, Target:1; }; //========================================================================== @@ -964,6 +965,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxLocalVariable +// +//========================================================================== + +class FxLocalVariable : public FxExpression +{ +public: + FxLocalVariableDeclaration *Variable; + bool AddressRequested; + + FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); + FxExpression *Resolve(FCompileContext&); + bool RequestAddress(bool *writable); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxSelf @@ -1382,13 +1401,15 @@ public: class FxLocalVariableDeclaration : public FxExpression { friend class FxCompoundStatement; + friend class FxLocalVariable; FName Name; FxExpression *Init; + int VarFlags; public: int RegNum = -1; - FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p); + FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index fc281e8e8a..7fcb0ce39d 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -90,7 +90,7 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArrayPush(NewPointer(cls)); - if (argflags != nullptr) argflags->Push(VARF_Implicit); + if (argflags != nullptr) argflags->Push(VARF_Implicit | VARF_ReadOnly); if (argnames != nullptr) argnames->Push(NAME_self); } if (funcflags & VARF_Action) @@ -111,8 +111,8 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArrayPush(VARF_Implicit); - argflags->Push(VARF_Implicit); + argflags->Push(VARF_Implicit | VARF_ReadOnly); + argflags->Push(VARF_Implicit | VARF_ReadOnly); } if (argnames != nullptr) { diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 5e5ce85db1..0ba6974950 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -693,8 +693,9 @@ void FFunctionBuildList::Build() { auto type = item.Func->Variants[0].Proto->ArgumentTypes[i]; auto name = item.Func->Variants[0].ArgNames[i]; - // this won't get resolved and won't get emitted. This is only needed so that the code generator can retrieve the necessary info to do its work. - auto local = new FxLocalVariableDeclaration(type, name, nullptr, FScriptPosition()); + 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(1); ctx.FunctionArgs.Push(local); } diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 9dbea7c51b..db4afa05ac 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -194,7 +194,7 @@ begin: 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]; reg.f[a+2] = v[2]; @@ -204,7 +204,7 @@ begin: 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]; @@ -290,20 +290,20 @@ begin: 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]; + v[2] = reg.f[B+2]; } NEXTOP; OP(SV_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]; + v[2] = reg.f[B+2]; } NEXTOP; OP(SBIT): diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 88486d9c35..d5b3a27050 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -42,6 +42,7 @@ #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" @@ -2344,11 +2345,42 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // The function name is a simple identifier. return new FxFunctionCall(static_cast(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast); + // not yet done + case AST_ExprTypeRef: + case AST_SwitchStmt: + case AST_CaseStmt: case AST_ExprMemberAccess: // calling a class member through its pointer // todo. break; + case AST_AssignStmt: + { + auto assign = static_cast(ast); + switch (assign->AssignOp) + { + case ZCC_EQ: + // this ignores multi-assign statements (these should probably be disabled in the grammar.) + return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources)); + + case ZCC_MULEQ: + case ZCC_DIVEQ: + case ZCC_MODEQ: + case ZCC_ADDEQ: + case ZCC_SUBEQ: + case ZCC_LSHEQ: + case ZCC_RSHEQ: + case ZCC_ANDEQ: + case ZCC_OREQ: + case ZCC_XOREQ: + //break; + default: + Error(ast, "Invalid assign statement"); + + } + break; + } + 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) @@ -2546,7 +2578,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) { val = node->Init ? ConvertNode(node->Init) : nullptr; } - list->Add(new FxLocalVariableDeclaration(type, node->Name, val, *node)); + list->Add(new FxLocalVariableDeclaration(type, node->Name, val, 0, *node)); // todo: Handle flags in the grammar. } node = static_cast(node->SiblingNext); @@ -2576,6 +2608,35 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *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); + } + } + + case AST_CompoundStmt: { auto x = new FxCompoundStatement(*ast); From 1450c3dffb1e432cf4baccbe9218c310c9ba0bc9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 21 Oct 2016 10:09:01 +0200 Subject: [PATCH 079/471] - tested and fixed the regular assignment statement for both local and member variables. The generated object code can definitely use an optimization pass but that's something left for later when more things are working. Right now it creates one opcode more than necessary for all member accesses (instead of using the offset in the store command it calculates an actual address of the variable in another address register) and can create one too many for non-constant expressions being assigned to local variables (a move between two registers because the emitted expression on the right hand side does not know that it can emit to the actual variable's register.) --- src/scripting/codegeneration/codegen.cpp | 13 +++--- src/scripting/codegeneration/codegen.h | 4 +- src/scripting/vm/vmbuilder.cpp | 4 ++ src/scripting/zscript/zcc_compile.cpp | 54 ++++++++++++------------ 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d3e7ef0299..1b169411fd 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -179,7 +179,7 @@ FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name) //========================================================================== ExpEmit::ExpEmit(VMFunctionBuilder *build, int type) -: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false), Final(false) +: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false), Final(false), Target(false) { } @@ -1807,16 +1807,16 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) ExpEmit FxAssign::Emit(VMFunctionBuilder *build) { - static const BYTE loadops[] = { OP_NOP, OP_LK, OP_LKF, OP_LKS, OP_LKP }; + static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; assert(ValueType == Base->ValueType && IsNumeric()); assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); - ExpEmit pointer = Base->Emit(build); - Address = pointer; - ExpEmit result = Right->Emit(build); assert(result.RegType <= REGT_TYPE); + ExpEmit pointer = Base->Emit(build); + Address = pointer; + if (pointer.Target) { if (result.Konst) @@ -4025,6 +4025,7 @@ FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptP : FxExpression(sc) { Variable = var; + ValueType = var->ValueType; AddressRequested = false; } @@ -5167,7 +5168,7 @@ FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx) ctx.Block = this; auto x = FxSequence::Resolve(ctx); ctx.Block = outer; - return this; + return x; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 7a69f39896..5253252764 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -193,8 +193,8 @@ struct ExpVal struct ExpEmit { - ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false), Final(false) {} - ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), Konst(konst), Fixed(fixed), Final(false) {} + ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false), Final(false), Target(false) {} + ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), Konst(konst), Fixed(fixed), Final(false), Target(false) {} ExpEmit(VMFunctionBuilder *build, int type); void Free(VMFunctionBuilder *build); void Reuse(VMFunctionBuilder *build); diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 0ba6974950..a5f15b262b 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -682,6 +682,10 @@ void FFunctionBuildList::Build() for (auto &item : mItems) { + if (item.PrintableName.CompareNoCase("Middle.StateFunction.3") == 0) + { + int a = 0; + } assert(item.Code != NULL); // We don't know the return type in advance for anonymous functions. diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index d5b3a27050..eb039f996c 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2354,33 +2354,6 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // todo. break; - case AST_AssignStmt: - { - auto assign = static_cast(ast); - switch (assign->AssignOp) - { - case ZCC_EQ: - // this ignores multi-assign statements (these should probably be disabled in the grammar.) - return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources)); - - case ZCC_MULEQ: - case ZCC_DIVEQ: - case ZCC_MODEQ: - case ZCC_ADDEQ: - case ZCC_SUBEQ: - case ZCC_LSHEQ: - case ZCC_RSHEQ: - case ZCC_ANDEQ: - case ZCC_OREQ: - case ZCC_XOREQ: - //break; - default: - Error(ast, "Invalid assign statement"); - - } - break; - } - 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) @@ -2400,6 +2373,33 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) break; } + case AST_AssignStmt: + { + auto assign = static_cast(ast); + switch (assign->AssignOp) + { + case ZCC_EQ: + // this ignores multi-assign statements (these should probably be disabled in the grammar.) + return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources)); + + case ZCC_MULEQ: + case ZCC_DIVEQ: + case ZCC_MODEQ: + case ZCC_ADDEQ: + case ZCC_SUBEQ: + case ZCC_LSHEQ: + case ZCC_RSHEQ: + case ZCC_ANDEQ: + case ZCC_OREQ: + case ZCC_XOREQ: + //break; + default: + Error(ast, "Invalid assign statement"); + + } + break; + } + case AST_FuncParm: { auto fparm = static_cast(ast); From 3e995d7aac7620848e7058e3a03748e145162cce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 21 Oct 2016 12:22:42 +0200 Subject: [PATCH 080/471] - changed assignment operators to be expressions, like they are in C and DECORATE. This also means that for now Lua-style multi-assignments are disabled, those should be easy to enable by making some changes to the assignment_statement grammar so that it doesn't recognize single assignments, but for now this is low priority because it adds a significant amount of complexity to do this right with functions that have multiple return values. --- src/scripting/zscript/ast.cpp | 15 ----- src/scripting/zscript/zcc-parse.lemon | 87 +++++++++++++++++++++------ src/scripting/zscript/zcc_compile.cpp | 46 ++++++-------- src/scripting/zscript/zcc_exprlist.h | 13 ++++ src/scripting/zscript/zcc_parser.cpp | 1 + 5 files changed, 102 insertions(+), 60 deletions(-) diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index 2f15c019e4..e23fc5a879 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -747,21 +747,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(); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 0c493d54aa..42c3014c13 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -104,7 +104,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) %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. @@ -1247,6 +1247,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). { @@ -1402,7 +1463,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; } @@ -1553,7 +1614,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 -----*/ @@ -1614,28 +1674,19 @@ 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" -----*/ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index eb039f996c..b2c58c1240 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2373,33 +2373,6 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) break; } - case AST_AssignStmt: - { - auto assign = static_cast(ast); - switch (assign->AssignOp) - { - case ZCC_EQ: - // this ignores multi-assign statements (these should probably be disabled in the grammar.) - return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources)); - - case ZCC_MULEQ: - case ZCC_DIVEQ: - case ZCC_MODEQ: - case ZCC_ADDEQ: - case ZCC_SUBEQ: - case ZCC_LSHEQ: - case ZCC_RSHEQ: - case ZCC_ANDEQ: - case ZCC_OREQ: - case ZCC_XOREQ: - //break; - default: - Error(ast, "Invalid assign statement"); - - } - break; - } - case AST_FuncParm: { auto fparm = static_cast(ast); @@ -2526,6 +2499,23 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_NEQ: return new FxCompareEq(op == PEX_NEQ ? TK_Neq : TK_Eq, left, right); + case PEX_Assign: + return new FxAssign(left, right); +/* + case ZCC_MULEQ: + case ZCC_DIVEQ: + case ZCC_MODEQ: + case ZCC_ADDEQ: + case ZCC_SUBEQ: + case ZCC_LSHEQ: + case ZCC_RSHEQ: + case ZCC_ANDEQ: + case ZCC_OREQ: + case ZCC_XOREQ: + //break; + default: + Error(ast, "Invalid assign statement"); +*/ // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_LTGTEQ: @@ -2537,6 +2527,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // vector operations will be done later. case PEX_CrossProduct: case PEX_DotProduct: + + default: I_Error("Binary operator %d not implemented yet", op); } diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index eeabb10e5d..5c9936988c 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -53,6 +53,19 @@ xx(BitXor, ) xx(BoolAnd, ) xx(BoolOr, ) +xx(Assign, ) +xx(AddAssign, ) +xx(SubAssign, ) +xx(MulAssign, ) +xx(DivAssign, ) +xx(ModAssign, ) +xx(LshAssign, ) +xx(RshAssign, ) +xx(URshAssign, ) +xx(AndAssign, ) +xx(OrAssign, ) +xx(XorAssign, ) + xx(Scope, ) xx(Trinary, ) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 48fd28f453..222e8e6c53 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -73,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); From 9f260983c752586b5a1eb71923f6573a1eb2493d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 21 Oct 2016 14:18:31 +0200 Subject: [PATCH 081/471] - implemented all assign/modify operators. - use a table to translate from PEX to tokens to make the code easier to read. --- src/scripting/codegeneration/codegen.cpp | 8 +- src/scripting/zscript/zcc_compile.cpp | 78 +++++++++----- src/scripting/zscript/zcc_exprlist.h | 124 +++++++++++------------ 3 files changed, 120 insertions(+), 90 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 1b169411fd..9deeeaed27 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1550,7 +1550,7 @@ FxExpression *FxSizeAlign::Resolve(FCompileContext& ctx) } else { - FxExpression *x = new FxConstant(Which == 'a' ? int(type->Align) : int(type->Size), Operand->ScriptPosition); + FxExpression *x = new FxConstant(Which == TK_AlignOf ? int(type->Align) : int(type->Size), Operand->ScriptPosition); delete this; return x->Resolve(ctx); } @@ -1811,12 +1811,12 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) assert(ValueType == Base->ValueType && IsNumeric()); assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); - ExpEmit result = Right->Emit(build); - assert(result.RegType <= REGT_TYPE); - ExpEmit pointer = Base->Emit(build); Address = pointer; + ExpEmit result = Right->Emit(build); + assert(result.RegType <= REGT_TYPE); + if (pointer.Target) { if (result.Konst) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index b2c58c1240..297ac2ef0b 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2324,6 +2324,33 @@ FxExpression *ZCCCompiler::ConvertAST(ZCC_TreeNode *ast) } } + +#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); + assignself->Assignment = assignment; + return assignment; +} + + +//========================================================================== +// +// Convert an AST node and its children +// +//========================================================================== + FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) { // Note: Do not call 'Simplify' here because that function tends to destroy identifiers due to lack of context in which to resolve them. @@ -2426,11 +2453,11 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) { case PEX_PostDec: case PEX_PostInc: - return new FxPostIncrDecr(operand, op == PEX_PostDec ? TK_Decr : TK_Incr); + return new FxPostIncrDecr(operand, Pex2Tok[op]); case PEX_PreDec: case PEX_PreInc: - return new FxPreIncrDecr(operand, op == PEX_PostDec ? TK_Decr : TK_Incr); + return new FxPreIncrDecr(operand, Pex2Tok[op]); case PEX_Negate: return new FxMinusSign(operand); @@ -2446,7 +2473,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_SizeOf: case PEX_AlignOf: - return new FxSizeAlign(operand, op == PEX_AlignOf ? 'a' : 's'); + return new FxSizeAlign(operand, Pex2Tok[op]); default: assert(0 && "Unknown unary operator."); // should never happen @@ -2463,16 +2490,17 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *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(op == PEX_Add ? '+' : '-', left, right); + return new FxAddSub(tok, left, right); case PEX_Mul: case PEX_Div: case PEX_Mod: - return new FxMulDiv(op == PEX_Mul ? '*' : op == PEX_Div ? '/' : '%', left, right); + return new FxMulDiv(tok, left, right); case PEX_Pow: return new FxPow(left, right); @@ -2483,39 +2511,41 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_BitAnd: case PEX_BitOr: case PEX_BitXor: - return new FxBinaryInt(op == PEX_LeftShift ? TK_LShift : op == PEX_RightShift ? TK_RShift : op == PEX_URightShift ? TK_URShift : op == PEX_BitAnd ? '&' : op == PEX_BitOr ? '|' : '^', left, right); + return new FxBinaryInt(tok, left, right); case PEX_BoolOr: case PEX_BoolAnd: - return new FxBinaryLogical(op == PEX_BoolAnd ? TK_AndAnd : TK_OrOr, left, right); + return new FxBinaryLogical(tok, left, right); case PEX_LT: case PEX_LTEQ: case PEX_GT: case PEX_GTEQ: - return new FxCompareRel(op == PEX_LT ? '<' : op == PEX_RightShift ? '>' : op == PEX_LTEQ ? TK_Leq : TK_Geq, left, right); + return new FxCompareRel(tok, left, right); case PEX_EQEQ: case PEX_NEQ: - return new FxCompareEq(op == PEX_NEQ ? TK_Neq : TK_Eq, left, right); + return new FxCompareEq(tok, left, right); case PEX_Assign: return new FxAssign(left, right); -/* - case ZCC_MULEQ: - case ZCC_DIVEQ: - case ZCC_MODEQ: - case ZCC_ADDEQ: - case ZCC_SUBEQ: - case ZCC_LSHEQ: - case ZCC_RSHEQ: - case ZCC_ANDEQ: - case ZCC_OREQ: - case ZCC_XOREQ: - //break; - default: - Error(ast, "Invalid assign statement"); -*/ + + 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); // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_LTGTEQ: diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index 5c9936988c..4770a08a47 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -1,75 +1,75 @@ -// Name n-ary -xx(Nil, ) +// Name Token used in the code generator +xx(Nil, TK_None) -xx(ID, ) -xx(Super, ) -xx(Null, ) -xx(Self, ) -xx(ConstValue, ) -xx(FuncCall, ) -xx(ArrayAccess, ) -xx(MemberAccess, ) -xx(TypeRef, ) +xx(ID, TK_Identifier) +xx(Super, TK_Super) +xx(Null, TK_Null) +xx(Self, TK_Self) +xx(ConstValue, TK_Const) +xx(FuncCall, '(') +xx(ArrayAccess, TK_Array) +xx(MemberAccess, '.') +xx(TypeRef, TK_Class) -xx(PostInc, ) -xx(PostDec, ) +xx(PostInc, TK_Incr) +xx(PostDec, TK_Decr) -xx(PreInc, ) -xx(PreDec, ) -xx(Negate, ) -xx(AntiNegate, ) -xx(BitNot, ) -xx(BoolNot, ) -xx(SizeOf, ) -xx(AlignOf, ) +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, ) -xx(CrossProduct, ) -xx(DotProduct, ) -xx(LeftShift, ) -xx(RightShift, ) -xx(URightShift, ) -xx(Concat, ) +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, ) -xx(GT, ) -xx(GTEQ, ) -xx(LTGTEQ, ) -xx(Is, ) +xx(LT, '<') +xx(LTEQ, TK_Leq) +xx(GT, '>') +xx(GTEQ, TK_Geq) +xx(LTGTEQ, TK_LtGtEq) +xx(Is, TK_Is) -xx(EQEQ, ) -xx(NEQ, ) -xx(APREQ, ) +xx(EQEQ, TK_Eq) +xx(NEQ, TK_Neq) +xx(APREQ, TK_ApproxEq) -xx(BitAnd, ) -xx(BitOr, ) -xx(BitXor, ) -xx(BoolAnd, ) -xx(BoolOr, ) +xx(BitAnd, '&') +xx(BitOr, '|') +xx(BitXor, '^') +xx(BoolAnd, TK_AndAnd) +xx(BoolOr, TK_OrOr) -xx(Assign, ) -xx(AddAssign, ) -xx(SubAssign, ) -xx(MulAssign, ) -xx(DivAssign, ) -xx(ModAssign, ) -xx(LshAssign, ) -xx(RshAssign, ) -xx(URshAssign, ) -xx(AndAssign, ) -xx(OrAssign, ) -xx(XorAssign, ) +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, ) +xx(Scope, TK_ColonColon) -xx(Trinary, ) +xx(Trinary, '?') -xx(Cast, ) +xx(Cast, TK_Coerce) #undef xx From f5e4c4b1096aa8d9e8b2e880a49016409fd4465e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 21 Oct 2016 16:35:07 +0200 Subject: [PATCH 082/471] - implemented the '<>=' operator - more as a VM coding exercise than for its usefulness, though. --- src/scripting/codegeneration/codegen.cpp | 92 ++++++++++++++++++++++++ src/scripting/codegeneration/codegen.h | 15 ++++ src/scripting/zscript/zcc_compile.cpp | 4 +- 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9deeeaed27..4bde29ac66 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2678,6 +2678,98 @@ ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build) // //========================================================================== +FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r) + : FxBinary(TK_LtGtEq, l, r) +{ + ValueType = TypeSInt32; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + if (!ResolveLR(ctx, false)) return NULL; + + 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(l->ScriptPosition) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 5253252764..6bcc328301 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -769,6 +769,21 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxLtGtEq : public FxBinary +{ +public: + FxLtGtEq(FxExpression*, FxExpression*); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxBinaryLogical diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 297ac2ef0b..52d21784e3 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2547,8 +2547,10 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_XorAssign: return ModifyAssign(new FxBinaryInt(tok, new FxAssignSelf(*ast), right), left); - // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_LTGTEQ: + return new FxLtGtEq(left, right); + + // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_Concat: case PEX_Is: // more esoteric operators From 5bed0a2b3973a69ba9dd6f8bf2ac98d308050ae1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 21 Oct 2016 17:41:39 +0200 Subject: [PATCH 083/471] - implemented class member access for variables. (Struct members and functions not done yet.) --- src/namedef.h | 1 + src/scripting/codegeneration/codegen.cpp | 152 ++++++++++++++++++----- src/scripting/codegeneration/codegen.h | 17 +++ src/scripting/thingdef_data.cpp | 2 + src/scripting/zscript/zcc_compile.cpp | 17 ++- 5 files changed, 153 insertions(+), 36 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index 43856aad16..d512a79486 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -436,6 +436,7 @@ xx(Scale) xx(ScaleX) xx(ScaleY) xx(Floatbobphase) +xx(Target) xx(Blocking) xx(Blockmonsters) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4bde29ac66..a271d240a4 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4019,7 +4019,12 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else if (sym->IsKindOf(RUNTIME_CLASS(PField))) { - ABORT(ctx.Function); // only valid when resolving a function. + if (!ctx.Function) + { + ScriptPosition.Message(MSG_ERROR, "Cannot resolve class member outside a function", sym->SymbolName.GetChars()); + delete this; + return nullptr; + } PField *vsym = static_cast(sym); // We have 4 cases to consider here: @@ -4029,11 +4034,11 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) // 4. This is a normal member or unrestricted action function. if (vsym->Flags & VARF_Deprecated) { - ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", sym->SymbolName.GetChars()); } if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols) { - ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars()); + ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", sym->SymbolName.GetChars()); delete this; return nullptr; } @@ -4041,6 +4046,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) 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."); delete this; return nullptr; } @@ -4051,29 +4057,29 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) delete this; return nullptr; } - else + + if (ctx.Function->Variants[0].SelfClass != ctx.Class) { - if (ctx.Function->Variants[0].SelfClass != ctx.Class) + // Check if the restricted class can access it. + PSymbol *sym2; + if ((sym2 = ctx.FindInSelfClass(Identifier, symtbl)) != nullptr) { - // Check if the restricted class can access it. - PSymbol *sym2; - if ((sym2 = ctx.FindInSelfClass(Identifier, symtbl)) != nullptr) + if (sym != sym2) { - if (sym != sym2) - { - ScriptPosition.Message(MSG_ERROR, "Member variable of %s not accessible through restricted self pointer", ctx.Class->TypeName.GetChars()); - delete this; - return nullptr; - } + ScriptPosition.Message(MSG_ERROR, "Member variable of %s not accessible through restricted self pointer", ctx.Class->TypeName.GetChars()); + delete this; + return nullptr; } } + } 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()); + delete this; + return nullptr; } } @@ -4100,10 +4106,109 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) else { ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); - newex = new FxConstant(0, ScriptPosition); + delete this; + return nullptr; } delete this; - return newex? newex->Resolve(ctx) : NULL; + return newex? newex->Resolve(ctx) : nullptr; +} + + +//========================================================================== +// +// +// +//========================================================================== + +FxMemberIdentifier::FxMemberIdentifier(FxExpression *left, FName name, const FScriptPosition &pos) + : FxIdentifier(name, pos) +{ + Object = left; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) +{ + PSymbol * sym; + FxExpression *newex = nullptr; + + CHECKRESOLVED(); + + SAFE_RESOLVE(Object, ctx); + + if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + { + PSymbolTable *symtbl; + PClass *cls = static_cast(Object->ValueType)->ClassRestriction; + if ((sym = cls->Symbols.FindSymbolInTable(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); + } + 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) + { + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); + } + if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols) + { + ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars()); + delete this; + 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."); + delete this; + return nullptr; + } + auto x = new FxClassMember(Object, vsym, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); + delete this; + return nullptr; + } + } + else + { + ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); + delete this; + return nullptr; + } + } + else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct))) + { + // todo + } + else if (Object->ValueType->IsA(RUNTIME_CLASS(PPointer))) + { + // todo + } + + ScriptPosition.Message(MSG_ERROR, "Left side of %s is not a struct or class", Identifier.GetChars()); + delete this; + return nullptr; } @@ -4248,19 +4353,6 @@ FxExpression *FxClassMember::Resolve(FCompileContext &ctx) 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); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 6bcc328301..333075961e 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -245,6 +245,7 @@ public: class FxIdentifier : public FxExpression { +protected: FName Identifier; public: @@ -253,6 +254,22 @@ public: }; +//========================================================================== +// +// FxIdentifier +// +//========================================================================== + +class FxMemberIdentifier : public FxIdentifier +{ + FxExpression *Object; + +public: + FxMemberIdentifier(FxExpression *obj, FName i, const FScriptPosition &p); + FxExpression *Resolve(FCompileContext&); +}; + + //========================================================================== // // FxDotIdentifier diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index bdb992fba9..4705948973 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -636,6 +636,7 @@ void InitThingdef() // Define some member variables we feel like exposing to the user PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols; PType *array5 = NewArray(TypeSInt32, 5); + PType *TypeActor = NewClassPointer(RUNTIME_CLASS(AActor)); 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))); @@ -675,4 +676,5 @@ void InitThingdef() 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))); + symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 52d21784e3..a91d27a4ee 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2372,13 +2372,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // The function name is a simple identifier. return new FxFunctionCall(static_cast(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast); - // not yet done - case AST_ExprTypeRef: - case AST_SwitchStmt: - case AST_CaseStmt: case AST_ExprMemberAccess: - // calling a class member through its pointer - // todo. break; case AST_ExprBinary: @@ -2400,6 +2394,12 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) 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); @@ -2660,6 +2660,11 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } } + // not yet done + case AST_SwitchStmt: + case AST_CaseStmt: + break; + case AST_CompoundStmt: { From 89416835a8426c79cf36a55c297e20a55810dcf8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 21 Oct 2016 19:18:39 +0200 Subject: [PATCH 084/471] - preparations for null pointer support. - add pointer support to FxAssign. --- src/dobjtype.cpp | 4 +- src/dobjtype.h | 3 +- src/scripting/codegeneration/codegen.cpp | 98 +++++++++++++++++++----- src/scripting/codegeneration/codegen.h | 7 ++ 4 files changed, 90 insertions(+), 22 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index ded832f2df..0cd1a8d31d 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -84,6 +84,7 @@ PColor *TypeColor; PStatePointer *TypeState; PStruct *TypeVector2; PStruct *TypeVector3; +PPointer *TypeNullPtr; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -616,6 +617,7 @@ void PType::StaticInit() TypeTable.AddType(TypeSound = new PSound); TypeTable.AddType(TypeColor = new PColor); TypeTable.AddType(TypeState = new PStatePointer); + TypeTable.AddType(TypeNullPtr = new PPointer); TypeVector2 = new PStruct(NAME_Vector2, nullptr); TypeVector2->AddField(NAME_X, TypeFloat64); @@ -1635,7 +1637,7 @@ END_POINTERS PPointer::PPointer() : PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL) { - mDescriptiveName = "Pointer"; + mDescriptiveName = "NullPointer"; } //========================================================================== diff --git a/src/dobjtype.h b/src/dobjtype.h index 4a15078fd2..e6f2a491b0 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -530,6 +530,7 @@ class PPointer : public PBasicType DECLARE_CLASS(PPointer, PBasicType); HAS_OBJECT_POINTERS; public: + PPointer(); PPointer(PType *pointsat); PType *PointedType; @@ -546,7 +547,6 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; protected: - PPointer(); }; class PClassPointer : public PPointer @@ -890,6 +890,7 @@ extern PColor *TypeColor; extern PStruct *TypeVector2; extern PStruct *TypeVector3; extern PStatePointer *TypeState; +extern PPointer *TypeNullPtr; // A constant value --------------------------------------------------------- diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index a271d240a4..f3cf4867ee 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1078,6 +1078,10 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) // 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 (ValueType->GetRegType() == REGT_FLOAT) { FxExpression *x = new FxFloatCast(basex); @@ -1199,6 +1203,7 @@ basereturn: auto x = basex; basex = nullptr; delete this; + x->ValueType = ValueType; return x; } @@ -1772,9 +1777,64 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) SAFE_RESOLVE(Right, ctx); - if (!Base->IsNumeric() || !Right->IsNumeric()) + if (Base->IsNumeric() && Right->IsNumeric()) { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + 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->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 if ((Base->ValueType == TypeState || Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) && Right->ValueType == TypeNullPtr) + { + // null pointers can be assigned to any other pointer + } + else if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + { + // class pointers may be assignable so add a cast which performs a check. + Right = new FxClassTypeCast(static_cast(ValueType), Right); + SAFE_RESOLVE(Right, ctx); + } + else if (Base->ValueType == TypeString && (Right->ValueType == TypeName || Right->ValueType == TypeSound)) + { + Right = new FxStringCast(Right); + SAFE_RESOLVE(Right, ctx); + } + else if (Base->ValueType == TypeName && Right->ValueType == TypeString) + { + Right = new FxNameCast(Right); + SAFE_RESOLVE(Right, ctx); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Assignment between incompatible types."); delete this; return nullptr; } @@ -1785,22 +1845,6 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) return nullptr; } - 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); - } return this; } @@ -1808,7 +1852,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) ExpEmit FxAssign::Emit(VMFunctionBuilder *build) { static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; - assert(ValueType == Base->ValueType && IsNumeric()); + assert(ValueType == Base->ValueType); assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); ExpEmit pointer = Base->Emit(build); @@ -2272,8 +2316,14 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return NULL; + if (!ResolveLR(ctx, true)) return nullptr; + if (!IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } if (left->isConstant() && right->isConstant()) { double v1 = static_cast(left)->GetValue().GetFloat(); @@ -6015,6 +6065,14 @@ 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; + } if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer)) { auto to = static_cast(ValueType); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 333075961e..0348468a92 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -379,6 +379,13 @@ public: ValueType = value.Type = TypeState; isresolved = true; } + + FxConstant(nullptr_t *nullp, const FScriptPosition &pos) : FxExpression(pos) + { + value.pointer = nullptr; + ValueType = value.Type = TypeNullPtr; + isresolved = true; + } static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos); From 4b41e735f1cf0514279583a92d4623c42bdd7007 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 00:50:04 +0200 Subject: [PATCH 085/471] - added null pointer. - fixed: FxMemberIdentifier checked for ClassPointers instead of object pointers to resolve the left hand side of the expression. - allow comparison of pointers. --- src/dobjtype.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 139 +++++++++++++---------- src/scripting/codegeneration/codegen.h | 2 +- src/scripting/thingdef_data.cpp | 2 +- src/scripting/zscript/zcc-parse.lemon | 8 ++ src/scripting/zscript/zcc_compile.cpp | 10 ++ src/scripting/zscript/zcc_parser.cpp | 2 +- 7 files changed, 104 insertions(+), 61 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 0cd1a8d31d..9191c60c00 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1671,7 +1671,7 @@ int PPointer::GetStoreOp() const int PPointer::GetLoadOp() const { - return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP; + return (PointedType && PointedType->IsKindOf(RUNTIME_CLASS(PClass))) ? OP_LO : OP_LP; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f3cf4867ee..f78dcdff6c 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -229,6 +229,31 @@ static PSymbol *FindDecorateBuiltinFunction(FName funcname, VMNativeFunction::Na // //========================================================================== +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 (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"); @@ -1174,21 +1199,9 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) if (fromtype->IsDescendantOf(totype)) goto basereturn; } } - else if (ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + else if (AreCompatiblePointerTypes(ValueType, basex->ValueType)) { - // Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type. - if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) - { - auto fromtype = static_cast(basex->ValueType); - auto totype = static_cast(ValueType); - 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); - if (fromcls->IsDescendantOf(tocls)) goto basereturn; - } - } + 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. @@ -1201,9 +1214,9 @@ errormsg: basereturn: auto x = basex; + x->ValueType = ValueType; basex = nullptr; delete this; - x->ValueType = ValueType; return x; } @@ -1996,14 +2009,21 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) ValueType = TypeFloat64; } } - else if (left->ValueType->GetRegType() == REGT_POINTER && left->ValueType == right->ValueType) + else if (left->ValueType->GetRegType() == REGT_POINTER) { - ValueType = left->ValueType; + if (left->ValueType == right->ValueType || right->ValueType == TypeNullPtr || left->ValueType == TypeNullPtr || + AreCompatiblePointerTypes(left->ValueType, right->ValueType)) + { + // pointers can only be compared for equality. + assert(Operator == TK_Eq || Operator == TK_Neq); + ValueType = TypeBool; + } } else { ValueType = TypeVoid; } + assert(ValueType > nullptr && ValueType < (PType*)0xfffffffffffffff); if (castnumeric) { @@ -4191,70 +4211,75 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) SAFE_RESOLVE(Object, ctx); - if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { PSymbolTable *symtbl; - PClass *cls = static_cast(Object->ValueType)->ClassRestriction; - if ((sym = cls->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr) + auto ptype = static_cast(Object->ValueType)->PointedType; + + if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) { - if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) + PClass *cls = static_cast(ptype); + if ((sym = cls->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr) { - 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); - - // 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) + if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) { - ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars()); + newex = FxConstant::MakeConstant(sym, ScriptPosition); } - if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols) + else if (sym->IsKindOf(RUNTIME_CLASS(PField))) { - ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars()); + 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) + { + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); + } + if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols) + { + ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars()); + delete this; + 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."); + delete this; + return nullptr; + } + auto x = new FxClassMember(Object, vsym, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); delete this; 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."); - delete this; - return nullptr; - } - auto x = new FxClassMember(Object, vsym, ScriptPosition); - delete this; - return x->Resolve(ctx); } else { - ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); + ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); delete this; return nullptr; } } - else + else if (ptype->IsA(RUNTIME_CLASS(PStruct))) { - ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); - delete this; - return nullptr; + // todo } } else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct))) { // todo } - else if (Object->ValueType->IsA(RUNTIME_CLASS(PPointer))) - { - // todo - } ScriptPosition.Message(MSG_ERROR, "Left side of %s is not a struct or class", Identifier.GetChars()); delete this; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 0348468a92..32dc4bfbf1 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -380,7 +380,7 @@ public: isresolved = true; } - FxConstant(nullptr_t *nullp, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(const FScriptPosition &pos) : FxExpression(pos) { value.pointer = nullptr; ValueType = value.Type = TypeNullPtr; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 4705948973..260cc64088 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -636,7 +636,7 @@ void InitThingdef() // Define some member variables we feel like exposing to the user PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols; PType *array5 = NewArray(TypeSInt32, 5); - PType *TypeActor = NewClassPointer(RUNTIME_CLASS(AActor)); + PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); 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))); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 42c3014c13..eeeba6295a 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -1450,6 +1450,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 ************/ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index a91d27a4ee..06c08f6811 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1462,6 +1462,10 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) { return TypeSInt32; // hack this to an integer until we can resolve the enum mess. } + if (type->IsKindOf(RUNTIME_CLASS(PClass))) + { + return NewPointer(type); + } return type; } return TypeError; @@ -2353,6 +2357,8 @@ static FxExpression *ModifyAssign(FxBinary *operation, FxExpression *left) 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) @@ -2436,6 +2442,10 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) { return new FxConstant(*cnst->StringVal, *ast); } + else if (cnst->Type == TypeNullPtr) + { + return new FxConstant(*ast); + } else { // can there be other types? diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 222e8e6c53..7d4edf78a3 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -154,7 +154,7 @@ static void InitTokenMap() TOKENDEF (TK_Out, ZCC_OUT); TOKENDEF (TK_Optional, ZCC_OPTIONAL); TOKENDEF (TK_Super, ZCC_SUPER); - TOKENDEF (TK_Null, ZCC_NULL); + TOKENDEF (TK_Null, ZCC_NULLPTR); TOKENDEF (TK_Self, ZCC_SELF); TOKENDEF ('~', ZCC_TILDE); TOKENDEF ('!', ZCC_BANG); From 1e11042de099442363eee88c1660dc6e3f8c253d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 02:52:28 +0200 Subject: [PATCH 086/471] - changed VM_EPSILON from 1/1024 to 1/65536 so that the ~== operator can actually be used. 1/1024 is far too coarse for ZDoom's purposes, this needs to be at least fixed point precision. --- src/scripting/vm/vm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 8cd63f3e51..b9dafde0c0 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -17,7 +17,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 { From 43aec685590f32a5f228a212e495a543da800ed1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 09:31:37 +0200 Subject: [PATCH 087/471] - implemented ~== operator. Turned out this was really simple because the functionality was already there. --- src/scripting/codegeneration/codegen.cpp | 5 +++-- src/scripting/zscript/zcc_compile.cpp | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f78dcdff6c..a9c5d40e74 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2525,6 +2525,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) return NULL; } + if (Operator == TK_ApproxEq && ValueType->GetRegType() != REGT_FLOAT) Operator = TK_Eq; if (left->isConstant() && right->isConstant()) { int v; @@ -2533,7 +2534,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) { double v1 = static_cast(left)->GetValue().GetFloat(); double v2 = static_cast(right)->GetValue().GetFloat(); - v = Operator == TK_Eq? v1 == v2 : v1 != v2; + v = Operator == TK_Eq? v1 == v2 : Operator == TK_Neq? v1 != v2 : fabs(v1-v2) < VM_EPSILON; } else { @@ -2588,7 +2589,7 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) // 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(instr, Operator == TK_ApproxEq? CMP_APPROX : Operator != TK_Eq, op1.RegNum, op2.RegNum); build->Emit(OP_JMP, 1); build->Emit(OP_LI, to.RegNum, 1); return to; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 06c08f6811..bf3d14d06e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2535,6 +2535,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_EQEQ: case PEX_NEQ: + case PEX_APREQ: return new FxCompareEq(tok, left, right); case PEX_Assign: @@ -2563,8 +2564,6 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_Concat: case PEX_Is: - // more esoteric operators - case PEX_APREQ: // vector operations will be done later. case PEX_CrossProduct: From d6047ae651ac9166ac713f7eca018e0977abaf0c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 12:10:19 +0200 Subject: [PATCH 088/471] - added the required code genration nodes for member function calls. This is not testable right now because finally the action function mess has come full circle. The current setup makes it impossible to call action functions from non-action functions because the needed info is local to the functions. Long avoided, this needs to be refactored now so that the different semantics for action functions are no longer needed. --- src/scripting/codegeneration/codegen.cpp | 181 +++++++++++++++++---- src/scripting/codegeneration/codegen.h | 25 ++- src/scripting/decorate/thingdef_exp.cpp | 2 +- src/scripting/decorate/thingdef_states.cpp | 4 +- src/scripting/thingdef.cpp | 2 +- src/scripting/thingdef.h | 2 +- src/scripting/zscript/zcc_compile.cpp | 2 +- 7 files changed, 180 insertions(+), 38 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index a9c5d40e74..dce724a324 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4717,12 +4717,26 @@ static bool CheckArgSize(FName fname, FArgumentList *args, int min, int max, FSc FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { ABORT(ctx.Class); + bool error = false; - PFunction *afd = FindClassMemberFunction(ctx.Class, ctx.Class, MethodName, ScriptPosition); + PFunction *afd = FindClassMemberFunction(ctx.Class, ctx.Class, MethodName, ScriptPosition, &error); + + if (error) + { + delete this; + return nullptr; + } if (afd != nullptr) { - auto x = new FxVMFunctionCall(afd, ArgList, ScriptPosition, false); + 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); ArgList = nullptr; delete this; return x->Resolve(ctx); @@ -4867,6 +4881,105 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } +//========================================================================== +// +// +// +//========================================================================== + +FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos) + : FxExpression(pos) +{ + Self = self; + MethodName = methodname; + ArgList = args; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMemberFunctionCall::~FxMemberFunctionCall() +{ + SAFE_DELETE(Self); + SAFE_DELETE(ArgList); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) +{ + ABORT(ctx.Class); + SAFE_RESOLVE(Self, ctx); + + PClass *cls; + bool staticonly = false; + if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + { + cls = static_cast(Self->ValueType)->ClassRestriction; + staticonly = true; + } + else 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; + } + + bool error = false; + PFunction *afd = FindClassMemberFunction(cls, cls, 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_Static)) + { + 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; + } + // If this is a qualified call to a parent class function, let it through (but this needs to disable virtual calls later.) + } + + // do not pass the self pointer to static functions. + auto self = !(afd->Variants[0].Flags & VARF_Static) ? Self : nullptr; + auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly); + ArgList = nullptr; + delete this; + return x->Resolve(ctx); +} + + //========================================================================== // // FxActionSpecialCall @@ -5042,13 +5155,14 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) // //========================================================================== -FxVMFunctionCall::FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool ownerisself) +FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool novirtual) : FxExpression(pos) { + Self = self; Function = func; ArgList = args; EmitTail = false; - OwnerIsSelf = ownerisself; + NoVirtual = novirtual; } //========================================================================== @@ -5103,6 +5217,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction() FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); + SAFE_RESOLVE_OPT(Self, ctx); bool failed = false; auto proto = Function->Variants[0].Proto; auto argtypes = proto->ArgumentTypes; @@ -5112,6 +5227,14 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) else if (Function->Variants[0].Flags & VARF_Method) implicit = 1; else implicit = 0; + // This should never happen. + if (Self == nullptr && !(Function->Variants[0].Flags & VARF_Static)) + { + ScriptPosition.Message(MSG_ERROR, "Call to non-static function without a self pointer"); + delete this; + return nullptr; + } + if (ArgList != NULL) { for (unsigned i = 0; i < ArgList->Size(); i++) @@ -5142,16 +5265,14 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) //========================================================================== // -// 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)); + (!build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 1)); int count = (ArgList ? ArgList->Size() : 0); if (count == 1) @@ -5163,35 +5284,34 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } } - // Passing the caller as 'self' is a serious design mistake in DECORATE because it mixes up the types of the two actors involved. - // For ZSCRIPT 'self' is properly used for the state's owning actor, meaning we have to pass the second argument here. - // If both functions are non-action or both are action, there is no need for special treatment. - if (!OwnerIsSelf || (!!(Function->Variants[0].Flags & VARF_Action) == build->IsActionFunc)) + //if (elf || (!!(Function->Variants[0].Flags & VARF_Action) == build->IsActionFunc)) { - // Emit code to pass implied parameters + // Emit code to pass implied parameters if (Function->Variants[0].Flags & VARF_Method) - { - build->Emit(OP_PARAM, 0, REGT_POINTER, 0); - count += 1; - } + { + assert(Self != nullptr); + Self->Emit(build); + count += 1; + } if (Function->Variants[0].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); + 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; } - 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; - } } + /* else { if (build->IsActionFunc && (Function->Variants[0].Flags & VARF_Method)) @@ -5207,6 +5327,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) I_Error("Cannot call action function from non-action functions."); } } + */ // Emit code to pass explicit parameters if (ArgList != NULL) diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 32dc4bfbf1..4f3b57c131 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -1080,6 +1080,26 @@ public: }; +//========================================================================== +// +// 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 @@ -1130,12 +1150,13 @@ public: class FxVMFunctionCall : public FxExpression { bool EmitTail; - bool OwnerIsSelf; // ZSCRIPT makes the state's owner the self pointer to ensure proper type handling + bool NoVirtual; + FxExpression *Self; PFunction *Function; FArgumentList *ArgList; public: - FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool ownerisself); + FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool novirtual); ~FxVMFunctionCall(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 5be69390e7..2d1d189b4a 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -515,7 +515,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) args = nullptr; } - return new FxVMFunctionCall(func, args, sc, false); + return new FxVMFunctionCall(new FxSelf(sc), func, args, sc, false); } } diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 11db1504d5..8b75b935f4 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -99,7 +99,7 @@ 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, false); + return new FxVMFunctionCall(new FxSelf(sc), FindGlobalActionFunction("A_CallSpecial"), args, sc, false); } return NULL; } @@ -571,7 +571,7 @@ FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, B { FArgumentList *args = new FArgumentList; ParseFunctionParameters(sc, bag.Info, *args, afd, statestring, &bag.statedef); - call = new FxVMFunctionCall(afd, args->Size() > 0 ? args : NULL, sc, false); + call = new FxVMFunctionCall(new FxSelf(sc), afd, args->Size() > 0 ? args : NULL, sc, false); if (args->Size() == 0) { delete args; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 7fcb0ce39d..45e77b3ad9 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -155,7 +155,7 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i // //========================================================================== -PFunction *FindClassMemberFunction(PClass *selfcls, PClass *funccls, FName name, FScriptPosition &sc) +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; diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index bdee476ee4..51df4821ea 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -153,7 +153,7 @@ class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestr FName CheckCastKludges(FName in); void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags); PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); -PFunction *FindClassMemberFunction(PClass *cls, PClass *funccls, FName name, FScriptPosition &sc); +PFunction *FindClassMemberFunction(PClass *cls, PClass *funccls, FName name, FScriptPosition &sc, bool *error); //========================================================================== // diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index bf3d14d06e..ba038a7160 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2066,7 +2066,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a if (fc->Parameters == nullptr && (afd->Variants[0].Flags & VARF_Action)) { // We can use this function directly without wrapping it in a caller. - return new FxVMFunctionCall(afd, nullptr, *af, true); + return new FxVMFunctionCall(new FxSelf(*af), afd, nullptr, *af, false); } } else From d714670acc85712ddecf0da39e03c051184cde67 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 16:35:48 +0200 Subject: [PATCH 089/471] - allow calling non-action functions directly from a state. Ironically this only requires a very minor change in the calling code and an added member for the VMFunction to tell that code how many parameters to pass. This change will allow to turn the vast majority of action functions into regular members, the only ones that still need to be an action function are the few that actually use the pointers. --- src/d_dehacked.cpp | 2 ++ src/dobjtype.h | 6 ++++++ src/info.cpp | 4 ++-- src/p_actionfunctions.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 9 +++------ src/scripting/vm/vm.h | 4 ++-- src/scripting/vm/vmbuilder.cpp | 1 + src/scripting/zscript/zcc_compile.cpp | 8 +++++--- 8 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 81ee907f47..66bdc652c9 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -823,7 +823,9 @@ void SetDehParams(FState *state, int codepointer) VMScriptFunction *sfunc = new VMScriptFunction; buildit.MakeFunction(sfunc); sfunc->NumArgs = NAP; + sfunc->ImplicitArgs = NAP; state->SetAction(sfunc); + sfunc->PrintableName.Format("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2); } } diff --git a/src/dobjtype.h b/src/dobjtype.h index e6f2a491b0..c5d96972b1 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -719,6 +719,12 @@ public: PClass *OwningClass = nullptr; 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(); diff --git a/src/info.cpp b/src/info.cpp index 44f485e6ce..5e267b39c8 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -94,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; diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index c8e110a68d..bbeeca3743 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -168,7 +168,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) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index dce724a324..1de5c13c2f 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5196,11 +5196,11 @@ PPrototype *FxVMFunctionCall::ReturnProto() VMFunction *FxVMFunctionCall::GetDirectFunction() { - // If this return statement calls a function with no arguments, + // 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 ? ArgList->Size() : 0) == 0 && (Function->Variants[0].Flags & VARF_Action)) + if ((ArgList ? ArgList->Size() : 0) == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) { return Function->Variants[0].Implementation; } @@ -5222,10 +5222,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) auto proto = Function->Variants[0].Proto; auto argtypes = proto->ArgumentTypes; - int implicit; - if (Function->Variants[0].Flags & VARF_Action) implicit = 3; - else if (Function->Variants[0].Flags & VARF_Method) implicit = 1; - else implicit = 0; + int implicit = Function->GetImplicitArgs(); // This should never happen. if (Self == nullptr && !(Function->Variants[0].Flags & VARF_Static)) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index b9dafde0c0..a37b7449b6 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -179,12 +179,12 @@ class VMFunction : public DObject HAS_OBJECT_POINTERS; public: bool Native; + BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action FName Name; class PPrototype *Proto; - VMFunction() : Native(false), Name(NAME_None), Proto(NULL) {} - VMFunction(FName name) : Native(false), Name(name), Proto(NULL) {} + VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {} }; enum EVMOpMode diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index a5f15b262b..b58de0ea4b 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -665,6 +665,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c it.Code = code; it.PrintableName = name; it.Function = new VMScriptFunction; + it.Function->ImplicitArgs = functype->GetImplicitArgs(); it.Proto = nullptr; it.FromDecorate = fromdecorate; mItems.Push(it); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index ba038a7160..9b4212820e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1951,14 +1951,15 @@ void ZCCCompiler::InitFunctions() 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_Action) varflags |= VARF_Action|VARF_Final; // Action implies Final. - if (f->Flags & ZCC_Static) varflags = (varflags & ~VARF_Method) | VARF_Final; // Static implies Final. + 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 ((f->Flags & (ZCC_Action | ZCC_Static)) == (ZCC_Action | ZCC_Static)) { Error(f, "%s: Action and Static on the same function is not allowed.", FName(f->Name).GetChars()); @@ -1973,6 +1974,7 @@ void ZCCCompiler::InitFunctions() { Error(f, "The function '%s' has not been exported from the executable.", FName(f->Name).GetChars()); } + (*afd->VMPointer)->ImplicitArgs = BYTE(implicitargs); } SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags); auto p = f->Params; @@ -2063,7 +2065,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a PFunction *afd = dyn_cast(cls->Symbols.FindSymbol(id->Identifier, true)); if (afd != nullptr) { - if (fc->Parameters == nullptr && (afd->Variants[0].Flags & VARF_Action)) + if (fc->Parameters == nullptr && !(afd->Variants[0].Flags & VARF_Virtual)) { // We can use this function directly without wrapping it in a caller. return new FxVMFunctionCall(new FxSelf(*af), afd, nullptr, *af, false); From 32ac1a8ad7613baf369bb0e5d3780c72ee4b2d69 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 16:46:47 +0200 Subject: [PATCH 090/471] - moved the special weapon functions from Inventory to StateProvider. This will restrict them to the only classes that may use them: Weapon and CustomInventory. Note: Should a mod surface which uses them improperly the better solution would be a warning message and NULLing the bogus code pointer instead of leaving them in Inventory. --- src/d_dehacked.cpp | 8 +-- wadsrc/static/zscript/shared/inventory.txt | 63 +++++++++++----------- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 66bdc652c9..71deb01691 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -797,7 +797,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)) @@ -2113,7 +2113,7 @@ static int PatchCodePtrs (int dummy) // 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); @@ -2721,11 +2721,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); diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index bf2f7e188c..80771e1a13 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -10,6 +10,37 @@ class Inventory : Actor native Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"; } + // These are regular functions for the item itself. + private action native void A_RestoreSpecialPosition(); + private action native void A_RestoreSpecialDoomThing(); + private action native void A_RestoreSpecialThing1(); + private action native void 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; + } +} + +class StateProvider : Inventory native +{ action native state A_JumpIfNoAmmo(state label); action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = ""); action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); @@ -47,38 +78,6 @@ class Inventory : Actor native 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, state label, bool dontincrement = false); action native void A_ResetReloadCounter(); - - // These are regular functions for the item itself. - private action native void A_RestoreSpecialPosition(); - private action native void A_RestoreSpecialDoomThing(); - private action native void A_RestoreSpecialThing1(); - private action native void 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; - } -} - -class StateProvider : Inventory native -{ } class ScoreItem : Inventory native From 371712c53a92cdce5bc2ac0e7b41306d884a4836 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 17:49:08 +0200 Subject: [PATCH 091/471] - turned everything I could into non-action functions. - fixed emission of the self pointer in FxVMFunctionCall. I did not realize that the self expression only sets up a register for the value, not pushing it onto the stack. --- src/g_doom/a_arachnotron.cpp | 4 +- src/g_doom/a_archvile.cpp | 12 +- src/g_doom/a_bossbrain.cpp | 16 +- src/g_doom/a_bruiser.cpp | 2 +- src/g_doom/a_cacodemon.cpp | 2 +- src/g_doom/a_cyberdemon.cpp | 4 +- src/g_doom/a_demon.cpp | 2 +- src/g_doom/a_doomimp.cpp | 2 +- src/g_doom/a_doommisc.cpp | 2 +- src/g_doom/a_doomweaps.cpp | 38 +- src/g_doom/a_fatso.cpp | 10 +- src/g_doom/a_keen.cpp | 2 +- src/g_doom/a_lostsoul.cpp | 4 +- src/g_doom/a_painelemental.cpp | 6 +- src/g_doom/a_possessed.cpp | 10 +- src/g_doom/a_revenant.cpp | 8 +- src/g_doom/a_scriptedmarine.cpp | 34 +- src/g_doom/a_spidermaster.cpp | 4 +- src/g_heretic/a_chicken.cpp | 10 +- src/g_heretic/a_dsparil.cpp | 20 +- src/g_heretic/a_hereticartifacts.cpp | 2 +- src/g_heretic/a_hereticimp.cpp | 8 +- src/g_heretic/a_hereticmisc.cpp | 14 +- src/g_heretic/a_hereticweaps.cpp | 54 +-- src/g_heretic/a_ironlich.cpp | 8 +- src/g_heretic/a_knight.cpp | 4 +- src/g_heretic/a_wizard.cpp | 8 +- src/g_hexen/a_bats.cpp | 6 +- src/g_hexen/a_bishop.cpp | 18 +- src/g_hexen/a_blastradius.cpp | 2 +- src/g_hexen/a_centaur.cpp | 2 +- src/g_hexen/a_clericflame.cpp | 8 +- src/g_hexen/a_clericholy.cpp | 14 +- src/g_hexen/a_clericmace.cpp | 2 +- src/g_hexen/a_clericstaff.cpp | 10 +- src/g_hexen/a_dragon.cpp | 14 +- src/g_hexen/a_fighteraxe.cpp | 12 +- src/g_hexen/a_fighterhammer.cpp | 4 +- src/g_hexen/a_fighterplayer.cpp | 2 +- src/g_hexen/a_fighterquietus.cpp | 6 +- src/g_hexen/a_firedemon.cpp | 10 +- src/g_hexen/a_flechette.cpp | 10 +- src/g_hexen/a_flies.cpp | 4 +- src/g_hexen/a_fog.cpp | 4 +- src/g_hexen/a_heresiarch.cpp | 26 +- src/g_hexen/a_hexenspecialdecs.cpp | 24 +- src/g_hexen/a_iceguy.cpp | 10 +- src/g_hexen/a_korax.cpp | 16 +- src/g_hexen/a_magecone.cpp | 4 +- src/g_hexen/a_magelightning.cpp | 14 +- src/g_hexen/a_magestaff.cpp | 8 +- src/g_hexen/a_pig.cpp | 4 +- src/g_hexen/a_serpent.cpp | 26 +- src/g_hexen/a_spike.cpp | 10 +- src/g_hexen/a_summon.cpp | 2 +- src/g_hexen/a_teleportother.cpp | 10 +- src/g_hexen/a_wraith.cpp | 14 +- src/g_raven/a_minotaur.cpp | 20 +- src/g_shared/a_action.cpp | 46 +-- src/g_shared/a_bridge.cpp | 4 +- src/g_shared/a_pickups.cpp | 8 +- src/g_shared/a_specialspot.cpp | 2 +- src/g_shared/a_weapons.cpp | 4 +- src/g_strife/a_acolyte.cpp | 8 +- src/g_strife/a_alienspectres.cpp | 8 +- src/g_strife/a_crusader.cpp | 10 +- src/g_strife/a_entityboss.cpp | 8 +- src/g_strife/a_inquisitor.cpp | 12 +- src/g_strife/a_loremaster.cpp | 2 +- src/g_strife/a_oracle.cpp | 2 +- src/g_strife/a_programmer.cpp | 8 +- src/g_strife/a_reaver.cpp | 2 +- src/g_strife/a_rebels.cpp | 4 +- src/g_strife/a_sentinel.cpp | 6 +- src/g_strife/a_spectral.cpp | 8 +- src/g_strife/a_stalker.cpp | 10 +- src/g_strife/a_strifeitems.cpp | 2 +- src/g_strife/a_strifestuff.cpp | 30 +- src/g_strife/a_strifeweapons.cpp | 56 +-- src/g_strife/a_templar.cpp | 2 +- src/g_strife/a_thingstoblowup.cpp | 8 +- src/info.h | 4 +- src/p_actionfunctions.cpp | 116 +++--- src/p_enemy.cpp | 44 +-- src/p_pspr.cpp | 38 +- src/p_user.cpp | 6 +- src/scripting/codegeneration/codegen.cpp | 53 +-- wadsrc/static/zscript/actor.txt | 342 +++++++++--------- wadsrc/static/zscript/doom/scriptedmarine.txt | 32 +- wadsrc/static/zscript/heretic/chicken.txt | 6 +- wadsrc/static/zscript/heretic/dsparil.txt | 20 +- .../zscript/heretic/hereticartifacts.txt | 2 +- wadsrc/static/zscript/heretic/hereticimp.txt | 8 +- wadsrc/static/zscript/heretic/hereticmisc.txt | 14 +- .../static/zscript/heretic/hereticweaps.txt | 54 +-- wadsrc/static/zscript/heretic/ironlich.txt | 8 +- wadsrc/static/zscript/heretic/knight.txt | 4 +- wadsrc/static/zscript/heretic/wizard.txt | 8 +- wadsrc/static/zscript/hexen/bats.txt | 6 +- wadsrc/static/zscript/hexen/bishop.txt | 14 +- wadsrc/static/zscript/hexen/clericboss.txt | 2 +- wadsrc/static/zscript/hexen/clericflame.txt | 8 +- wadsrc/static/zscript/hexen/clericholy.txt | 12 +- wadsrc/static/zscript/hexen/clericmace.txt | 2 +- wadsrc/static/zscript/hexen/clericstaff.txt | 8 +- wadsrc/static/zscript/hexen/dragon.txt | 14 +- wadsrc/static/zscript/hexen/fighteraxe.txt | 12 +- wadsrc/static/zscript/hexen/fighterboss.txt | 2 +- wadsrc/static/zscript/hexen/fighterfist.txt | 2 +- wadsrc/static/zscript/hexen/fighterhammer.txt | 4 +- .../static/zscript/hexen/fighterquietus.txt | 4 +- wadsrc/static/zscript/hexen/firedemon.txt | 10 +- wadsrc/static/zscript/hexen/flechette.txt | 14 +- wadsrc/static/zscript/hexen/flies.txt | 4 +- wadsrc/static/zscript/hexen/fog.txt | 4 +- wadsrc/static/zscript/hexen/heresiarch.txt | 26 +- .../static/zscript/hexen/hexenspecialdecs.txt | 22 +- wadsrc/static/zscript/hexen/iceguy.txt | 8 +- wadsrc/static/zscript/hexen/korax.txt | 16 +- wadsrc/static/zscript/hexen/mageboss.txt | 2 +- wadsrc/static/zscript/hexen/magecone.txt | 4 +- wadsrc/static/zscript/hexen/magelightning.txt | 14 +- wadsrc/static/zscript/hexen/magestaff.txt | 6 +- wadsrc/static/zscript/hexen/pig.txt | 2 +- wadsrc/static/zscript/hexen/serpent.txt | 26 +- wadsrc/static/zscript/hexen/spike.txt | 10 +- wadsrc/static/zscript/hexen/summon.txt | 2 +- wadsrc/static/zscript/hexen/teleportother.txt | 10 +- wadsrc/static/zscript/hexen/wraith.txt | 14 +- wadsrc/static/zscript/raven/minotaur.txt | 20 +- wadsrc/static/zscript/shared/bridge.txt | 4 +- wadsrc/static/zscript/shared/ice.txt | 2 +- wadsrc/static/zscript/shared/inventory.txt | 50 +-- wadsrc/static/zscript/shared/specialspot.txt | 2 +- wadsrc/static/zscript/strife/acolyte.txt | 8 +- .../static/zscript/strife/alienspectres.txt | 2 +- wadsrc/static/zscript/strife/crusader.txt | 10 +- wadsrc/static/zscript/strife/entityboss.txt | 8 +- wadsrc/static/zscript/strife/inquisitor.txt | 14 +- wadsrc/static/zscript/strife/loremaster.txt | 2 +- wadsrc/static/zscript/strife/oracle.txt | 2 +- wadsrc/static/zscript/strife/programmer.txt | 8 +- wadsrc/static/zscript/strife/reaver.txt | 2 +- wadsrc/static/zscript/strife/rebels.txt | 2 +- wadsrc/static/zscript/strife/sentinel.txt | 2 +- wadsrc/static/zscript/strife/sigil.txt | 20 +- wadsrc/static/zscript/strife/spectral.txt | 14 +- wadsrc/static/zscript/strife/stalker.txt | 10 +- wadsrc/static/zscript/strife/strifeplayer.txt | 6 +- .../static/zscript/strife/strifeweapons.txt | 28 +- wadsrc/static/zscript/strife/templar.txt | 2 +- .../static/zscript/strife/thingstoblowup.txt | 6 +- 152 files changed, 1051 insertions(+), 1072 deletions(-) diff --git a/src/g_doom/a_arachnotron.cpp b/src/g_doom/a_arachnotron.cpp index e558b05b26..22223d24b3 100644 --- a/src/g_doom/a_arachnotron.cpp +++ b/src/g_doom/a_arachnotron.cpp @@ -9,7 +9,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BspiAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; @@ -23,7 +23,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BspiAttack) DEFINE_ACTION_FUNCTION(AActor, A_BabyMetal) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); 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 index 06be5cc0c2..b635646541 100644 --- a/src/g_doom/a_archvile.cpp +++ b/src/g_doom/a_archvile.cpp @@ -21,7 +21,7 @@ void A_Fire(AActor *self, double height); // DEFINE_ACTION_FUNCTION(AActor, A_VileStart) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_VOICE, "vile/start", 1, ATTN_NORM); return 0; } @@ -33,7 +33,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VileStart) // DEFINE_ACTION_FUNCTION(AActor, A_StartFire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_BODY, "vile/firestrt", 1, ATTN_NORM); A_Fire (self, 0); return 0; @@ -41,7 +41,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StartFire) DEFINE_ACTION_FUNCTION(AActor, A_FireCrackle) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_BODY, "vile/firecrkl", 1, ATTN_NORM); A_Fire (self, 0); return 0; @@ -49,7 +49,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrackle) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Fire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(height) { height = 0; } A_Fire(self, height); @@ -80,7 +80,7 @@ void A_Fire(AActor *self, double height) // DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(fire, AActor) { fire = PClass::FindActor("ArchvileFire"); } AActor *fog; @@ -111,7 +111,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND_OPT (snd) { snd = "vile/stop"; } PARAM_INT_OPT (dmg) { dmg = 20; } PARAM_INT_OPT (blastdmg) { blastdmg = 70; } diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 8d4163c095..84cd9040c6 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -18,7 +18,7 @@ static FRandom pr_spawnfly ("SpawnFly"); DEFINE_ACTION_FUNCTION(AActor, A_BrainAwake) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // killough 3/26/98: only generates sound now S_Sound (self, CHAN_VOICE, "brain/sight", 1, ATTN_NONE); return 0; @@ -26,7 +26,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainAwake) DEFINE_ACTION_FUNCTION(AActor, A_BrainPain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_VOICE, "brain/pain", 1, ATTN_NONE); return 0; } @@ -56,7 +56,7 @@ static void BrainishExplosion (const DVector3 &pos) DEFINE_ACTION_FUNCTION(AActor, A_BrainScream) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); for (double x = -196; x < +320; x += 8) { @@ -69,7 +69,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainScream) DEFINE_ACTION_FUNCTION(AActor, A_BrainExplode) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double x = pr_brainexplode.Random2() / 32.; DVector3 pos = self->Vec2OffsetZ(x, 0, 1 / 512. + pr_brainexplode() * 2); BrainishExplosion(pos); @@ -78,7 +78,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainExplode) DEFINE_ACTION_FUNCTION(AActor, A_BrainDie) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // [RH] If noexit, then don't end the level. if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT)) @@ -111,7 +111,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainDie) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } DSpotState *state = DSpotState::GetSpotState(); @@ -297,7 +297,7 @@ static void SpawnFly(AActor *self, PClassActor *spawntype, FSoundID sound) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnFly) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; } FSoundID sound; @@ -318,7 +318,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnFly) // travelling cube sound DEFINE_ACTION_FUNCTION(AActor, A_SpawnSound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); 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 index 0d2f83aee0..1d2be64f03 100644 --- a/src/g_doom/a_bruiser.cpp +++ b/src/g_doom/a_bruiser.cpp @@ -3,7 +3,7 @@ static FRandom pr_bruisattack ("BruisAttack"); DEFINE_ACTION_FUNCTION(AActor, A_BruisAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; diff --git a/src/g_doom/a_cacodemon.cpp b/src/g_doom/a_cacodemon.cpp index 775580c293..354443bd69 100644 --- a/src/g_doom/a_cacodemon.cpp +++ b/src/g_doom/a_cacodemon.cpp @@ -14,7 +14,7 @@ static FRandom pr_headattack ("HeadAttack"); DEFINE_ACTION_FUNCTION(AActor, A_HeadAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; diff --git a/src/g_doom/a_cyberdemon.cpp b/src/g_doom/a_cyberdemon.cpp index 55d9181bf2..6e78759c37 100644 --- a/src/g_doom/a_cyberdemon.cpp +++ b/src/g_doom/a_cyberdemon.cpp @@ -9,7 +9,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CyberAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; @@ -21,7 +21,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CyberAttack) DEFINE_ACTION_FUNCTION(AActor, A_Hoof) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_BODY, "cyber/hoof", 1, ATTN_IDLE); A_Chase (stack, self); diff --git a/src/g_doom/a_demon.cpp b/src/g_doom/a_demon.cpp index 330b02b30b..5ac3e9e748 100644 --- a/src/g_doom/a_demon.cpp +++ b/src/g_doom/a_demon.cpp @@ -13,7 +13,7 @@ static FRandom pr_sargattack ("SargAttack"); DEFINE_ACTION_FUNCTION(AActor, A_SargAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; diff --git a/src/g_doom/a_doomimp.cpp b/src/g_doom/a_doomimp.cpp index 6130d39ca8..1b9dd9485a 100644 --- a/src/g_doom/a_doomimp.cpp +++ b/src/g_doom/a_doomimp.cpp @@ -17,7 +17,7 @@ static FRandom pr_troopattack ("TroopAttack"); // DEFINE_ACTION_FUNCTION(AActor, A_TroopAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index b68ded59da..a4eca67b70 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -44,7 +44,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BarrelDestroy) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (dmflags2 & DF2_BARRELS_RESPAWN) { diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index fd60e85d84..f7511b2be6 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -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,7 +115,7 @@ enum SAW_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; } PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; } PARAM_INT_OPT (damage) { damage = 2; } @@ -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; @@ -338,21 +338,21 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) DEFINE_ACTION_FUNCTION(AActor, A_OpenShotgun2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_WEAPON, "weapons/sshoto", 1, ATTN_NORM); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_LoadShotgun2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_CloseShotgun2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_WEAPON, "weapons/sshotc", 1, ATTN_NORM); A_ReFire (self); return 0; @@ -411,7 +411,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 +456,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCGun) // DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -479,7 +479,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) // DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS_OPT(grenade, AActor) { grenade = PClass::FindActor("Grenade"); } player_t *player; @@ -511,7 +511,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,21 +574,21 @@ 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; } @@ -605,7 +605,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RailWait) DEFINE_ACTION_FUNCTION(AActor, A_FireBFG) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -638,7 +638,7 @@ enum BFG_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT (spraytype, AActor) { spraytype = NULL; } PARAM_INT_OPT (numrays) { numrays = 0; } PARAM_INT_OPT (damagecnt) { damagecnt = 0; } @@ -722,7 +722,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray) // DEFINE_ACTION_FUNCTION(AActor, A_BFGsound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM); return 0; } @@ -738,7 +738,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 index eeef39984c..d840461048 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -19,7 +19,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatRaise) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_FaceTarget (self); S_Sound (self, CHAN_WEAPON, "fatso/raiseguns", 1, ATTN_NORM); @@ -28,7 +28,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatRaise) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } AActor *missile; @@ -54,7 +54,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } AActor *missile; @@ -80,7 +80,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack2) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack3) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } AActor *missile; @@ -122,7 +122,7 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; } PARAM_INT_OPT (n) { n = 0; } PARAM_INT_OPT (flags) { flags = 0; } diff --git a/src/g_doom/a_keen.cpp b/src/g_doom/a_keen.cpp index 5c57128a3b..3040e0545f 100644 --- a/src/g_doom/a_keen.cpp +++ b/src/g_doom/a_keen.cpp @@ -16,7 +16,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(doortag) { doortag = 666; } A_Unblock(self, false); diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp index 35468ac08d..18b8251e96 100644 --- a/src/g_doom/a_lostsoul.cpp +++ b/src/g_doom/a_lostsoul.cpp @@ -36,7 +36,7 @@ void A_SkullAttack(AActor *self, double speed) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(speed) { speed = SKULLSPEED; } if (speed <= 0) @@ -47,7 +47,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack) DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int damage; if (!self || !self->target || self->target->GetSpecies() == self->GetSpecies()) diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 8a0aa41bfb..30136f9f75 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -147,7 +147,7 @@ void A_PainShootSkull (AActor *self, DAngle Angle, PClassActor *spawntype, int f // DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; @@ -165,7 +165,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } if (!self->target) @@ -179,7 +179,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainDie) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } if (self->target != NULL && self->IsFriend(self->target)) diff --git a/src/g_doom/a_possessed.cpp b/src/g_doom/a_possessed.cpp index e665e8f11d..0b9a9ecfdd 100644 --- a/src/g_doom/a_possessed.cpp +++ b/src/g_doom/a_possessed.cpp @@ -20,7 +20,7 @@ static FRandom pr_cposrefire ("CPosRefire"); // DEFINE_ACTION_FUNCTION(AActor, A_PosAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int damage; DAngle angle; @@ -60,7 +60,7 @@ static void A_SPosAttack2 (AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_SPosAttackUseAtkSound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; @@ -74,7 +74,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SPosAttackUseAtkSound) // meant for Dehacked only. DEFINE_ACTION_FUNCTION(AActor, A_SPosAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; @@ -86,7 +86,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SPosAttack) DEFINE_ACTION_FUNCTION(AActor, A_CPosAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle angle; DAngle bangle; @@ -115,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CPosAttack) DEFINE_ACTION_FUNCTION(AActor, A_CPosRefire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // keep firing unless target got out of sight A_FaceTarget (self); diff --git a/src/g_doom/a_revenant.cpp b/src/g_doom/a_revenant.cpp index adb0ea100a..0ffaed7534 100644 --- a/src/g_doom/a_revenant.cpp +++ b/src/g_doom/a_revenant.cpp @@ -20,7 +20,7 @@ static FRandom pr_skelfist ("SkelFist"); // DEFINE_ACTION_FUNCTION(AActor, A_SkelMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *missile; @@ -44,7 +44,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkelMissile) DEFINE_ACTION_FUNCTION(AActor, A_Tracer) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double dist; double slope; @@ -123,7 +123,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer) DEFINE_ACTION_FUNCTION(AActor, A_SkelWhoosh) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; @@ -134,7 +134,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkelWhoosh) DEFINE_ACTION_FUNCTION(AActor, A_SkelFist) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) return 0; diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 76f3e45772..61c7c8ac4c 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -150,7 +150,7 @@ void AScriptedMarine::Tick () DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Refire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_OPT(ignoremissile) { ignoremissile = false; } 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,7 +249,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MarineLook) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND_OPT (fullsound) { fullsound = "weapons/sawfull"; } PARAM_SOUND_OPT (hitsound) { hitsound = "weapons/sawhit"; } PARAM_INT_OPT (damage) { damage = 2; } @@ -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 index ab12db4f0a..37d0deb184 100644 --- a/src/g_doom/a_spidermaster.cpp +++ b/src/g_doom/a_spidermaster.cpp @@ -13,7 +13,7 @@ static FRandom pr_spidrefire ("SpidRefire"); DEFINE_ACTION_FUNCTION(AActor, A_SpidRefire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // keep firing unless target got out of sight A_FaceTarget (self); @@ -33,7 +33,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpidRefire) DEFINE_ACTION_FUNCTION(AActor, A_Metal) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); S_Sound (self, CHAN_BODY, "spider/walk", 1, ATTN_IDLE); A_Chase (stack, self); diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp index 78eb7ca8d8..883eac353f 100644 --- a/src/g_heretic/a_chicken.cpp +++ b/src/g_heretic/a_chicken.cpp @@ -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_SELF_PROLOGUE(AActor); player_t *player; @@ -170,7 +170,7 @@ void P_PlayPeck (AActor *chicken) DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_PROLOGUE(AActor); DAngle angle; int damage; diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp index 632260648c..5ab4067d39 100644 --- a/src/g_heretic/a_dsparil.cpp +++ b/src/g_heretic/a_dsparil.cpp @@ -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 1c4677cb60..eceb2cfe15 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -47,7 +47,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; diff --git a/src/g_heretic/a_hereticimp.cpp b/src/g_heretic/a_hereticimp.cpp index 41e207ef14..39dfb049ec 100644 --- a/src/g_heretic/a_hereticimp.cpp +++ b/src/g_heretic/a_hereticimp.cpp @@ -21,7 +21,7 @@ static FRandom pr_imp ("ImpExplode"); DEFINE_ACTION_FUNCTION(AActor, A_ImpMsAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target || pr_impmsatk() > 64) { @@ -40,7 +40,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ImpMsAttack) DEFINE_ACTION_FUNCTION(AActor, A_ImpExplode) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *chunk; @@ -70,7 +70,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ImpExplode) DEFINE_ACTION_FUNCTION(AActor, A_ImpDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~MF_SOLID; self->flags2 |= MF2_FLOORCLIP; @@ -85,7 +85,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ImpDeath) DEFINE_ACTION_FUNCTION(AActor, A_ImpXDeath1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~MF_SOLID; self->flags |= MF_NOGRAVITY; diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index d3ffbac238..02c1393ddf 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -47,7 +47,7 @@ static FRandom pr_volcimpact ("VolcBallImpact"); DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT (gootype, AActor) { gootype = PClass::FindActor("PodGoo"); } int count; @@ -78,7 +78,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain) DEFINE_ACTION_FUNCTION(AActor, A_RemovePod) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -102,7 +102,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RemovePod) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MakePod) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(podtype, AActor) { podtype = PClass::FindActor("Pod"); } AActor *mo; @@ -133,7 +133,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) { @@ -151,7 +151,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; @@ -165,7 +165,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcanoSet) DEFINE_ACTION_FUNCTION(AActor, A_VolcanoBlast) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; int count; @@ -193,7 +193,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 c86cafce7d..51d759640b 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -61,7 +61,7 @@ extern bool P_AutoUseChaosDevice (player_t *player); DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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_SELF_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_SELF_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_SELF_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_SELF_PROLOGUE(AActor); DAngle Angle; int damage; @@ -421,7 +421,7 @@ void FireMacePL1B (AActor *actor) DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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; @@ -761,7 +761,7 @@ int ARipper::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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; @@ -888,7 +888,7 @@ void ARainTracker::Serialize(FSerializer &arc) DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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; @@ -1218,7 +1218,7 @@ int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -1246,7 +1246,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 +1271,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff) DEFINE_ACTION_FUNCTION(AActor, A_InitPhoenixPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player != NULL) { @@ -1294,7 +1294,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InitPhoenixPL2) DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -1347,7 +1347,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) DEFINE_ACTION_FUNCTION(AActor, A_ShutdownPhoenixPL2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -1373,7 +1373,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 +1387,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 c80a7bbed4..e2e1cb0214 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -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 index 9c4ae24732..a3125f77d4 100644 --- a/src/g_heretic/a_knight.cpp +++ b/src/g_heretic/a_knight.cpp @@ -21,7 +21,7 @@ static FRandom pr_knightatk ("KnightAttack"); DEFINE_ACTION_FUNCTION(AActor, A_DripBlood) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -42,7 +42,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DripBlood) DEFINE_ACTION_FUNCTION(AActor, A_KnightAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) { diff --git a/src/g_heretic/a_wizard.cpp b/src/g_heretic/a_wizard.cpp index e66bc5531d..271fd55926 100644 --- a/src/g_heretic/a_wizard.cpp +++ b/src/g_heretic/a_wizard.cpp @@ -20,7 +20,7 @@ static FRandom pr_wizatk3 ("WizAtk3"); DEFINE_ACTION_FUNCTION(AActor, A_GhostOff) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->RenderStyle = STYLE_Normal; self->flags3 &= ~MF3_GHOST; @@ -35,7 +35,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GhostOff) DEFINE_ACTION_FUNCTION(AActor, A_WizAtk1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_FaceTarget (self); CALL_ACTION(A_GhostOff, self); @@ -50,7 +50,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WizAtk1) DEFINE_ACTION_FUNCTION(AActor, A_WizAtk2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_FaceTarget (self); self->Alpha = HR_SHADOW; @@ -67,7 +67,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WizAtk2) DEFINE_ACTION_FUNCTION(AActor, A_WizAtk3) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; diff --git a/src/g_hexen/a_bats.cpp b/src/g_hexen/a_bats.cpp index 875910059f..5be91b69b4 100644 --- a/src/g_hexen/a_bats.cpp +++ b/src/g_hexen/a_bats.cpp @@ -27,7 +27,7 @@ static FRandom pr_batmove ("BatMove"); DEFINE_ACTION_FUNCTION(AActor, A_BatSpawnInit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->special1 = 0; // Frequency count return 0; @@ -35,7 +35,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BatSpawnInit) DEFINE_ACTION_FUNCTION(AActor, A_BatSpawn) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; int delta; @@ -64,7 +64,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BatSpawn) DEFINE_ACTION_FUNCTION(AActor, A_BatMove) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle newangle; diff --git a/src/g_hexen/a_bishop.cpp b/src/g_hexen/a_bishop.cpp index a88daa23b2..bd9f240618 100644 --- a/src/g_hexen/a_bishop.cpp +++ b/src/g_hexen/a_bishop.cpp @@ -24,7 +24,7 @@ static FRandom pr_pain ("BishopPainBlur"); DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (!self->target) { @@ -51,7 +51,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack) DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -78,7 +78,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack2) DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_Weave(self, 2, 2, 2., 1.); return 0; @@ -92,7 +92,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) DEFINE_ACTION_FUNCTION(AActor, A_BishopDecide) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (pr_decide() < 220) { @@ -113,7 +113,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopDecide) DEFINE_ACTION_FUNCTION(AActor, A_BishopDoBlur) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->special1 = (pr_doblur() & 3) + 3; // Random number of blurs if (pr_doblur() < 120) @@ -140,7 +140,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopDoBlur) DEFINE_ACTION_FUNCTION(AActor, A_BishopSpawnBlur) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -172,7 +172,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopSpawnBlur) DEFINE_ACTION_FUNCTION(AActor, A_BishopChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); double newz = self->Z() - BobSin(self->special2) / 2.; self->special2 = (self->special2 + 4) & 63; @@ -189,7 +189,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopChase) DEFINE_ACTION_FUNCTION(AActor, A_BishopPuff) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -209,7 +209,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopPuff) DEFINE_ACTION_FUNCTION(AActor, A_BishopPainBlur) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp index f906d247c1..0b0ab5d10e 100644 --- a/src/g_hexen/a_blastradius.cpp +++ b/src/g_hexen/a_blastradius.cpp @@ -95,7 +95,7 @@ enum DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT_OPT (blastflags) { blastflags = 0; } PARAM_FLOAT_OPT (strength) { strength = 255; } PARAM_FLOAT_OPT (radius) { radius = 255; } diff --git a/src/g_hexen/a_centaur.cpp b/src/g_hexen/a_centaur.cpp index 75049650d5..9bf5e60467 100644 --- a/src/g_hexen/a_centaur.cpp +++ b/src/g_hexen/a_centaur.cpp @@ -16,7 +16,7 @@ static FRandom pr_centaurdefend ("CentaurDefend"); DEFINE_ACTION_FUNCTION(AActor, A_CentaurDefend) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_FaceTarget (self); if (self->CheckMeleeRange() && pr_centaurdefend() < 32) diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp index a9c8b6378c..b03b9b6b9e 100644 --- a/src/g_hexen/a_clericflame.cpp +++ b/src/g_hexen/a_clericflame.cpp @@ -66,7 +66,7 @@ void ACFlameMissile::Effect () DEFINE_ACTION_FUNCTION(AActor, A_CFlameAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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,7 +159,7 @@ 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); diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index f660b1e7de..b87bd3986c 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -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_SELF_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_SELF_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 fce979af12..9b81489307 100644 --- a/src/g_hexen/a_clericmace.cpp +++ b/src/g_hexen/a_clericmace.cpp @@ -15,7 +15,7 @@ static FRandom pr_maceatk ("CMaceAttack"); DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle angle; int damage; diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index 6b54d4de3b..a0e6b94c66 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -46,7 +46,7 @@ int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetyp DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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_SELF_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_SELF_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 ca56525a9c..b79d92b368 100644 --- a/src/g_hexen/a_dragon.cpp +++ b/src/g_hexen/a_dragon.cpp @@ -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 a194869f3a..696dda019d 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -68,7 +68,7 @@ FState *AFWeapAxe::GetAtkState (bool hold) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReady) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -95,7 +95,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReady) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -122,7 +122,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUp) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -149,7 +149,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUp) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -176,7 +176,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -199,7 +199,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle angle; int power; diff --git a/src/g_hexen/a_fighterhammer.cpp b/src/g_hexen/a_fighterhammer.cpp index f8fbe33e35..faa15d8af0 100644 --- a/src/g_hexen/a_fighterhammer.cpp +++ b/src/g_hexen/a_fighterhammer.cpp @@ -25,7 +25,7 @@ static FRandom pr_hammeratk ("FHammerAtk"); DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle angle; int damage; @@ -95,7 +95,7 @@ hammerdone: DEFINE_ACTION_FUNCTION(AActor, A_FHammerThrow) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; player_t *player; diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index d946c689c2..020cec78e5 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -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_SELF_PROLOGUE(AActor); int damage; int i; diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index a86d4911a2..6a4daabb23 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -78,7 +78,7 @@ int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype DEFINE_ACTION_FUNCTION(AActor, A_FSwordAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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 index b60c904e3e..cc9beaaeb8 100644 --- a/src/g_hexen/a_firedemon.cpp +++ b/src/g_hexen/a_firedemon.cpp @@ -80,7 +80,7 @@ void A_FiredSpawnRock (AActor *actor) DEFINE_ACTION_FUNCTION(AActor, A_FiredRocks) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_FiredSpawnRock (self); A_FiredSpawnRock (self); @@ -98,7 +98,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredRocks) DEFINE_ACTION_FUNCTION(AActor, A_SmBounce) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); // give some more velocity (x,y,&z) self->SetZ(self->floorz + 1); @@ -116,7 +116,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SmBounce) DEFINE_ACTION_FUNCTION(AActor, A_FiredAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->target == NULL) return 0; @@ -133,7 +133,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredAttack) DEFINE_ACTION_FUNCTION(AActor, A_FiredChase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int weaveindex = self->special1; AActor *target = self->target; @@ -226,7 +226,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredChase) DEFINE_ACTION_FUNCTION(AActor, A_FiredSplotch) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index 3d9555843e..bc13d5cf77 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -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 1023c12aec..7281dd8f25 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 98dbf62b7f..6b2bc97069 100644 --- a/src/g_hexen/a_fog.cpp +++ b/src/g_hexen/a_fog.cpp @@ -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_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index 267320029b..03ffcc5d61 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -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_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index 61d5780d1a..866fc83722 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -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; @@ -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; @@ -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 d518c7db7b..1163a117a3 100644 --- a/src/g_hexen/a_iceguy.cpp +++ b/src/g_hexen/a_iceguy.cpp @@ -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 01457b91c2..2824d8c0aa 100644 --- a/src/g_hexen/a_korax.cpp +++ b/src/g_hexen/a_korax.cpp @@ -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 b33f937877..57e68c16f8 100644 --- a/src/g_hexen/a_magecone.cpp +++ b/src/g_hexen/a_magecone.cpp @@ -51,7 +51,7 @@ int AFrostMissile::DoSpecialDamage (AActor *victim, int damage, FName damagetype DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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 f322d88a68..e4390131a0 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -126,7 +126,7 @@ int ALightningZap::SpecialMissileHit (AActor *thing) DEFINE_ACTION_FUNCTION(AActor, A_LightningReady) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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,7 +257,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningZap) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MLightningAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(floor, AActor) { floor = PClass::FindActor("LightningFloor"); } PARAM_CLASS_OPT(ceiling, AActor) { ceiling = PClass::FindActor("LightningCeiling"); } @@ -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 ca846d794a..710af81982 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -122,7 +122,7 @@ void MStaffSpawn (AActor *pmo, DAngle angle, AActor *alttarget) DEFINE_ACTION_FUNCTION(AActor, A_MStaffAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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 11bfe3ce83..cafcbcda3f 100644 --- a/src/g_hexen/a_pig.cpp +++ b/src/g_hexen/a_pig.cpp @@ -58,7 +58,7 @@ void APigPlayer::MorphPlayerThink () DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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 1f6d1dd2b8..6f435747ed 100644 --- a/src/g_hexen/a_serpent.cpp +++ b/src/g_hexen/a_serpent.cpp @@ -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 1e81f568f6..3f5f4d2e83 100644 --- a/src/g_hexen/a_spike.cpp +++ b/src/g_hexen/a_spike.cpp @@ -79,7 +79,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 +92,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 +108,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 +137,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 +152,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 c9daad6ec1..e1b2bae096 100644 --- a/src/g_hexen/a_summon.cpp +++ b/src/g_hexen/a_summon.cpp @@ -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 a89e62b4b0..99d6876a51 100644 --- a/src/g_hexen/a_teleportother.cpp +++ b/src/g_hexen/a_teleportother.cpp @@ -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 f5c1f44f42..fcd0d75f34 100644 --- a/src/g_hexen/a_wraith.cpp +++ b/src/g_hexen/a_wraith.cpp @@ -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_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index e3636fe1b8..8bdbe122b0 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -135,7 +135,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) @@ -145,7 +145,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDeath) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player; @@ -180,7 +180,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; @@ -237,7 +237,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurCharge) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *puff; @@ -280,7 +280,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurCharge) DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; DAngle angle; @@ -330,7 +330,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; @@ -386,7 +386,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk3) DEFINE_ACTION_FUNCTION(AActor, A_MntrFloorFire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *mo; @@ -443,7 +443,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; @@ -491,7 +491,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))) { @@ -562,7 +562,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_shared/a_action.cpp b/src/g_shared/a_action.cpp index 3b11911314..abd58dec11 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -104,14 +104,14 @@ void A_Unblock(AActor *self, bool drop) DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_Unblock(self, true); return 0; } DEFINE_ACTION_FUNCTION(AActor, A_Fall) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_Unblock(self, true); return 0; } @@ -124,7 +124,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Fall) DEFINE_ACTION_FUNCTION(AActor, A_SetFloorClip) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 |= MF2_FLOORCLIP; self->AdjustFloorClip (); @@ -139,7 +139,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetFloorClip) DEFINE_ACTION_FUNCTION(AActor, A_UnSetFloorClip) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 &= ~MF2_FLOORCLIP; self->Floorclip = 0; @@ -154,7 +154,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_UnSetFloorClip) DEFINE_ACTION_FUNCTION(AActor, A_HideThing) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->renderflags |= RF_INVISIBLE; return 0; @@ -168,7 +168,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_HideThing) DEFINE_ACTION_FUNCTION(AActor, A_UnHideThing) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->renderflags &= ~RF_INVISIBLE; return 0; @@ -182,7 +182,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 +228,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 +243,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenericFreezeDeath) DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int floor; @@ -268,7 +268,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics) DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; int numChunks; @@ -446,7 +446,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 +458,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; @@ -483,7 +483,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeQueueCorpse) DEFINE_ACTION_FUNCTION(AActor, A_SetInvulnerable) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 |= MF2_INVULNERABLE; return 0; @@ -497,7 +497,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetInvulnerable) DEFINE_ACTION_FUNCTION(AActor, A_UnSetInvulnerable) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 &= ~MF2_INVULNERABLE; return 0; @@ -511,7 +511,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_UnSetInvulnerable) DEFINE_ACTION_FUNCTION(AActor, A_SetReflective) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 |= MF2_REFLECTIVE; return 0; @@ -525,7 +525,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetReflective) DEFINE_ACTION_FUNCTION(AActor, A_UnSetReflective) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 &= ~MF2_REFLECTIVE; return 0; @@ -539,7 +539,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_UnSetReflective) DEFINE_ACTION_FUNCTION(AActor, A_SetReflectiveInvulnerable) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 |= MF2_REFLECTIVE|MF2_INVULNERABLE; return 0; @@ -553,7 +553,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetReflectiveInvulnerable) DEFINE_ACTION_FUNCTION(AActor, A_UnSetReflectiveInvulnerable) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 &= ~(MF2_REFLECTIVE|MF2_INVULNERABLE); return 0; @@ -567,7 +567,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_UnSetReflectiveInvulnerable) DEFINE_ACTION_FUNCTION(AActor, A_SetShootable) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 &= ~MF2_NONSHOOTABLE; self->flags |= MF_SHOOTABLE; @@ -582,7 +582,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetShootable) DEFINE_ACTION_FUNCTION(AActor, A_UnSetShootable) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags2 |= MF2_NONSHOOTABLE; self->flags &= ~MF_SHOOTABLE; @@ -597,7 +597,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_UnSetShootable) DEFINE_ACTION_FUNCTION(AActor, A_NoGravity) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags |= MF_NOGRAVITY; return 0; @@ -611,7 +611,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoGravity) DEFINE_ACTION_FUNCTION(AActor, A_Gravity) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~MF_NOGRAVITY; self->Gravity = 1; @@ -626,7 +626,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Gravity) DEFINE_ACTION_FUNCTION(AActor, A_LowGravity) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~MF_NOGRAVITY; self->Gravity = 1. / 8;; diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 3161c2a45c..f3b12a1d16 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -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,7 +121,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BridgeInit) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(balltype, AActor) { balltype = NULL; } AActor *ball; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 38f0a51300..ae7516d173 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -355,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 ()) @@ -373,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)) @@ -393,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; @@ -418,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; diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 48a8ce1a18..1af9f6db7f 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -380,7 +380,7 @@ 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; } diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 84305b9cdc..d7f432a7a2 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -1922,7 +1922,7 @@ PClassWeapon *Net_ReadWeapon(BYTE **stream) DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_ZoomFactor) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT (zoom) { zoom = 1; } PARAM_INT_OPT (flags) { flags = 0; } @@ -1950,7 +1950,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_strife/a_acolyte.cpp b/src/g_strife/a_acolyte.cpp index 6f08a84c84..a21c06619e 100644 --- a/src/g_strife/a_acolyte.cpp +++ b/src/g_strife/a_acolyte.cpp @@ -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 d4103015cf..a1c20355fe 100644 --- a/src/g_strife/a_alienspectres.cpp +++ b/src/g_strife/a_alienspectres.cpp @@ -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_crusader.cpp b/src/g_strife/a_crusader.cpp index 8e340b820d..05835a5f98 100644 --- a/src/g_strife/a_crusader.cpp +++ b/src/g_strife/a_crusader.cpp @@ -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 b7f60e26ff..84a4b3fa3f 100644 --- a/src/g_strife/a_entityboss.cpp +++ b/src/g_strife/a_entityboss.cpp @@ -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; diff --git a/src/g_strife/a_inquisitor.cpp b/src/g_strife/a_inquisitor.cpp index 16871300a1..a4c2d72f4f 100644 --- a/src/g_strife/a_inquisitor.cpp +++ b/src/g_strife/a_inquisitor.cpp @@ -12,7 +12,7 @@ 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 2d695ac8df..5043245903 100644 --- a/src/g_strife/a_loremaster.cpp +++ b/src/g_strife/a_loremaster.cpp @@ -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 139786d893..f498499226 100644 --- a/src/g_strife/a_oracle.cpp +++ b/src/g_strife/a_oracle.cpp @@ -10,7 +10,7 @@ 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 9c8cb6be3a..b46b47e70d 100644 --- a/src/g_strife/a_programmer.cpp +++ b/src/g_strife/a_programmer.cpp @@ -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 09d771a19b..9c6e9f6b93 100644 --- a/src/g_strife/a_reaver.cpp +++ b/src/g_strife/a_reaver.cpp @@ -13,7 +13,7 @@ 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 c4df1cba11..e460dd91aa 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -22,7 +22,7 @@ static FRandom pr_shootgun ("ShootGun"); DEFINE_ACTION_FUNCTION(AActor, A_ShootGun) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle pitch; @@ -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 42a7aeb476..44946c84ac 100644 --- a/src/g_strife/a_sentinel.cpp +++ b/src/g_strife/a_sentinel.cpp @@ -11,7 +11,7 @@ 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 1b1f13b1af..b348e54dc9 100644 --- a/src/g_strife/a_spectral.cpp +++ b/src/g_strife/a_spectral.cpp @@ -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 210bd8c22a..9189ef8de6 100644 --- a/src/g_strife/a_stalker.cpp +++ b/src/g_strife/a_stalker.cpp @@ -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 20de58d4f9..6cda8a0fcf 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -23,7 +23,7 @@ IMPLEMENT_CLASS(ADegninOre) DEFINE_ACTION_FUNCTION(AActor, A_RemoveForceField) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~MF_SPECIAL; diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 32ce0e3958..ef60b77e7e 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -87,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; @@ -97,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; @@ -109,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) @@ -128,7 +128,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GetHurt) DEFINE_ACTION_FUNCTION(AActor, A_TurretLook) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *target; @@ -160,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) { @@ -249,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); @@ -269,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)) { @@ -280,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) { @@ -292,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)) { @@ -303,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; @@ -332,7 +332,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain) DEFINE_ACTION_FUNCTION(AActor, A_ClearSoundTarget) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *actor; @@ -347,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); @@ -365,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.; @@ -375,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) { @@ -401,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 66d635aa53..91f4ac75e7 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -94,7 +94,7 @@ void P_DaggerAlert (AActor *target, AActor *emitter) DEFINE_ACTION_FUNCTION(AActor, A_JabDagger) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); DAngle angle; int damage; @@ -146,7 +146,7 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_AlertMonsters) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(maxdist) { maxdist = 0; } PARAM_INT_OPT(Flags) { Flags = 0; } @@ -212,7 +212,7 @@ int APoisonBolt::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_ClearFlash) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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_SELF_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_SELF_PROLOGUE(AActor); bool accurate; @@ -343,7 +343,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireAssaultGun) DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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_SELF_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_SELF_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_SELF_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; @@ -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_SELF_PROLOGUE(AActor); PARAM_CLASS(grenadetype, AActor); PARAM_ANGLE(angleofs); PARAM_STATE(flash) @@ -821,7 +821,7 @@ AInventory *ASigil::CreateCopy (AActor *other) DEFINE_ACTION_FUNCTION(AActor, A_SelectPiece) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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_SELF_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_SELF_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_SELF_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_SELF_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_SELF_PROLOGUE(AActor); AActor *spot; player_t *player = self->player; @@ -1007,7 +1007,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_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_SELF_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_SELF_PROLOGUE(AActor); AActor *spot; player_t *player = self->player; @@ -1103,7 +1103,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil5) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player = self->player; diff --git a/src/g_strife/a_templar.cpp b/src/g_strife/a_templar.cpp index 5ca2ef862b..0bfa00b24e 100644 --- a/src/g_strife/a_templar.cpp +++ b/src/g_strife/a_templar.cpp @@ -13,7 +13,7 @@ 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 6d1294b53d..5e1bc42d2c 100644 --- a/src/g_strife/a_thingstoblowup.cpp +++ b/src/g_strife/a_thingstoblowup.cpp @@ -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/info.h b/src/info.h index 0fe479d20e..5e1d045f23 100644 --- a/src/info.h +++ b/src/info.h @@ -360,14 +360,12 @@ void AddStateLight(FState *state, const char *lname); // 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) \ +#define PARAM_ACTION_PROLOGUE(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 diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index bbeeca3743..f389cd1eeb 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -891,7 +891,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TransferPointer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopyFriendliness) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT (ptr_source) { ptr_source = AAPTR_MASTER; } if (self->player != NULL) @@ -914,28 +914,28 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopyFriendliness) //========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_SetSolid) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags |= MF_SOLID; return 0; } DEFINE_ACTION_FUNCTION(AActor, A_UnsetSolid) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~MF_SOLID; return 0; } DEFINE_ACTION_FUNCTION(AActor, A_SetFloat) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags |= MF_FLOAT; return 0; } DEFINE_ACTION_FUNCTION(AActor, A_UnsetFloat) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->flags &= ~(MF_FLOAT|MF_INFLOAT); return 0; } @@ -980,7 +980,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); @@ -989,7 +989,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; @@ -997,7 +997,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); @@ -1028,7 +1028,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BasicAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND_OPT (soundid) { soundid = "weapons/pistol"; } PARAM_INT_OPT (channel) { channel = CHAN_BODY; } PARAM_FLOAT_OPT (volume) { volume = 1; } @@ -1051,7 +1051,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSound) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(slot) { slot = CHAN_VOICE; } S_StopSound(self, slot); @@ -1167,7 +1167,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SeekerMissile) //========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); int i; @@ -1415,7 +1415,7 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT (damage) { damage = -1; } PARAM_INT_OPT (distance) { distance = -1; } PARAM_INT_OPT (flags) { flags = XF_HURTSOURCE; } @@ -1484,7 +1484,7 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT (force) { force = 128; } PARAM_INT_OPT (distance) { distance = -1; } PARAM_INT_OPT (flags) { flags = RTF_AFFECTSOURCE; } @@ -1524,7 +1524,7 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusDamageSelf) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(damage) { damage = 128; } PARAM_FLOAT_OPT(distance) { distance = 128; } PARAM_INT_OPT(flags) { flags = 0; } @@ -1859,7 +1859,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) //========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMeleeAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT (damage) { damage = 0; } PARAM_SOUND_OPT (meleesound) { meleesound = 0; } PARAM_SOUND_OPT (misssound) { misssound = 0; } @@ -1946,7 +1946,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack) //========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfNoAmmo) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE(jump); if (!ACTION_CALL_FROM_PSPRITE() || self->player->ReadyWeapon == nullptr) @@ -2017,7 +2017,7 @@ 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); @@ -2147,7 +2147,7 @@ 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; } @@ -2224,7 +2224,7 @@ 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; } @@ -2328,7 +2328,7 @@ 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; } @@ -2632,7 +2632,7 @@ 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; } @@ -3012,7 +3012,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS_OPT (missile, AActor) { missile = PClass::FindActor("Unknown"); } PARAM_FLOAT_OPT (distance) { distance = 0; } PARAM_FLOAT_OPT (zheight) { zheight = 0; } @@ -3144,7 +3144,7 @@ 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; } @@ -3442,7 +3442,7 @@ enum FadeFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(reduce) { reduce = 0.1; } PARAM_INT_OPT(flags) { flags = 0; } @@ -3476,7 +3476,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeOut) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(reduce) { reduce = 0.1; } PARAM_INT_OPT(flags) { flags = FTF_REMOVE; } @@ -4036,7 +4036,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)) { @@ -4074,7 +4074,7 @@ enum RS_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(flags) { flags = RSF_FOG; } bool oktorespawn = false; @@ -4189,7 +4189,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetGravity) DEFINE_ACTION_FUNCTION(AActor, A_ClearTarget) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); self->target = NULL; self->LastHeard = NULL; self->lastenemy = NULL; @@ -4747,7 +4747,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if ( self->player == NULL || self->player->ReadyWeapon == NULL ) { @@ -4800,7 +4800,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) DEFINE_ACTION_FUNCTION(AActor, A_ResetReloadCounter) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player == NULL || self->player->ReadyWeapon == NULL) return 0; @@ -4859,7 +4859,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) //=========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_RaiseMaster) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_OPT(copy) { copy = false; } if (self->master != NULL) @@ -4876,7 +4876,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseMaster) //=========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_OPT(copy) { copy = false; } TThinkerIterator it; @@ -4899,7 +4899,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren) //=========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_OPT(copy) { copy = false; } TThinkerIterator it; @@ -4975,7 +4975,7 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(angle) { angle = 0; } PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } @@ -5077,7 +5077,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ScaleVelocity) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT (x) { x = 0; } PARAM_FLOAT_OPT (y) { y = 0; } PARAM_FLOAT_OPT (z) { z = 0; } @@ -5302,7 +5302,7 @@ enum T_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); 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"); } @@ -5478,7 +5478,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Turn) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(angle) { angle = 0; } self->Angles.Yaw += angle; return 0; @@ -5606,7 +5606,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Weave) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LineEffect) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(special) { special = 0; } PARAM_INT_OPT(tag) { tag = 0; } @@ -5641,7 +5641,7 @@ enum WolfAttackFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT (flags) { flags = 0; } PARAM_SOUND_OPT (sound) { sound = "weapons/pistol"; } PARAM_FLOAT_OPT (snipe) { snipe = 1.; } @@ -5746,7 +5746,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT(destination_selector); PARAM_FLOAT_OPT(xofs) { xofs = 0; } PARAM_FLOAT_OPT(yofs) { yofs = 0; } @@ -6170,7 +6170,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()) @@ -6567,7 +6567,7 @@ static void DoKill(AActor *killtarget, AActor *inflictor, AActor *source, FName //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } @@ -6590,7 +6590,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } @@ -6613,7 +6613,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } @@ -6636,7 +6636,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } @@ -6667,7 +6667,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } @@ -6743,7 +6743,7 @@ static void DoRemove(AActor *removetarget, int flags, PClassActor *filter, FName //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } @@ -6762,7 +6762,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } @@ -6781,7 +6781,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } @@ -6800,7 +6800,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_OPT (removeall) { removeall = false; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } @@ -6826,7 +6826,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_OPT (removeall) { removeall = false; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } @@ -6897,7 +6897,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; @@ -6974,7 +6974,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetHealth) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } AActor *mobj = COPY_AAPTR(self, ptr); @@ -7291,7 +7291,7 @@ enum FMDFlags }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_OPT(offset) { offset = 0.; } PARAM_ANGLE_OPT(anglelimit) { anglelimit = 0.; } PARAM_ANGLE_OPT(pitchlimit) { pitchlimit = 0.; } @@ -7385,7 +7385,7 @@ 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; } @@ -7412,7 +7412,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpriteAngle) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(angle) { angle = 0.; } PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } @@ -7435,7 +7435,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpriteAngle) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpriteRotation) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_OPT(angle) { angle = 0.; } PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } @@ -7466,7 +7466,7 @@ enum VRFFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetVisibleRotation) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_OPT(anglestart) { anglestart = 0.; } PARAM_ANGLE_OPT(angleend) { angleend = 0.; } PARAM_ANGLE_OPT(pitchstart) { pitchstart = 0.; } diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 5f63ff1e5f..1a2bddda49 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1789,7 +1789,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; @@ -1909,7 +1909,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT (flags) { flags = 0; } PARAM_FLOAT_OPT (minseedist) { minseedist = 0; } PARAM_FLOAT_OPT (maxseedist) { maxseedist = 0; } @@ -2101,7 +2101,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; } @@ -2126,7 +2126,7 @@ enum ChaseFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Wander) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(flags) { flags = 0; } A_Wander(self, flags); return 0; @@ -2186,7 +2186,7 @@ void A_Wander(AActor *self, int flags) //========================================================================== DEFINE_ACTION_FUNCTION(AActor, A_Look2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); AActor *targ; @@ -2768,7 +2768,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_STATE_OPT (melee) { melee = NULL; } PARAM_STATE_OPT (missile) { missile = NULL; } PARAM_INT_OPT (flags) { flags = 0; } @@ -2790,14 +2790,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); @@ -2947,7 +2947,7 @@ void A_FaceTarget(AActor *self) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_OPT(max_turn) { max_turn = 0.; } PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270.; } PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0.; } @@ -2961,7 +2961,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_OPT(max_turn) { max_turn = 0.; } PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270.; } PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0.; } @@ -2975,7 +2975,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_OPT(max_turn) { max_turn = 0.; } PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270.; } PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0.; } @@ -2996,7 +2996,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; @@ -3042,7 +3042,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. @@ -3061,7 +3061,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 @@ -3077,7 +3077,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_XScream) DEFINE_ACTION_FUNCTION(AActor, A_ScreamAndUnblock) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); CALL_ACTION(A_Scream, self); A_Unblock(self, true); return 0; @@ -3091,7 +3091,7 @@ 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); @@ -3107,7 +3107,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ActiveSound) DEFINE_ACTION_FUNCTION(AActor, A_ActiveAndUnblock) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); CALL_ACTION(A_ActiveSound, self); A_Unblock(self, true); return 0; @@ -3257,7 +3257,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) @@ -3306,7 +3306,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain) // killough 11/98: kill an object DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Die) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_OPT (damagetype) { damagetype = NAME_None; } P_DamageMobj(self, NULL, NULL, self->health, damagetype, DMG_FORCED); @@ -3320,7 +3320,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); @@ -3463,7 +3463,7 @@ void A_BossDeath(AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_BossDeath) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); A_BossDeath(self); return 0; } @@ -3541,7 +3541,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_pspr.cpp b/src/p_pspr.cpp index e2e0778ab4..055649466d 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -743,7 +743,7 @@ void DoReadyWeapon(AActor *self) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(flags) { flags = 0; } DoReadyWeaponToSwitch(self, !(flags & WRF_NoSwitch)); @@ -875,7 +875,7 @@ static void P_CheckWeaponButtons (player_t *player) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_ReFire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_STATE_OPT(state) { state = NULL; } A_ReFire(self, state); return 0; @@ -913,7 +913,7 @@ void A_ReFire(AActor *self, FState *state) DEFINE_ACTION_FUNCTION(AInventory, A_ClearReFire) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player = self->player; if (NULL != player) @@ -935,7 +935,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_ClearReFire) DEFINE_ACTION_FUNCTION(AInventory, A_CheckReload) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player != NULL) { @@ -1002,7 +1002,7 @@ void A_OverlayOffset(AActor *self, int layer, double wx, double wy, int flags) DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT_OPT(layer) { layer = PSP_WEAPON; } PARAM_FLOAT_OPT(wx) { wx = 0.; } PARAM_FLOAT_OPT(wy) { wy = 32.; } @@ -1013,7 +1013,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset) DEFINE_ACTION_FUNCTION(AActor, A_WeaponOffset) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_OPT(wx) { wx = 0.; } PARAM_FLOAT_OPT(wy) { wy = 32.; } PARAM_INT_OPT(flags) { flags = 0; } @@ -1029,7 +1029,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); @@ -1072,7 +1072,7 @@ static double GetOverlayPosition(AActor *self, int layer, bool gety) DEFINE_ACTION_FUNCTION(AActor, OverlayX) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT_OPT(layer) { layer = 0; } if (ACTION_CALL_FROM_PSPRITE()) @@ -1085,7 +1085,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayX) DEFINE_ACTION_FUNCTION(AActor, OverlayY) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT_OPT(layer) { layer = 0; } if (ACTION_CALL_FROM_PSPRITE()) @@ -1104,7 +1104,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayY) DEFINE_ACTION_FUNCTION(AActor, OverlayID) { - PARAM_ACTION_PROLOGUE; + PARAM_ACTION_PROLOGUE(AActor); if (ACTION_CALL_FROM_PSPRITE()) { @@ -1123,7 +1123,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayID) DEFINE_ACTION_FUNCTION(AInventory, A_Lower) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); player_t *player = self->player; DPSprite *psp; @@ -1171,7 +1171,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Lower) DEFINE_ACTION_FUNCTION(AInventory, A_Raise) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self == nullptr) { @@ -1212,7 +1212,7 @@ 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; } @@ -1232,7 +1232,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Overlay) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ClearOverlays) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT_OPT(start) { start = 0; } PARAM_INT_OPT(stop) { stop = 0; } PARAM_BOOL_OPT(safety) { safety = true; } @@ -1283,7 +1283,7 @@ enum GF_Flags DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_STATE_OPT(flash) { flash = nullptr; } PARAM_INT_OPT (flags) { flags = 0; } @@ -1373,7 +1373,7 @@ void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch) DEFINE_ACTION_FUNCTION(AInventory, A_Light0) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player != NULL) { @@ -1384,7 +1384,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Light0) DEFINE_ACTION_FUNCTION(AInventory, A_Light1) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player != NULL) { @@ -1395,7 +1395,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Light1) DEFINE_ACTION_FUNCTION(AInventory, A_Light2) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); if (self->player != NULL) { @@ -1406,7 +1406,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Light2) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_Light) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_INT(light); if (self->player != NULL) diff --git a/src/p_user.cpp b/src/p_user.cpp index 7cea484de5..00d22a9bae 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1546,7 +1546,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; @@ -1622,7 +1622,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop) { - PARAM_ACTION_PROLOGUE; + PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_OPT(spawntype, APlayerChunk) { spawntype = NULL; } APlayerPawn *mo; @@ -1672,7 +1672,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/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 1de5c13c2f..c4a466873a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5281,50 +5281,31 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } } - // If both functions are non-action or both are action, there is no need for special treatment. - //if (elf || (!!(Function->Variants[0].Flags & VARF_Action) == build->IsActionFunc)) + // Emit code to pass implied parameters + if (Function->Variants[0].Flags & VARF_Method) { - // Emit code to pass implied parameters - if (Function->Variants[0].Flags & VARF_Method) - { - assert(Self != nullptr); - Self->Emit(build); - count += 1; - } - if (Function->Variants[0].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; - } + assert(Self != nullptr); + ExpEmit selfemit = Self->Emit(build); + assert(selfemit.RegType == REGT_POINTER); + build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); + count += 1; } - /* - else + if (Function->Variants[0].Flags & VARF_Action) { - if (build->IsActionFunc && (Function->Variants[0].Flags & VARF_Method)) + static_assert(NAP == 3, "This code needs to be updated if NAP changes"); + if (build->IsActionFunc) { - build->Emit(OP_PARAM, 0, REGT_POINTER, 0); - count += 1; + build->Emit(OP_PARAM, 0, REGT_POINTER, 1); + build->Emit(OP_PARAM, 0, REGT_POINTER, 2); } - // and calling an action function from a non-action function. - // This must be blocked because it lacks crucial information. - if (!build->IsActionFunc && (Function->Variants[0].Flags & VARF_Action)) + else { - // This case should be eliminated in the analyzing stage. - I_Error("Cannot call action function from non-action functions."); + 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) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 4c09e86640..5144a1bd09 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -68,139 +68,139 @@ class Actor : Thinker native // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. - action native void A_Turn(float angle = 0); - action native bool A_LineEffect(int boomspecial = 0, int tag = 0); + native void A_Turn(float angle = 0); + native bool A_LineEffect(int boomspecial = 0, int tag = 0); // End of MBF redundant functions. - action native void A_MonsterRail(); - action 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); - action native void A_Pain(); - action native void A_NoBlocking(); - action native void A_XScream(); - action native void A_Look(); - action native void A_Chase(state melee = "*", state missile = "none", int flags = 0); - action native void A_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); - action native void A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); - action native void A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); - action native void A_PosAttack(); - action native void A_Scream(); - action native void A_SPosAttack(); - action native void A_SPosAttackUseAtkSound(); - action native void A_VileChase(); - action native void A_VileStart(); - action native void A_VileTarget(class fire = "ArchvileFire"); - action native void 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 void A_StartFire(); - action native void A_Fire(float spawnheight = 0); - action native void A_FireCrackle(); - action native void A_Tracer(); - action native void A_SkelWhoosh(); - action native void A_SkelFist(); - action native void A_SkelMissile(); - action native void A_FatRaise(); - action native void A_FatAttack1(class spawntype = "FatShot"); - action native void A_FatAttack2(class spawntype = "FatShot"); - action native void A_FatAttack3(class spawntype = "FatShot"); - action native void A_BossDeath(); - action native void A_CPosAttack(); - action native void A_CPosRefire(); - action native void A_TroopAttack(); - action native void A_SargAttack(); - action native void A_HeadAttack(); - action native void A_BruisAttack(); - action native void A_SkullAttack(float speed = 20); - action native void A_BetaSkullAttack(); - action native void A_Metal(); - action native void A_SpidRefire(); - action native void A_BabyMetal(); - action native void A_BspiAttack(); - action native void A_Hoof(); - action native void A_CyberAttack(); - action native void A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); - action native void A_DualPainAttack(class spawntype = "LostSoul"); - action native void A_PainDie(class spawntype = "LostSoul"); - action native void A_KeenDie(int doortag = 666); - action native void A_BrainPain(); - action native void A_BrainScream(); - action native void A_BrainDie(); - action native void A_BrainAwake(); - action native void A_BrainSpit(class spawntype = "none"); // needs special treatment for default - action native void A_SpawnSound(); - action native void A_SpawnFly(class spawntype = "none"); // needs special treatment for default - action native void A_BrainExplode(); - action native void A_Die(name damagetype = "none"); - action native void A_Detonate(); - action native void A_Mushroom(class spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5); + 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(); + native void A_XScream(); + native void A_Look(); + native void A_Chase(state melee = "*", state missile = "none", int flags = 0); + native void A_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); + native void A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); + native void A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); + native void A_PosAttack(); + native void A_Scream(); + native void A_SPosAttack(); + native void A_SPosAttackUseAtkSound(); + native void A_VileChase(); + native void A_VileStart(); + native void A_VileTarget(class fire = "ArchvileFire"); + native void 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); + native void A_StartFire(); + native void A_Fire(float spawnheight = 0); + native void A_FireCrackle(); + native void A_Tracer(); + native void A_SkelWhoosh(); + native void A_SkelFist(); + native void A_SkelMissile(); + native void A_FatRaise(); + native void A_FatAttack1(class spawntype = "FatShot"); + native void A_FatAttack2(class spawntype = "FatShot"); + native void A_FatAttack3(class spawntype = "FatShot"); + native void A_BossDeath(); + native void A_CPosAttack(); + native void A_CPosRefire(); + native void A_TroopAttack(); + native void A_SargAttack(); + native void A_HeadAttack(); + native void A_BruisAttack(); + native void A_SkullAttack(float speed = 20); + native void A_BetaSkullAttack(); + native void A_Metal(); + native void A_SpidRefire(); + native void A_BabyMetal(); + native void A_BspiAttack(); + native void A_Hoof(); + native void A_CyberAttack(); + native void A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); + native void A_DualPainAttack(class spawntype = "LostSoul"); + native void A_PainDie(class spawntype = "LostSoul"); + native void A_KeenDie(int doortag = 666); + native void A_BrainPain(); + native void A_BrainScream(); + native void A_BrainDie(); + native void A_BrainAwake(); + native void A_BrainSpit(class spawntype = "none"); // needs special treatment for default + native void A_SpawnSound(); + native void A_SpawnFly(class spawntype = "none"); // needs special treatment for default + native void A_BrainExplode(); + native void A_Die(name damagetype = "none"); + native void A_Detonate(); + native void 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 void A_SetFloorClip(); - action native void A_UnSetFloorClip(); - action native void A_HideThing(); - action native void A_UnHideThing(); - action native void A_SetInvulnerable(); - action native void A_UnSetInvulnerable(); - action native void A_SetReflective(); - action native void A_UnSetReflective(); - action native void A_SetReflectiveInvulnerable(); - action native void A_UnSetReflectiveInvulnerable(); - action native void A_SetShootable(); - action native void A_UnSetShootable(); - action native void A_NoGravity(); - action native void A_Gravity(); - action native void A_LowGravity(); + native void A_SetFloorClip(); + native void A_UnSetFloorClip(); + native void A_HideThing(); + native void A_UnHideThing(); + native void A_SetInvulnerable(); + native void A_UnSetInvulnerable(); + native void A_SetReflective(); + native void A_UnSetReflective(); + native void A_SetReflectiveInvulnerable(); + native void A_UnSetReflectiveInvulnerable(); + native void A_SetShootable(); + native void A_UnSetShootable(); + native void A_NoGravity(); + native void A_Gravity(); + native void A_LowGravity(); native void A_SetGravity(float gravity); - action native void A_Fall(); - action native void A_SetSolid(); - action native void A_UnsetSolid(); - action native void A_SetFloat(); - action native void A_UnsetFloat(); + native void A_Fall(); + native void A_SetSolid(); + native void A_UnsetSolid(); + native void A_SetFloat(); + native void A_UnsetFloat(); - action native void A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); + native void A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); - action native void A_ScreamAndUnblock(); - action native void A_ActiveAndUnblock(); - action native void A_ActiveSound(); + native void A_ScreamAndUnblock(); + native void A_ActiveAndUnblock(); + native void A_ActiveSound(); - action native void A_FastChase(); - action native void A_FreezeDeath(); - action native void A_FreezeDeathChunks(); - action native void A_GenericFreezeDeath(); - action native void A_IceGuyDie(); - action native void A_CentaurDefend(); - action native void A_BishopMissileWeave(); - action native void A_CStaffMissileSlither(); - action native void A_PlayerScream(); - action native void A_SkullPop(class skulltype = "BloodySkull"); - action native void A_CheckPlayerDone(); + native void A_FastChase(); + native void A_FreezeDeath(); + native void A_FreezeDeathChunks(); + native void A_GenericFreezeDeath(); + native void A_IceGuyDie(); + native void A_CentaurDefend(); + native void A_BishopMissileWeave(); + native void A_CStaffMissileSlither(); + native void A_PlayerScream(); + native void A_SkullPop(class skulltype = "BloodySkull"); + native void A_CheckPlayerDone(); - action native void A_Wander(int flags = 0); - action native void A_Look2(); - action native void A_TossGib(); - action native void A_SentinelBob(); - action native void A_SentinelRefire(); - action native void A_Tracer2(); - action native void A_SetShadow(); - action native void A_ClearShadow(); - action native void A_GetHurt(); - action native void A_TurretLook(); - action native void A_KlaxonBlare(); - action native void A_Countdown(); - action native void A_AlertMonsters(float maxdist = 0, int flags = 0); - action native void A_ClearSoundTarget(); - action native void A_FireAssaultGun(); - action native void A_CheckTerrain(); - action native void A_FaceConsolePlayer(float MaxTurnAngle = 0); // [TP] no-op + 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_FireAssaultGun(); + native void A_CheckTerrain(); + native void A_FaceConsolePlayer(float MaxTurnAngle = 0); // [TP] no-op - deprecated action native void A_MissileAttack(); - deprecated action native void A_MeleeAttack(); - deprecated action native void A_ComboAttack(); - deprecated action native void A_BulletAttack(); - action 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"); - action native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM); + 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); native void A_PlayWeaponSound(sound whattoplay); - action native void A_FLoopActiveSound(); - action native void A_LoopActiveSound(); - action native void A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was... + 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); @@ -227,8 +227,8 @@ class Actor : Thinker native 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 void A_FadeIn(float reduce = 0.1, int flags = 0); - action native void A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true + 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_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false); native void A_SetMass(int mass); @@ -241,15 +241,15 @@ class Actor : Thinker native 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 void A_RaiseMaster(bool copy = 0); - action native void A_RaiseChildren(bool copy = 0); - action native void A_RaiseSiblings(bool copy = 0); + native void A_RaiseMaster(bool copy = 0); + native void A_RaiseChildren(bool copy = 0); + native void A_RaiseSiblings(bool copy = 0); native state A_CheckFloor(state label); native state A_CheckCeiling(state label); native state A_PlayerSkinCheck(state label); deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); - 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); + native state, bool A_Teleport(state teleportstate = "", class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT); + native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "", float heightoffset = 0, float radiusoffset = 0, float pitch = 0); 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); @@ -260,42 +260,42 @@ class Actor : Thinker native 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 void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); + 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"); - action native void A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0); - action native void 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 void A_Stop(); - action native void A_Respawn(int flags = 1); - action native void A_BarrelDestroy(); - action native void A_QueueCorpse(); - action native void A_DeQueueCorpse(); - action native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = ""); - action native void A_ClearLastHeard(); - action native void A_ClearTarget(); + 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 = "None"); + 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_BarrelDestroy(); + native void A_QueueCorpse(); + native void A_DeQueueCorpse(); + native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = ""); + native void A_ClearLastHeard(); + native void A_ClearTarget(); native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, float offsetforward = 0); native state A_JumpIfTargetInLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); native state A_JumpIfInTargetLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); native bool A_SelectWeapon(class whichweapon, int flags = 0); action native void A_Punch(); - action native void A_Feathers(); - action native void A_ClassBossHealth(); - action native void A_ShootGun(); - action native void A_RocketInFlight(); - action native void A_Bang4Cloud(); - action native void A_DropFire(); + 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); - action native void A_RemoveForcefield(); + native void A_RemoveForcefield(); native void A_DropWeaponPieces(class p1, class p2, class p3); - action native void A_PigPain (); + native void A_PigPain (); native state A_MonsterRefire(int chance, state label); - action native void A_SetAngle(float angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + 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); - action native void A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + native void 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); deprecated native void A_SetUserVar(name varname, int value); deprecated native void A_SetUserArray(name varname, int index, int value); @@ -316,26 +316,26 @@ class Actor : Thinker native 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 void A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native void A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native void A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native void A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native void A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - action native void A_RemoveTarget(int flags = 0, class filter = "None", name species = "None"); - action native void A_RemoveMaster(int flags = 0, class filter = "None", name species = "None"); - action native void A_RemoveTracer(int flags = 0, class filter = "None", name species = "None"); - action native void A_RemoveChildren(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); - action native void A_RemoveSiblings(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); + native void A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_RemoveTarget(int flags = 0, class filter = "None", name species = "None"); + native void A_RemoveMaster(int flags = 0, class filter = "None", name species = "None"); + native void A_RemoveTracer(int flags = 0, class filter = "None", name species = "None"); + native void A_RemoveChildren(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); + native void 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 void A_SwapTeleFog(); + native void A_SwapTeleFog(); native void A_SetFloatBobPhase(int bob); native void A_SetHealth(int health, int ptr = AAPTR_DEFAULT); - action native void A_ResetHealth(int ptr = AAPTR_DEFAULT); + native void 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); @@ -346,20 +346,20 @@ class Actor : Thinker native 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 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_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT); + native bool A_SetSpriteRotation(float angle = 0, int ptr = AAPTR_DEFAULT); + 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 void A_CopyFriendliness(int ptr_source = AAPTR_MASTER); + native void A_CopyFriendliness(int ptr_source = AAPTR_MASTER); action native bool A_Overlay(int layer, state start = "", bool nooverride = false); - action native void A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0); + native void A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0); action native void A_OverlayOffset(int layer = PSP_WEAPON, float wx = 0, float wy = 32, int flags = 0); action native void A_OverlayFlags(int layer, int flags, bool set); diff --git a/wadsrc/static/zscript/doom/scriptedmarine.txt b/wadsrc/static/zscript/doom/scriptedmarine.txt index 358bf4ea45..7a82513cb8 100644 --- a/wadsrc/static/zscript/doom/scriptedmarine.txt +++ b/wadsrc/static/zscript/doom/scriptedmarine.txt @@ -19,22 +19,22 @@ class ScriptedMarine : Actor native PainSound "*pain50"; } - action native void A_M_Refire (bool ignoremissile=false); - action native void A_M_CheckAttack (); - action native void A_MarineChase (); - action native void A_MarineLook (); - action native void A_MarineNoise (); - action native void A_M_Punch (int force); - action native void A_M_SawRefire (); - action native void A_M_FirePistol (bool accurate); - action native void A_M_FireShotgun (); - action native void A_M_FireShotgun2 (); - action native void A_M_FireCGun(bool accurate); - action native void A_M_FireMissile (); - action native void A_M_FirePlasma (); - action native void A_M_FireRailgun (); - action native void A_M_BFGsound (); - action native void A_M_FireBFG (); + 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 { diff --git a/wadsrc/static/zscript/heretic/chicken.txt b/wadsrc/static/zscript/heretic/chicken.txt index 2e5ada81c8..77e2b0a92e 100644 --- a/wadsrc/static/zscript/heretic/chicken.txt +++ b/wadsrc/static/zscript/heretic/chicken.txt @@ -26,8 +26,8 @@ class Beak : Weapon Weapon.SisterWeapon "BeakPowered"; } - action native void A_BeakRaise (); - action native void A_BeakAttackPL1(); + native void A_BeakRaise (); + native void A_BeakAttackPL1(); States { @@ -55,7 +55,7 @@ class BeakPowered : Beak Weapon.SisterWeapon "Beak"; } - action native void A_BeakAttackPL2(); + native void A_BeakAttackPL2(); States { diff --git a/wadsrc/static/zscript/heretic/dsparil.txt b/wadsrc/static/zscript/heretic/dsparil.txt index ebf60eb47b..8cd60c8bb4 100644 --- a/wadsrc/static/zscript/heretic/dsparil.txt +++ b/wadsrc/static/zscript/heretic/dsparil.txt @@ -38,10 +38,10 @@ class Sorcerer1 : Actor HitObituary "$OB_DSPARIL1HIT"; } - action native void A_Sor1Pain (); - action native void A_Sor1Chase (); - action native void A_Srcr1Attack (); - action native void A_SorcererRise (); + native void A_Sor1Pain (); + native void A_Sor1Chase (); + native void A_Srcr1Attack (); + native void A_SorcererRise (); States { @@ -142,10 +142,10 @@ class Sorcerer2 : Actor HitObituary "$OB_DSPARIL2HIT"; } - action native void A_Srcr2Decide (); - action native void A_Srcr2Attack (); - action native void A_Sor2DthInit (); - action native void A_Sor2DthLoop (); + native void A_Srcr2Decide (); + native void A_Srcr2Attack (); + native void A_Sor2DthInit (); + native void A_Sor2DthLoop (); States { @@ -210,7 +210,7 @@ class Sorcerer2FX1 : Actor RenderStyle "Add"; } - action native void A_BlueSpark (); + native void A_BlueSpark (); States { @@ -263,7 +263,7 @@ class Sorcerer2FX2 : Actor RenderStyle "Add"; } - action native void A_GenWizard (); + native void A_GenWizard (); States { diff --git a/wadsrc/static/zscript/heretic/hereticartifacts.txt b/wadsrc/static/zscript/heretic/hereticartifacts.txt index 154f48ad3b..94271c8cdd 100644 --- a/wadsrc/static/zscript/heretic/hereticartifacts.txt +++ b/wadsrc/static/zscript/heretic/hereticartifacts.txt @@ -80,7 +80,7 @@ Class ActivatedTimeBomb : Actor DeathSound "misc/timebomb"; } - action native void A_Timebomb(); + native void A_Timebomb(); States { diff --git a/wadsrc/static/zscript/heretic/hereticimp.txt b/wadsrc/static/zscript/heretic/hereticimp.txt index 9f5c0a23e1..5764094de4 100644 --- a/wadsrc/static/zscript/heretic/hereticimp.txt +++ b/wadsrc/static/zscript/heretic/hereticimp.txt @@ -26,10 +26,10 @@ class HereticImp : Actor HitObituary "$OB_HERETICIMPHIT"; } - action native void A_ImpMsAttack(); - action native void A_ImpDeath(); - action native void A_ImpXDeath1(); - action native void A_ImpExplode(); + native void A_ImpMsAttack(); + native void A_ImpDeath(); + native void A_ImpXDeath1(); + native void A_ImpExplode(); States diff --git a/wadsrc/static/zscript/heretic/hereticmisc.txt b/wadsrc/static/zscript/heretic/hereticmisc.txt index 0b90208b9f..f858a6fa25 100644 --- a/wadsrc/static/zscript/heretic/hereticmisc.txt +++ b/wadsrc/static/zscript/heretic/hereticmisc.txt @@ -16,8 +16,8 @@ class Pod : Actor DeathSound "world/podexplode"; PushFactor 0.5; } - action native void A_PodPain (class podtype = "PodGoo"); - action native void A_RemovePod (); + native void A_PodPain (class podtype = "PodGoo"); + native void A_RemovePod (); States { @@ -75,7 +75,7 @@ class PodGenerator : Actor AttackSound "world/podgrow"; } - action native void A_MakePod (class podtype = "Pod"); + native void A_MakePod (class podtype = "Pod"); States { @@ -136,7 +136,7 @@ class TeleGlitter1 : Actor Damage 0; } - action native void A_AccTeleGlitter (); + native void A_AccTeleGlitter (); States { @@ -178,8 +178,8 @@ class Volcano : Actor +SOLID } - action native void A_VolcanoSet (); - action native void A_VolcanoBlast (); + native void A_VolcanoSet (); + native void A_VolcanoBlast (); States { @@ -210,7 +210,7 @@ class VolcanoBlast : Actor DeathSound "world/volcano/blast"; } - action native void A_VolcBallImpact (); + native void A_VolcBallImpact (); States { diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index eabecd9d86..0c3123c7c6 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -23,7 +23,7 @@ class Staff : HereticWeapon Tag "$TAG_STAFF"; } - action native void A_StaffAttack (int damage, class puff); + native void A_StaffAttack (int damage, class puff); States { @@ -142,7 +142,7 @@ class GoldWand : HereticWeapon Tag "$TAG_GOLDWAND"; } - action native void A_FireGoldWandPL1 (); + native void A_FireGoldWandPL1 (); States { @@ -178,7 +178,7 @@ class GoldWandPowered : GoldWand Tag "$TAG_GOLDWANDP"; } - action native void A_FireGoldWandPL2 (); + native void A_FireGoldWandPL2 (); States { @@ -294,7 +294,7 @@ class Crossbow : HereticWeapon Tag "$TAG_CROSSBOW"; } - action native void A_FireCrossbowPL1 (); + native void A_FireCrossbowPL1 (); States { @@ -330,7 +330,7 @@ class CrossbowPowered : Crossbow Tag "$TAG_CROSSBOWP"; } - action native void A_FireCrossbowPL2(); + native void A_FireCrossbowPL2(); States { @@ -462,7 +462,7 @@ class Gauntlets : Weapon Obituary "$OB_MPGAUNTLETS"; } - action native void A_GauntletAttack (int power); + native void A_GauntletAttack (int power); States { @@ -574,7 +574,7 @@ class Mace : HereticWeapon Tag "$TAG_MACE"; } - action native void A_FireMacePL1(); + native void A_FireMacePL1(); States { @@ -611,7 +611,7 @@ class MacePowered : Mace Tag "$TAG_MACEP"; } - action native void A_FireMacePL2(); + native void A_FireMacePL2(); States { @@ -642,8 +642,8 @@ class MaceFX1 : Actor Obituary "$OB_MPMACE"; } - action native void A_MacePL1Check(); - action native void A_MaceBallImpact(); + native void A_MacePL1Check(); + native void A_MaceBallImpact(); States { @@ -670,7 +670,7 @@ class MaceFX2 : MaceFX1 SeeSound ""; } - action native void A_MaceBallImpact2(); + native void A_MaceBallImpact2(); States { @@ -725,7 +725,7 @@ class MaceFX4 : Actor native Obituary "$OB_MPPMACE"; } - action native void A_DeathBallImpact(); + native void A_DeathBallImpact(); States { @@ -778,7 +778,7 @@ class Blaster : HereticWeapon Obituary "$OB_MPBLASTER"; } - action native void A_FireBlasterPL1(); + native void A_FireBlasterPL1(); States { @@ -843,7 +843,7 @@ class BlasterFX1 : FastProjectile native Obituary "$OB_MPPBLASTER"; } - action native void A_SpawnRippers(); + native void A_SpawnRippers(); States { @@ -950,7 +950,7 @@ class SkullRod : HereticWeapon Tag "$TAG_SKULLROD"; } - action native void A_FireSkullRodPL1(); + native void A_FireSkullRodPL1(); States { @@ -984,7 +984,7 @@ class SkullRodPowered : SkullRod Tag "$TAG_SKULLRODP"; } - action native void A_FireSkullRodPL2(); + native void A_FireSkullRodPL2(); States { @@ -1053,9 +1053,9 @@ class HornRodFX2 : Actor native Obituary "$OB_MPPSKULLROD"; } - action native void A_AddPlayerRain(); - action native void A_HideInCeiling(); - action native void A_SkullRodStorm(); + native void A_AddPlayerRain(); + native void A_HideInCeiling(); + native void A_SkullRodStorm(); States { @@ -1094,7 +1094,7 @@ class RainPillar : Actor native Obituary "$OB_MPPSKULLROD"; } - action native void A_RainImpact(); + native void A_RainImpact(); States { @@ -1140,7 +1140,7 @@ class PhoenixRod : Weapon native Tag "$TAG_PHOENIXROD"; } - action native void A_FirePhoenixPL1(); + native void A_FirePhoenixPL1(); States { @@ -1176,9 +1176,9 @@ class PhoenixRodPowered : PhoenixRod native Tag "$TAG_PHOENIXRODP"; } - action native void A_InitPhoenixPL2(); - action native void A_FirePhoenixPL2(); - action native void A_ShutdownPhoenixPL2(); + native void A_InitPhoenixPL2(); + native void A_FirePhoenixPL2(); + native void A_ShutdownPhoenixPL2(); States { @@ -1212,7 +1212,7 @@ class PhoenixFX1 : Actor native Obituary "$OB_MPPHOENIXROD"; } - action native void A_PhoenixPuff(); + native void A_PhoenixPuff(); States { @@ -1265,8 +1265,8 @@ class PhoenixFX2 : Actor native Obituary "$OB_MPPPHOENIXROD"; } - action native void A_FlameEnd(); - action native void A_FloatPuff(); + native void A_FlameEnd(); + native void A_FloatPuff(); States { diff --git a/wadsrc/static/zscript/heretic/ironlich.txt b/wadsrc/static/zscript/heretic/ironlich.txt index 9b66bcb0d7..e6ba05e059 100644 --- a/wadsrc/static/zscript/heretic/ironlich.txt +++ b/wadsrc/static/zscript/heretic/ironlich.txt @@ -27,7 +27,7 @@ class Ironlich : Actor DropItem "ArtiEgg", 51, 0; } - action native void A_LichAttack (); + native void A_LichAttack (); States { @@ -74,7 +74,7 @@ class HeadFX1 : Actor RenderStyle "Add"; } - action native void A_LichIceImpact(); + native void A_LichIceImpact(); States { @@ -135,7 +135,7 @@ class HeadFX3 : Actor RenderStyle "Add"; } - action native void A_LichFireGrow (); + native void A_LichFireGrow (); States { @@ -174,7 +174,7 @@ class Whirlwind : Actor native Alpha 0.4; } - action native void A_WhirlwindSeek(); + native void A_WhirlwindSeek(); States { diff --git a/wadsrc/static/zscript/heretic/knight.txt b/wadsrc/static/zscript/heretic/knight.txt index f8b84b9aad..1eb341859b 100644 --- a/wadsrc/static/zscript/heretic/knight.txt +++ b/wadsrc/static/zscript/heretic/knight.txt @@ -23,7 +23,7 @@ class Knight : Actor DropItem "CrossbowAmmo", 84, 5; } - action native void A_KnightAttack (); + native void A_KnightAttack (); States { @@ -116,7 +116,7 @@ class RedAxe : KnightAxe Damage 7; } - action native void A_DripBlood (); + native void A_DripBlood (); States { diff --git a/wadsrc/static/zscript/heretic/wizard.txt b/wadsrc/static/zscript/heretic/wizard.txt index 3599354ad9..d33e2dd8a6 100644 --- a/wadsrc/static/zscript/heretic/wizard.txt +++ b/wadsrc/static/zscript/heretic/wizard.txt @@ -26,10 +26,10 @@ class Wizard : Actor DropItem "ArtiTomeOfPower", 4, 0; } - action native void A_GhostOff (); - action native void A_WizAtk1 (); - action native void A_WizAtk2 (); - action native void A_WizAtk3 (); + native void A_GhostOff (); + native void A_WizAtk1 (); + native void A_WizAtk2 (); + native void A_WizAtk3 (); States { diff --git a/wadsrc/static/zscript/hexen/bats.txt b/wadsrc/static/zscript/hexen/bats.txt index f96f932729..1e6ee459f5 100644 --- a/wadsrc/static/zscript/hexen/bats.txt +++ b/wadsrc/static/zscript/hexen/bats.txt @@ -9,8 +9,8 @@ class BatSpawner : SwitchableDecoration RenderStyle "None"; } - action native void A_BatSpawnInit(); - action native void A_BatSpawn(); + native void A_BatSpawnInit(); + native void A_BatSpawn(); States { @@ -39,7 +39,7 @@ class Bat : Actor +NOTELEPORT +CANPASS } - action native void A_BatMove(); + native void A_BatMove(); States { diff --git a/wadsrc/static/zscript/hexen/bishop.txt b/wadsrc/static/zscript/hexen/bishop.txt index 4dbb0d2262..d116ee9324 100644 --- a/wadsrc/static/zscript/hexen/bishop.txt +++ b/wadsrc/static/zscript/hexen/bishop.txt @@ -23,13 +23,13 @@ class Bishop : Actor Obituary"$OB_BISHOP"; } - action native void A_BishopChase(); - action native void A_BishopDecide(); - action native void A_BishopDoBlur(); - action native void A_BishopSpawnBlur(); - action native void A_BishopPainBlur(); - action native void A_BishopAttack(); - action native void A_BishopAttack2(); + native void A_BishopChase(); + native void A_BishopDecide(); + native void A_BishopDoBlur(); + native void A_BishopSpawnBlur(); + native void A_BishopPainBlur(); + native void A_BishopAttack(); + native void A_BishopAttack2(); States { diff --git a/wadsrc/static/zscript/hexen/clericboss.txt b/wadsrc/static/zscript/hexen/clericboss.txt index 6493cde89c..a2019bae53 100644 --- a/wadsrc/static/zscript/hexen/clericboss.txt +++ b/wadsrc/static/zscript/hexen/clericboss.txt @@ -18,7 +18,7 @@ class ClericBoss : Actor Obituary "$OBCBOSS"; } - action native void A_ClericAttack(); + native void A_ClericAttack(); States { diff --git a/wadsrc/static/zscript/hexen/clericflame.txt b/wadsrc/static/zscript/hexen/clericflame.txt index ae5ecaac3e..e724965300 100644 --- a/wadsrc/static/zscript/hexen/clericflame.txt +++ b/wadsrc/static/zscript/hexen/clericflame.txt @@ -16,7 +16,7 @@ class CWeapFlame : ClericWeapon Tag "$TAG_CWEAPFLAME"; } - action native void A_CFlameAttack(); + native void A_CFlameAttack(); States { @@ -140,7 +140,7 @@ class CircleFlame : Actor Obituary "$OB_MPCWEAPFLAME"; } - action native void A_CFlameRotate(); + native void A_CFlameRotate(); States { @@ -184,8 +184,8 @@ class CFlameMissile : FastProjectile native Obituary "$OB_MPCWEAPFLAME"; } - action native void A_CFlamePuff(); - action native void A_CFlameMissile(); + native void A_CFlamePuff(); + native void A_CFlameMissile(); States { diff --git a/wadsrc/static/zscript/hexen/clericholy.txt b/wadsrc/static/zscript/hexen/clericholy.txt index b238ce09be..6fc9cf43d4 100644 --- a/wadsrc/static/zscript/hexen/clericholy.txt +++ b/wadsrc/static/zscript/hexen/clericholy.txt @@ -96,8 +96,8 @@ class CWeapWraithverge : ClericWeapon native Inventory.PickupSound "WeaponBuild"; } - action native void A_CHolyAttack(); - action native void A_CHolyPalette(); + native void A_CHolyAttack(); + native void A_CHolyPalette(); States { @@ -139,7 +139,7 @@ class HolyMissile : Actor +EXTREMEDEATH } - action native void A_CHolyAttack2(); + native void A_CHolyAttack2(); States { @@ -211,8 +211,8 @@ class HolySpirit : Actor native Obituary "$OB_MPCWEAPWRAITHVERGE"; } - action native void A_CHolySeek(); - action native void A_CHolyCheckScream(); + native void A_CHolySeek(); + native void A_CHolyCheckScream(); States { @@ -242,7 +242,7 @@ class HolyTail : Actor Alpha 0.6; } - action native void A_CHolyTail(); + native void A_CHolyTail(); States { diff --git a/wadsrc/static/zscript/hexen/clericmace.txt b/wadsrc/static/zscript/hexen/clericmace.txt index 5e00b9c3b7..b47974d4b8 100644 --- a/wadsrc/static/zscript/hexen/clericmace.txt +++ b/wadsrc/static/zscript/hexen/clericmace.txt @@ -13,7 +13,7 @@ class CWeapMace : ClericWeapon Tag "$TAG_CWEAPMACE"; } - action native void A_CMaceAttack(); + native void A_CMaceAttack(); States { diff --git a/wadsrc/static/zscript/hexen/clericstaff.txt b/wadsrc/static/zscript/hexen/clericstaff.txt index 7ae0e9da37..c33f14a803 100644 --- a/wadsrc/static/zscript/hexen/clericstaff.txt +++ b/wadsrc/static/zscript/hexen/clericstaff.txt @@ -16,10 +16,10 @@ class CWeapStaff : ClericWeapon Tag "$TAG_CWEAPSTAFF"; } - action native void A_CStaffInitBlink(); - action native void A_CStaffCheckBlink(); - action native void A_CStaffCheck(); - action native void A_CStaffAttack(); + native void A_CStaffInitBlink(); + native void A_CStaffCheckBlink(); + native void A_CStaffCheck(); + native void A_CStaffAttack(); States { diff --git a/wadsrc/static/zscript/hexen/dragon.txt b/wadsrc/static/zscript/hexen/dragon.txt index bfc037e713..6df3da9437 100644 --- a/wadsrc/static/zscript/hexen/dragon.txt +++ b/wadsrc/static/zscript/hexen/dragon.txt @@ -23,12 +23,12 @@ class Dragon : Actor Obituary "$OB_DRAGON"; } - action native void A_DragonInitFlight(); - action native void A_DragonFlap(); - action native void A_DragonFlight(); - action native void A_DragonPain(); - action native void A_DragonAttack(); - action native void A_DragonCheckCrash(); + 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 { @@ -77,7 +77,7 @@ class DragonFireball : Actor DeathSound "DragonFireballExplode"; } - action native void A_DragonFX2(); + native void A_DragonFX2(); States { diff --git a/wadsrc/static/zscript/hexen/fighteraxe.txt b/wadsrc/static/zscript/hexen/fighteraxe.txt index 30b235192d..436172bef4 100644 --- a/wadsrc/static/zscript/hexen/fighteraxe.txt +++ b/wadsrc/static/zscript/hexen/fighteraxe.txt @@ -17,12 +17,12 @@ class FWeapAxe : FighterWeapon native 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(); + native void A_FAxeCheckUp(); + native void A_FAxeCheckReady(); + native void A_FAxeCheckAtk(); + native void A_FAxeAttack(); + native void A_FAxeCheckUpG(); + native void A_FAxeCheckReadyG(); States { diff --git a/wadsrc/static/zscript/hexen/fighterboss.txt b/wadsrc/static/zscript/hexen/fighterboss.txt index aa3e28ce77..8e862de30c 100644 --- a/wadsrc/static/zscript/hexen/fighterboss.txt +++ b/wadsrc/static/zscript/hexen/fighterboss.txt @@ -19,7 +19,7 @@ class FighterBoss : Actor Obituary "$OB_FBOSS"; } - action native void A_FighterAttack(); + native void A_FighterAttack(); States { diff --git a/wadsrc/static/zscript/hexen/fighterfist.txt b/wadsrc/static/zscript/hexen/fighterfist.txt index 8428ebe7da..e556ebd870 100644 --- a/wadsrc/static/zscript/hexen/fighterfist.txt +++ b/wadsrc/static/zscript/hexen/fighterfist.txt @@ -13,7 +13,7 @@ class FWeapFist : FighterWeapon Tag "$TAG_FWEAPFIST"; } - action native void A_FPunchAttack(); + native void A_FPunchAttack(); States { diff --git a/wadsrc/static/zscript/hexen/fighterhammer.txt b/wadsrc/static/zscript/hexen/fighterhammer.txt index f415cbb722..0104c76704 100644 --- a/wadsrc/static/zscript/hexen/fighterhammer.txt +++ b/wadsrc/static/zscript/hexen/fighterhammer.txt @@ -18,8 +18,8 @@ class FWeapHammer : FighterWeapon Tag "$TAG_FWEAPHAMMER"; } - action native void A_FHammerAttack(); - action native void A_FHammerThrow(); + native void A_FHammerAttack(); + native void A_FHammerThrow(); States { diff --git a/wadsrc/static/zscript/hexen/fighterquietus.txt b/wadsrc/static/zscript/hexen/fighterquietus.txt index 5fe132237a..2430cd70c4 100644 --- a/wadsrc/static/zscript/hexen/fighterquietus.txt +++ b/wadsrc/static/zscript/hexen/fighterquietus.txt @@ -97,7 +97,7 @@ class FWeapQuietus : FighterWeapon Tag "$TAG_FWEAPQUIETUS"; } - action native void A_FSwordAttack(); + native void A_FSwordAttack(); States { @@ -146,7 +146,7 @@ class FSwordMissile : Actor native Obituary "$OB_MPFWEAPQUIETUS"; } - action native void A_FSwordFlames(); + native void A_FSwordFlames(); States { diff --git a/wadsrc/static/zscript/hexen/firedemon.txt b/wadsrc/static/zscript/hexen/firedemon.txt index f793034006..001e1629f2 100644 --- a/wadsrc/static/zscript/hexen/firedemon.txt +++ b/wadsrc/static/zscript/hexen/firedemon.txt @@ -23,10 +23,10 @@ class FireDemon : Actor Obituary "$OB_FIREDEMON"; } - action native void A_FiredRocks(); - action native void A_FiredChase(); - action native void A_FiredAttack(); - action native void A_FiredSplotch(); + native void A_FiredRocks(); + native void A_FiredChase(); + native void A_FiredAttack(); + native void A_FiredSplotch(); States { @@ -124,7 +124,7 @@ class FireDemonRock1 : Actor +NOTELEPORT } - action native void A_SmBounce(); + native void A_SmBounce(); States { diff --git a/wadsrc/static/zscript/hexen/flechette.txt b/wadsrc/static/zscript/hexen/flechette.txt index 4b3cd914c5..6f7b3a818c 100644 --- a/wadsrc/static/zscript/hexen/flechette.txt +++ b/wadsrc/static/zscript/hexen/flechette.txt @@ -10,7 +10,7 @@ class PoisonBag : Actor +NOBLOCKMAP +NOGRAVITY } - action native void A_PoisonBagInit(); + native void A_PoisonBagInit(); States { @@ -37,7 +37,7 @@ class FireBomb : Actor DeathSound "FlechetteExplode"; } - action native void A_TimeBomb(); + native void A_TimeBomb(); States { @@ -69,8 +69,8 @@ class ThrowingBomb : Actor DeathSound "FlechetteExplode"; } - action native void A_CheckThrowBomb(); - action native void A_CheckThrowBomb2(); + native void A_CheckThrowBomb(); + native void A_CheckThrowBomb2(); States { @@ -193,8 +193,8 @@ class PoisonCloud : Actor native DamageType "PoisonCloud"; } - action native void A_PoisonBagDamage(); - action native void A_PoisonBagCheck(); + native void A_PoisonBagDamage(); + native void A_PoisonBagCheck(); States { @@ -233,7 +233,7 @@ class ZPoisonShroom : PoisonBag DeathSound "PoisonShroomDeath"; } - action native void A_PoisonShroom(); + native void A_PoisonShroom(); States { diff --git a/wadsrc/static/zscript/hexen/flies.txt b/wadsrc/static/zscript/hexen/flies.txt index 35c52a124e..464e6e9d94 100644 --- a/wadsrc/static/zscript/hexen/flies.txt +++ b/wadsrc/static/zscript/hexen/flies.txt @@ -15,8 +15,8 @@ class LittleFly : Actor ActiveSound "FlyBuzz"; } - action native void A_FlySearch(); - action native void A_FlyBuzz(); + native void A_FlySearch(); + native void A_FlyBuzz(); States { diff --git a/wadsrc/static/zscript/hexen/fog.txt b/wadsrc/static/zscript/hexen/fog.txt index 84cc6c03eb..93b5e9593e 100644 --- a/wadsrc/static/zscript/hexen/fog.txt +++ b/wadsrc/static/zscript/hexen/fog.txt @@ -11,7 +11,7 @@ class FogSpawner : Actor +INVISIBLE } - action native void A_FogSpawn(); + native void A_FogSpawn(); States { @@ -34,7 +34,7 @@ class FogPatchSmall : Actor Alpha 0.6; } - action native void A_FogMove(); + native void A_FogMove(); States { diff --git a/wadsrc/static/zscript/hexen/heresiarch.txt b/wadsrc/static/zscript/hexen/heresiarch.txt index 076bc01cac..6ffc11b3b4 100644 --- a/wadsrc/static/zscript/hexen/heresiarch.txt +++ b/wadsrc/static/zscript/hexen/heresiarch.txt @@ -27,10 +27,10 @@ class Heresiarch native Obituary "$OB_HERESIARCH"; } - action native void A_SorcSpinBalls(); - action native void A_SpeedBalls(); - action native void A_SorcBossAttack(); - action native void A_SpawnFizzle(); + native void A_SorcSpinBalls(); + native void A_SpeedBalls(); + native void A_SorcBossAttack(); + native void A_SpawnFizzle(); States { @@ -93,9 +93,9 @@ class SorcBall native DeathSound "SorcererBigBallExplode"; } - action native void A_SorcBallOrbit(); - action native void A_SorcBallPop(); - action native void A_BounceCheck (); + native void A_SorcBallOrbit(); + native void A_SorcBallPop(); + native void A_BounceCheck (); } // First ball (purple) - fires projectiles ---------------------------------- @@ -188,7 +188,7 @@ class SorcFX1 : Actor DeathSound "SorcererHeadScream"; } - action native void A_SorcFX1Seek(); + native void A_SorcFX1Seek(); States { @@ -218,8 +218,8 @@ class SorcFX2 : Actor +NOTELEPORT } - action native void A_SorcFX2Split(); - action native void A_SorcFX2Orbit (); + native void A_SorcFX2Split(); + native void A_SorcFX2Orbit (); states { @@ -268,8 +268,8 @@ class SorcFX3 : Actor SeeSound "SorcererBishopSpawn"; } - action native void A_SpawnBishop(); - action native void A_SorcererBishopEntry(); + native void A_SpawnBishop(); + native void A_SorcererBishopEntry(); States { @@ -323,7 +323,7 @@ class SorcFX4 : Actor DeathSound "SorcererBallExplode"; } - action native void A_SorcFX4Check(); + native void A_SorcFX4Check(); States { diff --git a/wadsrc/static/zscript/hexen/hexenspecialdecs.txt b/wadsrc/static/zscript/hexen/hexenspecialdecs.txt index 97c6ea41ea..30ae0fff14 100644 --- a/wadsrc/static/zscript/hexen/hexenspecialdecs.txt +++ b/wadsrc/static/zscript/hexen/hexenspecialdecs.txt @@ -95,7 +95,7 @@ class Pottery1 : Actor native +NOICEDEATH } - action native void A_PotteryExplode(); + native void A_PotteryExplode(); States { @@ -153,8 +153,8 @@ class PotteryBit : Actor +NOICEDEATH } - action native void A_PotteryChooseBit(); - action native void A_PotteryCheck(); + native void A_PotteryChooseBit(); + native void A_PotteryCheck(); States { @@ -212,7 +212,7 @@ class ZCorpseLynchedNoHeart : Actor native +SOLID +SPAWNCEILING +NOGRAVITY } - action native void A_CorpseBloodDrip(); + native void A_CorpseBloodDrip(); States { @@ -289,7 +289,7 @@ class ZCorpseSitting : Actor DeathSound "FireDemonDeath"; } - action native void A_CorpseExplode(); + native void A_CorpseExplode(); States { @@ -313,7 +313,7 @@ class LeafSpawner : Actor +INVISIBLE } - action native void A_LeafSpawn(); + native void A_LeafSpawn(); States { @@ -338,8 +338,8 @@ class Leaf1 : Actor +NOICEDEATH } - action native void A_LeafThrust(); - action native void A_LeafCheck(); + native void A_LeafThrust(); + native void A_LeafCheck(); States { @@ -556,7 +556,7 @@ class ZSuitOfArmor : Actor DeathSound "SuitofArmorBreak"; } - action native void A_SoAExplode(); + native void A_SoAExplode(); States { @@ -621,8 +621,8 @@ class ZBell : Actor native DeathSound "BellRing"; } - action native void A_BellReset1(); - action native void A_BellReset2(); + native void A_BellReset1(); + native void A_BellReset2(); States { diff --git a/wadsrc/static/zscript/hexen/iceguy.txt b/wadsrc/static/zscript/hexen/iceguy.txt index 635aea07f1..8081d5a61d 100644 --- a/wadsrc/static/zscript/hexen/iceguy.txt +++ b/wadsrc/static/zscript/hexen/iceguy.txt @@ -22,9 +22,9 @@ class IceGuy : Actor Obituary "$OB_ICEGUY"; } - action native void A_IceGuyLook(); - action native void A_IceGuyChase(); - action native void A_IceGuyAttack(); + native void A_IceGuyLook(); + native void A_IceGuyChase(); + native void A_IceGuyAttack(); States { @@ -69,7 +69,7 @@ class IceGuyFX : Actor DeathSound "IceGuyMissileExplode"; } - action native void A_IceGuyMissileExplode(); + native void A_IceGuyMissileExplode(); States { diff --git a/wadsrc/static/zscript/hexen/korax.txt b/wadsrc/static/zscript/hexen/korax.txt index 3928de8840..16bf172a46 100644 --- a/wadsrc/static/zscript/hexen/korax.txt +++ b/wadsrc/static/zscript/hexen/korax.txt @@ -24,11 +24,11 @@ class Korax : Actor Obituary "$OB_KORAX"; } - action native void A_KoraxChase(); - action native void A_KoraxDecide(); - action native void A_KoraxBonePop(); - action native void A_KoraxMissile(); - action native void A_KoraxCommand(); + native void A_KoraxChase(); + native void A_KoraxDecide(); + native void A_KoraxBonePop(); + native void A_KoraxMissile(); + native void A_KoraxCommand(); States { @@ -94,7 +94,7 @@ class KoraxSpirit : Actor Alpha 0.4; } - action native void A_KSpiritRoam(); + native void A_KSpiritRoam(); States { @@ -119,8 +119,8 @@ class KoraxBolt : Actor RenderStyle "Add"; } - action native void A_KBolt(); - action native void A_KBoltRaise(); + native void A_KBolt(); + native void A_KBoltRaise(); States { diff --git a/wadsrc/static/zscript/hexen/mageboss.txt b/wadsrc/static/zscript/hexen/mageboss.txt index 083d210162..f9637f8d17 100644 --- a/wadsrc/static/zscript/hexen/mageboss.txt +++ b/wadsrc/static/zscript/hexen/mageboss.txt @@ -18,7 +18,7 @@ class MageBoss : Actor Obituary "$OB_MBOSS"; } - action native void A_MageAttack(); + native void A_MageAttack(); States { diff --git a/wadsrc/static/zscript/hexen/magecone.txt b/wadsrc/static/zscript/hexen/magecone.txt index 94452985cf..471b5b0b70 100644 --- a/wadsrc/static/zscript/hexen/magecone.txt +++ b/wadsrc/static/zscript/hexen/magecone.txt @@ -17,7 +17,7 @@ class MWeapFrost : MageWeapon Tag "$TAG_MWEAPFROST"; } - action native void A_FireConePL1(); + native void A_FireConePL1(); States { @@ -63,7 +63,7 @@ class FrostMissile : Actor native Obituary "$OB_MPMWEAPFROST"; } - action native void A_ShedShard(); + native void A_ShedShard(); States { diff --git a/wadsrc/static/zscript/hexen/magelightning.txt b/wadsrc/static/zscript/hexen/magelightning.txt index 2c35a41e5a..46687e813c 100644 --- a/wadsrc/static/zscript/hexen/magelightning.txt +++ b/wadsrc/static/zscript/hexen/magelightning.txt @@ -16,8 +16,8 @@ class MWeapLightning : MageWeapon Tag "$TAG_MWEAPLIGHTNING"; } - action native void A_LightningReady(); - action native void A_MLightningAttack(class floor = "LightningFloor", class ceiling = "LightningCeiling"); + native void A_LightningReady(); + native void A_MLightningAttack(class floor = "LightningFloor", class ceiling = "LightningCeiling"); States { @@ -79,9 +79,9 @@ class LightningCeiling : Lightning RenderStyle "Add"; } - action native void A_LightningZap(); - action native void A_LightningClip(); - action native void A_LightningRemove(); + native void A_LightningZap(); + native void A_LightningClip(); + native void A_LightningRemove(); States { @@ -117,7 +117,7 @@ class LightningFloor : LightningCeiling RenderStyle "Add"; } - action native void A_LastZap(); + native void A_LastZap(); States { @@ -155,7 +155,7 @@ class LightningZap : Actor native Obituary "$OB_MPMWEAPLIGHTNING"; } - action native void A_ZapMimic(); + native void A_ZapMimic(); States { diff --git a/wadsrc/static/zscript/hexen/magestaff.txt b/wadsrc/static/zscript/hexen/magestaff.txt index b71c1e3dc7..9338febe63 100644 --- a/wadsrc/static/zscript/hexen/magestaff.txt +++ b/wadsrc/static/zscript/hexen/magestaff.txt @@ -97,8 +97,8 @@ class MWeapBloodscourge : MageWeapon native Tag "$TAG_MWEAPBLOODSCOURGE"; } - action native void A_MStaffAttack(); - action native void A_MStaffPalette(); + native void A_MStaffAttack(); + native void A_MStaffPalette(); States { @@ -143,7 +143,7 @@ class MageStaffFX2 : Actor native Obituary "$OB_MPMWEAPBLOODSCOURGE"; } - action native void A_MStaffTrack(); + native void A_MStaffTrack(); States { diff --git a/wadsrc/static/zscript/hexen/pig.txt b/wadsrc/static/zscript/hexen/pig.txt index 8fa4468827..6362ff36e8 100644 --- a/wadsrc/static/zscript/hexen/pig.txt +++ b/wadsrc/static/zscript/hexen/pig.txt @@ -34,7 +34,7 @@ class Snout : Weapon Weapon.YAdjust 10; } - action native void A_SnoutAttack (); + native void A_SnoutAttack (); States { diff --git a/wadsrc/static/zscript/hexen/serpent.txt b/wadsrc/static/zscript/hexen/serpent.txt index 516d0c703b..d8886ccb27 100644 --- a/wadsrc/static/zscript/hexen/serpent.txt +++ b/wadsrc/static/zscript/hexen/serpent.txt @@ -24,15 +24,15 @@ class Serpent : Actor HitObituary "$OB_SERPENTHIT"; } - action native void A_SerpentHumpDecide(); - action native void A_SerpentHide(); - action native void A_SerpentCheckForAttack(); - action native void A_SerpentSpawnGibs(); - action native void A_SerpentUnHide(); - action native void A_SerpentRaiseHump(); - action native void A_SerpentLowerHump(); - action native void A_SerpentChooseAttack(); - action native void A_SerpentMeleeAttack(); + 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 { @@ -159,7 +159,7 @@ class SerpentHead : Actor +NOBLOCKMAP } - action native void A_SerpentHeadCheck(); + native void A_SerpentHeadCheck(); States { @@ -183,9 +183,9 @@ class SerpentGib1 : Actor +NOBLOCKMAP +NOGRAVITY } - action native void A_FloatGib(); - action native void A_DelayGib(); - action native void A_SinkGib(); + native void A_FloatGib(); + native void A_DelayGib(); + native void A_SinkGib(); States { diff --git a/wadsrc/static/zscript/hexen/spike.txt b/wadsrc/static/zscript/hexen/spike.txt index 2c8b4e80a3..58f763ccc7 100644 --- a/wadsrc/static/zscript/hexen/spike.txt +++ b/wadsrc/static/zscript/hexen/spike.txt @@ -26,11 +26,11 @@ class ThrustFloor : Actor native Height 128; } - action native void A_ThrustRaise(); - action native void A_ThrustImpale(); - action native void A_ThrustLower(); - action native void A_ThrustInitDn(); - action native void A_ThrustInitUp(); + native void A_ThrustRaise(); + native void A_ThrustImpale(); + native void A_ThrustLower(); + native void A_ThrustInitDn(); + native void A_ThrustInitUp(); States { diff --git a/wadsrc/static/zscript/hexen/summon.txt b/wadsrc/static/zscript/hexen/summon.txt index 395d4760d5..06ceb7e174 100644 --- a/wadsrc/static/zscript/hexen/summon.txt +++ b/wadsrc/static/zscript/hexen/summon.txt @@ -36,7 +36,7 @@ class SummoningDoll : Actor +NOTELEPORT } - action native void A_Summon(); + native void A_Summon(); States { diff --git a/wadsrc/static/zscript/hexen/teleportother.txt b/wadsrc/static/zscript/hexen/teleportother.txt index 90015b2075..2de144d5fa 100644 --- a/wadsrc/static/zscript/hexen/teleportother.txt +++ b/wadsrc/static/zscript/hexen/teleportother.txt @@ -41,11 +41,11 @@ class TelOtherFX1 : Actor native Speed 20; } - action native void A_TeloSpawnA(); - action native void A_TeloSpawnB(); - action native void A_TeloSpawnC(); - action native void A_TeloSpawnD(); - action native void A_CheckTeleRing (); + native void A_TeloSpawnA(); + native void A_TeloSpawnB(); + native void A_TeloSpawnC(); + native void A_TeloSpawnD(); + native void A_CheckTeleRing (); States { diff --git a/wadsrc/static/zscript/hexen/wraith.txt b/wadsrc/static/zscript/hexen/wraith.txt index a8b648a727..9d811ec5c7 100644 --- a/wadsrc/static/zscript/hexen/wraith.txt +++ b/wadsrc/static/zscript/hexen/wraith.txt @@ -23,10 +23,10 @@ class Wraith : Actor Obituary "$OB_WRAITH"; } - action native void A_WraithInit(); - action native void A_WraithChase(); - action native void A_WraithFX3(); - action native void A_WraithMelee(); + native void A_WraithInit(); + native void A_WraithChase(); + native void A_WraithFX3(); + native void A_WraithMelee(); States { @@ -97,8 +97,8 @@ class WraithBuried : Wraith PainChance 0; } - action native void A_WraithRaiseInit(); - action native void A_WraithRaise(); + native void A_WraithRaiseInit(); + native void A_WraithRaise(); States { @@ -133,7 +133,7 @@ class WraithFX1 : Actor DeathSound "WraithMissileExplode"; } - action native void A_WraithFX2(); + native void A_WraithFX2(); States { diff --git a/wadsrc/static/zscript/raven/minotaur.txt b/wadsrc/static/zscript/raven/minotaur.txt index 9bc02fced2..9bbbe81a0a 100644 --- a/wadsrc/static/zscript/raven/minotaur.txt +++ b/wadsrc/static/zscript/raven/minotaur.txt @@ -26,15 +26,15 @@ class Minotaur : Actor native DropItem "PhoenixRodAmmo", 84, 10; } - action native void A_MinotaurDecide(); - action native void A_MinotaurAtk1(); - action native void A_MinotaurAtk2(); - action native void A_MinotaurAtk3(); - action native void A_MinotaurCharge(); - action native void A_MinotaurLook(); - action native void A_MinotaurRoam(); - action native void A_MinotaurChase(); - action native void A_MinotaurDeath(); + 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 { @@ -179,7 +179,7 @@ class MinotaurFX2 : MinotaurFX1 DeathSound "minotaur/fx2hit"; } - action native void A_MntrFloorFire(); + native void A_MntrFloorFire(); states { diff --git a/wadsrc/static/zscript/shared/bridge.txt b/wadsrc/static/zscript/shared/bridge.txt index 08c788f8e3..ea38796a70 100644 --- a/wadsrc/static/zscript/shared/bridge.txt +++ b/wadsrc/static/zscript/shared/bridge.txt @@ -9,7 +9,7 @@ class BridgeBall : Actor +NOGRAVITY } - action native void A_BridgeOrbit(); + native void A_BridgeOrbit(); States { @@ -36,7 +36,7 @@ class CustomBridge : Actor native RenderStyle "None"; } - action native void A_BridgeInit(class balltype = "BridgeBall"); + native void A_BridgeInit(class balltype = "BridgeBall"); states { diff --git a/wadsrc/static/zscript/shared/ice.txt b/wadsrc/static/zscript/shared/ice.txt index 9668466cbe..5341137855 100644 --- a/wadsrc/static/zscript/shared/ice.txt +++ b/wadsrc/static/zscript/shared/ice.txt @@ -21,7 +21,7 @@ class IceChunk : Actor +NOBLOCKMAP +MOVEWITHSECTOR } - action native void A_IceSetTics (); + native void A_IceSetTics (); States { diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 80771e1a13..2fde3b3cd0 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -11,10 +11,10 @@ class Inventory : Actor native } // These are regular functions for the item itself. - private action native void A_RestoreSpecialPosition(); - private action native void A_RestoreSpecialDoomThing(); - private action native void A_RestoreSpecialThing1(); - private action native void A_RestoreSpecialThing2(); + private native void A_RestoreSpecialPosition(); + private native void A_RestoreSpecialDoomThing(); + private native void A_RestoreSpecialThing1(); + private native void A_RestoreSpecialThing2(); States { @@ -46,20 +46,20 @@ class StateProvider : Inventory native action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); action native void A_FireCustomMissile(class missiletype, float angle = 0, bool useammo = true, float spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0); action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); - action native void A_Light(int extralight); - action native void A_Light0(); - action native void A_Light1(); - action native void A_Light2(); - action native void A_LightInverse(); - action native void A_WeaponReady(int flags = 0); - action native void A_Lower(); - action native void A_Raise(); + native void A_Light(int extralight); + native void A_Light0(); + native void A_Light1(); + native void A_Light2(); + native void A_LightInverse(); + native void A_WeaponReady(int flags = 0); + native void A_Lower(); + native void A_Raise(); action native void A_FirePistol(); action native void A_FireShotgun(); action native void A_FireShotgun2(); - action native void A_OpenShotgun2(); - action native void A_LoadShotgun2(); - action native void A_CloseShotgun2(); + native void A_OpenShotgun2(); + native void A_LoadShotgun2(); + native void A_CloseShotgun2(); action native void A_FireCGun(); action native void A_FireSTGrenade(class grenadetype = "Grenade"); action native void A_FireMissile(); @@ -67,17 +67,17 @@ class StateProvider : Inventory native action native void A_FireRailgun(); action native void A_FireRailgunLeft(); action native void A_FireRailgunRight(); - action native void A_RailWait(); - action native void A_BFGsound(); + native void A_RailWait(); + native void A_BFGsound(); action native void A_FireBFG(); action native void A_FireOldBFG(); - action native void A_ReFire(state flash = ""); - action native void A_ClearReFire(); - action native void A_CheckReload(); - action native void A_GunFlash(state flash = "", int flags = 0); + native void A_ReFire(state flash = ""); + native void A_ClearReFire(); + native void A_CheckReload(); + native void A_GunFlash(state flash = "", int flags = 0); action native void A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff", int flags = 0, float range = 0, float spread_xy = 2.8125, float spread_z = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus"); - action native state A_CheckForReload(int counter, state label, bool dontincrement = false); - action native void A_ResetReloadCounter(); + native state A_CheckForReload(int counter, state label, bool dontincrement = false); + native void A_ResetReloadCounter(); } class ScoreItem : Inventory native @@ -468,11 +468,11 @@ class Weapon : StateProvider native Stop; } - action native void A_ZoomFactor(float scale = 1, int flags = 0); + native void A_ZoomFactor(float scale = 1, int flags = 0); const ZOOM_INSTANT = 1; const ZOOM_NOSCALETURNING = 2; - action native void A_SetCrosshair(int xhair); + native void A_SetCrosshair(int xhair); } class WeaponGiver : Weapon native diff --git a/wadsrc/static/zscript/shared/specialspot.txt b/wadsrc/static/zscript/shared/specialspot.txt index a06d41c279..c0bf84de56 100644 --- a/wadsrc/static/zscript/shared/specialspot.txt +++ b/wadsrc/static/zscript/shared/specialspot.txt @@ -1,5 +1,5 @@ class SpecialSpot : Actor native { - action native void A_SpawnSingleItem(class type, int fail_sp = 0, int fail_co = 0, int fail_dm = 0); + native void A_SpawnSingleItem(class type, int fail_sp = 0, int fail_co = 0, int fail_dm = 0); } diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt index 2f01cb836e..0c1305b57d 100644 --- a/wadsrc/static/zscript/strife/acolyte.txt +++ b/wadsrc/static/zscript/strife/acolyte.txt @@ -26,9 +26,9 @@ class Acolyte : StrifeHumanoid Obituary "$OB_ACOLYTE"; } - action native void A_BeShadowyFoe (); - action native void A_AcolyteBits (); - action native void A_AcolyteDie (); + native void A_BeShadowyFoe (); + native void A_AcolyteBits (); + native void A_AcolyteDie (); States { @@ -202,7 +202,7 @@ class AcolyteToBe : Acolyte -ISMONSTER } - action native void A_HideDecepticon (); + native void A_HideDecepticon (); States { diff --git a/wadsrc/static/zscript/strife/alienspectres.txt b/wadsrc/static/zscript/strife/alienspectres.txt index 42c8293d0f..0fe9826f00 100644 --- a/wadsrc/static/zscript/strife/alienspectres.txt +++ b/wadsrc/static/zscript/strife/alienspectres.txt @@ -32,7 +32,7 @@ class AlienSpectre1 : SpectralMonster +NOICEDEATH } - action native void A_AlienSpectreDeath (); + native void A_AlienSpectreDeath (); States { diff --git a/wadsrc/static/zscript/strife/crusader.txt b/wadsrc/static/zscript/strife/crusader.txt index 334e9d803d..02b08fc937 100644 --- a/wadsrc/static/zscript/strife/crusader.txt +++ b/wadsrc/static/zscript/strife/crusader.txt @@ -28,11 +28,11 @@ class Crusader : Actor Obituary "$OB_CRUSADER"; } - action native void A_CrusaderChoose (); - action native void A_CrusaderSweepLeft (); - action native void A_CrusaderSweepRight (); - action native void A_CrusaderRefire (); - action native void A_CrusaderDeath (); + native void A_CrusaderChoose (); + native void A_CrusaderSweepLeft (); + native void A_CrusaderSweepRight (); + native void A_CrusaderRefire (); + native void A_CrusaderDeath (); States { diff --git a/wadsrc/static/zscript/strife/entityboss.txt b/wadsrc/static/zscript/strife/entityboss.txt index d54a95a76e..8ccdbbd02f 100644 --- a/wadsrc/static/zscript/strife/entityboss.txt +++ b/wadsrc/static/zscript/strife/entityboss.txt @@ -32,7 +32,7 @@ class EntityPod : Actor SeeSound "misc/gibbed"; } - action native void A_SpawnEntity (); + native void A_SpawnEntity (); States { @@ -87,8 +87,8 @@ class EntityBoss : SpectralMonster Obituary "$OB_ENTITY"; } - action native void A_EntityAttack(); - action native void A_EntityDeath(); + native void A_EntityAttack(); + native void A_EntityDeath(); States { @@ -167,7 +167,7 @@ class EntitySecond : SpectralMonster Obituary "$OB_ENTITY"; } - action native void A_SubEntityDeath (); + native void A_SubEntityDeath (); States { diff --git a/wadsrc/static/zscript/strife/inquisitor.txt b/wadsrc/static/zscript/strife/inquisitor.txt index 5a053c74f3..b27818a61a 100644 --- a/wadsrc/static/zscript/strife/inquisitor.txt +++ b/wadsrc/static/zscript/strife/inquisitor.txt @@ -25,13 +25,13 @@ class Inquisitor : Actor Obituary "$OB_INQUISITOR"; } - action native void A_InquisitorWalk (); - action native void A_InquisitorDecide (); - action native void A_InquisitorAttack (); - action native void A_InquisitorJump (); - action native void A_InquisitorCheckLand (); - action native void A_TossArm (); - action native void A_ReaverRanged (); + 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 { diff --git a/wadsrc/static/zscript/strife/loremaster.txt b/wadsrc/static/zscript/strife/loremaster.txt index d3b437bbdd..4a48cf4d30 100644 --- a/wadsrc/static/zscript/strife/loremaster.txt +++ b/wadsrc/static/zscript/strife/loremaster.txt @@ -91,7 +91,7 @@ class LoreShot : Actor native ActiveSound "loremaster/swish"; } - action native void A_LoremasterChain (); + native void A_LoremasterChain (); States { diff --git a/wadsrc/static/zscript/strife/oracle.txt b/wadsrc/static/zscript/strife/oracle.txt index 206dee1641..6023629c28 100644 --- a/wadsrc/static/zscript/strife/oracle.txt +++ b/wadsrc/static/zscript/strife/oracle.txt @@ -19,7 +19,7 @@ class Oracle : Actor DropItem "Meat"; } - action native void A_WakeOracleSpectre (); + native void A_WakeOracleSpectre (); States { diff --git a/wadsrc/static/zscript/strife/programmer.txt b/wadsrc/static/zscript/strife/programmer.txt index cd577ff13c..dc88a790f4 100644 --- a/wadsrc/static/zscript/strife/programmer.txt +++ b/wadsrc/static/zscript/strife/programmer.txt @@ -33,10 +33,10 @@ class Programmer : Actor DropItem "Sigil1"; } - action native void A_ProgrammerMelee (); - action native void A_SpawnProgrammerBase (); - action native void A_ProgrammerDeath (); - action native void A_SpotLightning(); + native void A_ProgrammerMelee (); + native void A_SpawnProgrammerBase (); + native void A_ProgrammerDeath (); + native void A_SpotLightning(); States { diff --git a/wadsrc/static/zscript/strife/reaver.txt b/wadsrc/static/zscript/strife/reaver.txt index 0ce15fab81..7656a37a93 100644 --- a/wadsrc/static/zscript/strife/reaver.txt +++ b/wadsrc/static/zscript/strife/reaver.txt @@ -22,7 +22,7 @@ class Reaver : Actor Obituary "$OB_REAVER"; } - action native void A_ReaverRanged (); + native void A_ReaverRanged (); States { diff --git a/wadsrc/static/zscript/strife/rebels.txt b/wadsrc/static/zscript/strife/rebels.txt index 3ee0200dcc..d9e65560fe 100644 --- a/wadsrc/static/zscript/strife/rebels.txt +++ b/wadsrc/static/zscript/strife/rebels.txt @@ -122,7 +122,7 @@ class TeleporterBeacon : Inventory native Inventory.PickupMessage "$TXT_BEACON"; } - action native void A_Beacon (); + native void A_Beacon (); States { diff --git a/wadsrc/static/zscript/strife/sentinel.txt b/wadsrc/static/zscript/strife/sentinel.txt index 8108265cb5..946a99ea24 100644 --- a/wadsrc/static/zscript/strife/sentinel.txt +++ b/wadsrc/static/zscript/strife/sentinel.txt @@ -28,7 +28,7 @@ class Sentinel : Actor Obituary "$OB_SENTINEL"; } - action native void A_SentinelAttack (); + native void A_SentinelAttack (); States { diff --git a/wadsrc/static/zscript/strife/sigil.txt b/wadsrc/static/zscript/strife/sigil.txt index d8b1f80f8a..dab1db2f57 100644 --- a/wadsrc/static/zscript/strife/sigil.txt +++ b/wadsrc/static/zscript/strife/sigil.txt @@ -16,16 +16,16 @@ class Sigil : Weapon native 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 (); + native void A_SelectPiece (); + native void A_SelectSigilView (); + native void A_SelectSigilDown (); + native void A_SelectSigilAttack (); + native void A_SigilCharge (); + native void A_FireSigil1 (); + native void A_FireSigil2 (); + native void A_FireSigil3 (); + native void A_FireSigil4 (); + native void A_FireSigil5 (); States { diff --git a/wadsrc/static/zscript/strife/spectral.txt b/wadsrc/static/zscript/strife/spectral.txt index df23f3663e..d6a2349048 100644 --- a/wadsrc/static/zscript/strife/spectral.txt +++ b/wadsrc/static/zscript/strife/spectral.txt @@ -12,10 +12,10 @@ class SpectralMonster : Actor native +NOICEDEATH } - action native void A_SpectreChunkSmall (); - action native void A_SpectreChunkLarge (); - action native void A_Spectre3Attack (); - action native void A_SpotLightning (); + native void A_SpectreChunkSmall (); + native void A_SpectreChunkLarge (); + native void A_Spectre3Attack (); + native void A_SpotLightning (); } @@ -124,7 +124,7 @@ class SpectralLightningH1 : SpectralLightningBase +SPECTRAL } - action native void A_SpectralLightningTail (); + native void A_SpectralLightningTail (); States { @@ -189,7 +189,7 @@ class SpectralLightningBigBall1 : SpectralLightningDeath2 +SPECTRAL } - action native void A_SpectralBigBallLightning (); + native void A_SpectralBigBallLightning (); States { @@ -259,7 +259,7 @@ class SpectralLightningSpot : SpectralLightningDeath1 Alpha 0.6; } - action native void A_SpectralLightning (); + native void A_SpectralLightning (); States { diff --git a/wadsrc/static/zscript/strife/stalker.txt b/wadsrc/static/zscript/strife/stalker.txt index b22e432c68..51a9190415 100644 --- a/wadsrc/static/zscript/strife/stalker.txt +++ b/wadsrc/static/zscript/strife/stalker.txt @@ -28,11 +28,11 @@ class Stalker : Actor HitObituary "$OB_STALKER"; } - action native void A_StalkerLookInit (); - action native void A_StalkerChaseDecide (); - action native void A_StalkerWalk (); - action native void A_StalkerDrop (); - action native void A_StalkerAttack (); + native void A_StalkerLookInit (); + native void A_StalkerChaseDecide (); + native void A_StalkerWalk (); + native void A_StalkerDrop (); + native void A_StalkerAttack (); States { diff --git a/wadsrc/static/zscript/strife/strifeplayer.txt b/wadsrc/static/zscript/strife/strifeplayer.txt index 311bf308af..0b61e3122a 100644 --- a/wadsrc/static/zscript/strife/strifeplayer.txt +++ b/wadsrc/static/zscript/strife/strifeplayer.txt @@ -36,9 +36,9 @@ class StrifePlayer : PlayerPawn 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 void A_ItBurnsItBurns(); - action native void A_CrispyPlayer(); - action native void A_HandLower(); + native void A_ItBurnsItBurns(); + native void A_CrispyPlayer(); + native void A_HandLower(); States { diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index 4ae358bfa6..bf94706c9d 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -62,7 +62,7 @@ class PunchDagger : StrifeWeapon Tag "$TAG_PUNCHDAGGER"; } - action native void A_JabDagger (); + native void A_JabDagger (); States { @@ -184,9 +184,9 @@ class StrifeCrossbow : StrifeWeapon Inventory.Icon "CBOWA0"; } - action native void A_ClearFlash (); - action native void A_ShowElectricFlash (); - action native void A_FireArrow (class proj); + native void A_ClearFlash (); + native void A_ShowElectricFlash (); + native void A_FireArrow (class proj); States { @@ -331,7 +331,7 @@ class MiniMissileLauncher : StrifeWeapon Inventory.PickupMessage "$TXT_MMLAUNCHER"; } - action native void A_FireMiniMissile (); + native void A_FireMiniMissile (); States { @@ -446,7 +446,7 @@ class FlameThrower : StrifeWeapon Inventory.PickupMessage "$TXT_FLAMER"; } - action native void A_FireFlamer (); + native void A_FireFlamer (); States { @@ -492,7 +492,7 @@ class FlameMissile : Actor Obituary "$OB_MPFLAMETHROWER"; } - action native void A_FlameDie (); + native void A_FlameDie (); States { @@ -528,7 +528,7 @@ class Mauler : StrifeWeapon Obituary "$OB_MPMAULER1"; } - action native void A_FireMauler1 (); + native void A_FireMauler1 (); States { @@ -571,8 +571,8 @@ class Mauler2 : Mauler Tag "$TAG_MAULER2"; } - action native void A_FireMauler2Pre (); - action native void A_FireMauler2 (); + native void A_FireMauler2Pre (); + native void A_FireMauler2 (); States { @@ -639,7 +639,7 @@ class MaulerTorpedo : Actor Obituary "$OB_MPMAULER"; } - action native void A_MaulerTorpedoWave (); + native void A_MaulerTorpedoWave (); States { @@ -775,8 +775,8 @@ class PhosphorousFire : Actor native Obituary "$OB_MPPHOSPHOROUSGRENADE"; } - action native void A_Burnarea (); - action native void A_Burnination (); + native void A_Burnarea (); + native void A_Burnination (); States { @@ -816,7 +816,7 @@ class StrifeGrenadeLauncher : StrifeWeapon Inventory.PickupMessage "$TXT_GLAUNCHER"; } - action native void A_FireGrenade (class grenadetype, float angleofs, state flash); + native void A_FireGrenade (class grenadetype, float angleofs, state flash); States { diff --git a/wadsrc/static/zscript/strife/templar.txt b/wadsrc/static/zscript/strife/templar.txt index 4c640fd541..5b1605cf42 100644 --- a/wadsrc/static/zscript/strife/templar.txt +++ b/wadsrc/static/zscript/strife/templar.txt @@ -25,7 +25,7 @@ class Templar : Actor Obituary "$OB_TEMPLAR"; DropItem "EnergyPod"; } - action native void A_TemplarAttack(); + native void A_TemplarAttack(); States { diff --git a/wadsrc/static/zscript/strife/thingstoblowup.txt b/wadsrc/static/zscript/strife/thingstoblowup.txt index 659c13f56f..dbbad8ed60 100644 --- a/wadsrc/static/zscript/strife/thingstoblowup.txt +++ b/wadsrc/static/zscript/strife/thingstoblowup.txt @@ -121,9 +121,9 @@ class PowerCrystal : Actor ActiveSound "misc/reactor"; } - action native void A_ExtraLightOff (); - action native void A_Explode512 (); - action native void A_LightGoesOut (); + native void A_ExtraLightOff (); + native void A_Explode512 (); + native void A_LightGoesOut (); States { From 37914223f0bcae69a3f8095e66c504715a9f42ec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 18:13:54 +0200 Subject: [PATCH 092/471] - reviewed all places where VARF_Action and NAP were used and fixed what was still wrong. --- src/d_dehacked.cpp | 17 ++++++++++------- src/p_enemy.cpp | 2 +- src/scripting/decorate/thingdef_states.cpp | 14 +++++++------- src/scripting/thingdef.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 71deb01691..97d15e4d0d 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -808,22 +808,23 @@ void SetDehParams(FState *state, int codepointer) else { VMFunctionBuilder buildit(true); + int numargs = sym->GetImplicitArgs(); // 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 = new VMScriptFunction; buildit.MakeFunction(sfunc); - sfunc->NumArgs = NAP; - sfunc->ImplicitArgs = NAP; + sfunc->NumArgs = numargs; + sfunc->ImplicitArgs = numargs; state->SetAction(sfunc); sfunc->PrintableName.Format("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2); } @@ -2121,7 +2122,8 @@ static int PatchCodePtrs (int dummy) else { TArray &args = sym->Variants[0].ArgFlags; - if ((sym->Variants[0].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); sym = NULL; @@ -2733,7 +2735,8 @@ static bool LoadDehSupp () else { TArray &args = sym->Variants[0].ArgFlags; - if ((sym->Variants[0].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); } diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 1a2bddda49..14ea2b7c1e 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2773,7 +2773,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) PARAM_STATE_OPT (missile) { missile = NULL; } PARAM_INT_OPT (flags) { flags = 0; } - if (numparam >= NAP + 1) + if (numparam > 1) { if ((flags & CHF_RESURRECT) && P_CheckForResurrection(self, false)) return 0; diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 8b75b935f4..dda25f9265 100644 --- a/src/scripting/decorate/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" @@ -602,16 +602,16 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArrayVariants[0].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->Variants[0].Flags & VARF_Action) - { - numparams -= 2; - pnum += 2; - } assert(numparams >= 0); zeroparm = numparams == 0; if (numparams > 0 && !(paramflags[pnum] & VARF_Optional)) diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 45e77b3ad9..2798ab633a 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -143,7 +143,7 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i SetImplicitArgs(&args, &argflags, &argnames, containingclass, flags); PFunction *sym = new PFunction(containingclass, NAME_None); // anonymous functions do not have names. - sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, VARF_Action|VARF_Method); + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, flags); return sym; } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 9b4212820e..e702f7d2a4 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -32,7 +32,7 @@ ** */ -#include "actor.h" +#include "a_pickups.h" #include "thingdef.h" #include "sc_man.h" #include "c_console.h" From c2b37aeeea85a3774a5c19c3411f466fa62773c1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 19:43:53 +0200 Subject: [PATCH 093/471] - fixed a conversion warning with the pointer-type AActor fields. - added master and tracer to the list of exported variables. - fixed: 'none' as class type must map to the real null pointer so that it won't get rejected by the stricter type checks. - added handling for member function calls to zcc_compile.cpp. - fixed: FxMemberFunctionCall may not delete the self expression if it gets passed on to the actual function call. --- src/dobjtype.h | 2 +- src/namedef.h | 2 ++ src/scripting/codegeneration/codegen.cpp | 8 +++++++- src/scripting/thingdef_data.cpp | 2 ++ src/scripting/zscript/zcc_compile.cpp | 6 +++++- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index c5d96972b1..f3e043bd92 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -574,7 +574,7 @@ class PField : public PSymbol 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, size_t offset) : PSymbol(name), Offset(unsigned(offset)), Type(type), Flags(flags) {} unsigned int Offset; PType *Type; diff --git a/src/namedef.h b/src/namedef.h index d512a79486..9735578744 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -437,6 +437,8 @@ xx(ScaleX) xx(ScaleY) xx(Floatbobphase) xx(Target) +xx(Master) +xx(Tracer) xx(Blocking) xx(Blockmonsters) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c4a466873a..c7cd6e524f 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4975,6 +4975,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) auto self = !(afd->Variants[0].Flags & VARF_Static) ? Self : nullptr; auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly); ArgList = nullptr; + if (Self == self) Self = nullptr; delete this; return x->Resolve(ctx); } @@ -6226,6 +6227,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { FName clsname = static_cast(basex)->GetValue().GetName(); PClass *cls = NULL; + FxExpression *x; if (clsname != NAME_None) { @@ -6248,8 +6250,12 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) } ScriptPosition.Message(MSG_DEBUG, "resolving '%s' as class name", clsname.GetChars()); } + x = new FxConstant(cls, ScriptPosition); + } + else + { + x = new FxConstant(ScriptPosition); // create a genuine null pointer to get past the type checks. } - FxExpression *x = new FxConstant(cls, ScriptPosition); delete this; return x; } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 260cc64088..7e0668a0fc 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -677,4 +677,6 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle))); symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch))); symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); + symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master))); + symt.AddSymbol(new PField(NAME_Tracer, TypeActor, VARF_Native, myoffsetof(AActor, tracer))); } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e702f7d2a4..5d309bedc5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2381,7 +2381,11 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) return new FxFunctionCall(static_cast(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast); case AST_ExprMemberAccess: - break; + { + auto ema = static_cast(fcall->Function); + Printf("Member call to %s\n", FName(ema->Right).GetChars()); + return new FxMemberFunctionCall(ConvertNode(ema->Left), ema->Right, ConvertNodeList(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. From 32d33618eab1933aba8decea604263aa0464f46a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2016 19:51:24 +0200 Subject: [PATCH 094/471] - better fix for the class type problem: We already know the wanted type so let's use that instead of trying to determine it from the actual name. --- src/scripting/codegeneration/codegen.cpp | 9 ++------- src/scripting/codegeneration/codegen.h | 6 ++---- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c7cd6e524f..87f2e1f73c 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6199,9 +6199,9 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + auto to = static_cast(ValueType); if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer)) { - auto to = static_cast(ValueType); auto from = static_cast(basex->ValueType); if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction)) { @@ -6227,7 +6227,6 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { FName clsname = static_cast(basex)->GetValue().GetName(); PClass *cls = NULL; - FxExpression *x; if (clsname != NAME_None) { @@ -6250,12 +6249,8 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) } ScriptPosition.Message(MSG_DEBUG, "resolving '%s' as class name", clsname.GetChars()); } - x = new FxConstant(cls, ScriptPosition); - } - else - { - x = new FxConstant(ScriptPosition); // create a genuine null pointer to get past the type checks. } + FxExpression *x = new FxConstant(cls, to, ScriptPosition); delete this; return x; } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 4f3b57c131..15ba2a933e 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -364,12 +364,10 @@ public: isresolved = true; } - FxConstant(PClass *val, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(PClass *val, PClassPointer *valtype, const FScriptPosition &pos) : FxExpression(pos) { value.pointer = (void*)val; - if (val != nullptr) ValueType = NewClassPointer(val); - else ValueType = NewClassPointer(RUNTIME_CLASS(DObject)); - value.Type = NewClassPointer(RUNTIME_CLASS(DObject)); + value.Type = ValueType = valtype; isresolved = true; } From ccabb6f9bdc1e9ddf7549fe4b6f4eb98cdfc8e0d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2016 01:14:49 +0200 Subject: [PATCH 095/471] - Gave FxExpression a type identifier field so that certain combinations that are easy to optimize can be detected. --- src/scripting/codegeneration/codegen.cpp | 96 +++++++++---------- src/scripting/codegeneration/codegen.h | 114 ++++++++++++++++------- 2 files changed, 129 insertions(+), 81 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 87f2e1f73c..d0713c50b9 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -435,7 +435,7 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build) //========================================================================== FxBoolCast::FxBoolCast(FxExpression *x) - : FxExpression(x->ScriptPosition) + : FxExpression(EFX_BoolCast, x->ScriptPosition) { basex = x; ValueType = TypeBool; @@ -533,7 +533,7 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) //========================================================================== FxIntCast::FxIntCast(FxExpression *x, bool nowarn) -: FxExpression(x->ScriptPosition) +: FxExpression(EFX_IntCast, x->ScriptPosition) { basex=x; ValueType = TypeSInt32; @@ -632,7 +632,7 @@ ExpEmit FxIntCast::Emit(VMFunctionBuilder *build) //========================================================================== FxFloatCast::FxFloatCast(FxExpression *x) - : FxExpression(x->ScriptPosition) + : FxExpression(EFX_FloatCast, x->ScriptPosition) { basex = x; ValueType = TypeFloat64; @@ -723,7 +723,7 @@ ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build) //========================================================================== FxNameCast::FxNameCast(FxExpression *x) - : FxExpression(x->ScriptPosition) + : FxExpression(EFX_NameCast, x->ScriptPosition) { basex = x; ValueType = TypeName; @@ -801,7 +801,7 @@ ExpEmit FxNameCast::Emit(VMFunctionBuilder *build) //========================================================================== FxStringCast::FxStringCast(FxExpression *x) - : FxExpression(x->ScriptPosition) + : FxExpression(EFX_StringCast, x->ScriptPosition) { basex = x; ValueType = TypeString; @@ -898,7 +898,7 @@ ExpEmit FxStringCast::Emit(VMFunctionBuilder *build) //========================================================================== FxColorCast::FxColorCast(FxExpression *x) - : FxExpression(x->ScriptPosition) + : FxExpression(EFX_ColorCast, x->ScriptPosition) { basex = x; ValueType = TypeColor; @@ -977,7 +977,7 @@ ExpEmit FxColorCast::Emit(VMFunctionBuilder *build) //========================================================================== FxSoundCast::FxSoundCast(FxExpression *x) - : FxExpression(x->ScriptPosition) + : FxExpression(EFX_SoundCast, x->ScriptPosition) { basex = x; ValueType = TypeSound; @@ -1056,7 +1056,7 @@ ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build) //========================================================================== FxTypeCast::FxTypeCast(FxExpression *x, PType *type, bool nowarn) - : FxExpression(x->ScriptPosition) + : FxExpression(EFX_TypeCast, x->ScriptPosition) { basex = x; ValueType = type; @@ -1241,7 +1241,7 @@ ExpEmit FxTypeCast::Emit(VMFunctionBuilder *build) //========================================================================== FxPlusSign::FxPlusSign(FxExpression *operand) -: FxExpression(operand->ScriptPosition) +: FxExpression(EFX_PlusSign, operand->ScriptPosition) { Operand=operand; } @@ -1295,7 +1295,7 @@ ExpEmit FxPlusSign::Emit(VMFunctionBuilder *build) //========================================================================== FxMinusSign::FxMinusSign(FxExpression *operand) -: FxExpression(operand->ScriptPosition) +: FxExpression(EFX_MinusSign, operand->ScriptPosition) { Operand=operand; } @@ -1375,7 +1375,7 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) //========================================================================== FxUnaryNotBitwise::FxUnaryNotBitwise(FxExpression *operand) -: FxExpression(operand->ScriptPosition) +: FxExpression(EFX_UnaryNotBitwise, operand->ScriptPosition) { Operand=operand; } @@ -1455,7 +1455,7 @@ ExpEmit FxUnaryNotBitwise::Emit(VMFunctionBuilder *build) //========================================================================== FxUnaryNotBoolean::FxUnaryNotBoolean(FxExpression *operand) -: FxExpression(operand->ScriptPosition) +: FxExpression(EFX_UnaryNotBoolean, operand->ScriptPosition) { Operand=operand; } @@ -1525,7 +1525,7 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) //========================================================================== FxSizeAlign::FxSizeAlign(FxExpression *operand, int which) - : FxExpression(operand->ScriptPosition) + : FxExpression(EFX_SizeAlign, operand->ScriptPosition) { Operand = operand; Which = which; @@ -1586,7 +1586,7 @@ ExpEmit FxSizeAlign::Emit(VMFunctionBuilder *build) //========================================================================== FxPreIncrDecr::FxPreIncrDecr(FxExpression *base, int token) -: FxExpression(base->ScriptPosition), Token(token), Base(base) +: FxExpression(EFX_PreIncrDecr, base->ScriptPosition), Token(token), Base(base) { AddressRequested = false; AddressWritable = false; @@ -1680,7 +1680,7 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) //========================================================================== FxPostIncrDecr::FxPostIncrDecr(FxExpression *base, int token) -: FxExpression(base->ScriptPosition), Token(token), Base(base) +: FxExpression(EFX_PostIncrDecr, base->ScriptPosition), Token(token), Base(base) { } @@ -1762,7 +1762,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) //========================================================================== FxAssign::FxAssign(FxExpression *base, FxExpression *right) -: FxExpression(base->ScriptPosition), Base(base), Right(right) +: FxExpression(EFX_Assign, base->ScriptPosition), Base(base), Right(right) { AddressRequested = false; AddressWritable = false; @@ -1915,7 +1915,7 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) //========================================================================== FxAssignSelf::FxAssignSelf(const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_AssignSelf, pos) { Assignment = nullptr; } @@ -1955,7 +1955,7 @@ ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) //========================================================================== FxBinary::FxBinary(int o, FxExpression *l, FxExpression *r) -: FxExpression(l->ScriptPosition) +: FxExpression(EFX_Binary, l->ScriptPosition) { Operator=o; left=l; @@ -2842,7 +2842,7 @@ ExpEmit FxLtGtEq::Emit(VMFunctionBuilder *build) //========================================================================== FxBinaryLogical::FxBinaryLogical(int o, FxExpression *l, FxExpression *r) -: FxExpression(l->ScriptPosition) +: FxExpression(EFX_BinaryLogical, l->ScriptPosition) { Operator=o; left=l; @@ -3020,7 +3020,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) //========================================================================== FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f) -: FxExpression(c->ScriptPosition) +: FxExpression(EFX_Conditional, c->ScriptPosition) { condition = c; truex=t; @@ -3185,7 +3185,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) // //========================================================================== FxAbs::FxAbs(FxExpression *v) -: FxExpression(v->ScriptPosition) +: FxExpression(EFX_Abs, v->ScriptPosition) { val = v; ValueType = v->ValueType; @@ -3275,7 +3275,7 @@ ExpEmit FxAbs::Emit(VMFunctionBuilder *build) // //========================================================================== FxATan2::FxATan2(FxExpression *y, FxExpression *x, const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_ATan2, pos) { yval = y; xval = x; @@ -3368,7 +3368,7 @@ ExpEmit FxATan2::ToReg(VMFunctionBuilder *build, FxExpression *val) // //========================================================================== FxMinMax::FxMinMax(TArray &expr, FName type, const FScriptPosition &pos) -: FxExpression(pos), Type(type) +: FxExpression(EFX_MinMax, pos), Type(type) { assert(expr.Size() > 0); assert(type == NAME_Min || type == NAME_Max); @@ -3586,7 +3586,7 @@ ExpEmit FxMinMax::Emit(VMFunctionBuilder *build) // //========================================================================== FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos, bool nowarn) -: FxExpression(pos) +: FxExpression(EFX_Random, pos) { EmitTail = false; if (mi != NULL && ma != NULL) @@ -3719,7 +3719,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build) // //========================================================================== FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, const FScriptPosition &pos, bool nowarn) -: FxExpression(pos) +: FxExpression(EFX_RandomPick, pos) { assert(expr.Size() > 0); choices.Resize(expr.Size()); @@ -3891,6 +3891,7 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri max = new FxFloatCast(ma); } ValueType = TypeFloat64; + ExprType = EFX_FRandom; } //========================================================================== @@ -3965,7 +3966,7 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) //========================================================================== FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos, bool nowarn) -: FxExpression(pos) +: FxExpression(EFX_Random2, pos) { EmitTail = false; rng = r; @@ -4051,7 +4052,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) //========================================================================== FxIdentifier::FxIdentifier(FName name, const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_Identifier, pos) { Identifier = name; } @@ -4195,6 +4196,7 @@ FxMemberIdentifier::FxMemberIdentifier(FxExpression *left, FName name, const FSc : FxIdentifier(name, pos) { Object = left; + ExprType = EFX_MemberIdentifier; } //========================================================================== @@ -4295,7 +4297,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) //========================================================================== FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptPosition &sc) - : FxExpression(sc) + : FxExpression(EFX_LocalVariable, sc) { Variable = var; ValueType = var->ValueType; @@ -4330,7 +4332,7 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) //========================================================================== FxSelf::FxSelf(const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_Self, pos) { } @@ -4373,7 +4375,7 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build) //========================================================================== FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_ClassMember, pos) { classx = x; membervar = mem; @@ -4471,7 +4473,7 @@ ExpEmit FxClassMember::Emit(VMFunctionBuilder *build) //========================================================================== FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index) -:FxExpression(base->ScriptPosition) +:FxExpression(EFX_ArrayElement, base->ScriptPosition) { Array=base; index = _index; @@ -4650,7 +4652,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) //========================================================================== FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_FunctionCall, pos) { MethodName = methodname; RNG = nullptr; @@ -4888,7 +4890,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) //========================================================================== FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos) - : FxExpression(pos) + : FxExpression(EFX_MemberFunctionCall, pos) { Self = self; MethodName = methodname; @@ -4991,7 +4993,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) //========================================================================== FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgumentList *args, const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_ActionSpecialCall, pos) { Self = self; Special = special; @@ -5157,7 +5159,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) //========================================================================== FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool novirtual) -: FxExpression(pos) +: FxExpression(EFX_VMFunctionCall, pos) { Self = self; Function = func; @@ -5391,7 +5393,7 @@ bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, Ex //========================================================================== FxFlopFunctionCall::FxFlopFunctionCall(size_t index, FArgumentList *args, const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_FlopFunctionCall, pos) { assert(index < countof(FxFlops) && "FLOP index out of range"); Index = (int)index; @@ -5612,7 +5614,7 @@ bool FxCompoundStatement::CheckLocalVariable(FName name) FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part, FxExpression *false_part, const FScriptPosition &pos) -: FxExpression(pos) +: FxExpression(EFX_IfStatement, pos) { Condition = cond; WhenTrue = true_part; @@ -5764,7 +5766,7 @@ void FxLoopStatement::Backpatch(VMFunctionBuilder *build, size_t loopstart, size //========================================================================== FxWhileLoop::FxWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) -: FxLoopStatement(pos), Condition(condition), Code(code) +: FxLoopStatement(EFX_WhileLoop, pos), Condition(condition), Code(code) { ValueType = TypeVoid; } @@ -5850,7 +5852,7 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) //========================================================================== FxDoWhileLoop::FxDoWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) -: FxLoopStatement(pos), Condition(condition), Code(code) +: FxLoopStatement(EFX_DoWhileLoop, pos), Condition(condition), Code(code) { ValueType = TypeVoid; } @@ -5938,7 +5940,7 @@ ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) //========================================================================== FxForLoop::FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos) -: FxLoopStatement(pos), Init(init), Condition(condition), Iteration(iteration), Code(code) +: FxLoopStatement(EFX_ForLoop, pos), Init(init), Condition(condition), Iteration(iteration), Code(code) { ValueType = TypeVoid; } @@ -6050,7 +6052,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) //========================================================================== FxJumpStatement::FxJumpStatement(int token, const FScriptPosition &pos) -: FxExpression(pos), Token(token) +: FxExpression(EFX_JumpStatement, pos), Token(token) { ValueType = TypeVoid; } @@ -6084,7 +6086,7 @@ ExpEmit FxJumpStatement::Emit(VMFunctionBuilder *build) //========================================================================== FxReturnStatement::FxReturnStatement(FxExpression *value, const FScriptPosition &pos) -: FxExpression(pos), Value(value) +: FxExpression(EFX_ReturnStatement, pos), Value(value) { ValueType = TypeVoid; } @@ -6162,7 +6164,7 @@ VMFunction *FxReturnStatement::GetDirectFunction() //========================================================================== FxClassTypeCast::FxClassTypeCast(PClassPointer *dtype, FxExpression *x) -: FxExpression(x->ScriptPosition) +: FxExpression(EFX_ClassTypeCast, x->ScriptPosition) { ValueType = dtype; desttype = dtype->ClassRestriction; @@ -6348,7 +6350,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) //========================================================================== FxRuntimeStateIndex::FxRuntimeStateIndex(FxExpression *index) -: FxExpression(index->ScriptPosition), Index(index) +: FxExpression(EFX_RuntimeStateIndex, index->ScriptPosition), Index(index) { EmitTail = false; ValueType = TypeState; @@ -6468,7 +6470,7 @@ ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build) //========================================================================== FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPosition &pos) - :FxExpression(pos) + :FxExpression(EFX_MultiNameState, pos) { FName scopename; FString statestring = _statestring; @@ -6645,7 +6647,7 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) //========================================================================== FxDamageValue::FxDamageValue(FxExpression *v) -: FxExpression(v->ScriptPosition) +: FxExpression(EFX_DamageValue, v->ScriptPosition) { val = v; ValueType = TypeVoid; @@ -6696,7 +6698,7 @@ ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build) //========================================================================== FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p) - :FxExpression(p) + :FxExpression(EFX_LocalVariableDeclaration, p) { ValueType = type; VarFlags = varflags; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 15ba2a933e..8cce34a159 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -202,6 +202,68 @@ struct ExpEmit BYTE RegNum, RegType, 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_Conditional, + EFX_Abs, + EFX_ATan2, + EFX_MinMax, + EFX_Random, + EFX_RandomPick, + EFX_FRandom, + EFX_Random2, + EFX_ClassMember, + 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_COUNT +}; + //========================================================================== // // @@ -211,8 +273,8 @@ struct ExpEmit class FxExpression { protected: - FxExpression(const FScriptPosition &pos) - : ScriptPosition(pos) + FxExpression(EFxType type, const FScriptPosition &pos) + : ScriptPosition(pos), ExprType(type) { } @@ -235,6 +297,7 @@ public: PType *ValueType = nullptr; bool isresolved = false; + EFxType ExprType; }; //========================================================================== @@ -270,23 +333,6 @@ public: }; -//========================================================================== -// -// FxDotIdentifier -// -//========================================================================== - -class FxDotIdentifier : public FxExpression -{ - FxExpression *container; - FName Identifier; - -public: - FxDotIdentifier(FxExpression*, FName, const FScriptPosition &); - ~FxDotIdentifier(); - FxExpression *Resolve(FCompileContext&); -}; - //========================================================================== // // FxClassDefaults @@ -315,70 +361,70 @@ 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, PClassPointer *valtype, const FScriptPosition &pos) : FxExpression(pos) + FxConstant(PClass *val, PClassPointer *valtype, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { value.pointer = (void*)val; 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(pos) + FxConstant(const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { value.pointer = nullptr; ValueType = value.Type = TypeNullPtr; @@ -1175,7 +1221,7 @@ 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); } @@ -1232,8 +1278,8 @@ public: class FxLoopStatement : public FxExpression { protected: - FxLoopStatement(const FScriptPosition &pos) - : FxExpression(pos) + FxLoopStatement(EFxType etype, const FScriptPosition &pos) + : FxExpression(etype, pos) { } @@ -1367,7 +1413,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; } @@ -1440,7 +1486,7 @@ class FxNop : public FxExpression { public: FxNop(const FScriptPosition &p) - : FxExpression(p) + : FxExpression(EFX_Nop, p) { isresolved = true; } From f9cd2c9af7fa4dce1edfb32097ed813ff4f38527 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2016 12:00:25 +0200 Subject: [PATCH 096/471] - added switch/case processing. Right now it is just a sequence of test/jmp instructions. It may make sense to add a special opcode that can perform the comparisons natively but that's an option for later. - added a TESTN instruction. This is like TEST but negates the operand. This was added to avoid flooding the constant table with too many case labels. With TEST and TESTN combined, all numbers between -65535 and 65535 can be kept entirely inside the instruction. Numbers outside this range still use a BEQ instruction. --- src/scripting/codegeneration/codegen.cpp | 228 +++++++++++++++++++++++ src/scripting/codegeneration/codegen.h | 47 +++++ src/scripting/vm/vmexec.h | 7 + src/scripting/vm/vmops.h | 1 + src/scripting/zscript/zcc_compile.cpp | 21 ++- wadsrc/static/zscript.txt | 2 + 6 files changed, 304 insertions(+), 2 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d0713c50b9..9568c34a55 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5606,6 +5606,234 @@ bool FxCompoundStatement::CheckLocalVariable(FName name) return false; } +//========================================================================== +// +// FxSwitchStatement +// +//========================================================================== + +FxSwitchStatement::FxSwitchStatement(FxExpression *cond, FArgumentList *content, const FScriptPosition &pos) + : FxExpression(EFX_SwitchStatement, pos) +{ + Condition = new FxIntCast(cond, false); + Content = content; +} + +FxSwitchStatement::~FxSwitchStatement() +{ + SAFE_DELETE(Condition); + SAFE_DELETE(Content); +} + +FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Condition, ctx); + + if (Content == nullptr || 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; + return Condition; + } + } + + 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); + } + } + + if (Condition->isConstant()) + { + ScriptPosition.Message(MSG_WARNING, "Case expression is constant"); + auto &content = *Content; + unsigned defaultindex = -1; + unsigned defaultbreak = -1; + unsigned caseindex = -1; + unsigned 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 (unsigned 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); + } + return ExpEmit(); +} + + +//========================================================================== +// +// 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 diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 8cce34a159..3ea97ba665 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -261,6 +261,8 @@ enum EFxType EFX_DamageValue, EFX_Nop, EFX_LocalVariableDeclaration, + EFX_SwitchStatement, + EFX_CaseStatement, EFX_COUNT }; @@ -1250,6 +1252,51 @@ public: 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); +}; + +//========================================================================== +// +// 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&); +}; + //========================================================================== // // FxIfStatement diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index d3c1632b82..2ddc505997 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -372,6 +372,13 @@ begin: pc++; } NEXTOP; + OP(TESTN): + ASSERTD(a); + if (-reg.d[a] != BC) + { + pc++; + } + NEXTOP; OP(JMP): pc += JMPOFS(pc); NEXTOP; diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 1b34dcc0fc..9ffe2d847d 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -69,6 +69,7 @@ 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) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 5d309bedc5..ed85ab6b32 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2677,9 +2677,26 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // not yet done case AST_SwitchStmt: - case AST_CaseStmt: - break; + { + 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); + return new FxSwitchStatement(ConvertNode(swtch->Condition), ConvertNodeList(cmpnd->Content), *ast); + } + } + case AST_CaseStmt: + { + auto cases = static_cast(ast); + return new FxCaseStatement(ConvertNode(cases->Condition), *ast); + } case AST_CompoundStmt: { diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 6de64d07e5..3ab33bfd96 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -177,3 +177,5 @@ zscript/chex/chexweapons.txt zscript/chex/chexitems.txt zscript/chex/chexdecorations.txt zscript/chex/chexplayer.txt + +zscript/test2.txt From a2116fc7bf682cb67d3c9c675930743fd83072ff Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2016 12:57:21 +0200 Subject: [PATCH 097/471] - created an export for P_SpawnMissile so that I can do some tests with functions. - allow class extensions. These are separate blocks in different files that get concatenated to one class body for processing. The reason is to allow spreading the many functions in Actor over multiple files, so that they remain manageable. For example, all the Doom action functions should be in their respective files, but their symbols need to be in Actor. To extend a class, both files need to be in the same translation unit, so it won't allow user-side extension of internal classes. --- src/p_mobj.cpp | 9 ++++++++ src/sc_man_scanner.re | 2 +- src/sc_man_tokens.h | 2 +- src/scripting/vm/vm.h | 1 + src/scripting/zscript/zcc-parse.lemon | 12 +++++++++++ src/scripting/zscript/zcc_compile.cpp | 31 +++++++++++++++++++++++++-- src/scripting/zscript/zcc_parser.cpp | 1 + src/scripting/zscript/zcc_parser.h | 1 + wadsrc/static/zscript/actor.txt | 7 ++++-- 9 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f61ad34bb7..d89a89576c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5824,6 +5824,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, P_SpawnMissile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(dest, AActor); + PARAM_CLASS(type, AActor); + PARAM_OBJECT_OPT(owner, AActor) { owner = self; } + ACTION_RETURN_OBJECT(P_SpawnMissile(self, dest, type, owner)); +} + AActor *P_SpawnMissileZ (AActor *source, double z, AActor *dest, PClassActor *type) { if (source == NULL) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index caeb18f8cc..cc9968ae3f 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -151,7 +151,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); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 69927883cb..19d3313019 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -89,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'") diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index a37b7449b6..12ce012736 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1013,6 +1013,7 @@ struct AFuncDesc #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_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) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index eeeba6295a..fc34fd2d76 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -171,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); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index ed85ab6b32..8389975efa 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -61,8 +61,29 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) { - Classes.Push(new ZCC_ClassWork(static_cast(cnode), treenode)); - auto cls = Classes.Last(); + 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; @@ -220,6 +241,12 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, 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: diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 7d4edf78a3..bc78576306 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -198,6 +198,7 @@ static void InitTokenMap() TOKENDEF (TK_Offset, ZCC_OFFSET); TOKENDEF (TK_CanRaise, ZCC_CANRAISE); TOKENDEF (TK_Light, ZCC_LIGHT); + TOKENDEF (TK_Extend, ZCC_EXTEND); ZCC_InitOperators(); ZCC_InitConversions(); diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 503ef7e9e3..ca8c3f3cbf 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -32,6 +32,7 @@ enum ZCC_ReadOnly = 1 << 9, ZCC_FuncConst = 1 << 10, ZCC_Abstract = 1 << 11, + ZCC_Extension = 1 << 12, }; // Function parameter modifiers diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5144a1bd09..502b8d0cfa 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -47,6 +47,9 @@ class Actor : Thinker native } // Functions + native Actor P_SpawnMissile(Actor dest, class type, Actor owner = null); + + // DECORATE compatible 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); @@ -112,8 +115,8 @@ class Actor : Thinker native native void A_BetaSkullAttack(); native void A_Metal(); native void A_SpidRefire(); - native void A_BabyMetal(); - native void A_BspiAttack(); + //native void A_BabyMetal(); + //native void A_BspiAttack(); native void A_Hoof(); native void A_CyberAttack(); native void A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); From 46c7f1151fe074b75e8b4d3cf663b5ff625a6376 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2016 12:58:03 +0200 Subject: [PATCH 098/471] - restored zscript.txt. --- wadsrc/static/zscript.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 3ab33bfd96..6de64d07e5 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -177,5 +177,3 @@ zscript/chex/chexweapons.txt zscript/chex/chexitems.txt zscript/chex/chexdecorations.txt zscript/chex/chexplayer.txt - -zscript/test2.txt From 5b952b116aa9d1563b432a5f2cf2f6d048792264 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2016 14:26:33 +0200 Subject: [PATCH 099/471] - named class functions are working. Yay!! - converted A_BspiAttack and A_BabyMetal to script functions to test the implementation. --- src/CMakeLists.txt | 1 - src/g_doom/a_arachnotron.cpp | 30 ---------------------- src/g_doom/a_doommisc.cpp | 1 - src/scripting/vm/vmbuilder.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 9 +++++++ wadsrc/static/zscript/doom/arachnotron.txt | 23 +++++++++++++++++ 6 files changed, 33 insertions(+), 33 deletions(-) delete mode 100644 src/g_doom/a_arachnotron.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ddd027c802..2720f026d5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -835,7 +835,6 @@ 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 diff --git a/src/g_doom/a_arachnotron.cpp b/src/g_doom/a_arachnotron.cpp deleted file mode 100644 index 22223d24b3..0000000000 --- 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 "vm.h" -*/ - -DEFINE_ACTION_FUNCTION(AActor, A_BspiAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_BODY, "baby/walk", 1, ATTN_IDLE); - A_Chase (stack, self); - return 0; -} diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index a4eca67b70..81e5a253aa 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -22,7 +22,6 @@ #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" diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index b58de0ea4b..1b7c4ce703 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -693,7 +693,7 @@ void FFunctionBuildList::Build() FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate); // Allocate registers for the function's arguments and create local variable nodes before starting to resolve it. - VMFunctionBuilder buildit(true); + VMFunctionBuilder buildit(!!(item.Func->Variants[0].Flags & VARF_Action)); for(unsigned i=0;iVariants[0].Proto->ArgumentTypes.Size();i++) { auto type = item.Func->Variants[0].Proto->ArgumentTypes[i]; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 8389975efa..723e82c8d5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2042,6 +2042,15 @@ void ZCCCompiler::InitFunctions() 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(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); + } + } + // todo: Check inheritance. // todo: Process function bodies. } diff --git a/wadsrc/static/zscript/doom/arachnotron.txt b/wadsrc/static/zscript/doom/arachnotron.txt index e3aa17d484..0e093323b2 100644 --- a/wadsrc/static/zscript/doom/arachnotron.txt +++ b/wadsrc/static/zscript/doom/arachnotron.txt @@ -88,4 +88,27 @@ class ArachnotronPlasma : Actor } } +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + void A_BspiAttack() + { + if (target) + { + A_FaceTarget(); + P_SpawnMissile(target, "ArachnotronPlasma"); + } + } + + void A_BabyMetal() + { + A_PlaySound("baby/walk", CHAN_BODY, 1, false, ATTN_IDLE); + A_Chase(); + } +} From da56e5908d9f2e2ac3c94ecc56d07f2daad91dd8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2016 15:30:58 +0200 Subject: [PATCH 100/471] - added an optimization to FxBoolCast that it doesn't force the source value to a 0/1 integer if not explicitly needed. When doing comparisons we do not care about actual values, we only want to know if it is 0 or not. - added the above for the 'if' condition. It works for integers, floats and pointers and will save 3 instructions if the condition is a non-boolean that can be implicitly casted to bool. --- src/scripting/codegeneration/codegen.cpp | 72 ++++++++++++++++-------- src/scripting/codegeneration/codegen.h | 3 +- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9568c34a55..f882b8b2bd 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -434,11 +434,12 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build) // //========================================================================== -FxBoolCast::FxBoolCast(FxExpression *x) +FxBoolCast::FxBoolCast(FxExpression *x, bool needvalue) : FxExpression(EFX_BoolCast, x->ScriptPosition) { basex = x; ValueType = TypeBool; + NeedValue = needvalue; } //========================================================================== @@ -499,31 +500,37 @@ 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) + if (NeedValue) { - 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); + ExpEmit to(build, REGT_INT); + from.Free(build); + // Preload result with 0. + build->Emit(OP_LI, to.RegNum, 0); - // Reload result with 1 if the comparison fell through. - build->Emit(OP_LI, to.RegNum, 1); + // 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); - return to; + // Reload result with 1 if the comparison fell through. + build->Emit(OP_LI, to.RegNum, 1); + return to; + } + else + { + return from; + } } //========================================================================== @@ -5871,7 +5878,7 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) if (Condition->ValueType != TypeBool) { - Condition = new FxBoolCast(Condition); + Condition = new FxBoolCast(Condition, false); SAFE_RESOLVE(Condition, ctx); } @@ -5914,7 +5921,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) // 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); + assert(cond.RegType != REGT_STRING && !cond.Konst); if (WhenTrue != NULL) { @@ -5933,7 +5940,22 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) } // Test condition. - build->Emit(OP_EQ_K, condcheck, cond.RegNum, build->GetConstantInt(0)); + + 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); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 3ea97ba665..9125d5d8c8 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -457,10 +457,11 @@ public: class FxBoolCast : public FxExpression { FxExpression *basex; + bool NeedValue; public: - FxBoolCast(FxExpression *x); + FxBoolCast(FxExpression *x, bool needvalue = true); ~FxBoolCast(); FxExpression *Resolve(FCompileContext&); From 9f8a5dae214b03e73aa51c80c59760c202c293be Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2016 17:15:24 +0200 Subject: [PATCH 101/471] - scriptified A_BruisAttack. - removed 'self' as a dedicated token. Internally this gets handled as a normal but implicitly named variable so the token just gets in the way of proper processing. - removed P_ prefix from SpawnMissile export. - fixed a crash with misnamed function exports. --- src/g_doom/a_bruiser.cpp | 23 ------------------ src/g_doom/a_doommisc.cpp | 1 - src/p_enemy.cpp | 6 +++++ src/p_interaction.cpp | 12 ++++++++++ src/p_map.cpp | 10 ++++++++ src/p_mobj.cpp | 2 +- src/sc_man_scanner.re | 1 - src/sc_man_tokens.h | 1 - src/scripting/zscript/zcc-parse.lemon | 15 +----------- src/scripting/zscript/zcc_compile.cpp | 5 +++- src/scripting/zscript/zcc_exprlist.h | 1 - src/scripting/zscript/zcc_parser.cpp | 1 - src/scripting/zscript/zcc_parser.h | 1 - wadsrc/static/zscript/actor.txt | 8 +++---- wadsrc/static/zscript/doom/arachnotron.txt | 2 +- wadsrc/static/zscript/doom/bruiser.txt | 27 ++++++++++++++++++++++ 16 files changed, 66 insertions(+), 50 deletions(-) delete mode 100644 src/g_doom/a_bruiser.cpp diff --git a/src/g_doom/a_bruiser.cpp b/src/g_doom/a_bruiser.cpp deleted file mode 100644 index 1d2be64f03..0000000000 --- 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_SELF_PROLOGUE(AActor); - - 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_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 81e5a253aa..2115e70e1a 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -24,7 +24,6 @@ // Include all the other Doom stuff here to reduce compile time #include "a_archvile.cpp" #include "a_bossbrain.cpp" -#include "a_bruiser.cpp" #include "a_cacodemon.cpp" #include "a_cyberdemon.cpp" #include "a_demon.cpp" diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 14ea2b7c1e..0c2cb8e28b 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -310,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 diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 261cfb8f3d..f3d02428d1 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1555,6 +1555,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_OPT(flags) { flags = 0; } + PARAM_FLOAT_OPT(angle) { angle = 0; } + 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_map.cpp b/src/p_map.cpp index 5cc9bdf72c..849f8dd241 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4574,6 +4574,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_mobj.cpp b/src/p_mobj.cpp index d89a89576c..8e630b77a5 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5824,7 +5824,7 @@ 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, P_SpawnMissile) +DEFINE_ACTION_FUNCTION(AActor, SpawnMissile) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(dest, AActor); diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index cc9968ae3f..8fbb28ef55 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -169,7 +169,6 @@ std2: 'virtual' { RET(TK_Virtual); } 'super' { RET(TK_Super); } 'global' { RET(TK_Global); } - 'self' { RET(TK_Self); } 'stop' { RET(TK_Stop); } 'null' { RET(TK_Null); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 19d3313019..7d9f81e9b9 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -108,7 +108,6 @@ xx(TK_Virtual, "'virtual'") xx(TK_Super, "'super'") xx(TK_Null, "'null'") xx(TK_Global, "'global'") -xx(TK_Self, "'self'") xx(TK_Stop, "'stop'") xx(TK_Include, "'include'") diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index fc34fd2d76..0cf061bef0 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -977,13 +977,6 @@ primary(X) ::= IDENTIFIER(A). expr->Type = NULL; X = expr; } -primary(X) ::= NULL(T). -{ - NEW_AST_NODE(Expression, expr, T); - expr->Operation = PEX_Null; - expr->Type = NULL; - X = expr; -} primary(X) ::= SUPER(T). { NEW_AST_NODE(Expression, expr, T); @@ -992,13 +985,7 @@ primary(X) ::= SUPER(T). X = expr; } primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ } -primary(X) ::= SELF(T). -{ - NEW_AST_NODE(Expression, expr, T); - expr->Operation = PEX_Self; - expr->Type = NULL; - X = expr; -} + primary(X) ::= LPAREN expr(A) RPAREN. { X = A; /*X-overwrites-A*/ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 723e82c8d5..274778dfee 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2001,7 +2001,10 @@ void ZCCCompiler::InitFunctions() { Error(f, "The function '%s' has not been exported from the executable.", FName(f->Name).GetChars()); } - (*afd->VMPointer)->ImplicitArgs = BYTE(implicitargs); + else + { + (*afd->VMPointer)->ImplicitArgs = BYTE(implicitargs); + } } SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags); auto p = f->Params; diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index 4770a08a47..bbf99189c3 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -4,7 +4,6 @@ xx(Nil, TK_None) xx(ID, TK_Identifier) xx(Super, TK_Super) xx(Null, TK_Null) -xx(Self, TK_Self) xx(ConstValue, TK_Const) xx(FuncCall, '(') xx(ArrayAccess, TK_Array) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index bc78576306..18d683c4cc 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -155,7 +155,6 @@ static void InitTokenMap() TOKENDEF (TK_Optional, ZCC_OPTIONAL); TOKENDEF (TK_Super, ZCC_SUPER); TOKENDEF (TK_Null, ZCC_NULLPTR); - TOKENDEF (TK_Self, ZCC_SELF); TOKENDEF ('~', ZCC_TILDE); TOKENDEF ('!', ZCC_BANG); TOKENDEF (TK_SizeOf, ZCC_SIZEOF); diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index ca8c3f3cbf..7ba48d711c 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -44,7 +44,6 @@ enum }; - // Syntax tree structures. enum EZCCTreeNodeType { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 502b8d0cfa..caea22aaec 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -47,7 +47,10 @@ class Actor : Thinker native } // Functions - native Actor P_SpawnMissile(Actor dest, class type, Actor owner = null); + native Actor SpawnMissile(Actor dest, class type, Actor owner = null); + native void TraceBleed(int damage, Actor missile); + native bool CheckMeleeRange(); + native int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); @@ -110,13 +113,10 @@ class Actor : Thinker native native void A_TroopAttack(); native void A_SargAttack(); native void A_HeadAttack(); - native void A_BruisAttack(); native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); native void A_Metal(); native void A_SpidRefire(); - //native void A_BabyMetal(); - //native void A_BspiAttack(); native void A_Hoof(); native void A_CyberAttack(); native void A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); diff --git a/wadsrc/static/zscript/doom/arachnotron.txt b/wadsrc/static/zscript/doom/arachnotron.txt index 0e093323b2..c7e11ab146 100644 --- a/wadsrc/static/zscript/doom/arachnotron.txt +++ b/wadsrc/static/zscript/doom/arachnotron.txt @@ -101,7 +101,7 @@ extend class Actor if (target) { A_FaceTarget(); - P_SpawnMissile(target, "ArachnotronPlasma"); + SpawnMissile(target, "ArachnotronPlasma"); } } diff --git a/wadsrc/static/zscript/doom/bruiser.txt b/wadsrc/static/zscript/doom/bruiser.txt index bbeb319f61..c1faa23c19 100644 --- a/wadsrc/static/zscript/doom/bruiser.txt +++ b/wadsrc/static/zscript/doom/bruiser.txt @@ -138,3 +138,30 @@ class BaronBall : Actor } } +//=========================================================================== +// +// 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"); + } + } + } +} From 3f1673f34ffdfb468c5680ca0328b1f05041ccf7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Oct 2016 00:50:28 +0200 Subject: [PATCH 102/471] - scriptified A_HeadAttack, A_CyberAttack and A_Hoof. --- src/g_doom/a_cacodemon.cpp | 35 ----------------------- src/g_doom/a_cyberdemon.cpp | 29 ------------------- src/g_doom/a_doommisc.cpp | 2 -- src/scripting/thingdef_data.cpp | 1 + wadsrc/static/zscript/actor.txt | 3 -- wadsrc/static/zscript/doom/cacodemon.txt | 29 +++++++++++++++++++ wadsrc/static/zscript/doom/cyberdemon.txt | 25 ++++++++++++++++ 7 files changed, 55 insertions(+), 69 deletions(-) delete mode 100644 src/g_doom/a_cacodemon.cpp delete mode 100644 src/g_doom/a_cyberdemon.cpp diff --git a/src/g_doom/a_cacodemon.cpp b/src/g_doom/a_cacodemon.cpp deleted file mode 100644 index 354443bd69..0000000000 --- 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 "vm.h" -*/ - -static FRandom pr_headattack ("HeadAttack"); - -DEFINE_ACTION_FUNCTION(AActor, A_HeadAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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 6e78759c37..0000000000 --- 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 "vm.h" -*/ - -DEFINE_ACTION_FUNCTION(AActor, A_CyberAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - S_Sound (self, CHAN_BODY, "cyber/hoof", 1, ATTN_IDLE); - A_Chase (stack, self); - return 0; -} diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 2115e70e1a..fb5ae3b28f 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -24,8 +24,6 @@ // Include all the other Doom stuff here to reduce compile time #include "a_archvile.cpp" #include "a_bossbrain.cpp" -#include "a_cacodemon.cpp" -#include "a_cyberdemon.cpp" #include "a_demon.cpp" #include "a_doomimp.cpp" #include "a_doomweaps.cpp" diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 7e0668a0fc..e11e249ceb 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -676,6 +676,7 @@ void InitThingdef() 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))); + symt.AddSymbol(new PField("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound))); symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master))); symt.AddSymbol(new PField(NAME_Tracer, TypeActor, VARF_Native, myoffsetof(AActor, tracer))); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index caea22aaec..b6d65a29e9 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -112,13 +112,10 @@ class Actor : Thinker native native void A_CPosRefire(); native void A_TroopAttack(); native void A_SargAttack(); - native void A_HeadAttack(); native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); native void A_Metal(); native void A_SpidRefire(); - native void A_Hoof(); - native void A_CyberAttack(); native void A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); native void A_DualPainAttack(class spawntype = "LostSoul"); native void A_PainDie(class spawntype = "LostSoul"); diff --git a/wadsrc/static/zscript/doom/cacodemon.txt b/wadsrc/static/zscript/doom/cacodemon.txt index 6a07feb705..b21acacd24 100644 --- a/wadsrc/static/zscript/doom/cacodemon.txt +++ b/wadsrc/static/zscript/doom/cacodemon.txt @@ -86,3 +86,32 @@ class CacodemonBall : Actor 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 index 75f4fd211a..1a2890f9a5 100644 --- a/wadsrc/static/zscript/doom/cyberdemon.txt +++ b/wadsrc/static/zscript/doom/cyberdemon.txt @@ -62,3 +62,28 @@ class Cyberdemon : Actor } } + +//=========================================================================== +// +// 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(); + } + +} From 808188ff184cb935126cd2a0a37ad135ea2adacf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Oct 2016 13:18:13 +0200 Subject: [PATCH 103/471] - added handling for structs. When defined inside classes or other structs the double member access will be merged, so there is no performance hit by using structs to group data. --- src/scripting/codegeneration/codegen.cpp | 134 +++++++++++++++++++---- src/scripting/codegeneration/codegen.h | 22 +++- src/scripting/thingdef_data.cpp | 25 +++-- 3 files changed, 145 insertions(+), 36 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f882b8b2bd..bcea7e9fa5 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4226,14 +4226,15 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) PSymbolTable *symtbl; auto ptype = static_cast(Object->ValueType)->PointedType; - if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) + if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) // PClass is a child class of PStruct so this covers both. { - PClass *cls = static_cast(ptype); + PStruct *cls = static_cast(ptype); + bool isclass = cls->IsKindOf(RUNTIME_CLASS(PClass)); if ((sym = cls->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr) { if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) { - ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars()); + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as %s constant\n", Identifier.GetChars(), isclass? "class" : "struct"); newex = FxConstant::MakeConstant(sym, ScriptPosition); } else if (sym->IsKindOf(RUNTIME_CLASS(PField))) @@ -4263,7 +4264,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) delete this; return nullptr; } - auto x = new FxClassMember(Object, vsym, ScriptPosition); + auto x = isclass? new FxClassMember(Object, vsym, ScriptPosition) : new FxStructMember(Object, vsym, ScriptPosition); delete this; return x->Resolve(ctx); } @@ -4281,14 +4282,41 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) return nullptr; } } - else if (ptype->IsA(RUNTIME_CLASS(PStruct))) - { - // todo - } } else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct))) { - // todo + if ((sym = Object->ValueType->Symbols.FindSymbol(Identifier, false)) != nullptr) + { + if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) + { + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as struct constant\n", Identifier.GetChars()); + newex = FxConstant::MakeConstant(sym, ScriptPosition); + } + else if (sym->IsKindOf(RUNTIME_CLASS(PField))) + { + PField *vsym = static_cast(sym); + + if (vsym->Flags & VARF_Deprecated) + { + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); + } + auto x = new FxStructMember(Object, vsym, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); + delete this; + return nullptr; + } + } + else + { + ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); + delete this; + return nullptr; + } } ScriptPosition.Message(MSG_ERROR, "Left side of %s is not a struct or class", Identifier.GetChars()); @@ -4381,13 +4409,13 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build) // //========================================================================== -FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition &pos) -: FxExpression(EFX_ClassMember, pos) +FxStructMember::FxStructMember(FxExpression *x, PField* mem, const FScriptPosition &pos) + : FxExpression(EFX_StructMember, pos) { classx = x; membervar = mem; AddressRequested = false; - //if (classx->IsDefaultObject()) Readonly=true; + AddressWritable = true; // must be true unless classx tells us otherwise if requested. } //========================================================================== @@ -4396,7 +4424,7 @@ FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition // //========================================================================== -FxClassMember::~FxClassMember() +FxStructMember::~FxStructMember() { SAFE_DELETE(classx); } @@ -4407,10 +4435,10 @@ FxClassMember::~FxClassMember() // //========================================================================== -bool FxClassMember::RequestAddress(bool *writable) +bool FxStructMember::RequestAddress(bool *writable) { AddressRequested = true; - if (writable != nullptr) *writable = !(membervar->Flags & VARF_ReadOnly); + if (writable != nullptr) *writable = AddressWritable && !(membervar->Flags & VARF_ReadOnly); return true; } @@ -4420,23 +4448,50 @@ bool FxClassMember::RequestAddress(bool *writable) // //========================================================================== -FxExpression *FxClassMember::Resolve(FCompileContext &ctx) +FxExpression *FxStructMember::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); SAFE_RESOLVE(classx, ctx); - PPointer *ptrtype = dyn_cast(classx->ValueType); - if (ptrtype == NULL || !ptrtype->IsKindOf(RUNTIME_CLASS(DObject))) + if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { - ScriptPosition.Message(MSG_ERROR, "Member variable requires a class or object"); - delete this; - return NULL; + PPointer *ptrtype = dyn_cast(classx->ValueType); + if (ptrtype == nullptr || !ptrtype->PointedType->IsA(RUNTIME_CLASS(PStruct))) + { + ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct"); + delete this; + return nullptr; + } + } + else if (classx->ValueType->IsA(RUNTIME_CLASS(PStruct))) + { + // 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); + 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->RequestAddress(&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 FxClassMember::Emit(VMFunctionBuilder *build) +ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) { ExpEmit obj = classx->Emit(build); assert(obj.RegType == REGT_POINTER); @@ -4473,6 +4528,41 @@ ExpEmit FxClassMember::Emit(VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition &pos) +: FxStructMember(x, mem, pos) +{ + ExprType = EFX_ClassMember; + //if (classx->IsDefaultObject()) Readonly=true; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxClassMember::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(classx, ctx); + + PPointer *ptrtype = dyn_cast(classx->ValueType); + if (ptrtype == NULL || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass))) + { + ScriptPosition.Message(MSG_ERROR, "Member variable requires a class or object"); + delete this; + return NULL; + } + ValueType = membervar->Type; + return this; +} + //========================================================================== // // diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 9125d5d8c8..771faa2c8a 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -237,6 +237,7 @@ enum EFxType EFX_FRandom, EFX_Random2, EFX_ClassMember, + EFX_StructMember, EFX_LocalVariable, EFX_Self, EFX_ArrayElement, @@ -1037,20 +1038,35 @@ public: // //========================================================================== -class FxClassMember : public FxExpression +class FxStructMember : public FxExpression { public: FxExpression *classx; PField *membervar; bool AddressRequested; + bool AddressWritable; - FxClassMember(FxExpression*, PField*, const FScriptPosition&); - ~FxClassMember(); + FxStructMember(FxExpression*, PField*, const FScriptPosition&); + ~FxStructMember(); FxExpression *Resolve(FCompileContext&); bool RequestAddress(bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxClassMember +// +//========================================================================== + +class FxClassMember : public FxStructMember +{ +public: + + FxClassMember(FxExpression*, PField*, const FScriptPosition&); + FxExpression *Resolve(FCompileContext&); +}; + //========================================================================== // // FxLocalVariable diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index e11e249ceb..03e88b1492 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -650,17 +650,17 @@ void InitThingdef() 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_X, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, __Pos.X))); // must remain read-only! + symt.AddSymbol(new PField(NAME_Y, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, __Pos.Y))); // must remain read-only! + symt.AddSymbol(new PField(NAME_Z, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, __Pos.Z))); // must remain read-only! + symt.AddSymbol(new PField(NAME_VelX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.X))); + symt.AddSymbol(new PField(NAME_VelY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Y))); + symt.AddSymbol(new PField(NAME_VelZ, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Z))); + symt.AddSymbol(new PField(NAME_MomX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.X))); + symt.AddSymbol(new PField(NAME_MomY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Y))); + symt.AddSymbol(new PField(NAME_MomZ, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Z))); + symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Scale.X))); + symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Scale.Y))); symt.AddSymbol(new PField(NAME_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))); @@ -677,6 +677,9 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle))); symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch))); symt.AddSymbol(new PField("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound))); + symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos))); + symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel))); + symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale))); symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master))); symt.AddSymbol(new PField(NAME_Tracer, TypeActor, VARF_Native, myoffsetof(AActor, tracer))); From f810b981672a082ef3543fd2df0b0d70bde484f3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Oct 2016 17:18:20 +0200 Subject: [PATCH 104/471] - implement flag variables with the VM's sbit and lbit instructions. - synthesize PField entries from the flag list for AActor. This intentionally excludes the bounce flags for now. - allow deprecated flags that do not call the deprecated flag handler. - disallow constructs like (a = b) = c by not allowing an address request on an assignment operation. - restrict modify/assign on boolean variables to the bit operators. Everything else needs to promote the result to an integer to make sense so it should be disallowed. --- src/dobjtype.cpp | 25 +++++ src/dobjtype.h | 5 +- src/scripting/codegeneration/codegen.cpp | 135 ++++++++++++++++------- src/scripting/codegeneration/codegen.h | 9 +- src/scripting/decorate/thingdef_exp.cpp | 2 +- src/scripting/thingdef.h | 1 + src/scripting/thingdef_data.cpp | 46 +++++--- src/scripting/zscript/zcc_compile.cpp | 7 +- 8 files changed, 166 insertions(+), 64 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 9191c60c00..3bce521c8a 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2479,6 +2479,31 @@ PField::PField() { } +PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue) + : PSymbol(name), Offset(unsigned(offset)), Type(type), Flags(flags) +{ + BitValue = bitvalue; + if (bitvalue > -1) + { + if (type->IsA(RUNTIME_CLASS(PInt)) && unsigned(bitvalue) < 8 * 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) diff --git a/src/dobjtype.h b/src/dobjtype.h index f3e043bd92..0c26f3a358 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -572,13 +572,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, size_t offset) : PSymbol(name), Offset(unsigned(offset)), Type(type), Flags(flags) {} + PField(FName name, PType *type, DWORD flags = 0, size_t offset = 0, int bitvalue = -1); unsigned int Offset; PType *Type; DWORD Flags; + int BitValue; protected: PField(); }; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index bcea7e9fa5..c8a682189a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1768,8 +1768,8 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) // //========================================================================== -FxAssign::FxAssign(FxExpression *base, FxExpression *right) -: FxExpression(EFX_Assign, base->ScriptPosition), Base(base), Right(right) +FxAssign::FxAssign(FxExpression *base, FxExpression *right, bool ismodify) +: FxExpression(EFX_Assign, base->ScriptPosition), Base(base), Right(right), IsModifyAssign(ismodify), IsBitWrite(-1) { AddressRequested = false; AddressWritable = false; @@ -1781,12 +1781,14 @@ FxAssign::~FxAssign() SAFE_DELETE(Right); } +/* I don't think we should allow constructs like (a = b) = c;... bool FxAssign::RequestAddress(bool *writable) { AddressRequested = true; if (writable != nullptr) *writable = AddressWritable; return true; } +*/ FxExpression *FxAssign::Resolve(FCompileContext &ctx) { @@ -1797,6 +1799,15 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) 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; + } + if (Base->IsNumeric() && Right->IsNumeric()) { if (Right->ValueType != ValueType) @@ -1865,6 +1876,16 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) 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 && !(f->Flags & VARF_ReadOnly)) + { + IsBitWrite = f->BitValue; + return this; + } + } return this; } @@ -1902,7 +1923,15 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) result = temp; } - build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); + 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) @@ -1941,12 +1970,19 @@ FxExpression *FxAssignSelf::Resolve(FCompileContext &ctx) ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) { - assert(ValueType = Assignment->ValueType); + assert(ValueType == Assignment->ValueType); ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it if (!pointer.Target) { ExpEmit out(build, ValueType->GetRegType()); - build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0)); + 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 @@ -1999,11 +2035,29 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) if (left->ValueType == TypeBool && right->ValueType == TypeBool) { - 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) { - 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()) { @@ -2022,13 +2076,25 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) AreCompatiblePointerTypes(left->ValueType, right->ValueType)) { // pointers can only be compared for equality. - assert(Operator == TK_Eq || Operator == TK_Neq); - ValueType = TypeBool; + 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 { - ValueType = TypeVoid; + // 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); @@ -2077,7 +2143,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } else if (left->isConstant() && right->isConstant()) { @@ -2771,7 +2837,7 @@ FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r) FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, false)) return NULL; + if (!ResolveLR(ctx, true)) return NULL; if (!left->IsNumeric() || !right->IsNumeric()) { @@ -4456,21 +4522,21 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { PPointer *ptrtype = dyn_cast(classx->ValueType); - if (ptrtype == nullptr || !ptrtype->PointedType->IsA(RUNTIME_CLASS(PStruct))) + if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PStruct))) { - ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct"); + ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object."); delete this; return nullptr; } } - else if (classx->ValueType->IsA(RUNTIME_CLASS(PStruct))) + 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); + 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); @@ -4522,7 +4588,17 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) int offsetreg = build->GetConstantInt((int)membervar->Offset); ExpEmit loc(build, membervar->Type->GetRegType()); - build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg); + 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; } @@ -4530,7 +4606,8 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) //========================================================================== // -// +// not really needed at the moment but may become useful with meta properties +// and some other class-specific extensions. // //========================================================================== @@ -4547,28 +4624,6 @@ FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition // //========================================================================== -FxExpression *FxClassMember::Resolve(FCompileContext &ctx) -{ - CHECKRESOLVED(); - SAFE_RESOLVE(classx, ctx); - - PPointer *ptrtype = dyn_cast(classx->ValueType); - if (ptrtype == NULL || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass))) - { - ScriptPosition.Message(MSG_ERROR, "Member variable requires a class or object"); - delete this; - return NULL; - } - ValueType = membervar->Type; - return this; -} - -//========================================================================== -// -// -// -//========================================================================== - FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index) :FxExpression(EFX_ArrayElement, base->ScriptPosition) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 771faa2c8a..3fb1b15761 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -703,14 +703,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 *writable); + //bool RequestAddress(bool *writable); ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Address; @@ -1064,7 +1068,6 @@ class FxClassMember : public FxStructMember public: FxClassMember(FxExpression*, PField*, const FScriptPosition&); - FxExpression *Resolve(FCompileContext&); }; //========================================================================== diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 2d1d189b4a..84e1200e9e 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -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; } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 51df4821ea..a8c9b0b9be 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -24,6 +24,7 @@ struct FFlagDef const char *name; int structoffset; int fieldsize; + bool deprecated; }; FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bool strict = false); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 03e88b1492..063b6e2042 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -54,10 +54,11 @@ 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), false } +#define DEFINE_FLAG2(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), false } +#define DEFINE_FLAG2_DEPRECATED(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), true } +#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1, 0, true } +#define DEFINE_DUMMY_FLAG(name, deprec) { DEPF_UNUSED, #name, -1, 0, deprec } static FFlagDef ActorFlagDefs[]= { @@ -171,7 +172,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), @@ -278,7 +278,11 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF, MASKROTATION, AActor, renderflags), DEFINE_FLAG(RF, ABSMASKANGLE, AActor, renderflags), DEFINE_FLAG(RF, ABSMASKPITCH, AActor, renderflags), +}; +// These won't be accessible through bitfield variables +static FFlagDef MoreFlagDefs[] = +{ // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_Floors, BOUNCEONFLOORS, AActor, BounceFlags), @@ -308,15 +312,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 +377,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[] = @@ -394,6 +399,7 @@ 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), MoreFlagDefs, countof(MoreFlagDefs) }, { &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs) }, { &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs) }, { &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs) }, @@ -443,7 +449,7 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bo if (part2 == NULL) { // Search all lists - int max = strict ? 1 : NUM_FLAG_LISTS; + int max = strict ? 2 : NUM_FLAG_LISTS; for (i = 0; i < max; ++i) { if (type->IsDescendantOf (*FlagLists[i].Type)) @@ -683,4 +689,14 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master))); symt.AddSymbol(new PField(NAME_Tracer, TypeActor, VARF_Native, myoffsetof(AActor, tracer))); + + // synthesize a symbol for each flag. The bounce flags are excluded on purpose. + for (size_t i = 0; i < countof(ActorFlagDefs); i++) + { + int bit = 0; + unsigned val = ActorFlagDefs[i].flagbit; + while ((val >>= 1)) bit++; + symt.AddSymbol(new PField(FStringf("b%s", ActorFlagDefs[i].name), (ActorFlagDefs[i].fieldsize == 4? TypeSInt32 : TypeSInt16), VARF_Native, ActorFlagDefs[i].structoffset, bit)); + } + } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 274778dfee..49ba68f0a7 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1836,9 +1836,12 @@ void ZCCCompiler::ProcessDefaultFlag(PClassActor *cls, ZCC_FlagStmt *flg) auto fd = FindFlag(cls, n1, n2, true); if (fd != nullptr) { - if (fd->structoffset == -1) + if (fd->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 @@ -2384,7 +2387,7 @@ static int Pex2Tok[] = { static FxExpression *ModifyAssign(FxBinary *operation, FxExpression *left) { auto assignself = static_cast(operation->left); - auto assignment = new FxAssign(left, operation); + auto assignment = new FxAssign(left, operation, true); assignself->Assignment = assignment; return assignment; } From ae728cc61a1e4777bcdab90d4ba7d316431b2a45 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 09:55:13 +0200 Subject: [PATCH 105/471] - made the count flags and NOBLOCKMAP and NOSECTOR read-only. These require special treatment to work which can only be done by a setter function. --- src/CMakeLists.txt | 3 --- src/scripting/thingdef.h | 2 +- src/scripting/thingdef_data.cpp | 21 +++++++++++---------- src/scripting/zscript/zcc_compile.cpp | 2 +- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2720f026d5..9e64f1d294 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -837,9 +837,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re 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 diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index a8c9b0b9be..44a441bee9 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -24,7 +24,7 @@ struct FFlagDef const char *name; int structoffset; int fieldsize; - bool deprecated; + int varflags; }; FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bool strict = false); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 063b6e2042..4622e764ce 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -54,11 +54,12 @@ 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), false } -#define DEFINE_FLAG2(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), false } -#define DEFINE_FLAG2_DEPRECATED(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), true } +#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_READONLY_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 } +#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 } +#define DEFINE_DUMMY_FLAG(name, deprec) { DEPF_UNUSED, #name, -1, 0, deprec? VARF_Deprecated:0 } static FFlagDef ActorFlagDefs[]= { @@ -66,8 +67,8 @@ static FFlagDef ActorFlagDefs[]= 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_READONLY_FLAG(MF, NOSECTOR, AActor, flags), + DEFINE_READONLY_FLAG(MF, NOBLOCKMAP, AActor, flags), DEFINE_FLAG(MF, AMBUSH, AActor, flags), DEFINE_FLAG(MF, JUSTHIT, AActor, flags), DEFINE_FLAG(MF, JUSTATTACKED, AActor, flags), @@ -83,8 +84,8 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF, NOBLOOD, AActor, flags), DEFINE_FLAG(MF, CORPSE, AActor, flags), DEFINE_FLAG(MF, INFLOAT, AActor, flags), - DEFINE_FLAG(MF, COUNTKILL, AActor, flags), - DEFINE_FLAG(MF, COUNTITEM, AActor, flags), + DEFINE_READONLY_FLAG(MF, COUNTKILL, AActor, flags), + DEFINE_READONLY_FLAG(MF, COUNTITEM, AActor, flags), DEFINE_FLAG(MF, SKULLFLY, AActor, flags), DEFINE_FLAG(MF, NOTDMATCH, AActor, flags), DEFINE_FLAG(MF, SPAWNSOUNDSOURCE, AActor, flags), @@ -185,7 +186,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF5, GETOWNER, AActor, flags5), DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5), DEFINE_FLAG(MF5, NOFORWARDFALL, AActor, flags5), - DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5), + DEFINE_READONLY_FLAG(MF5, COUNTSECRET, AActor, flags5), DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5), DEFINE_FLAG(MF5, BLOODSPLATTER, AActor, flags5), DEFINE_FLAG(MF5, OLDRADIUSDMG, AActor, flags5), @@ -696,7 +697,7 @@ void InitThingdef() int bit = 0; unsigned val = ActorFlagDefs[i].flagbit; while ((val >>= 1)) bit++; - symt.AddSymbol(new PField(FStringf("b%s", ActorFlagDefs[i].name), (ActorFlagDefs[i].fieldsize == 4? TypeSInt32 : TypeSInt16), VARF_Native, ActorFlagDefs[i].structoffset, bit)); + symt.AddSymbol(new PField(FStringf("b%s", ActorFlagDefs[i].name), (ActorFlagDefs[i].fieldsize == 4? TypeSInt32 : TypeSInt16), ActorFlagDefs[i].varflags, ActorFlagDefs[i].structoffset, bit)); } } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 49ba68f0a7..22107796fe 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1836,7 +1836,7 @@ void ZCCCompiler::ProcessDefaultFlag(PClassActor *cls, ZCC_FlagStmt *flg) auto fd = FindFlag(cls, n1, n2, true); if (fd != nullptr) { - if (fd->deprecated) + if (fd->varflags & VARF_Deprecated) { Warn(flg, "Deprecated flag '%s%s%s' used", n1, n2 ? "." : "", n2 ? n2 : ""); } From 656b8cb16e0baec82589f124b689397f5271e2f2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 10:15:24 +0200 Subject: [PATCH 106/471] - added explicit setter functions for the count and link flags so that A_ChangeFlag and A_SetFlag can be deprecated. --- src/p_actionfunctions.cpp | 68 +++++++++++++++++++++++++++++ wadsrc/static/zscript.txt | 2 + wadsrc/static/zscript/actor.txt | 6 ++- wadsrc/static/zscript/constants.txt | 5 +++ 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index f389cd1eeb..3d9ccb3262 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -4852,6 +4852,74 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) } +//=========================================================================== +// +// A_ChangeCountFlags (needed, because these flags affect global counters) +// +//=========================================================================== +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeLinkFlags) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_OPT(blockmap) { blockmap = -1; } + PARAM_INT_OPT(sector) { sector = -1; } + + self->UnlinkFromWorld(); + + if (blockmap != -1) + { + if (blockmap == 0) self->flags &= MF_NOBLOCKMAP; + else self->flags |= MF_NOBLOCKMAP; + } + + if (sector != -1) + { + if (sector == 0) self->flags &= MF_NOSECTOR; + else self->flags |= MF_NOSECTOR; + } + + self->LinkToWorld(); + return 0; +} + +//=========================================================================== +// +// A_ChangeCountFlags (needed, because these flags affect global counters) +// +//=========================================================================== +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeCountFlags) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_OPT(kill) { kill = -1; } + PARAM_INT_OPT(item) { item = -1; } + PARAM_INT_OPT(secret) { secret = -1; } + + 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 diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 6de64d07e5..3ab33bfd96 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -177,3 +177,5 @@ zscript/chex/chexweapons.txt zscript/chex/chexitems.txt zscript/chex/chexdecorations.txt zscript/chex/chexplayer.txt + +zscript/test2.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index b6d65a29e9..fa45eb0e67 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -238,8 +238,10 @@ class Actor : Thinker native 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); + deprecated native void A_ChangeFlag(string flagname, bool value); + deprecated native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); + native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); + native void A_ChangeLinkFlags(int blockmap = FLAG_NO_CHANGE, int sector = FLAG_NO_CHANGE); native state A_JumpIf(bool expression, state label); native void A_RaiseMaster(bool copy = 0); native void A_RaiseChildren(bool copy = 0); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index b98846d8bd..9792ec2301 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,3 +1,6 @@ +// for flag changer functions. +const int FLAG_NO_CHANGE = -1; + // Flags for A_PainAttack enum EPainAttackFlags { @@ -820,3 +823,5 @@ struct FStateParamInfo EStateType mStateType; int mPSPIndex; } + + From e39bf9eaeb7544762d65be41c1571a612c5595e3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 11:38:02 +0200 Subject: [PATCH 107/471] - made the bounce flags accessible after verifying that the code works for 16 bit variables. - fixed a deprecation warning with the Heresiarch by replacing A_ChangeFlag. --- wadsrc/static/zscript/constants.txt | 2 +- wadsrc/static/zscript/hexen/heresiarch.txt | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 9792ec2301..41c4bfec90 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,5 +1,5 @@ // for flag changer functions. -const int FLAG_NO_CHANGE = -1; +const FLAG_NO_CHANGE = -1; // Flags for A_PainAttack enum EPainAttackFlags diff --git a/wadsrc/static/zscript/hexen/heresiarch.txt b/wadsrc/static/zscript/hexen/heresiarch.txt index 6ffc11b3b4..7d3ba63a51 100644 --- a/wadsrc/static/zscript/hexen/heresiarch.txt +++ b/wadsrc/static/zscript/hexen/heresiarch.txt @@ -96,6 +96,12 @@ class SorcBall native 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 ---------------------------------- @@ -112,8 +118,7 @@ class SorcBall1 : SorcBall native SBMP B 2 A_BounceCheck; Wait; Death: - SBS4 D 0 A_ChangeFlag("NOBOUNCESOUND", 1); - SBS4 D 5 A_Explode(255,255); + SBS4 D 5 A_SorcBallExplode; SBS4 E 5; SBS4 FGH 6; Stop; @@ -135,8 +140,7 @@ class SorcBall2 : SorcBall native SBMB B 2 A_BounceCheck; Wait; Death: - SBS4 D 0 A_ChangeFlag("NOBOUNCESOUND", 1); - SBS3 D 5 A_Explode(255,255); + SBS3 D 5 A_SorcBallExplode; SBS3 E 5; SBS3 FGH 6; Stop; @@ -157,8 +161,7 @@ class SorcBall3 : SorcBall native SBMG B 2 A_BounceCheck; Wait; Death: - SBS4 D 0 A_ChangeFlag("NOBOUNCESOUND", 1); - SBS3 D 5 A_Explode(255,255); + SBS3 D 5 A_SorcBallExplode; SBS3 E 5; SBS3 FGH 6; Stop; From 142278a8186725f65d4ac2fe8add1ad965f365ee Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 13:29:58 +0200 Subject: [PATCH 108/471] - fixed incomplete commit for bounce flags - fixed flag clearing in new function. --- src/p_actionfunctions.cpp | 10 +++++----- src/scripting/thingdef_data.cpp | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 3d9ccb3262..f5d7251c38 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -4867,13 +4867,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeLinkFlags) if (blockmap != -1) { - if (blockmap == 0) self->flags &= MF_NOBLOCKMAP; + if (blockmap == 0) self->flags &= *MF_NOBLOCKMAP; else self->flags |= MF_NOBLOCKMAP; } if (sector != -1) { - if (sector == 0) self->flags &= MF_NOSECTOR; + if (sector == 0) self->flags &= *MF_NOSECTOR; else self->flags |= MF_NOSECTOR; } @@ -4899,19 +4899,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeCountFlags) if (kill != -1) { - if (kill == 0) self->flags &= MF_COUNTKILL; + if (kill == 0) self->flags &= ~MF_COUNTKILL; else self->flags |= MF_COUNTKILL; } if (item != -1) { - if (item == 0) self->flags &= MF_COUNTITEM; + if (item == 0) self->flags &= ~MF_COUNTITEM; else self->flags |= MF_COUNTITEM; } if (secret != -1) { - if (secret == 0) self->flags5 &= MF5_COUNTSECRET; + if (secret == 0) self->flags5 &= ~MF5_COUNTSECRET; else self->flags5 |= MF5_COUNTSECRET; } if (self->CountsAsKill() && self->health > 0) ++level.total_monsters; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 4622e764ce..a4815cb33e 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -279,11 +279,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF, MASKROTATION, AActor, renderflags), DEFINE_FLAG(RF, ABSMASKANGLE, AActor, renderflags), DEFINE_FLAG(RF, ABSMASKPITCH, AActor, renderflags), -}; -// These won't be accessible through bitfield variables -static FFlagDef MoreFlagDefs[] = -{ // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_Floors, BOUNCEONFLOORS, AActor, BounceFlags), @@ -299,6 +295,11 @@ static FFlagDef MoreFlagDefs[] = DEFINE_FLAG2(BOUNCE_MBF, MBFBOUNCER, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_AutoOffFloorOnly, BOUNCEAUTOOFFFLOORONLY, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_UseBounceState, USEBOUNCESTATE, AActor, BounceFlags), +}; + +// These won't be accessible through bitfield variables +static FFlagDef MoreFlagDefs[] = +{ // Deprecated flags. Handling must be performed in HandleDeprecatedFlags DEFINE_DEPRECATED_FLAG(FIREDAMAGE), From 449dfc3cdccc9bc50587e908ff2cee517bf6a3b0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 13:30:22 +0200 Subject: [PATCH 109/471] - removed test file from zscript.txt. --- wadsrc/static/zscript.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 3ab33bfd96..6de64d07e5 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -177,5 +177,3 @@ zscript/chex/chexweapons.txt zscript/chex/chexitems.txt zscript/chex/chexdecorations.txt zscript/chex/chexplayer.txt - -zscript/test2.txt From 576fc0c237fe31bd30b618100d7dd183184b7a2d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 14:27:49 +0200 Subject: [PATCH 110/471] - how did this happen. --- src/p_actionfunctions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index f5d7251c38..57c6768018 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -4867,13 +4867,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeLinkFlags) if (blockmap != -1) { - if (blockmap == 0) self->flags &= *MF_NOBLOCKMAP; + if (blockmap == 0) self->flags &= ~MF_NOBLOCKMAP; else self->flags |= MF_NOBLOCKMAP; } if (sector != -1) { - if (sector == 0) self->flags &= *MF_NOSECTOR; + if (sector == 0) self->flags &= ~MF_NOSECTOR; else self->flags |= MF_NOSECTOR; } From 6d0dad3b38d9f9e89c492a5af51f35fcadeaf753 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 14:41:58 +0200 Subject: [PATCH 111/471] - scriptified the code for the Demon and DoomImp. --- src/CMakeLists.txt | 2 -- src/g_doom/a_demon.cpp | 29 -------------------- src/g_doom/a_doomimp.cpp | 38 -------------------------- src/g_doom/a_doommisc.cpp | 2 -- wadsrc/static/zscript/actor.txt | 2 -- wadsrc/static/zscript/doom/demon.txt | 18 ++++++++++++ wadsrc/static/zscript/doom/doomimp.txt | 28 +++++++++++++++++++ 7 files changed, 46 insertions(+), 73 deletions(-) delete mode 100644 src/g_doom/a_demon.cpp delete mode 100644 src/g_doom/a_doomimp.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e64f1d294..5a33518802 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -837,8 +837,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_doom/a_archvile.cpp g_doom/a_bossbrain.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 diff --git a/src/g_doom/a_demon.cpp b/src/g_doom/a_demon.cpp deleted file mode 100644 index 5ac3e9e748..0000000000 --- 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 "vm.h" -*/ - -static FRandom pr_sargattack ("SargAttack"); - -DEFINE_ACTION_FUNCTION(AActor, A_SargAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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 1b9dd9485a..0000000000 --- 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 "vm.h" -*/ - -static FRandom pr_troopattack ("TroopAttack"); - -// -// A_TroopAttack -// -DEFINE_ACTION_FUNCTION(AActor, A_TroopAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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 fb5ae3b28f..de53dc3af2 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -24,8 +24,6 @@ // Include all the other Doom stuff here to reduce compile time #include "a_archvile.cpp" #include "a_bossbrain.cpp" -#include "a_demon.cpp" -#include "a_doomimp.cpp" #include "a_doomweaps.cpp" #include "a_fatso.cpp" #include "a_keen.cpp" diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index fa45eb0e67..872a3ef986 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -110,8 +110,6 @@ class Actor : Thinker native native void A_BossDeath(); native void A_CPosAttack(); native void A_CPosRefire(); - native void A_TroopAttack(); - native void A_SargAttack(); native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); native void A_Metal(); diff --git a/wadsrc/static/zscript/doom/demon.txt b/wadsrc/static/zscript/doom/demon.txt index 398888e456..d4cd9002cc 100644 --- a/wadsrc/static/zscript/doom/demon.txt +++ b/wadsrc/static/zscript/doom/demon.txt @@ -75,3 +75,21 @@ class Spectre : Demon } +//=========================================================================== +// +// 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/doomimp.txt b/wadsrc/static/zscript/doom/doomimp.txt index 318e81471a..d2b93acdd7 100644 --- a/wadsrc/static/zscript/doom/doomimp.txt +++ b/wadsrc/static/zscript/doom/doomimp.txt @@ -92,3 +92,31 @@ class DoomImpBall : Actor 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"); + } + } + } +} From be4ce05aeebcbad43f1eaf865677e20b766860b4 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Tue, 25 Oct 2016 16:53:14 +0200 Subject: [PATCH 112/471] - Fixed Clang compiler errors and some warnings. --- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/thingdef_properties.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 6 +++--- src/scripting/zscript/zcc_parser.cpp | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c8a682189a..7bb18178ce 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1769,7 +1769,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) //========================================================================== FxAssign::FxAssign(FxExpression *base, FxExpression *right, bool ismodify) -: FxExpression(EFX_Assign, base->ScriptPosition), Base(base), Right(right), IsModifyAssign(ismodify), IsBitWrite(-1) +: FxExpression(EFX_Assign, base->ScriptPosition), Base(base), Right(right), IsBitWrite(-1), IsModifyAssign(ismodify) { AddressRequested = false; AddressWritable = false; diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index cb86886108..d3fb452cbf 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -2432,7 +2432,7 @@ 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)) && !bag.fromZScript) + if (cls == NULL || (!cls->IsDescendantOf(RUNTIME_CLASS(APowerup)) && !bag.fromZScript)) { FString st; st.Format("%s%s", strnicmp(str, "power", 5)? "Power" : "", str); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 22107796fe..340a777037 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1240,7 +1240,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel if (field->Flags & notallowed) { - Error(field, "Invalid qualifiers for %s (%s not allowed)", FName(field->Names->Name).GetChars(), FlagsToString(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; @@ -1977,7 +1977,7 @@ void ZCCCompiler::InitFunctions() if (f->Flags & notallowed) { - Error(f, "Invalid qualifiers for %s (%s not allowed)", FName(f->Name).GetChars(), FlagsToString(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; @@ -2018,7 +2018,7 @@ void ZCCCompiler::InitFunctions() if (p->Type != nullptr) { auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); - int flags; + int flags = 0; if (p->Flags & ZCC_In) flags |= VARF_In; if (p->Flags & ZCC_Out) flags |= VARF_Out; if (p->Default != nullptr) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 18d683c4cc..8ebc861678 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -331,7 +331,7 @@ static void DoParse(int lumpnum) // 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) { - I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum)); + I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); } #if 0 @@ -364,12 +364,12 @@ static void DoParse(int lumpnum) 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)); + 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)); + Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s", FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); } } From 33d00070b5e6ebb415fa04d477e85558b627b855 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 17:07:19 +0200 Subject: [PATCH 113/471] - made some variables signed that should not be unsigned. --- src/scripting/codegeneration/codegen.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7bb18178ce..de7048d880 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5812,10 +5812,10 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_WARNING, "Case expression is constant"); auto &content = *Content; - unsigned defaultindex = -1; - unsigned defaultbreak = -1; - unsigned caseindex = -1; - unsigned casebreak = -1; + 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++) { @@ -5846,7 +5846,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) if (caseindex > 0 && casebreak - caseindex > 1) { auto seq = new FxSequence(ScriptPosition); - for (unsigned i = caseindex + 1; i < casebreak; i++) + for (int i = caseindex + 1; i < casebreak; i++) { if (content[i] != nullptr && content[i]->ExprType != EFX_CaseStatement) { From 823c52aeb2d0c92c7a298709da44534528c6da7f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 26 Oct 2016 11:30:30 +0200 Subject: [PATCH 114/471] - scriptified the functions in a_possessed.cpp and added the needed exports and constants. - fixed: Script functions did not receive the function name when being created. - relaxed the asserts for PARAM_STATE, because the VM knows nothing about ATAG_STATE. Any state variable's content (e.g. Actor.SeeState) will receive ATAG_GENERIC, rather than ATAG_STATE. - added a 'NeedResult' flag so that certain operations can create shorter code if the result of the expression is not needed. So far only used for postdecrement/increment statements on local variables (which is the most frequent case where this matters.) - fixed postincrement and decrement for local variables. Due to the result preservation semantics it created faulty code. --- src/CMakeLists.txt | 1 - src/g_doom/a_doommisc.cpp | 1 - src/g_doom/a_possessed.cpp | 134 ----------------------- src/info.cpp | 2 +- src/p_enemy.cpp | 6 + src/p_map.cpp | 31 ++++++ src/p_mobj.cpp | 8 ++ src/p_sight.cpp | 8 ++ src/scripting/codegeneration/codegen.cpp | 75 +++++++++---- src/scripting/codegeneration/codegen.h | 3 +- src/scripting/thingdef_data.cpp | 2 + src/scripting/vm/vm.h | 6 +- src/scripting/vm/vmbuilder.cpp | 1 + wadsrc/static/zscript/actor.txt | 11 +- wadsrc/static/zscript/constants.txt | 37 +++++++ wadsrc/static/zscript/doom/possessed.txt | 90 +++++++++++++++ 16 files changed, 246 insertions(+), 170 deletions(-) delete mode 100644 src/g_doom/a_possessed.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5a33518802..a5164e84b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -842,7 +842,6 @@ set( NOT_COMPILED_SOURCE_FILES 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 diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index de53dc3af2..4c8be07f1e 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -29,7 +29,6 @@ #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" diff --git a/src/g_doom/a_possessed.cpp b/src/g_doom/a_possessed.cpp deleted file mode 100644 index 0b9a9ecfdd..0000000000 --- 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 "vm.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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - // 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/info.cpp b/src/info.cpp index 5e267b39c8..268d4f91c1 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -77,7 +77,7 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, { ActionCycles.Clock(); - static VMFrameStack stack; + VMFrameStack stack; VMValue params[3] = { self, stateowner, VMValue(info, ATAG_STATEINFO) }; // If the function returns a state, store it at *stateret. // If it doesn't return a state but stateret is non-NULL, we need diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 0c2cb8e28b..fbdc1a2121 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -461,6 +461,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, diff --git a/src/p_map.cpp b/src/p_map.cpp index 849f8dd241..ef46f6566a 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4043,6 +4043,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_OPT(pLineTarget, FTranslatedLineTarget) { pLineTarget = nullptr; } + PARAM_ANGLE_OPT(vrange) { vrange = 0.; } + PARAM_INT_OPT(flags) { flags = 0; } + PARAM_OBJECT_OPT(target, AActor) { target = nullptr; } + PARAM_OBJECT_OPT(friender, AActor) { friender = nullptr; } + ACTION_RETURN_FLOAT(P_AimLineAttack(self, angle, distance, pLineTarget, vrange, flags, target, friender).Degrees); +} //========================================================================== // @@ -4410,6 +4422,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_OPT(flags) { flags = 0; } + PARAM_POINTER_OPT(victim, FTranslatedLineTarget) { victim = nullptr; } + + 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 diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5d40d1ed37..7398fa29f1 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -510,6 +510,14 @@ bool AActor::SetState (FState *newstate, bool nofunction) return true; } +DEFINE_ACTION_FUNCTION(AActor, SetState) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STATE(state); + PARAM_BOOL_OPT(nofunction) { nofunction = false; } + ACTION_RETURN_BOOL(self->SetState(state, nofunction)); +}; + //============================================================================ // // AActor :: AddInventory diff --git a/src/p_sight.cpp b/src/p_sight.cpp index c10365eea3..fefe9eb27b 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_OPT(flags) { flags = 0; } + ACTION_RETURN_BOOL(P_CheckSight(self, target, flags)); +} + ADD_STAT (sight) { FString out; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index de7048d880..8fec40113e 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1519,9 +1519,8 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) 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)); + // 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; } @@ -1734,32 +1733,54 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) int zero = build->GetConstantInt(0); int regtype = ValueType->GetRegType(); ExpEmit pointer = Base->Emit(build); - ExpEmit out = pointer; if (!pointer.Target) { - out = ExpEmit(build, regtype); + 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, out.RegNum, zero); + pointer.Free(build); + assign.Free(build); + return out; } - - ExpEmit assign(build, regtype); - if (regtype == REGT_INT) + else if (NeedResult) { - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, assign.RegNum, out.RegNum, build->GetConstantInt(1)); + 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 { - build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, assign.RegNum, out.RegNum, build->GetConstantFloat(1.)); + 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(); } - - if (!pointer.Target) - { - build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero); - } - - pointer.Free(build); - assign.Free(build); - return out; } //========================================================================== @@ -5795,7 +5816,8 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) auto x = Condition; Condition = nullptr; delete this; - return Condition; + x->NeedResult = false; + return x; } } @@ -5805,6 +5827,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) if (line->ExprType != EFX_JumpStatement || static_cast(line)->Token != TK_Break) { SAFE_RESOLVE(line, ctx); + line->NeedResult = false; } } @@ -5999,6 +6022,8 @@ FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part, Condition = cond; WhenTrue = true_part; WhenFalse = false_part; + if (WhenTrue != nullptr) WhenTrue->NeedResult = false; + if (WhenFalse != nullptr) WhenFalse->NeedResult = false; assert(cond != NULL); } @@ -6338,6 +6363,8 @@ FxForLoop::FxForLoop(FxExpression *init, FxExpression *condition, FxExpression * : 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() @@ -7139,19 +7166,19 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) { default: case REGT_INT: - build->Emit(OP_LK, build->GetConstantInt(constval->GetValue().GetInt()), RegNum); + build->Emit(OP_LK, RegNum, build->GetConstantInt(constval->GetValue().GetInt())); break; case REGT_FLOAT: - build->Emit(OP_LKF, build->GetConstantFloat(constval->GetValue().GetFloat()), RegNum); + build->Emit(OP_LKF, RegNum, build->GetConstantFloat(constval->GetValue().GetFloat())); break; case REGT_POINTER: - build->Emit(OP_LKP, build->GetConstantAddress(constval->GetValue().GetPointer(), ATAG_GENERIC), RegNum); + build->Emit(OP_LKP, RegNum, build->GetConstantAddress(constval->GetValue().GetPointer(), ATAG_GENERIC)); break; case REGT_STRING: - build->Emit(OP_LKS, build->GetConstantString(constval->GetValue().GetString()), RegNum); + build->Emit(OP_LKS, RegNum, build->GetConstantString(constval->GetValue().GetString())); } emitval.Free(build); } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 3fb1b15761..d099daa22c 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -300,6 +300,7 @@ public: PType *ValueType = nullptr; 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; }; @@ -1246,7 +1247,7 @@ public: 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(); }; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index a4815cb33e..601fb5e9a4 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -680,6 +680,7 @@ void InitThingdef() 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("visdir", TypeSInt32, VARF_Native, myoffsetof(AActor, visdir))); 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))); @@ -688,6 +689,7 @@ void InitThingdef() symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos))); symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel))); symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale))); + symt.AddSymbol(new PField("SeeState", TypeState, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, SeeState))); symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master))); symt.AddSymbol(new PField(NAME_Tracer, TypeActor, VARF_Native, myoffsetof(AActor, tracer))); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 12ce012736..747d53c3b5 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -915,7 +915,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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_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_POINTER && (param[p].atag == ATAG_STATE || param[p].atag == ATAG_GENERIC || param[p].a == NULL)); FState *x = (FState *)param[p].a; #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))); @@ -932,8 +932,8 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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_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].atag == ATAG_GENERIC || 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].atag == ATAG_GENERIC || 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 diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 1b7c4ce703..c72c2b5670 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -665,6 +665,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c 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; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 872a3ef986..027aaf7dc9 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -51,6 +51,12 @@ class Actor : Thinker native 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 SetState(state st, bool nofunction = false); + // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); @@ -88,10 +94,7 @@ class Actor : Thinker native native void A_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); native void A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); native void A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); - native void A_PosAttack(); native void A_Scream(); - native void A_SPosAttack(); - native void A_SPosAttackUseAtkSound(); native void A_VileChase(); native void A_VileStart(); native void A_VileTarget(class fire = "ArchvileFire"); @@ -108,8 +111,6 @@ class Actor : Thinker native native void A_FatAttack2(class spawntype = "FatShot"); native void A_FatAttack3(class spawntype = "FatShot"); native void A_BossDeath(); - native void A_CPosAttack(); - native void A_CPosRefire(); native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); native void A_Metal(); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 41c4bfec90..f492640623 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -824,4 +824,41 @@ struct FStateParamInfo 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 +} diff --git a/wadsrc/static/zscript/doom/possessed.txt b/wadsrc/static/zscript/doom/possessed.txt index de1e50ff2b..8b6612076b 100644 --- a/wadsrc/static/zscript/doom/possessed.txt +++ b/wadsrc/static/zscript/doom/possessed.txt @@ -251,3 +251,93 @@ class WolfensteinSS : Actor 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); + } + } + } +} From e50315bd31bde9ed3f1040ed453b7bbce2bbd943 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 26 Oct 2016 13:22:36 +0200 Subject: [PATCH 115/471] - fixed: Deprecation messages should never appear in DECORATE. - removed some console message spam. --- src/d_dehacked.cpp | 7 ++++--- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/thingdef.cpp | 2 ++ src/scripting/zscript/zcc_compile.cpp | 2 -- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 97d15e4d0d..064f37c027 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -73,6 +73,7 @@ #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 :) @@ -2108,7 +2109,7 @@ 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()); } } @@ -2117,7 +2118,7 @@ static int PatchCodePtrs (int dummy) 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 { @@ -2125,7 +2126,7 @@ static int PatchCodePtrs (int dummy) 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; } } diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8fec40113e..aaa6888e6b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4198,7 +4198,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) // 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) + if ((vsym->Flags & VARF_Deprecated) && !ctx.FromDecorate) { ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", sym->SymbolName.GetChars()); } diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 2798ab633a..183c3f69ee 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -202,8 +202,10 @@ void LoadActors () FScriptPosition::ResetErrorCounter(); InitThingdef(); + FScriptPosition::StrictErrors = true; ParseScripts(); + FScriptPosition::StrictErrors = false; ParseAllDecorate(); FunctionBuildList.Build(); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 340a777037..afc74e75e5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1901,7 +1901,6 @@ void ZCCCompiler::InitDefaults() bag.CurrentState = 0; bag.Lumpnum = c->cls->SourceLump; bag.DropItemList = nullptr; - bag.ScriptPosition.StrictErrors = true; // The actual script position needs to be set per property. for (auto d : c->Defaults) @@ -2425,7 +2424,6 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_ExprMemberAccess: { auto ema = static_cast(fcall->Function); - Printf("Member call to %s\n", FName(ema->Right).GetChars()); return new FxMemberFunctionCall(ConvertNode(ema->Left), ema->Right, ConvertNodeList(fcall->Parameters), *ast); } From 7c759f9fcfb1116c716abf4a76dc337684c11c38 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 26 Oct 2016 14:04:49 +0200 Subject: [PATCH 116/471] - removed the FxDamageValue hack and implemented it properly using FxReturnStatement. - added handling of damage functions for ZScript. --- src/namedef.h | 2 ++ src/scripting/codegeneration/codegen.h | 19 ------------------- src/scripting/decorate/thingdef_parse.cpp | 2 +- src/scripting/thingdef.cpp | 22 ++++++++++++++++++++++ src/scripting/thingdef.h | 1 + src/scripting/thingdef_properties.cpp | 14 ++------------ src/scripting/vm/vmbuilder.cpp | 4 ---- src/scripting/zscript/zcc_compile.cpp | 9 +++++++++ 8 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index 9735578744..3587643e8a 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -727,3 +727,5 @@ xx(__decorate_internal_int__) xx(__decorate_internal_bool__) xx(__decorate_internal_state__) xx(__decorate_internal_float__) + +xx(DamageFunction) diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index d099daa22c..f6468e61f0 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -1531,25 +1531,6 @@ public: // //========================================================================== -class FxDamageValue : public FxExpression -{ - FxExpression *val; - -public: - - FxDamageValue(FxExpression *v); - ~FxDamageValue(); - FxExpression *Resolve(FCompileContext&); - - ExpEmit Emit(VMFunctionBuilder *build); -}; - -//========================================================================== -// -// -// -//========================================================================== - class FxNop : public FxExpression { public: diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index bd4885c87b..b344a12283 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -664,7 +664,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), true)); + x = ParseExpression(sc, bag.Info); sc.MustGetStringName(")"); conv.exp = x; params.Push(conv); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 183c3f69ee..8c42e8987d 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -184,6 +184,28 @@ PFunction *FindClassMemberFunction(PClass *selfcls, PClass *funccls, FName name, 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, VARF_Method); + defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate); + } +} + //========================================================================== // // LoadActors diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 44a441bee9..b2d34231de 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -155,6 +155,7 @@ FName CheckCastKludges(FName in); void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags); 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); //========================================================================== // diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index d3fb452cbf..6f1455e435 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -647,19 +647,9 @@ 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; - - if (id == nullptr) - { - defaults->DamageFunc = nullptr; - } - else - { - auto funcsym = CreateAnonymousFunction(bag.Info, TypeSInt32, VARF_Method); - defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, id, FStringf("%s.DamageFunction", bag.Info->TypeName.GetChars()), !bag.fromZScript); - } + // Only DECORATE can get here with a valid expression. + CreateDamageFunction(bag.Info, defaults, id, true); } //========================================================================== diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index c72c2b5670..7f8a643c68 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -684,10 +684,6 @@ void FFunctionBuildList::Build() for (auto &item : mItems) { - if (item.PrintableName.CompareNoCase("Middle.StateFunction.3") == 0) - { - int a = 0; - } assert(item.Code != NULL); // We don't know the return type in advance for anonymous functions. diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index afc74e75e5..f0f884f68e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1773,8 +1773,16 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro if (namenode->SiblingNext == namenode) { + if (namenode->Id == NAME_DamageFunction) + { + auto x = ConvertNode(prop->Values); + CreateDamageFunction(cls, (AActor *)bag.Info->Defaults, x, false); + return; + } + // a one-name property propname = FName(namenode->Id); + } else if (namenode->SiblingNext->SiblingNext == namenode) { @@ -1787,6 +1795,7 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro return; } + FPropertyInfo *property = FindProperty(propname); if (property != nullptr && property->category != CAT_INFO) From a166183ab49b07d6e0d9284761df918df74b4453 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 26 Oct 2016 14:15:11 +0200 Subject: [PATCH 117/471] -fixed type handling for varargs (i.e. A_Jump.) --- src/scripting/codegeneration/codegen.cpp | 64 +++++------------------- 1 file changed, 12 insertions(+), 52 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index aaa6888e6b..2bf1fedc83 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1067,6 +1067,7 @@ FxTypeCast::FxTypeCast(FxExpression *x, PType *type, bool nowarn) { basex = x; ValueType = type; + assert(ValueType != nullptr); } //========================================================================== @@ -5410,9 +5411,19 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) if (ArgList != NULL) { + bool foundvarargs = false; + PType * type = nullptr; for (unsigned i = 0; i < ArgList->Size(); i++) { - FxExpression *x = new FxTypeCast((*ArgList)[i], argtypes[i + implicit], false); + // 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; @@ -7062,57 +7073,6 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) return dest; } -//========================================================================== -// -// -// -//========================================================================== - -FxDamageValue::FxDamageValue(FxExpression *v) -: FxExpression(EFX_DamageValue, v->ScriptPosition) -{ - val = v; - ValueType = TypeVoid; -} - -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(); -} - //========================================================================== // // declares a single local variable (no arrays) From d32d52c0b9e55f375c2b52a3d8da7bca617be2d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 26 Oct 2016 17:21:25 +0200 Subject: [PATCH 118/471] - scriptified a_spidermaster.cpp. - fixed bad assert in XOR_RK instruction. --- src/CMakeLists.txt | 1 - src/g_doom/a_doommisc.cpp | 1 - src/g_doom/a_spidermaster.cpp | 41 --------------------- src/scripting/vm/vmexec.h | 2 +- wadsrc/static/zscript/actor.txt | 2 - wadsrc/static/zscript/doom/spidermaster.txt | 31 ++++++++++++++++ 6 files changed, 32 insertions(+), 46 deletions(-) delete mode 100644 src/g_doom/a_spidermaster.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5164e84b6..395e72e2c1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -844,7 +844,6 @@ set( NOT_COMPILED_SOURCE_FILES g_doom/a_painelemental.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 diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 4c8be07f1e..df42bfa7be 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -30,7 +30,6 @@ #include "a_lostsoul.cpp" #include "a_painelemental.cpp" #include "a_revenant.cpp" -#include "a_spidermaster.cpp" #include "a_scriptedmarine.cpp" // The barrel of green goop ------------------------------------------------ diff --git a/src/g_doom/a_spidermaster.cpp b/src/g_doom/a_spidermaster.cpp deleted file mode 100644 index 37d0deb184..0000000000 --- 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 "vm.h" -*/ - -static FRandom pr_spidrefire ("SpidRefire"); - -DEFINE_ACTION_FUNCTION(AActor, A_SpidRefire) -{ - PARAM_SELF_PROLOGUE(AActor); - - // 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_SELF_PROLOGUE(AActor); - - S_Sound (self, CHAN_BODY, "spider/walk", 1, ATTN_IDLE); - A_Chase (stack, self); - return 0; -} diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 2ddc505997..65891493e0 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -924,7 +924,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; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 027aaf7dc9..02cb4f3cfc 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -113,8 +113,6 @@ class Actor : Thinker native native void A_BossDeath(); native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); - native void A_Metal(); - native void A_SpidRefire(); native void A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); native void A_DualPainAttack(class spawntype = "LostSoul"); native void A_PainDie(class spawntype = "LostSoul"); diff --git a/wadsrc/static/zscript/doom/spidermaster.txt b/wadsrc/static/zscript/doom/spidermaster.txt index b9f0600688..9a72a2bbe6 100644 --- a/wadsrc/static/zscript/doom/spidermaster.txt +++ b/wadsrc/static/zscript/doom/spidermaster.txt @@ -60,3 +60,34 @@ class SpiderMastermind : Actor 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(); + } +} From 66b1f36e563233b80cae90fa9845cb6fb24a4e59 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 27 Oct 2016 01:30:34 +0200 Subject: [PATCH 119/471] - actually evaluate the default parameters and store them in the VMFunction. - disabled the assert in PType::GetRegType. This assert blocks any use to check for types that are incompatible with function parameters. - pass the default parameter constants to the native functions. At the moment this is not used yet. - use the function defaults to complete argument lists to script functions. - fixed all default values that got flagged by the expression evaluator as non-constant. Most were state labels and colors which were defaulted to "". The proper value is null for states and 0 for colors. - also replaced all "" defaults for names with "none". --- src/dobjtype.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 16 ++--- src/scripting/codegeneration/codegen.h | 2 +- src/scripting/decorate/thingdef_exp.cpp | 2 +- src/scripting/thingdef_data.cpp | 4 +- src/scripting/vm/vm.h | 61 ++++++++++++----- src/scripting/vm/vmexec.cpp | 7 +- src/scripting/vm/vmexec.h | 4 +- src/scripting/vm/vmframe.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 80 +++++++++++++++++++--- wadsrc/static/zscript/actor.txt | 24 +++---- wadsrc/static/zscript/shared/inventory.txt | 10 +-- 12 files changed, 152 insertions(+), 62 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 3bce521c8a..3f5b734c48 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -521,7 +521,7 @@ int PType::GetMoveOp() const int PType::GetRegType() const { - assert(0 && "No register for this type"); + //assert(0 && "No register for this type"); // wrong place for this assert, it makes it impossible to use this function to check for bad types. return REGT_NIL; } diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 2bf1fedc83..d4ee113836 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -96,7 +96,7 @@ FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecor if (fnc != nullptr) Class = fnc->OwningClass; } -FCompileContext::FCompileContext(PClass *cls) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(true) // only used by DECORATE constants. +FCompileContext::FCompileContext(PClass *cls, bool fromdecorate) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate) { } @@ -3745,7 +3745,7 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx) // //========================================================================== -int DecoRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int DecoRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam >= 1 && numparam <= 3); FRandom *rng = reinterpret_cast(param[0].a); @@ -3995,7 +3995,7 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri // //========================================================================== -int DecoFRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int DecoFRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 1 || numparam == 3); FRandom *rng = reinterpret_cast(param[0].a); @@ -5255,7 +5255,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) // //========================================================================== -int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam > 2 && numparam < 8); assert(param[0].Type == REGT_INT); @@ -6702,7 +6702,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) // //========================================================================== -int DecoNameToClass(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int DecoNameToClass(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 2); assert(numret == 1); @@ -6842,7 +6842,7 @@ static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int return false; } -static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { PARAM_PROLOGUE; PARAM_OBJECT(stateowner, AActor); @@ -7008,7 +7008,7 @@ static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMRetu } // Find a state with any number of dots in its name. -int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam > 1); assert(numret == 1); @@ -7024,7 +7024,7 @@ int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, } // Find a state without any dots in its name. -int BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) +int BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 2); assert(numret == 1); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index f6468e61f0..a55491a0b8 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -77,7 +77,7 @@ struct FCompileContext TDeletingArray FunctionArgs; FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate); - FCompileContext(PClass *cls); // only to be used to resolve constants! + FCompileContext(PClass *cls, bool fromdecorate); // only to be used to resolve constants! PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 84e1200e9e..c63677e0cf 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -87,7 +87,7 @@ FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve) if (mustresolve) { - FCompileContext ctx(cls); + FCompileContext ctx(cls, true); data = data->Resolve(ctx); } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 601fb5e9a4..e04935f586 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -667,8 +667,8 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_MomX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.X))); symt.AddSymbol(new PField(NAME_MomY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Y))); symt.AddSymbol(new PField(NAME_MomZ, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Z))); - symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Scale.X))); - symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Scale.Y))); + symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native|VARF_Deprecated, myoffsetof(AActor, Scale.X))); + symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native|VARF_Deprecated, myoffsetof(AActor, Scale.Y))); symt.AddSymbol(new PField(NAME_Score, TypeSInt32, VARF_Native, myoffsetof(AActor, Score))); symt.AddSymbol(new PField(NAME_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor, accuracy))); symt.AddSymbol(new PField(NAME_Stamina, TypeSInt32, VARF_Native, myoffsetof(AActor, stamina))); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 747d53c3b5..c6ff99d480 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -173,20 +173,6 @@ enum EVMAbortException X_BAD_SELF, }; -class VMFunction : public DObject -{ - DECLARE_ABSTRACT_CLASS(VMFunction, DObject); - HAS_OBJECT_POINTERS; -public: - bool Native; - BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action - FName Name; - - class PPrototype *Proto; - - VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {} -}; - enum EVMOpMode { MODE_ASHIFT = 0, @@ -642,6 +628,21 @@ do_double: if (inexact) } }; +class VMFunction : public DObject +{ + DECLARE_ABSTRACT_CLASS(VMFunction, DObject); + HAS_OBJECT_POINTERS; +public: + bool Native; + BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action + FName Name; + TArray Defaults; + + class PPrototype *Proto; + + VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {} +}; + // VM frame layout: // VMFrame header // parameter stack - 16 byte boundary, 16 bytes each @@ -829,7 +830,7 @@ class VMNativeFunction : public VMFunction { DECLARE_CLASS(VMNativeFunction, VMFunction); public: - typedef int (*NativeCallType)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret); + typedef int (*NativeCallType)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret); VMNativeFunction() : NativeCall(NULL) { Native = true; } VMNativeFunction(NativeCallType call) : NativeCall(call) { Native = true; } @@ -900,8 +901,8 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func); void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func); // Use this in the prototype for a native function. -#define VM_ARGS VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret -#define VM_ARGS_NAMES stack, param, numparam, ret, numret +#define VM_ARGS VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret +#define VM_ARGS_NAMES stack, param, defaultparam, numparam, ret, numret // Use these to collect the parameters in a native function. // variable name at position

@@ -924,6 +925,16 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction // PARAM_INT_OPT(0,myint) { myint = 55; } // Just make sure to fill it in when using these macros, because the compiler isn't likely // to give useful error messages if you don't. +#define PARAM_EXISTS ((p) < numparam && param[p].Type != REGT_NIL) +#define ASSERTINT(p) assert((p).Type == REGT_INT) +#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT) +#define ASSERTSTRING(p) assert((p).Type == REGT_STRING) +#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_OBJECT) +#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_GENERIC) +#define ASSERTSTATE(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_GENERIC || (p).atag == ATAG_STATE)) + +#define PARAM_INT_DEF_AT(p,x) int x; if (PARAM_EXISTS) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; } + #define PARAM_INT_OPT_AT(p,x) int x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = param[p].i; } else #define PARAM_BOOL_OPT_AT(p,x) bool x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = !!param[p].i; } else #define PARAM_NAME_OPT_AT(p,x) FName x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = ENamedName(param[p].i); } else @@ -954,6 +965,20 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type) #define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base) +#define PARAM_INT_DEF(x) ++paramnum; PARAM_INT_DEF_AT(paramnum,x) +#define PARAM_BOOL_DEF(x) ++paramnum; PARAM_BOOL_DEF_AT(paramnum,x) +#define PARAM_NAME_DEF(x) ++paramnum; PARAM_NAME_DEF_AT(paramnum,x) +#define PARAM_SOUND_DEF(x) ++paramnum; PARAM_SOUND_DEF_AT(paramnum,x) +#define PARAM_COLOR_DEF(x) ++paramnum; PARAM_COLOR_DEF_AT(paramnum,x) +#define PARAM_FLOAT_DEF(x) ++paramnum; PARAM_FLOAT_DEF_AT(paramnum,x) +#define PARAM_ANGLE_DEF(x) ++paramnum; PARAM_ANGLE_DEF_AT(paramnum,x) +#define PARAM_STRING_DEF(x) ++paramnum; PARAM_STRING_DEF_AT(paramnum,x) +#define PARAM_STATE_DEF(x) ++paramnum; PARAM_STATE_DEF_AT(paramnum,x) +#define PARAM_STATEINFO_DEF(x) ++paramnum; PARAM_STATEINFO_DEF_AT(paramnum,x) +#define PARAM_POINTER_DEF(x,type) ++paramnum; PARAM_POINTER_DEF_AT(paramnum,x,type) +#define PARAM_OBJECT_DEF(x,type) ++paramnum; PARAM_OBJECT_DEF_AT(paramnum,x,type) +#define PARAM_CLASS_DEF(x,base) ++paramnum; PARAM_CLASS_DEF_AT(paramnum,x,base) + #define PARAM_INT_OPT(x) ++paramnum; PARAM_INT_OPT_AT(paramnum,x) #define PARAM_BOOL_OPT(x) ++paramnum; PARAM_BOOL_OPT_AT(paramnum,x) #define PARAM_NAME_OPT(x) ++paramnum; PARAM_NAME_OPT_AT(paramnum,x) @@ -968,7 +993,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_OBJECT_OPT(x,type) ++paramnum; PARAM_OBJECT_OPT_AT(paramnum,x,type) #define PARAM_CLASS_OPT(x,base) ++paramnum; PARAM_CLASS_OPT_AT(paramnum,x,base) -typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ +typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ struct AFuncDesc { diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index fb428f7814..b8078f0718 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -188,13 +188,14 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) const VMRegisters calleereg(callee); assert(calleefunc != NULL && !calleefunc->Native); - assert(numparam == calleefunc->NumArgs); + assert(numparam == calleefunc->NumArgs || ((int)calleefunc->Defaults.Size() == numparam)); assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3); regd = regf = regs = rega = 0; - for (int i = 0; i < numparam; ++i) + for (int i = 0; i < calleefunc->NumArgs; ++i) { - VMValue &p = params[i]; + // get all actual parameters and fill the rest from the defaults. + VMValue &p = i < numparam? params[i] : calleefunc->Defaults[i]; if (p.Type < REGT_STRING) { if (p.Type == REGT_INT) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 65891493e0..a5ad3ac007 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -506,7 +506,7 @@ begin: FillReturns(reg, f, returns, pc+1, C); if (call->Native) { - numret = static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, B, returns, C); + numret = static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, returns, C); } else { @@ -550,7 +550,7 @@ begin: if (call->Native) { - return static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, B, ret, numret); + return static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, ret, numret); } else { // FIXME: Not a true tail call diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index e5e58aa477..bf2159fa14 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -415,7 +415,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur { if (func->Native) { - return static_cast(func)->NativeCall(this, params, numparams, results, numresults); + return static_cast(func)->NativeCall(this, params, func->Defaults, numparams, results, numresults); } else { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f0f884f68e..3a1e734a4f 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1952,6 +1952,7 @@ void ZCCCompiler::InitFunctions() TArray rets(1); TArray args; TArray argflags; + TArray argdefaults; TArray argnames; for (auto c : Classes) @@ -1961,6 +1962,7 @@ void ZCCCompiler::InitFunctions() rets.Clear(); args.Clear(); argflags.Clear(); + bool hasdefault = false; // For the time being, let's not allow overloading. This may be reconsidered later but really just adds an unnecessary amount of complexity here. if (AddTreeNode(f->Name, f, &c->TreeNodes, false)) { @@ -2018,36 +2020,96 @@ void ZCCCompiler::InitFunctions() } } SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags); + argdefaults.Resize(argnames.Size()); auto p = f->Params; if (p != nullptr) { do { + VMValue vmval; // default is REGT_NIL which means 'no default value' here. if (p->Type != nullptr) { auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); int flags = 0; if (p->Flags & ZCC_In) flags |= VARF_In; if (p->Flags & ZCC_Out) flags |= VARF_Out; - if (p->Default != nullptr) + if ((type->IsA(RUNTIME_CLASS(PStruct))) || (flags & VARF_Out)) { - auto val = Simplify(p->Default, &c->Type()->Symbols, true); - flags |= VARF_Optional; - if (val->Operation != PEX_ConstValue) + // 'out' parameters and all structs except vectors are passed by reference + if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3)) { - Error(c->cls, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars()); + type = NewPointer(type); } - // Todo: Store and handle the default value (native functions will discard it anyway but for scripted ones this should be done decently.) + } + if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3) + { + Error(p, "Invalid type %s for function parameter", type->DescriptiveName()); + } + else if (p->Default != nullptr) + { + flags |= VARF_Optional; + // The simplifier is not suited to convert the constant into something usable. + // All it does is reduce the expression to a constant but we still got to do proper type checking and conversion. + // It will also lose important type info about enums, once these get implemented + // The code generator can do this properly for us. + FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false); + FCompileContext ctx(c->Type(), false); + x = x->Resolve(ctx); + + if (x != nullptr) + { + if (!x->isConstant()) + { + Error(p, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars()); + } + else if (x->ValueType != type) + { + Error(p, "Default parameter %s could not be converted to target type %s", FName(p->Name).GetChars(), c->Type()->TypeName.GetChars()); + } + else + { + auto cnst = static_cast(x); + hasdefault = true; + switch (type->GetRegType()) + { + case REGT_INT: + vmval = cnst->GetValue().GetInt(); + break; + + case REGT_FLOAT: + vmval = cnst->GetValue().GetFloat(); + break; + + case REGT_POINTER: + if (type->IsKindOf(RUNTIME_CLASS(PClassPointer))) + vmval = (DObject*)cnst->GetValue().GetPointer(); + else + vmval = cnst->GetValue().GetPointer(); + break; + + case REGT_STRING: + vmval = cnst->GetValue().GetString(); + break; + + default: + assert(0 && "no valid type for constant"); + break; + } + } + } + if (x != nullptr) delete x; } // TBD: disallow certain types? For now, let everything pass that isn't an array. args.Push(type); argflags.Push(flags); + } else { args.Push(nullptr); argflags.Push(0); } + argdefaults.Push(vmval); p = static_cast(p->SiblingNext); } while (p != f->Params); } @@ -2064,9 +2126,11 @@ void ZCCCompiler::InitFunctions() sym->Variants[0].Implementation = FunctionBuildList.AddFunction(sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false); } } - + if (sym->Variants[0].Implementation != nullptr && hasdefault) // do not copy empty default lists, they only waste space and processing time. + { + sym->Variants[0].Implementation->Defaults = std::move(argdefaults); + } // todo: Check inheritance. - // todo: Process function bodies. } } } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 02cb4f3cfc..706acaee78 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -90,7 +90,7 @@ class Actor : Thinker native native void A_NoBlocking(); native void A_XScream(); native void A_Look(); - native void A_Chase(state melee = "*", state missile = "none", int flags = 0); + native void A_Chase(state melee = null, state missile = null, int flags = 0); native void A_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); native void A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); native void A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); @@ -203,8 +203,8 @@ class Actor : Thinker native native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); native state A_Jump(int chance = 256, state label, ...); native void A_CustomMissile(class missiletype, float spawnheight = 32, float spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET); - native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); - native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = null, float Spawnheight = 32, float Spawnofs_xy = 0); + native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); native state A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT); native state A_JumpIfCloser(float distance, state label, bool noz = false); native state A_JumpIfTracerCloser(float distance, state label, bool noz = false); @@ -217,8 +217,8 @@ class Actor : Thinker native native bool A_TakeInventory(class itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); action native bool A_SpawnItem(class itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); native bool A_SpawnItemEx(class itemtype, float xofs = 0, float yofs = 0, float zofs = 0, float xvel = 0, float yvel = 0, float zvel = 0, float angle = 0, int flags = 0, int failchance = 0, int tid=0); - native void A_Print(string whattoprint, float time = 0, name fontname = ""); - native void A_PrintBold(string whattoprint, float time = 0, name fontname = ""); + native void A_Print(string whattoprint, float time = 0, name fontname = "none"); + native void A_PrintBold(string whattoprint, float time = 0, name fontname = "none"); native void A_Log(string whattoprint); native void A_LogInt(int whattoprint); native void A_LogFloat(float whattoprint); @@ -234,7 +234,7 @@ class Actor : Thinker native native state A_CheckSight(state label); native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); native void A_DropInventory(class itemtype); - native void A_SetBlend(color color1, float alpha, int tics, color color2 = ""); + native void A_SetBlend(color color1, float alpha, int tics, color color2 = 0); deprecated native void A_ChangeFlag(string flagname, bool value); deprecated native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); @@ -247,8 +247,8 @@ class Actor : Thinker native native state A_CheckCeiling(state label); native state A_PlayerSkinCheck(state label); deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); - native state, bool A_Teleport(state teleportstate = "", class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT); - native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "", float heightoffset = 0, float radiusoffset = 0, float pitch = 0); + native state, bool A_Teleport(state teleportstate = null, class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT); + native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = null, float heightoffset = 0, float radiusoffset = 0, float pitch = 0); action native bool A_ThrowGrenade(class itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); native void A_Weave(int xspeed, int yspeed, float xdist, float ydist); @@ -257,8 +257,8 @@ class Actor : Thinker native native bool A_GiveToTarget(class itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT); native bool A_TakeFromTarget(class itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT); native int A_RadiusGive(class itemtype, float distance, int flags, int amount = 0, class filter = "None", name species = "None", float mindist = 0, int limit = 0); - native state A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT); - native void A_CountdownArg(int argnum, state targstate = ""); + native state A_CheckSpecies(state jump, name species = 'none', int ptr = AAPTR_DEFAULT); + native void A_CountdownArg(int argnum, state targstate = null); native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); native void A_CustomComboAttack(class missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); native void A_Burst(class chunktype); @@ -271,7 +271,7 @@ class Actor : Thinker native native void A_BarrelDestroy(); native void A_QueueCorpse(); native void A_DeQueueCorpse(); - native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = ""); + native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = null); native void A_ClearLastHeard(); native void A_ClearTarget(); native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, float offsetforward = 0); @@ -357,7 +357,7 @@ class Actor : Thinker native native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0); native void A_CopyFriendliness(int ptr_source = AAPTR_MASTER); - action native bool A_Overlay(int layer, state start = "", bool nooverride = false); + action native bool A_Overlay(int layer, state start = null, bool nooverride = false); native void A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0); action native void A_OverlayOffset(int layer = PSP_WEAPON, float wx = 0, float wy = 32, int flags = 0); action native void A_OverlayFlags(int layer, int flags, bool set); diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 2fde3b3cd0..4a9cde7407 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -42,10 +42,10 @@ class Inventory : Actor native class StateProvider : Inventory native { action native state A_JumpIfNoAmmo(state label); - action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = ""); - action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = "", float Spawnheight = 32, float Spawnofs_xy = 0); + action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = ""); + action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0, class missile = null, float Spawnheight = 32, float Spawnofs_xy = 0); action native void A_FireCustomMissile(class missiletype, float angle = 0, bool useammo = true, float spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0); - action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); native void A_Light(int extralight); native void A_Light0(); native void A_Light1(); @@ -71,10 +71,10 @@ class StateProvider : Inventory native native void A_BFGsound(); action native void A_FireBFG(); action native void A_FireOldBFG(); - native void A_ReFire(state flash = ""); + native void A_ReFire(state flash = null); native void A_ClearReFire(); native void A_CheckReload(); - native void A_GunFlash(state flash = "", int flags = 0); + native void A_GunFlash(state flash = null, int flags = 0); action native void A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff", int flags = 0, float range = 0, float spread_xy = 2.8125, float spread_z = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus"); native state A_CheckForReload(int counter, state label, bool dontincrement = false); native void A_ResetReloadCounter(); From 948ef62fcdbf8740e7e1a83fd43057095679a0b1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 27 Oct 2016 15:53:53 +0200 Subject: [PATCH 120/471] - use the function defaults from the script instead of explicitly setting them again in the code. This is a needless cause of potential errors and since the values are readily available now it's better to use them in the functions. - fixed: ZCCCompiler did not process array access nodes. - fixed: Function argument names were not placed in the destination list by the compiler. - scriptified several trivial functions from p_actionfunctions.cpp. --- src/info.h | 17 - src/p_actionfunctions.cpp | 1298 ++++++----------- src/p_maputl.cpp | 15 + src/scripting/codegeneration/codegen.cpp | 81 +- src/scripting/codegeneration/codegen.h | 6 +- src/scripting/thingdef_data.cpp | 24 +- src/scripting/vm/vm.h | 33 +- src/scripting/vm/vmexec.h | 4 +- src/scripting/zscript/zcc_compile.cpp | 15 +- src/scripting/zscript/zcc_compile.h | 4 +- wadsrc/static/zscript/actor.txt | 200 ++- .../static/zscript/heretic/hereticweaps.txt | 4 +- wadsrc/static/zscript/hexen/wraith.txt | 2 +- 13 files changed, 707 insertions(+), 996 deletions(-) diff --git a/src/info.h b/src/info.h index 5e1d045f23..2155734ad4 100644 --- a/src/info.h +++ b/src/info.h @@ -356,21 +356,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) \ - PARAM_PROLOGUE; \ - PARAM_OBJECT (self, type); \ - PARAM_OBJECT_OPT (stateowner, AActor) { stateowner = self; } \ - PARAM_STATEINFO_OPT (stateinfo) { stateinfo = nullptr; } \ - -// 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/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 57c6768018..a4f49607fc 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -197,6 +197,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 @@ -212,8 +228,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) @@ -248,8 +264,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) @@ -265,29 +281,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 @@ -303,7 +296,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) @@ -334,7 +327,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); @@ -377,7 +370,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); @@ -442,7 +435,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) @@ -471,7 +464,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) @@ -511,11 +504,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) @@ -599,7 +592,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) @@ -660,7 +653,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); @@ -693,8 +686,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) @@ -770,9 +763,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 @@ -852,8 +845,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; @@ -892,7 +885,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TransferPointer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopyFriendliness) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT (ptr_source) { ptr_source = AAPTR_MASTER; } + PARAM_INT_DEF (ptr_source); if (self->player != NULL) { @@ -907,39 +900,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopyFriendliness) return 0; } -//========================================================================== -// -// Simple flag changers -// -//========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_SetSolid) -{ - PARAM_SELF_PROLOGUE(AActor); - self->flags |= MF_SOLID; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_UnsetSolid) -{ - PARAM_SELF_PROLOGUE(AActor); - self->flags &= ~MF_SOLID; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_SetFloat) -{ - PARAM_SELF_PROLOGUE(AActor); - self->flags |= MF_FLOAT; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_UnsetFloat) -{ - PARAM_SELF_PROLOGUE(AActor); - self->flags &= ~(MF_FLOAT|MF_INFLOAT); - return 0; -} - //========================================================================== // // Customizable attack functions which use actor parameters. @@ -1029,11 +989,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BasicAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) { PARAM_SELF_PROLOGUE(AActor); - 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_SOUND_DEF (soundid); + PARAM_INT_DEF (channel); + PARAM_FLOAT_DEF (volume); + PARAM_BOOL_DEF (looping); + PARAM_FLOAT_DEF (attenuation); if (!looping) { @@ -1052,7 +1012,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSound) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(slot) { slot = CHAN_VOICE; } + PARAM_INT_DEF(slot); S_StopSound(self, slot); return 0; @@ -1067,22 +1027,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) @@ -1142,9 +1093,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()target, self, param, numparam, ret, numret); + return DoJumpIfInventory(self->target, VM_ARGS_NAMES); } //========================================================================== @@ -1389,7 +1340,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType) 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); @@ -1416,15 +1367,15 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) { PARAM_SELF_PROLOGUE(AActor); - 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_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 { @@ -1485,10 +1436,10 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust) { PARAM_SELF_PROLOGUE(AActor); - 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_INT_DEF (force); + PARAM_INT_DEF (distance); + PARAM_INT_DEF (flags); + PARAM_INT_DEF (fullthrustdistance); bool sourcenothrust = false; @@ -1525,10 +1476,10 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusDamageSelf) { PARAM_SELF_PROLOGUE(AActor); - 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_INT_DEF(damage); + PARAM_FLOAT_DEF(distance); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(flashtype, AActor); int i; int damageSteps; @@ -1587,11 +1538,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); @@ -1620,12 +1571,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); @@ -1772,13 +1723,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); @@ -1860,11 +1811,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMeleeAttack) { PARAM_SELF_PROLOGUE(AActor); - 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_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 @@ -1900,9 +1851,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; @@ -2022,12 +1973,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) 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; @@ -2149,12 +2100,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) { 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; @@ -2226,15 +2177,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) { 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; @@ -2330,23 +2281,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack) { 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; @@ -2409,23 +2360,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; @@ -2527,11 +2478,11 @@ 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) @@ -2635,8 +2586,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetInventory) 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) { ptr = AAPTR_DEFAULT; } + PARAM_BOOL_DEF(beyondMax) { beyondMax = false; } bool res = false; @@ -2725,8 +2676,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) { @@ -3013,11 +2964,11 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) { PARAM_ACTION_PROLOGUE(AActor); - 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_CLASS_DEF (missile, AActor) + PARAM_FLOAT_DEF (distance) + PARAM_FLOAT_DEF (zheight) + PARAM_BOOL_DEF (useammo) + PARAM_BOOL_DEF (transfer_translation) if (missile == NULL) { @@ -3062,16 +3013,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) { @@ -3144,15 +3095,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) { - 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_ACTION_PROLOGUE(AActor); + PARAM_CLASS (missile, AActor); + PARAM_FLOAT_DEF (zheight) + PARAM_FLOAT_DEF (xyvel) + PARAM_FLOAT_DEF (zvel) + PARAM_BOOL_DEF (useammo) - if (missile == NULL) - { + if (missile == NULL) + { ACTION_RETURN_BOOL(true); } if (ACTION_CALL_FROM_PSPRITE()) @@ -3243,7 +3194,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); @@ -3288,8 +3239,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) || @@ -3323,8 +3274,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; @@ -3400,7 +3351,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; @@ -3419,7 +3370,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); @@ -3443,8 +3394,10 @@ enum FadeFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(reduce) { reduce = 0.1; } - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_FLOAT_DEF(reduce); + PARAM_INT_DEF(flags); + PARAM_NAME_DEF(fontname); + if (reduce == 0) { @@ -3477,8 +3430,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeOut) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(reduce) { reduce = 0.1; } - PARAM_INT_OPT(flags) { flags = FTF_REMOVE; } + PARAM_FLOAT_DEF(reduce); + PARAM_INT_DEF(flags); if (reduce == 0) { @@ -3512,8 +3465,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; @@ -3546,50 +3499,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 @@ -3599,9 +3508,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; @@ -3655,22 +3564,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.); @@ -3786,7 +3695,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_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) @@ -3815,7 +3724,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_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) @@ -3872,7 +3781,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; @@ -3912,7 +3821,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]--) @@ -3927,6 +3836,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CountdownArg) } else { + if (state == nullptr) state = self->FindState(NAME_Death); self->SetState(state); } } @@ -4075,7 +3985,7 @@ enum RS_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(flags) { flags = RSF_FOG; } + PARAM_INT_DEF(flags); bool oktorespawn = false; DVector3 pos = self->Pos(); @@ -4164,38 +4074,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayerSkinCheck) ACTION_RETURN_STATE(NULL); } -//=========================================================================== -// -// 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_SELF_PROLOGUE(AActor); - self->target = NULL; - self->LastHeard = NULL; - self->lastenemy = NULL; - return 0; -} - //========================================================================== // // A_CheckLOF (state jump, int flags = CRF_AIM_VERT|CRF_AIM_HOR, @@ -4530,10 +4410,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) { 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; @@ -4668,10 +4548,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) { 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; @@ -4755,7 +4635,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) } PARAM_INT (count); PARAM_STATE (jump); - PARAM_BOOL_OPT (dontincrement) { dontincrement = false; } + PARAM_BOOL_DEF (dontincrement); if (numret > 0) { @@ -4836,7 +4716,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_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) @@ -4852,46 +4732,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) } -//=========================================================================== -// -// A_ChangeCountFlags (needed, because these flags affect global counters) -// -//=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeLinkFlags) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(blockmap) { blockmap = -1; } - PARAM_INT_OPT(sector) { sector = -1; } - - self->UnlinkFromWorld(); - - if (blockmap != -1) - { - if (blockmap == 0) self->flags &= ~MF_NOBLOCKMAP; - else self->flags |= MF_NOBLOCKMAP; - } - - if (sector != -1) - { - if (sector == 0) self->flags &= ~MF_NOSECTOR; - else self->flags |= MF_NOSECTOR; - } - - self->LinkToWorld(); - return 0; -} - -//=========================================================================== -// -// A_ChangeCountFlags (needed, because these flags affect global counters) -// -//=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeCountFlags) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(kill) { kill = -1; } - PARAM_INT_OPT(item) { item = -1; } - PARAM_INT_OPT(secret) { secret = -1; } + 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; @@ -4928,7 +4774,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeCountFlags) DEFINE_ACTION_FUNCTION(AActor, A_RaiseMaster) { PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL_OPT(copy) { copy = false; } + PARAM_BOOL_DEF(copy); if (self->master != NULL) { @@ -4945,7 +4791,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseMaster) DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren) { PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL_OPT(copy) { copy = false; } + PARAM_BOOL_DEF(copy); TThinkerIterator it; AActor *mo; @@ -4968,7 +4814,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren) DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings) { PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL_OPT(copy) { copy = false; } + PARAM_BOOL_DEF(copy); TThinkerIterator it; AActor *mo; @@ -4986,18 +4832,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 @@ -5044,9 +4878,9 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(angle) { angle = 0; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_FLOAT_DEF(angle); + PARAM_INT_DEF(flags); + PARAM_INT_DEF(ptr); AActor *ref = COPY_AAPTR(self, ptr); if (ref != NULL) @@ -5068,8 +4902,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); @@ -5092,8 +4926,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) @@ -5115,7 +4949,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); @@ -5146,11 +4980,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ScaleVelocity) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity) { PARAM_SELF_PROLOGUE(AActor); - 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_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); @@ -5186,51 +5020,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 @@ -5371,13 +5160,13 @@ enum T_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) { PARAM_SELF_PROLOGUE(AActor); - 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_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); @@ -5538,20 +5327,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) return numret; } -//=========================================================================== -// -// A_Turn -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Turn) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(angle) { angle = 0; } - self->Angles.Yaw += angle; - return 0; -} - //=========================================================================== // // A_Quake @@ -5565,7 +5340,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; @@ -5588,15 +5363,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; @@ -5675,8 +5450,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Weave) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LineEffect) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(special) { special = 0; } - PARAM_INT_OPT(tag) { tag = 0; } + PARAM_INT_DEF(special); + PARAM_INT_DEF(tag); line_t junk; maplinedef_t oldjunk; @@ -5710,15 +5485,15 @@ enum WolfAttackFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack) { PARAM_SELF_PROLOGUE(AActor); - 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_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; @@ -5816,15 +5591,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) { PARAM_SELF_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; @@ -5874,104 +5649,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(); @@ -6168,11 +5845,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) @@ -6218,8 +5895,8 @@ 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; } + PARAM_NAME_DEF(species); + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); @@ -6259,21 +5936,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 @@ -6284,77 +5946,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 @@ -6429,12 +6027,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); @@ -6452,12 +6050,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); @@ -6476,12 +6074,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); @@ -6500,12 +6098,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); @@ -6524,12 +6122,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); @@ -6554,12 +6152,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); @@ -6636,12 +6234,12 @@ static void DoKill(AActor *killtarget, AActor *inflictor, AActor *source, FName DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) { PARAM_SELF_PROLOGUE(AActor); - 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); @@ -6659,12 +6257,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) { PARAM_SELF_PROLOGUE(AActor); - 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); @@ -6682,14 +6280,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) { PARAM_SELF_PROLOGUE(AActor); - 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 *source = COPY_AAPTR(self, src); AActor *inflictor = COPY_AAPTR(self, inflict); if (self->master != NULL) @@ -6705,12 +6303,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) { PARAM_SELF_PROLOGUE(AActor); - 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); @@ -6736,12 +6334,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) { PARAM_SELF_PROLOGUE(AActor); - 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); @@ -6812,9 +6410,9 @@ static void DoRemove(AActor *removetarget, int flags, PClassActor *filter, FName DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); if (self->target != NULL) { @@ -6831,9 +6429,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); if (self->tracer != NULL) { @@ -6850,9 +6448,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } - PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); if (self->master != NULL) { @@ -6869,10 +6467,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) { PARAM_SELF_PROLOGUE(AActor); - 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_BOOL_DEF(removeall); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); TThinkerIterator it; AActor *mo; @@ -6895,10 +6493,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings) { PARAM_SELF_PROLOGUE(AActor); - 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_BOOL_DEF(removeall); + PARAM_INT_DEF(flags); + PARAM_CLASS_DEF(filter, AActor); + PARAM_NAME_DEF(species); TThinkerIterator it; AActor *mo; @@ -6924,10 +6522,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) @@ -6982,18 +6580,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 @@ -7006,7 +6592,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); @@ -7043,7 +6629,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetHealth) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); @@ -7080,10 +6666,10 @@ 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; } + PARAM_FLOAT_DEF(offsethigh); + PARAM_FLOAT_DEF(offsetlow); + PARAM_BOOL_DEF(includeHeight); + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); @@ -7111,7 +6697,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) @@ -7123,48 +6709,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) @@ -7177,8 +6721,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); @@ -7206,9 +6750,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) 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) { @@ -7250,12 +6794,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_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); @@ -7360,11 +6904,11 @@ enum FMDFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection) { PARAM_SELF_PROLOGUE(AActor); - 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_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); @@ -7456,7 +7000,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame) 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); @@ -7481,8 +7025,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpriteAngle) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(angle) { angle = 0.; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_FLOAT_DEF(angle); + PARAM_INT_DEF(ptr); AActor *mobj = COPY_AAPTR(self, ptr); @@ -7535,12 +7079,12 @@ enum VRFFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetVisibleRotation) { PARAM_SELF_PROLOGUE(AActor); - 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_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_maputl.cpp b/src/p_maputl.cpp index a3d4d0e9eb..04372f0eda 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 (); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d4ee113836..5148952a74 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -539,12 +539,13 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) // //========================================================================== -FxIntCast::FxIntCast(FxExpression *x, bool nowarn) +FxIntCast::FxIntCast(FxExpression *x, bool nowarn, bool explicitly) : FxExpression(EFX_IntCast, x->ScriptPosition) { basex=x; ValueType = TypeSInt32; NoWarn = nowarn; + Explicit = explicitly; } //========================================================================== @@ -571,9 +572,10 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) if (basex->ValueType->GetRegType() == REGT_INT) { - if (basex->ValueType != TypeName) + if (basex->ValueType != TypeName || Explicit) // names can be converted to int, but only with an explicit type cast. { FxExpression *x = basex; + x->ValueType = ValueType; basex = NULL; delete this; return x; @@ -582,7 +584,8 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) { // 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"); + 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; @@ -1062,11 +1065,13 @@ ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build) // //========================================================================== -FxTypeCast::FxTypeCast(FxExpression *x, PType *type, bool nowarn) +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); } @@ -1126,7 +1131,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) 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); + FxExpression *x = new FxIntCast(basex, NoWarn, Explicit); x = x->Resolve(ctx); basex = nullptr; delete this; @@ -4964,12 +4969,31 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) return x->Resolve(ctx); } - // Last but not least: Check builtins. The random functions can take a named RNG if specified. + // 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_Int: + case NAME_uInt: + case NAME_Double: + case NAME_Name: + case NAME_Color: + case NAME_Sound: + if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) + { + PType *type = MethodName == NAME_Int ? TypeSInt32 : + MethodName == NAME_uInt ? TypeUInt32 : + MethodName == NAME_Double ? TypeFloat64 : + MethodName == NAME_Name ? TypeName : + MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; + + func = new FxTypeCast((*ArgList)[0], type, true, true); + (*ArgList)[0] = nullptr; + } + break; + case NAME_Random: if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) { @@ -5044,6 +5068,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) break; default: + // todo: Check for class type casts break; } if (func != nullptr) @@ -5216,8 +5241,11 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) 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] == NULL) + { + failed = true; + } + else if (Special < 0 && i == 0) { if ((*ArgList)[i]->ValueType != TypeName) { @@ -5409,10 +5437,16 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } - if (ArgList != NULL) + if (ArgList != nullptr) { bool foundvarargs = false; PType * type = nullptr; + if (ArgList->Size() + implicit > proto->ArgumentTypes.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. @@ -5476,24 +5510,23 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *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->IsActionFunc) + if (Function->Variants[0].Flags & VARF_Action) { - build->Emit(OP_PARAM, 0, REGT_POINTER, 1); - build->Emit(OP_PARAM, 0, REGT_POINTER, 2); + static_assert(NAP == 3, "This code needs to be updated if NAP changes"); + if (build->IsActionFunc && 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; } - 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) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index a55491a0b8..cd93b8894b 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -474,10 +474,11 @@ class FxIntCast : public FxExpression { FxExpression *basex; bool NoWarn; + bool Explicit; public: - FxIntCast(FxExpression *x, bool nowarn); + FxIntCast(FxExpression *x, bool nowarn, bool explicitly = false); ~FxIntCast(); FxExpression *Resolve(FCompileContext&); @@ -559,10 +560,11 @@ class FxTypeCast : public FxExpression { FxExpression *basex; bool NoWarn; + bool Explicit; public: - FxTypeCast(FxExpression *x, PType *type, bool nowarn); + FxTypeCast(FxExpression *x, PType *type, bool nowarn, bool explicitly = false); ~FxTypeCast(); FxExpression *Resolve(FCompileContext&); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index e04935f586..55cc03c0c8 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -67,8 +67,8 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags), DEFINE_FLAG(MF, SOLID, AActor, flags), DEFINE_FLAG(MF, SHOOTABLE, AActor, flags), - DEFINE_READONLY_FLAG(MF, NOSECTOR, AActor, flags), - DEFINE_READONLY_FLAG(MF, NOBLOCKMAP, AActor, flags), + DEFINE_FLAG(MF, NOSECTOR, AActor, flags), + DEFINE_FLAG(MF, NOBLOCKMAP, AActor, flags), DEFINE_FLAG(MF, AMBUSH, AActor, flags), DEFINE_FLAG(MF, JUSTHIT, AActor, flags), DEFINE_FLAG(MF, JUSTATTACKED, AActor, flags), @@ -84,8 +84,8 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF, NOBLOOD, AActor, flags), DEFINE_FLAG(MF, CORPSE, AActor, flags), DEFINE_FLAG(MF, INFLOAT, AActor, flags), - DEFINE_READONLY_FLAG(MF, COUNTKILL, AActor, flags), - DEFINE_READONLY_FLAG(MF, COUNTITEM, AActor, flags), + DEFINE_FLAG(MF, COUNTKILL, AActor, flags), + DEFINE_FLAG(MF, COUNTITEM, AActor, flags), DEFINE_FLAG(MF, SKULLFLY, AActor, flags), DEFINE_FLAG(MF, NOTDMATCH, AActor, flags), DEFINE_FLAG(MF, SPAWNSOUNDSOURCE, AActor, flags), @@ -186,7 +186,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF5, GETOWNER, AActor, flags5), DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5), DEFINE_FLAG(MF5, NOFORWARDFALL, AActor, flags5), - DEFINE_READONLY_FLAG(MF5, COUNTSECRET, AActor, flags5), + DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5), DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5), DEFINE_FLAG(MF5, BLOODSPLATTER, AActor, flags5), DEFINE_FLAG(MF5, OLDRADIUSDMG, AActor, flags5), @@ -677,10 +677,20 @@ void InitThingdef() 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("FloatSpeed", TypeFloat64, VARF_Native, myoffsetof(AActor, FloatSpeed))); + symt.AddSymbol(new PField("PainThreshold", TypeSInt32, VARF_Native, myoffsetof(AActor, PainThreshold))); + symt.AddSymbol(new PField("spriteAngle", TypeFloat64, VARF_Native, myoffsetof(AActor, SpriteAngle))); + symt.AddSymbol(new PField("spriteRotation", TypeFloat64, VARF_Native, myoffsetof(AActor, SpriteRotation))); + symt.AddSymbol(new PField(NAME_Threshold, TypeSInt32, VARF_Native, 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("visdir", TypeSInt32, VARF_Native, myoffsetof(AActor, visdir))); + symt.AddSymbol(new PField("Gravity", TypeFloat64, VARF_Native, myoffsetof(AActor, Gravity))); + symt.AddSymbol(new PField("DamageType", TypeName, VARF_Native, myoffsetof(AActor, DamageType))); + symt.AddSymbol(new PField("FloatBobPhase", TypeUInt8, VARF_Native, myoffsetof(AActor, FloatBobPhase))); + symt.AddSymbol(new PField("RipperLevel", TypeSInt32, VARF_Native, myoffsetof(AActor, RipperLevel))); + symt.AddSymbol(new PField("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin))); + symt.AddSymbol(new PField("RipLevelMax", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMax))); 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))); @@ -693,6 +703,8 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master))); symt.AddSymbol(new PField(NAME_Tracer, TypeActor, VARF_Native, myoffsetof(AActor, tracer))); + symt.AddSymbol(new PField("LastHeard", TypeActor, VARF_Native, myoffsetof(AActor, LastHeard))); + symt.AddSymbol(new PField("LastEnemy", TypeActor, VARF_Native, myoffsetof(AActor, lastenemy))); // synthesize a symbol for each flag. The bounce flags are excluded on purpose. for (size_t i = 0; i < countof(ActorFlagDefs); i++) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index c6ff99d480..ae936b844e 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -925,7 +925,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction // PARAM_INT_OPT(0,myint) { myint = 55; } // Just make sure to fill it in when using these macros, because the compiler isn't likely // to give useful error messages if you don't. -#define PARAM_EXISTS ((p) < numparam && param[p].Type != REGT_NIL) +#define 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) @@ -933,7 +933,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_GENERIC) #define ASSERTSTATE(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_GENERIC || (p).atag == ATAG_STATE)) -#define PARAM_INT_DEF_AT(p,x) int x; if (PARAM_EXISTS) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; } +#define PARAM_INT_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)) { ASSERTSTATE(param[p]); x = (FState*)param[p].a; } else { ASSERTSTATE(defaultparam[p]); x = (FState*)defaultparam[p].a; } +#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; } #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 @@ -1048,6 +1059,24 @@ struct AFuncDesc #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_OPT (stateowner, AActor) { stateowner = self; } \ + PARAM_STATEINFO_OPT (stateinfo) { stateinfo = nullptr; } \ + +// Number of action paramaters +#define NAP 3 + +#define PARAM_SELF_PROLOGUE(type) \ + PARAM_PROLOGUE; \ + PARAM_OBJECT(self, type); + + class PFunction; PFunction *FindGlobalActionFunction(const char *name); diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index a5ad3ac007..4fbe29257d 100644 --- a/src/scripting/vm/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] = GC::ReadBarrier(*(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): diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 3a1e734a4f..370e659193 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2102,12 +2102,14 @@ void ZCCCompiler::InitFunctions() // 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); } argdefaults.Push(vmval); p = static_cast(p->SiblingNext); @@ -2120,7 +2122,7 @@ void ZCCCompiler::InitFunctions() if (!(f->Flags & ZCC_Native)) { - auto code = ConvertAST(f->Body); + 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); @@ -2157,7 +2159,7 @@ static bool CheckRandom(ZCC_Expression *duration) // Sets up the action function call // //========================================================================== -FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *af) +FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) { // We have 3 cases to consider here: // 1. An action function without parameters. This can be called directly @@ -2197,8 +2199,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a } } } - ConvertClass = cls; - return ConvertAST(af); + return ConvertAST(cls, af); } //========================================================================== @@ -2419,8 +2420,9 @@ void ZCCCompiler::CompileStates() // //========================================================================== -FxExpression *ZCCCompiler::ConvertAST(ZCC_TreeNode *ast) +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) { @@ -2680,6 +2682,9 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_LTGTEQ: return new FxLtGtEq(left, right); + case PEX_ArrayAccess: + return new FxArrayElement(left, right); + // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_Concat: case PEX_Is: diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index cf27758349..4ad72769a4 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -109,7 +109,7 @@ private: void InitFunctions(); void CompileStates(); - FxExpression *SetupActionFunction(PClassActor *cls, ZCC_TreeNode *sl); + FxExpression *SetupActionFunction(PClass *cls, ZCC_TreeNode *sl); bool SimplifyingConstant; TArray Constants; @@ -140,7 +140,7 @@ private: void Error(ZCC_TreeNode *node, const char *msg, ...); void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr); - FxExpression *ConvertAST(ZCC_TreeNode *ast); + FxExpression *ConvertAST(PClass *cclass, ZCC_TreeNode *ast); FxExpression *ConvertNode(ZCC_TreeNode *node); FArgumentList *ConvertNodeList(ZCC_TreeNode *head); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 706acaee78..4f859d3b0f 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -47,6 +47,13 @@ class Actor : Thinker native } // Functions + + bool IsPointerEqual(int ptr_select1, int ptr_select2) + { + return GetPointer(ptr_select1) == GetPointer(ptr_select2); + } + + native Actor GetPointer(int aaptr); native Actor SpawnMissile(Actor dest, class type, Actor owner = null); native void TraceBleed(int damage, Actor missile); native bool CheckMeleeRange(); @@ -56,11 +63,11 @@ class Actor : Thinker native native bool CheckSight(Actor target, int flags = 0); native bool HitFriend(); native bool SetState(state st, bool nofunction = false); + native void LinkToWorld(); + native void UnlinkFromWorld(); - // DECORATE compatible 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); @@ -78,9 +85,89 @@ class Actor : Thinker native 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_SetGravity(float newgravity) { gravity = clamp(newgravity, 0., 10.); } + 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_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(); + } + // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. - native void A_Turn(float angle = 0); native bool A_LineEffect(int boomspecial = 0, int tag = 0); // End of MBF redundant functions. @@ -121,9 +208,9 @@ class Actor : Thinker native native void A_BrainScream(); native void A_BrainDie(); native void A_BrainAwake(); - native void A_BrainSpit(class spawntype = "none"); // needs special treatment for default + native void A_BrainSpit(class spawntype = null); // needs special treatment for default native void A_SpawnSound(); - native void A_SpawnFly(class spawntype = "none"); // needs special treatment for default + native void A_SpawnFly(class spawntype = null); // needs special treatment for default native void A_BrainExplode(); native void A_Die(name damagetype = "none"); native void A_Detonate(); @@ -145,12 +232,8 @@ class Actor : Thinker native native void A_NoGravity(); native void A_Gravity(); native void A_LowGravity(); - native void A_SetGravity(float gravity); + native void A_Fall(); - native void A_SetSolid(); - native void A_UnsetSolid(); - native void A_SetFloat(); - native void A_UnsetFloat(); native void A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); @@ -186,7 +269,6 @@ class Actor : Thinker native native void A_ClearSoundTarget(); native void A_FireAssaultGun(); native void A_CheckTerrain(); - native void A_FaceConsolePlayer(float MaxTurnAngle = 0); // [TP] no-op deprecated native void A_MissileAttack(); deprecated native void A_MeleeAttack(); @@ -194,7 +276,7 @@ class Actor : Thinker native 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); - native void A_PlayWeaponSound(sound whattoplay); + 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... @@ -204,7 +286,7 @@ class Actor : Thinker native native state A_Jump(int chance = 256, state label, ...); native void A_CustomMissile(class missiletype, float spawnheight = 32, float spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET); native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = null, float Spawnheight = 32, float Spawnofs_xy = 0); - native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, float maxdiff = 0, class pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0); + native 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 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); @@ -213,6 +295,7 @@ class Actor : Thinker native 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); + 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); @@ -227,8 +310,6 @@ class Actor : Thinker native 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_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); @@ -238,7 +319,6 @@ class Actor : Thinker native deprecated native void A_ChangeFlag(string flagname, bool value); deprecated native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); - native void A_ChangeLinkFlags(int blockmap = FLAG_NO_CHANGE, int sector = FLAG_NO_CHANGE); native state A_JumpIf(bool expression, state label); native void A_RaiseMaster(bool copy = 0); native void A_RaiseChildren(bool copy = 0); @@ -247,7 +327,7 @@ class Actor : Thinker native native state A_CheckCeiling(state label); native state A_PlayerSkinCheck(state label); deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); - native state, bool A_Teleport(state teleportstate = null, class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT); + native state, bool A_Teleport(state teleportstate = null, class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 128, int ptr = AAPTR_DEFAULT); native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = null, float heightoffset = 0, float radiusoffset = 0, float pitch = 0); action native bool A_ThrowGrenade(class itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); native void A_Weave(int xspeed, int yspeed, float xdist, float ydist); @@ -256,7 +336,7 @@ class Actor : Thinker native 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 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 state A_CheckSpecies(state jump, name species = 'none', int ptr = AAPTR_DEFAULT); native void A_CountdownArg(int argnum, state targstate = null); native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); @@ -264,7 +344,7 @@ class Actor : Thinker native 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 = "None"); + 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); @@ -273,7 +353,6 @@ class Actor : Thinker native native void A_DeQueueCorpse(); native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = null); native void A_ClearLastHeard(); - native void A_ClearTarget(); native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, float offsetforward = 0); native state A_JumpIfTargetInLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); native state A_JumpIfInTargetLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); @@ -295,51 +374,41 @@ class Actor : Thinker native 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); - native void A_SetArg(int pos, int value); 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_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 void 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); - native void A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); - native void A_RemoveTarget(int flags = 0, class filter = "None", name species = "None"); - native void A_RemoveMaster(int flags = 0, class filter = "None", name species = "None"); - native void A_RemoveTracer(int flags = 0, class filter = "None", name species = "None"); - native void A_RemoveChildren(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); - native void 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 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_SetFloatBobPhase(int bob); native void A_SetHealth(int health, int ptr = AAPTR_DEFAULT); native void 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); @@ -348,8 +417,6 @@ class Actor : Thinker native 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_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT); - native bool A_SetSpriteRotation(float angle = 0, int ptr = AAPTR_DEFAULT); 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); @@ -362,13 +429,34 @@ class Actor : Thinker native 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); - 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); + 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 { diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index 0c3123c7c6..ae5e971797 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -479,7 +479,7 @@ class Gauntlets : Weapon GAUN A 1 A_Raise; Loop; Fire: - GAUN B 4 A_PlayWeaponSound("weapons/gauntletsuse"); + GAUN B 4 A_PlaySound("weapons/gauntletsuse", CHAN_WEAPON); GAUN C 4; Hold: GAUN DEF 4 BRIGHT A_GauntletAttack(0); @@ -512,7 +512,7 @@ class GauntletsPowered : Gauntlets GAUN G 1 A_Raise; Loop; Fire: - GAUN J 4 A_PlayWeaponSound("weapons/gauntletsuse"); + GAUN J 4 A_PlaySound("weapons/gauntletsuse", CHAN_WEAPON); GAUN K 4; Hold: GAUN LMN 4 BRIGHT A_GauntletAttack(1); diff --git a/wadsrc/static/zscript/hexen/wraith.txt b/wadsrc/static/zscript/hexen/wraith.txt index 9d811ec5c7..86df72d94e 100644 --- a/wadsrc/static/zscript/hexen/wraith.txt +++ b/wadsrc/static/zscript/hexen/wraith.txt @@ -52,7 +52,7 @@ class Wraith : Actor Missile: WRTH E 6 A_FaceTarget; WRTH F 6; - WRTH G 6 A_CustomMissile("WraithFX1", 32, 0); + WRTH G 6 A_CustomMissile("WraithFX1"); Goto See; Death: WRTH I 4; From c7347608a4db5f05c46686dba6494d6f442a8496 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 27 Oct 2016 17:47:46 +0200 Subject: [PATCH 121/471] - scriptified A_FatAttack*. - swapped parameters of two-parameter VelToAngle method, so that internal and script version are in line. - fixed parameter asserts to handle NULL pointers properly. --- src/actor.h | 2 +- src/g_doom/a_fatso.cpp | 93 ---------------------------- src/g_hexen/a_bats.cpp | 2 +- src/g_hexen/a_clericflame.cpp | 2 +- src/g_raven/a_minotaur.cpp | 2 +- src/g_strife/a_entityboss.cpp | 2 +- src/g_strife/a_strifeweapons.cpp | 4 +- src/info.cpp | 2 +- src/p_actionfunctions.cpp | 20 +++--- src/p_enemy.cpp | 12 +--- src/p_interaction.cpp | 4 +- src/p_map.cpp | 14 ++--- src/p_mobj.cpp | 27 +++++++- src/scripting/vm/vm.h | 20 ++---- src/scripting/vm/vmexec.cpp | 2 +- wadsrc/static/zscript/actor.txt | 12 ++-- wadsrc/static/zscript/constants.txt | 14 +++++ wadsrc/static/zscript/doom/fatso.txt | 72 +++++++++++++++++++++ 18 files changed, 152 insertions(+), 154 deletions(-) diff --git a/src/actor.h b/src/actor.h index 3f7c1178ee..df5ef3c175 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1366,7 +1366,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/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index d840461048..d373a7a08b 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -15,99 +15,6 @@ // firing three missiles in three different directions? // Doesn't look like it. // -#define FATSPREAD (90./8) - -DEFINE_ACTION_FUNCTION(AActor, A_FatRaise) -{ - PARAM_SELF_PROLOGUE(AActor); - - A_FaceTarget (self); - S_Sound (self, CHAN_WEAPON, "fatso/raiseguns", 1, ATTN_NORM); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1) -{ - PARAM_SELF_PROLOGUE(AActor); - 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_SELF_PROLOGUE(AActor); - 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_SELF_PROLOGUE(AActor); - 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 diff --git a/src/g_hexen/a_bats.cpp b/src/g_hexen/a_bats.cpp index 5be91b69b4..02fc6111ea 100644 --- a/src/g_hexen/a_bats.cpp +++ b/src/g_hexen/a_bats.cpp @@ -84,7 +84,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BatMove) } // Adjust velocity vector to new direction - self->VelFromAngle(newangle, self->Speed); + self->VelFromAngle(self->Speed, newangle); if (pr_batmove()<15) { diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp index b03b9b6b9e..56267b8e6e 100644 --- a/src/g_hexen/a_clericflame.cpp +++ b/src/g_hexen/a_clericflame.cpp @@ -162,7 +162,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlameRotate) 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_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index 8bdbe122b0..209afc9f42 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -415,7 +415,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.); diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp index 84a4b3fa3f..5350229015 100644 --- a/src/g_strife/a_entityboss.cpp +++ b/src/g_strife/a_entityboss.cpp @@ -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_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 91f4ac75e7..f80f3e863b 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -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) @@ -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; diff --git a/src/info.cpp b/src/info.cpp index 268d4f91c1..26bd306fa8 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -78,7 +78,7 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, ActionCycles.Clock(); VMFrameStack stack; - VMValue params[3] = { self, stateowner, VMValue(info, ATAG_STATEINFO) }; + 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. diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index a4f49607fc..fd67e0a645 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -137,7 +137,7 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) 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; @@ -4218,15 +4218,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) 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; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index fbdc1a2121..3f55706817 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2500,7 +2500,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 } } @@ -3315,16 +3315,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain) return 0; } -// killough 11/98: kill an object -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Die) -{ - PARAM_SELF_PROLOGUE(AActor); - 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 diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index f3d02428d1..b4ecc827eb 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1562,8 +1562,8 @@ DEFINE_ACTION_FUNCTION(AActor, DamageMobj) PARAM_OBJECT(source, AActor); PARAM_INT(damage); PARAM_NAME(mod); - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_FLOAT_OPT(angle) { angle = 0; } + PARAM_INT_DEF(flags); + PARAM_FLOAT_DEF(angle); ACTION_RETURN_INT(P_DamageMobj(self, inflictor, source, damage, mod, flags, angle)); } diff --git a/src/p_map.cpp b/src/p_map.cpp index ef46f6566a..a2e83b73f4 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4048,11 +4048,11 @@ DEFINE_ACTION_FUNCTION(AActor, AimLineAttack) PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE(angle); PARAM_FLOAT(distance); - PARAM_POINTER_OPT(pLineTarget, FTranslatedLineTarget) { pLineTarget = nullptr; } - PARAM_ANGLE_OPT(vrange) { vrange = 0.; } - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_OBJECT_OPT(target, AActor) { target = nullptr; } - PARAM_OBJECT_OPT(friender, AActor) { friender = nullptr; } + 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); } @@ -4431,8 +4431,8 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack) PARAM_INT(damage); PARAM_NAME(damageType); PARAM_CLASS(puffType, AActor); - PARAM_INT_OPT(flags) { flags = 0; } - PARAM_POINTER_OPT(victim, FTranslatedLineTarget) { victim = nullptr; } + 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); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7398fa29f1..7d37e35461 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5838,7 +5838,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissile) PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(dest, AActor); PARAM_CLASS(type, AActor); - PARAM_OBJECT_OPT(owner, AActor) { owner = self; } + PARAM_OBJECT_DEF(owner, AActor); ACTION_RETURN_OBJECT(P_SpawnMissile(self, dest, type, owner)); } @@ -6584,6 +6584,31 @@ void AActor::SetTranslation(const char *trname) // silently ignore if the name does not exist, this would create some insane message spam otherwise. } + +// 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; +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index ae936b844e..3d0dc166d6 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -159,7 +159,6 @@ enum ATAG_AREGISTER, // pointer to an address register ATAG_STATE, // pointer to FState - ATAG_STATEINFO, // FState plus some info. ATAG_RNG, // pointer to FRandom }; @@ -929,7 +928,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define ASSERTINT(p) assert((p).Type == REGT_INT) #define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT) #define ASSERTSTRING(p) assert((p).Type == REGT_STRING) -#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_OBJECT) +#define 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)) @@ -950,14 +949,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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].atag == ATAG_GENERIC || 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].atag == ATAG_GENERIC || 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 // The above, but with an automatically increasing position index. @@ -985,7 +979,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_ANGLE_DEF(x) ++paramnum; PARAM_ANGLE_DEF_AT(paramnum,x) #define PARAM_STRING_DEF(x) ++paramnum; PARAM_STRING_DEF_AT(paramnum,x) #define PARAM_STATE_DEF(x) ++paramnum; PARAM_STATE_DEF_AT(paramnum,x) -#define PARAM_STATEINFO_DEF(x) ++paramnum; PARAM_STATEINFO_DEF_AT(paramnum,x) #define PARAM_POINTER_DEF(x,type) ++paramnum; PARAM_POINTER_DEF_AT(paramnum,x,type) #define PARAM_OBJECT_DEF(x,type) ++paramnum; PARAM_OBJECT_DEF_AT(paramnum,x,type) #define PARAM_CLASS_DEF(x,base) ++paramnum; PARAM_CLASS_DEF_AT(paramnum,x,base) @@ -994,14 +987,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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) typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ @@ -1043,7 +1031,7 @@ struct AFuncDesc //#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) }; \ + VMValue params[3] = { self, self, VMValue(NULL, ATAG_GENERIC) }; \ stack->Call(name##_VMPtr, params, countof(params), NULL, 0, NULL); \ } @@ -1066,8 +1054,8 @@ struct AFuncDesc #define PARAM_ACTION_PROLOGUE(type) \ PARAM_PROLOGUE; \ PARAM_OBJECT (self, type); \ - PARAM_OBJECT_OPT (stateowner, AActor) { stateowner = self; } \ - PARAM_STATEINFO_OPT (stateinfo) { stateinfo = nullptr; } \ + PARAM_OBJECT (stateowner, AActor) \ + PARAM_POINTER (stateinfo, FStateParamInfo) \ // Number of action paramaters #define NAP 3 diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index b8078f0718..e2691470ed 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -188,7 +188,7 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) const VMRegisters calleereg(callee); assert(calleefunc != NULL && !calleefunc->Native); - assert(numparam == calleefunc->NumArgs || ((int)calleefunc->Defaults.Size() == numparam)); + assert(numparam == calleefunc->NumArgs || ((int)calleefunc->Defaults.Size() == calleefunc->NumArgs)); assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3); regd = regf = regs = rega = 0; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 4f859d3b0f..12a8ebb3ba 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -65,6 +65,7 @@ class Actor : Thinker native native bool SetState(state st, bool nofunction = false); native void LinkToWorld(); native void UnlinkFromWorld(); + native void VelFromAngle(float speed = 0, float angle = 0); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); @@ -166,6 +167,12 @@ class Actor : Thinker native LinkToWorld(); } + // killough 11/98: kill an object + void A_Die(name damagetype = "none") + { + DamageMobj(null, null, health, damagetype, DMG_FORCED); + } + // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. native bool A_LineEffect(int boomspecial = 0, int tag = 0); @@ -193,10 +200,6 @@ class Actor : Thinker native native void A_SkelWhoosh(); native void A_SkelFist(); native void A_SkelMissile(); - native void A_FatRaise(); - native void A_FatAttack1(class spawntype = "FatShot"); - native void A_FatAttack2(class spawntype = "FatShot"); - native void A_FatAttack3(class spawntype = "FatShot"); native void A_BossDeath(); native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); @@ -212,7 +215,6 @@ class Actor : Thinker native native void A_SpawnSound(); native void A_SpawnFly(class spawntype = null); // needs special treatment for default native void A_BrainExplode(); - native void A_Die(name damagetype = "none"); native void A_Detonate(); native void 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); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index f492640623..b14634e0d2 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -862,3 +862,17 @@ enum ESightFlags 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, +} diff --git a/wadsrc/static/zscript/doom/fatso.txt b/wadsrc/static/zscript/doom/fatso.txt index 46d013d7f2..c477cbb447 100644 --- a/wadsrc/static/zscript/doom/fatso.txt +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -93,3 +93,75 @@ class FatShot : Actor } +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + const FATSPREAD = 90./8; + + + void A_FatRaise() + { + A_FaceTarget(); + A_PlaySound("fatso/raiseguns", CHAN_WEAPON); + } + + 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(); + } + } + } +} + From 03efb63e93e38efc15869714f761127596ae86de Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 27 Oct 2016 19:14:16 +0200 Subject: [PATCH 122/471] - fixed bad register use in postincrement operator. --- src/scripting/codegeneration/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 5148952a74..3eaaa71702 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1753,7 +1753,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) { build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, assign.RegNum, out.RegNum, build->GetConstantFloat(1.)); } - build->Emit(ValueType->GetStoreOp(), pointer.RegNum, out.RegNum, zero); + build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero); pointer.Free(build); assign.Free(build); return out; From 286f9510d42f9df0a866479a5f5a6b25aea9ab5a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Oct 2016 00:32:52 +0200 Subject: [PATCH 123/471] - got rid of all default parameter redundancies. - scriptified a few more functions. --- src/g_doom/a_archvile.cpp | 18 ++--- src/g_doom/a_bossbrain.cpp | 4 +- src/g_doom/a_doomweaps.cpp | 40 ++++++------ src/g_doom/a_fatso.cpp | 10 +-- src/g_doom/a_keen.cpp | 2 +- src/g_doom/a_lostsoul.cpp | 2 +- src/g_doom/a_painelemental.cpp | 52 ++------------- src/g_doom/a_scriptedmarine.cpp | 10 +-- src/g_heretic/a_hereticmisc.cpp | 4 +- src/g_hexen/a_blastradius.cpp | 12 ++-- src/g_hexen/a_magelightning.cpp | 4 +- src/g_shared/a_bridge.cpp | 2 +- src/g_shared/a_specialspot.cpp | 6 +- src/g_shared/a_weapons.cpp | 4 +- src/g_strife/a_strifeweapons.cpp | 4 +- src/p_actionfunctions.cpp | 50 +------------- src/p_enemy.cpp | 69 ++++++-------------- src/p_mobj.cpp | 9 ++- src/p_pspr.cpp | 36 +++++----- src/p_sight.cpp | 2 +- src/p_user.cpp | 2 +- src/scripting/thingdef_data.cpp | 5 +- src/scripting/vm/vm.h | 18 ----- src/scripting/vm/vmbuilder.cpp | 4 ++ wadsrc/static/zscript/actor.txt | 23 +++++-- wadsrc/static/zscript/doom/painelemental.txt | 42 ++++++++++++ 26 files changed, 183 insertions(+), 251 deletions(-) diff --git a/src/g_doom/a_archvile.cpp b/src/g_doom/a_archvile.cpp index b635646541..959c5763d8 100644 --- a/src/g_doom/a_archvile.cpp +++ b/src/g_doom/a_archvile.cpp @@ -50,7 +50,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrackle) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Fire) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(height) { height = 0; } + PARAM_FLOAT_DEF(height); A_Fire(self, height); return 0; @@ -81,7 +81,7 @@ void A_Fire(AActor *self, double height) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_OPT(fire, AActor) { fire = PClass::FindActor("ArchvileFire"); } + PARAM_CLASS_DEF(fire, AActor); AActor *fog; @@ -112,13 +112,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack) { PARAM_SELF_PROLOGUE(AActor); - 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; } + PARAM_SOUND_DEF (snd) + PARAM_INT_DEF (dmg) + PARAM_INT_DEF (blastdmg) + PARAM_INT_DEF (blastrad) + PARAM_FLOAT_DEF (thrust) + PARAM_NAME_DEF (dmgtype) + PARAM_INT_DEF (flags) AActor *fire, *target; diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 84cd9040c6..1b50cb3cc6 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -112,7 +112,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainDie) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; } + PARAM_CLASS_DEF(spawntype, AActor); DSpotState *state = DSpotState::GetSpotState(); AActor *targ; @@ -298,7 +298,7 @@ static void SpawnFly(AActor *self, PClassActor *spawntype, FSoundID sound) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnFly) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_OPT (spawntype, AActor) { spawntype = NULL; } + PARAM_CLASS_DEF(spawntype, AActor); FSoundID sound; diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index f7511b2be6..37ff05c706 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -116,17 +116,17 @@ enum SAW_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) { PARAM_ACTION_PROLOGUE(AActor); - 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_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; @@ -480,7 +480,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade) { PARAM_ACTION_PROLOGUE(AActor); - PARAM_CLASS_OPT(grenade, AActor) { grenade = PClass::FindActor("Grenade"); } + PARAM_CLASS_DEF(grenade, AActor); player_t *player; @@ -639,14 +639,14 @@ enum BFG_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray) { PARAM_SELF_PROLOGUE(AActor); - 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_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; diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index d373a7a08b..ea2d8f3977 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -30,11 +30,11 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) { PARAM_SELF_PROLOGUE(AActor); - 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; } + PARAM_CLASS_DEF (spawntype, AActor) + PARAM_INT_DEF (n) + PARAM_INT_DEF (flags) + PARAM_FLOAT_DEF (vrange) + PARAM_FLOAT_DEF (hrange) int i, j; diff --git a/src/g_doom/a_keen.cpp b/src/g_doom/a_keen.cpp index 3040e0545f..b22f141b49 100644 --- a/src/g_doom/a_keen.cpp +++ b/src/g_doom/a_keen.cpp @@ -17,7 +17,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(doortag) { doortag = 666; } + PARAM_INT_DEF(doortag); A_Unblock(self, false); diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp index 18b8251e96..1c33f47a7d 100644 --- a/src/g_doom/a_lostsoul.cpp +++ b/src/g_doom/a_lostsoul.cpp @@ -37,7 +37,7 @@ void A_SkullAttack(AActor *self, double speed) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(speed) { speed = SKULLSPEED; } + PARAM_FLOAT_DEF(speed); if (speed <= 0) speed = SKULLSPEED; diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 30136f9f75..09160ddeb6 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -141,54 +141,14 @@ void A_PainShootSkull (AActor *self, DAngle Angle, PClassActor *spawntype, int f } -// -// A_PainAttack -// Spawn a lost soul and launch it at the target -// -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack) +DEFINE_ACTION_FUNCTION(AActor, A_PainShootSkull) { PARAM_SELF_PROLOGUE(AActor); - - 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); + PARAM_CLASS(spawntype, AActor); + PARAM_FLOAT(angle); + PARAM_INT_DEF(flags); + PARAM_INT_DEF(limit); + A_PainShootSkull(self, angle, spawntype, flags, limit); return 0; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - 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_SELF_PROLOGUE(AActor); - 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; - } - 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); - return 0; -} diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 61c7c8ac4c..4bf8283425 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -151,7 +151,7 @@ void AScriptedMarine::Tick () DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Refire) { PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL_OPT(ignoremissile) { ignoremissile = false; } + PARAM_BOOL_DEF(ignoremissile); if (self->target == NULL || self->target->health <= 0) { @@ -250,10 +250,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_MarineLook) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw) { PARAM_SELF_PROLOGUE(AActor); - 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_SOUND_DEF (fullsound) + PARAM_SOUND_DEF (hitsound) + PARAM_INT_DEF (damage) + PARAM_CLASS_DEF (pufftype, AActor) if (self->target == NULL) return 0; diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 02c1393ddf..2d4f3497ce 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -48,7 +48,7 @@ static FRandom pr_volcimpact ("VolcBallImpact"); DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_OPT (gootype, AActor) { gootype = PClass::FindActor("PodGoo"); } + PARAM_CLASS_DEF (gootype, AActor) int count; int chance; @@ -103,7 +103,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RemovePod) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MakePod) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_OPT(podtype, AActor) { podtype = PClass::FindActor("Pod"); } + PARAM_CLASS_DEF(podtype, AActor) AActor *mo; diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp index 0b0ab5d10e..f8bc60a7f6 100644 --- a/src/g_hexen/a_blastradius.cpp +++ b/src/g_hexen/a_blastradius.cpp @@ -96,12 +96,12 @@ enum DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast) { PARAM_ACTION_PROLOGUE(AActor); - 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_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_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index e4390131a0..192fd03e01 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -258,8 +258,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningZap) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MLightningAttack) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_OPT(floor, AActor) { floor = PClass::FindActor("LightningFloor"); } - PARAM_CLASS_OPT(ceiling, AActor) { ceiling = PClass::FindActor("LightningCeiling"); } + PARAM_CLASS_DEF(floor, AActor); + PARAM_CLASS_DEF(ceiling, AActor); AActor *fmo, *cmo; diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index f3b12a1d16..3cd7ee1725 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -122,7 +122,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BridgeInit) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_OPT(balltype, AActor) { balltype = NULL; } + PARAM_CLASS_DEF(balltype, AActor); AActor *ball; diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 1af9f6db7f..c47116f794 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -382,9 +382,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnSingleItem) { 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_weapons.cpp b/src/g_shared/a_weapons.cpp index d7f432a7a2..774d8d5e51 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -1923,8 +1923,8 @@ PClassWeapon *Net_ReadWeapon(BYTE **stream) DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_ZoomFactor) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT (zoom) { zoom = 1; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_FLOAT_DEF(zoom); + PARAM_INT_DEF(flags); if (self->player != NULL && self->player->ReadyWeapon != NULL) { diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index f80f3e863b..41ceff087a 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -147,8 +147,8 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_AlertMonsters) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(maxdist) { maxdist = 0; } - PARAM_INT_OPT(Flags) { Flags = 0; } + PARAM_FLOAT_DEF(maxdist); + PARAM_INT_DEF(Flags); AActor * target = NULL; AActor * emitter = self; diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index fd67e0a645..0e96205641 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1148,7 +1148,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(maxchance) { maxchance = 256; } + PARAM_INT_DEF(maxchance); paramnum++; // Increment paramnum to point at the first jump target int count = numparam - paramnum; @@ -2685,7 +2685,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) @@ -7015,52 +7015,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_SELF_PROLOGUE(AActor); - PARAM_FLOAT_DEF(angle); - PARAM_INT_DEF(ptr); - - 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_SELF_PROLOGUE(AActor); - 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) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 3f55706817..77082f3a43 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1922,12 +1922,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) { PARAM_SELF_PROLOGUE(AActor); - 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_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; @@ -2139,7 +2139,7 @@ enum ChaseFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Wander) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_INT_DEF(flags); A_Wander(self, flags); return 0; } @@ -2781,9 +2781,9 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE_OPT (melee) { melee = NULL; } - PARAM_STATE_OPT (missile) { missile = NULL; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_STATE_DEF (melee) + PARAM_STATE_DEF (missile) + PARAM_INT_DEF (flags) if (numparam > 1) { @@ -2822,8 +2822,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, @@ -2957,45 +2957,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_SELF_PROLOGUE(AActor); - 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_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_SELF_PROLOGUE(AActor); - 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_SELF_PROLOGUE(AActor); - 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; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7d37e35461..754ec516a8 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -514,7 +514,7 @@ DEFINE_ACTION_FUNCTION(AActor, SetState) { PARAM_SELF_PROLOGUE(AActor); PARAM_STATE(state); - PARAM_BOOL_OPT(nofunction) { nofunction = false; } + PARAM_BOOL_DEF(nofunction); ACTION_RETURN_BOOL(self->SetState(state, nofunction)); }; @@ -6257,6 +6257,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 diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 055649466d..e8be2e865d 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -744,7 +744,7 @@ void DoReadyWeapon(AActor *self) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_INT_DEF(flags); DoReadyWeaponToSwitch(self, !(flags & WRF_NoSwitch)); if ((flags & WRF_NoFire) != WRF_NoFire) DoReadyWeaponToFire(self, !(flags & WRF_NoPrimary), !(flags & WRF_NoSecondary)); @@ -876,7 +876,7 @@ static void P_CheckWeaponButtons (player_t *player) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_ReFire) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE_OPT(state) { state = NULL; } + PARAM_STATE_DEF(state); A_ReFire(self, state); return 0; } @@ -1003,10 +1003,10 @@ void A_OverlayOffset(AActor *self, int layer, double wx, double wy, int flags) DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset) { PARAM_ACTION_PROLOGUE(AActor); - 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_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; } @@ -1014,9 +1014,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset) DEFINE_ACTION_FUNCTION(AActor, A_WeaponOffset) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_OPT(wx) { wx = 0.; } - PARAM_FLOAT_OPT(wy) { wy = 32.; } - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_FLOAT_DEF(wx) + PARAM_FLOAT_DEF(wy) + PARAM_INT_DEF(flags) A_OverlayOffset(self, PSP_WEAPON, wx, wy, flags); return 0; } @@ -1073,7 +1073,7 @@ static double GetOverlayPosition(AActor *self, int layer, bool gety) DEFINE_ACTION_FUNCTION(AActor, OverlayX) { PARAM_ACTION_PROLOGUE(AActor); - PARAM_INT_OPT(layer) { layer = 0; } + PARAM_INT_DEF(layer); if (ACTION_CALL_FROM_PSPRITE()) { @@ -1086,7 +1086,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayX) DEFINE_ACTION_FUNCTION(AActor, OverlayY) { PARAM_ACTION_PROLOGUE(AActor); - PARAM_INT_OPT(layer) { layer = 0; } + PARAM_INT_DEF(layer); if (ACTION_CALL_FROM_PSPRITE()) { @@ -1214,8 +1214,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Overlay) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT (layer); - PARAM_STATE_OPT (state) { state = nullptr; } - PARAM_BOOL_OPT (dontoverride) { dontoverride = false; } + PARAM_STATE_DEF(state); + PARAM_BOOL_DEF(dontoverride); player_t *player = self->player; @@ -1233,9 +1233,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Overlay) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ClearOverlays) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_OPT(start) { start = 0; } - PARAM_INT_OPT(stop) { stop = 0; } - PARAM_BOOL_OPT(safety) { safety = true; } + PARAM_INT_DEF(start); + PARAM_INT_DEF(stop); + PARAM_BOOL_DEF(safety) if (self->player == nullptr) ACTION_RETURN_INT(0); @@ -1284,8 +1284,8 @@ enum GF_Flags DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE_OPT(flash) { flash = nullptr; } - PARAM_INT_OPT (flags) { flags = 0; } + PARAM_STATE_DEF(flash); + PARAM_INT_DEF(flags); player_t *player = self->player; diff --git a/src/p_sight.cpp b/src/p_sight.cpp index fefe9eb27b..319d5b3ecc 100644 --- a/src/p_sight.cpp +++ b/src/p_sight.cpp @@ -909,7 +909,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckSight) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(target, AActor); - PARAM_INT_OPT(flags) { flags = 0; } + PARAM_INT_DEF(flags); ACTION_RETURN_BOOL(P_CheckSight(self, target, flags)); } diff --git a/src/p_user.cpp b/src/p_user.cpp index 70c864c2aa..4092c85c25 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1626,7 +1626,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_OPT(spawntype, APlayerChunk) { spawntype = NULL; } + PARAM_CLASS_DEF(spawntype, APlayerChunk); APlayerPawn *mo; player_t *player; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 55cc03c0c8..f071614a84 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -447,12 +447,11 @@ static FFlagDef *FindFlag (FFlagDef *flags, int numflags, const char *flag) FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bool strict) { FFlagDef *def; - size_t i; if (part2 == NULL) { // Search all lists int max = strict ? 2 : NUM_FLAG_LISTS; - for (i = 0; i < max; ++i) + for (int i = 0; i < max; ++i) { if (type->IsDescendantOf (*FlagLists[i].Type)) { @@ -466,7 +465,7 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bo } 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) { diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 3d0dc166d6..5684d57754 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -945,15 +945,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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; } -#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_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_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].atag == ATAG_GENERIC || param[p].a == NULL)); x = (FState *)param[p].a; } 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 - // The above, but with an automatically increasing position index. #define PARAM_PROLOGUE int paramnum = -1; @@ -983,15 +974,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_OBJECT_DEF(x,type) ++paramnum; PARAM_OBJECT_DEF_AT(paramnum,x,type) #define PARAM_CLASS_DEF(x,base) ++paramnum; PARAM_CLASS_DEF_AT(paramnum,x,base) -#define PARAM_INT_OPT(x) ++paramnum; PARAM_INT_OPT_AT(paramnum,x) -#define PARAM_BOOL_OPT(x) ++paramnum; PARAM_BOOL_OPT_AT(paramnum,x) -#define PARAM_NAME_OPT(x) ++paramnum; PARAM_NAME_OPT_AT(paramnum,x) -#define PARAM_SOUND_OPT(x) ++paramnum; PARAM_SOUND_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_STATE_OPT(x) ++paramnum; PARAM_STATE_OPT_AT(paramnum,x) -#define PARAM_CLASS_OPT(x,base) ++paramnum; PARAM_CLASS_OPT_AT(paramnum,x,base) - typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ struct AFuncDesc diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 7f8a643c68..dd07d01008 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -728,6 +728,10 @@ void FFunctionBuildList::Build() sfunc->PrintableName = item.PrintableName; } delete item.Code; + if (dump != nullptr) + { + fflush(dump); + } } if (dump != nullptr) { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 12a8ebb3ba..3630365074 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -66,6 +66,7 @@ class Actor : Thinker native native void LinkToWorld(); native void UnlinkFromWorld(); native void VelFromAngle(float speed = 0, float angle = 0); + native bool isFriend(Actor other); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); @@ -173,6 +174,22 @@ class Actor : Thinker native 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); @@ -185,9 +202,6 @@ class Actor : Thinker native native void A_XScream(); native void A_Look(); native void A_Chase(state melee = null, state missile = null, int flags = 0); - native void A_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); - native void A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); - native void A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); native void A_Scream(); native void A_VileChase(); native void A_VileStart(); @@ -203,9 +217,6 @@ class Actor : Thinker native native void A_BossDeath(); native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); - native void A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); - native void A_DualPainAttack(class spawntype = "LostSoul"); - native void A_PainDie(class spawntype = "LostSoul"); native void A_KeenDie(int doortag = 666); native void A_BrainPain(); native void A_BrainScream(); diff --git a/wadsrc/static/zscript/doom/painelemental.txt b/wadsrc/static/zscript/doom/painelemental.txt index ce30bbfd30..fde690b394 100644 --- a/wadsrc/static/zscript/doom/painelemental.txt +++ b/wadsrc/static/zscript/doom/painelemental.txt @@ -51,3 +51,45 @@ class PainElemental : Actor 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); + } +} From 3fa315aaeac2217cda39b166d16edebcc0498398 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Oct 2016 01:14:21 +0200 Subject: [PATCH 124/471] - replaced 'vector<2>' and 'vector<3>' with 'vector2' and 'vector3'. - added initializer syntax for vectors. A vector can be set with vectorvar = (x,y,z); for a 3-dimensional vector and vectorvar = (x, y); for a 2-dimensional one. --- src/dobjtype.cpp | 2 ++ src/namedef.h | 1 + src/sc_man_scanner.re | 3 +- src/sc_man_tokens.h | 3 +- src/scripting/zscript/zcc-parse.lemon | 48 +++++++++++++++------------ src/scripting/zscript/zcc_exprlist.h | 1 + src/scripting/zscript/zcc_parser.cpp | 3 +- src/scripting/zscript/zcc_parser.h | 6 ++++ 8 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 3f5b734c48..603cb85d7c 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -628,6 +628,8 @@ void PType::StaticInit() 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); diff --git a/src/namedef.h b/src/namedef.h index 3587643e8a..ea4a7b890e 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -313,6 +313,7 @@ xx(WaterLevel) xx(X) xx(Y) xx(Z) +xx(XY) xx(MomX) xx(MomY) xx(MomZ) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 8fbb28ef55..bc0a4b2e24 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -124,7 +124,8 @@ std2: '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); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 7d9f81e9b9..2b93c9ac2a 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -113,7 +113,8 @@ 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/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 0cf061bef0..3f70799ec6 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -656,7 +656,8 @@ 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; } @@ -686,30 +687,10 @@ type_name(X) ::= DOT dottable_id(A). 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. /* Aggregate types */ %type aggregate_type {ZCC_Type *} @@ -986,6 +967,29 @@ primary(X) ::= SUPER(T). } primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ } +primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. +{ + NEW_AST_NODE(VectorInitializer, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector3; + expr->X = A; + expr->Y = B; + expr->Z = C; + XX = expr; +} + + +primary(X) ::= LPAREN expr(A) COMMA expr(B) RPAREN. +{ + NEW_AST_NODE(VectorInitializer, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector2; + expr->X = A; + expr->Y = B; + expr->Z = nullptr; + X = expr; +} + primary(X) ::= LPAREN expr(A) RPAREN. { X = A; /*X-overwrites-A*/ diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index bbf99189c3..b565c00fb2 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -9,6 +9,7 @@ xx(FuncCall, '(') xx(ArrayAccess, TK_Array) xx(MemberAccess, '.') xx(TypeRef, TK_Class) +xx(Vector, TK_Vector2) xx(PostInc, TK_Incr) xx(PostDec, TK_Decr) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 8ebc861678..ef4a2ac419 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -141,7 +141,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); diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 7ba48d711c..dafdb93e53 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -98,6 +98,7 @@ enum EZCCTreeNodeType AST_Default, AST_FlagStmt, AST_PropertyStmt, + AST_VectorInitializer, NUM_AST_NODE_TYPES }; @@ -385,6 +386,11 @@ struct ZCC_ExprTrinary : ZCC_Expression ZCC_Expression *Right; }; +struct ZCC_VectorInitializer : ZCC_Expression +{ + ZCC_Expression *X, *Y, *Z; +}; + struct ZCC_Statement : ZCC_TreeNode { }; From 35cd48b86b5cf2dcaec06215f7b0330b11ff2ba0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Oct 2016 09:47:22 +0200 Subject: [PATCH 125/471] - fixed grammar rule for two-dimensional vectors. --- src/scripting/zscript/zcc-parse.lemon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 3f70799ec6..bbed008dd3 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -979,7 +979,7 @@ primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. } -primary(X) ::= LPAREN expr(A) COMMA expr(B) RPAREN. +primary(XX) ::= LPAREN expr(A) COMMA expr(B) RPAREN. { NEW_AST_NODE(VectorInitializer, expr, A); expr->Operation = PEX_Vector; @@ -987,7 +987,7 @@ primary(X) ::= LPAREN expr(A) COMMA expr(B) RPAREN. expr->X = A; expr->Y = B; expr->Z = nullptr; - X = expr; + XX = expr; } primary(X) ::= LPAREN expr(A) RPAREN. From 3b1f411dce70fd3d11e9021840a791b3b57f947f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Oct 2016 10:13:07 +0200 Subject: [PATCH 126/471] - added a full set of 2D vector instructions to the VM. The existing one was 3D only but there's also need to handle two-dimensional vectors. - added the missing divv* instructions. --- src/scripting/vm/vmexec.h | 231 +++++++++++++++++++++++++++++++++----- src/scripting/vm/vmops.h | 66 +++++++---- 2 files changed, 250 insertions(+), 47 deletions(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 4fbe29257d..e3401eb380 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -196,7 +196,25 @@ 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); + { + 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); { @@ -206,7 +224,7 @@ begin: 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); { @@ -292,7 +310,25 @@ 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); + { + auto v = (double *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + } + NEXTOP; + OP(SV2_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]; + } + NEXTOP; + OP(SV3): ASSERTA(a); ASSERTF(B+2); ASSERTKD(C); GETADDR(PA,KC,X_WRITE_NIL); { @@ -302,7 +338,7 @@ begin: v[2] = reg.f[B+2]; } NEXTOP; - OP(SV_R): + OP(SV3_R): ASSERTA(a); ASSERTF(B+2); ASSERTD(C); GETADDR(PA,RC,X_WRITE_NIL); { @@ -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) { @@ -1246,51 +1293,159 @@ 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(MULVF2_KR): + ASSERTF(a+1); ASSERTKF(B+1); ASSERTF(C); + fc = reg.f[C]; + fbp = &konstf[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(DIVVF2_KR): + ASSERTF(a+1); ASSERTKF(B+1); ASSERTF(C); + fc = reg.f[C]; + fbp = &konstf[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; @@ -1319,35 +1474,55 @@ 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): + goto Do_MULV3; + OP(MULVF3_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(DIVVF3_KR): + ASSERTF(a+2); ASSERTKF(B+2); ASSERTF(C); + fc = reg.f[C]; + fbp = &konstf[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 && @@ -1359,10 +1534,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); diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 9ffe2d847d..ba86e2231b 100644 --- a/src/scripting/vm/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,6 +67,8 @@ 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), @@ -193,24 +199,46 @@ 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, RVRVRV), // vA = vkB * fkC +xx(MULVF2_RK, mulv2, RVRVKV), +xx(MULVF2_KR, mulv2, RVKVRV), +xx(DIVVF2_RR, divv2, RVRVRV), // vA = vkB / fkC +xx(DIVVF2_RK, divv2, RVRVKV), +xx(DIVVF2_KR, divv2, RVKVRV), +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, RVRVRV), // vA = vkB * fkC +xx(MULVF3_RK, mulv3, RVRVKV), +xx(MULVF3_KR, mulv3, RVKVRV), +xx(DIVVF3_RR, divv3, RVRVRV), // vA = vkB / fkC +xx(DIVVF3_RK, divv3, RVRVKV), +xx(DIVVF3_KR, divv3, RVKVRV), +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 From f511a9398ec07039ceaa27aa847740f73bf3ec57 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Oct 2016 10:44:01 +0200 Subject: [PATCH 127/471] - changed GetStore/LoadMoveOp and GetRegType to be based on a set of member variables instead of using virtual functions to return such trivial values. This not only creates significantly better code but also allows overriding these settings without having to create a new class just for changing them (as is needed for vectors.) --- src/dobjtype.cpp | 307 +++++--------------------- src/dobjtype.h | 46 ++-- src/scripting/zscript/zcc_compile.cpp | 2 +- 3 files changed, 75 insertions(+), 280 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 603cb85d7c..bec28c7ec3 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -191,18 +191,6 @@ IMPLEMENT_ABSTRACT_POINTY_CLASS(PType) DECLARE_POINTER(HashNext) END_POINTERS -//========================================================================== -// -// PType Default Constructor -// -//========================================================================== - -PType::PType() -: Size(0), Align(1), HashNext(NULL) -{ - mDescriptiveName = "Type"; -} - //========================================================================== // // PType Parameterized Constructor @@ -213,6 +201,10 @@ 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; } //========================================================================== @@ -477,54 +469,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 :: GetMoveOp -// -//========================================================================== - -int PType::GetMoveOp() const -{ - assert(0 && "Cannot move this type"); - return OP_NOP; -} - -//========================================================================== -// -// PType :: GetRegType -// -//========================================================================== - -int PType::GetRegType() const -{ - //assert(0 && "No register for this type"); // wrong place for this assert, it makes it impossible to use this function to check for bad types. - return REGT_NIL; -} - //========================================================================== // // PType :: IsMatch @@ -747,6 +691,7 @@ PInt::PInt() mDescriptiveName = "SInt32"; Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, -0x7FFFFFFF - 1)); Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, 0x7FFFFFFF)); + SetOps; } //========================================================================== @@ -773,6 +718,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; + } } //========================================================================== @@ -942,76 +914,6 @@ 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 :: GetLoadOp -// -//========================================================================== - -int PInt::GetMoveOp() const -{ - return OP_MOVE; -} - -//========================================================================== -// -// PInt :: GetRegType -// -//========================================================================== - -int PInt::GetRegType() const -{ - return REGT_INT; -} - /* PBool ******************************************************************/ IMPLEMENT_CLASS(PBool) @@ -1048,6 +950,7 @@ PFloat::PFloat() { mDescriptiveName = "Float"; SetDoubleSymbols(); + SetOps(); } //========================================================================== @@ -1070,6 +973,7 @@ PFloat::PFloat(unsigned int size) MemberOnly = true; SetSingleSymbols(); } + SetOps(); } //========================================================================== @@ -1264,60 +1168,21 @@ 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 :: GetMoveOp -// -//========================================================================== - -int PFloat::GetMoveOp() const -{ - return OP_MOVEF; -} - -//========================================================================== -// -// PFloat :: GetRegType -// -//========================================================================== - -int PFloat::GetRegType() const -{ - return REGT_FLOAT; + moveOp = OP_MOVEF; + RegType = REGT_FLOAT; } /* PString ****************************************************************/ @@ -1554,50 +1419,10 @@ PStatePointer::PStatePointer() : PBasicType(sizeof(FState *), __alignof(FState *)) { mDescriptiveName = "State"; -} - -//========================================================================== -// -// PStatePointer :: GetStoreOp -// -//========================================================================== - -int PStatePointer::GetStoreOp() const -{ - return OP_SP; -} - -//========================================================================== -// -// PStatePointer :: GetLoadOp -// -//========================================================================== - -int PStatePointer::GetLoadOp() const -{ - return OP_LP; -} - -//========================================================================== -// -// PStatePointer :: GetMoveOp -// -//========================================================================== - -int PStatePointer::GetMoveOp() const -{ - return OP_MOVEA; -} - -//========================================================================== -// -// PStatePointer :: GetRegType -// -//========================================================================== - -int PStatePointer::GetRegType() const -{ - return REGT_POINTER; + storeOp = OP_SP; + loadOp = OP_LP; + moveOp = OP_MOVEA; + RegType = REGT_POINTER; } //========================================================================== @@ -1640,6 +1465,7 @@ PPointer::PPointer() : PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL) { mDescriptiveName = "NullPointer"; + SetOps(); } //========================================================================== @@ -1652,6 +1478,7 @@ PPointer::PPointer(PType *pointsat) : PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat) { mDescriptiveName.Format("Pointer<%s>", pointsat->DescriptiveName()); + SetOps(); } //========================================================================== @@ -1660,42 +1487,12 @@ PPointer::PPointer(PType *pointsat) // //========================================================================== -int PPointer::GetStoreOp() const +void PPointer::SetOps() { - return OP_SP; -} - -//========================================================================== -// -// PPointer :: GetLoadOp -// -//========================================================================== - -int PPointer::GetLoadOp() const -{ - return (PointedType && PointedType->IsKindOf(RUNTIME_CLASS(PClass))) ? OP_LO : OP_LP; -} - -//========================================================================== -// -// PPointer :: GetMoveOp -// -//========================================================================== - -int PPointer::GetMoveOp() const -{ - return OP_MOVEA; -} - -//========================================================================== -// -// 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; } //========================================================================== diff --git a/src/dobjtype.h b/src/dobjtype.h index 0c26f3a358..984f5a379e 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -204,6 +204,7 @@ class PType : public PTypeBase HAS_OBJECT_POINTERS; protected: enum { MetaClassNum = CLASSREG_PClassType }; + public: typedef PClassType MetaClass; MetaClass *GetClass() const; @@ -223,9 +224,9 @@ public: 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; - PType(); - PType(unsigned int size, unsigned int align); + PType(unsigned int size = 1, unsigned int align = 1); virtual ~PType(); bool AddConversion(PType *target, void (*convertconst)(ZCC_ExprConstant *, class FSharedStringArena &)); @@ -267,16 +268,28 @@ 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 - virtual int GetMoveOp() const; + int GetMoveOp() const + { + return moveOp; + } // Gets the register type for this type - virtual int GetRegType() const; + int GetRegType() const + { + return RegType; + } // Returns true if this type matches the two identifiers. Referring to the // above table, any type is identified by at most two characteristics. Each @@ -410,14 +423,11 @@ 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 GetMoveOp() const; - virtual int GetRegType() const; bool Unsigned; protected: PInt(); + void SetOps(); }; class PBool : public PInt @@ -440,12 +450,9 @@ 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 GetMoveOp() const; - virtual int GetRegType() const; protected: PFloat(); + void SetOps(); private: struct SymbolInitF { @@ -518,11 +525,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 GetMoveOp() const; - virtual int GetRegType() const; }; class PPointer : public PBasicType @@ -535,11 +537,6 @@ public: PType *PointedType; - virtual int GetStoreOp() const; - virtual int GetLoadOp() const; - virtual int GetMoveOp() const; - virtual int GetRegType() const; - virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; @@ -547,6 +544,7 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; protected: + void SetOps(); }; class PClassPointer : public PPointer diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 370e659193..dc638de0f3 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1461,7 +1461,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n } if (retval != TypeError && retval->MemberOnly && !formember) { - Error(field, "Invalid type %s", retval->DescriptiveName()); // fixme: Types need a descriptive name that can be output here. + Error(field, "Invalid type %s", retval->DescriptiveName()); return TypeError; } return retval; From ed5a94d18733f5f70230d537dede7e04364b70c7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Oct 2016 13:30:19 +0200 Subject: [PATCH 128/471] - fixed GetOps() call and added info for vectors. --- src/dobjtype.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index bec28c7ec3..fd454896ed 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -567,6 +567,10 @@ void PType::StaticInit() 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|REGT_MULTIREG; TypeVector3 = new PStruct(NAME_Vector3, nullptr); TypeVector3->AddField(NAME_X, TypeFloat64); @@ -575,6 +579,10 @@ void PType::StaticInit() // 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); + TypeVector2->loadOp = OP_LV3; + TypeVector2->storeOp = OP_SV3; + TypeVector2->moveOp = OP_MOVEV3; + TypeVector2->RegType = REGT_FLOAT | REGT_MULTIREG; @@ -691,7 +699,7 @@ PInt::PInt() mDescriptiveName = "SInt32"; Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, -0x7FFFFFFF - 1)); Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, 0x7FFFFFFF)); - SetOps; + SetOps(); } //========================================================================== From f2f365bfef4bc8ecfc1ee306a994af8766d03f60 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Oct 2016 14:43:29 +0200 Subject: [PATCH 129/471] - fixed setup for PString which was missing the load/store/move instructions which caused me to overlook its register type. - properly set up the vector types. - fixed: a struct must start with a size of 0, not 1. This caused the layout of the vectors to be broken. --- src/dobjtype.cpp | 29 ++++++++++++++--------------- src/dobjtype.h | 8 +++++--- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index fd454896ed..7eb152ebdf 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -205,6 +205,7 @@ PType::PType(unsigned int size, unsigned int align) storeOp = OP_NOP; moveOp = OP_NOP; RegType = REGT_NIL; + RegCount = 1; } //========================================================================== @@ -570,7 +571,8 @@ void PType::StaticInit() TypeVector2->loadOp = OP_LV2; TypeVector2->storeOp = OP_SV2; TypeVector2->moveOp = OP_MOVEV2; - TypeVector2->RegType = REGT_FLOAT|REGT_MULTIREG; + TypeVector2->RegType = REGT_FLOAT; + TypeVector2->RegCount = 2; TypeVector3 = new PStruct(NAME_Vector3, nullptr); TypeVector3->AddField(NAME_X, TypeFloat64); @@ -579,10 +581,11 @@ void PType::StaticInit() // 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); - TypeVector2->loadOp = OP_LV3; - TypeVector2->storeOp = OP_SV3; - TypeVector2->moveOp = OP_MOVEV3; - TypeVector2->RegType = REGT_FLOAT | REGT_MULTIREG; + TypeVector3->loadOp = OP_LV3; + TypeVector3->storeOp = OP_SV3; + TypeVector3->moveOp = OP_MOVEV3; + TypeVector3->RegType = REGT_FLOAT; + TypeVector3->RegCount = 3; @@ -1207,17 +1210,11 @@ 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; } //========================================================================== @@ -2089,6 +2086,7 @@ IMPLEMENT_CLASS(PStruct) PStruct::PStruct() { mDescriptiveName = "Struct"; + Size = 0; } //========================================================================== @@ -2101,6 +2099,7 @@ PStruct::PStruct(FName name, PTypeBase *outer) : PNamedType(name, outer) { mDescriptiveName.Format("Struct<%s>", name.GetChars()); + Size = 0; } //========================================================================== diff --git a/src/dobjtype.h b/src/dobjtype.h index 984f5a379e..302352b21b 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -224,7 +224,7 @@ public: 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; + BYTE loadOp, storeOp, moveOp, RegType, RegCount; PType(unsigned int size = 1, unsigned int align = 1); virtual ~PType(); @@ -291,6 +291,10 @@ public: 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. @@ -477,8 +481,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; From 9400f97189543987bec49fccdf2ceed1069bab6c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 Oct 2016 15:15:30 +0200 Subject: [PATCH 130/471] - implemented local vector variables. Currently only the definition plus initial assignment works. - removed all vector4 handling that had already been added, now that this type can no longer be defined. --- src/scripting/codegeneration/codegen.cpp | 208 ++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 29 +++- src/scripting/vm/vm.h | 2 +- src/scripting/zscript/ast.cpp | 14 +- src/scripting/zscript/zcc-parse.lemon | 49 +++--- src/scripting/zscript/zcc_compile.cpp | 14 +- src/scripting/zscript/zcc_parser.cpp | 5 +- src/scripting/zscript/zcc_parser.h | 1 - 8 files changed, 278 insertions(+), 44 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 3eaaa71702..773fc4b1a4 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -178,8 +178,8 @@ FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name) // //========================================================================== -ExpEmit::ExpEmit(VMFunctionBuilder *build, int type) -: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false), Final(false), Target(false) +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) { } @@ -187,7 +187,7 @@ void ExpEmit::Free(VMFunctionBuilder *build) { if (!Fixed && !Konst && RegType <= REGT_TYPE) { - build->Registers[RegType].Return(RegNum, 1); + build->Registers[RegType].Return(RegNum, RegCount); } } @@ -195,6 +195,7 @@ 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"); } @@ -434,6 +435,200 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build) // //========================================================================== +FxVectorInitializer::FxVectorInitializer(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc) + :FxExpression(EFX_VectorInitializer, sc) +{ + xyz[0] = x; + xyz[1] = y; + xyz[2] = z; + isConst = false; + ValueType = TypeVoid; // we do not know yet +} + +FxVectorInitializer::~FxVectorInitializer() +{ + for (auto &a : xyz) + SAFE_DELETE(a); +} + +FxExpression *FxVectorInitializer::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_VectorInitializer) + { + // 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]; + 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 FxVectorInitializer::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 xval = EmitKonst(build, xyz[0]->Emit(build)); + ExpEmit yval = EmitKonst(build, xyz[1]->Emit(build)); + 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 zval = EmitKonst(build, xyz[1]->Emit(build)); + 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 xval = EmitKonst(build, xyz[0]->Emit(build)); + ExpEmit yval = EmitKonst(build, xyz[1]->Emit(build)); + ExpEmit zval = EmitKonst(build, xyz[2]->Emit(build)); + 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) { @@ -4613,7 +4808,7 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) } int offsetreg = build->GetConstantInt((int)membervar->Offset); - ExpEmit loc(build, membervar->Type->GetRegType()); + ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); if (membervar->BitValue == -1) { @@ -7118,6 +7313,7 @@ FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, ValueType = type; VarFlags = varflags; Name = name; + RegCount = type == TypeVector2 ? 2 : type == TypeVector3 ? 3 : 1; Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false); } @@ -7139,7 +7335,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) { if (Init == nullptr) { - RegNum = build->Registers[ValueType->GetRegType()].Get(1); + RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); } else { @@ -7188,5 +7384,5 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) { // Release the register after the containing block gets closed assert(RegNum != -1); - build->Registers[ValueType->GetRegType()].Return(RegNum, 1); + build->Registers[ValueType->GetRegType()].Return(RegNum, RegCount); } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index cd93b8894b..30401f9077 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -193,13 +193,13 @@ struct ExpVal struct ExpEmit { - ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false), Final(false), Target(false) {} - ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), Konst(konst), Fixed(fixed), Final(false), Target(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, Target:1; + BYTE RegNum, RegType, RegCount, Konst:1, Fixed:1, Final:1, Target:1; }; enum EFxType @@ -264,6 +264,7 @@ enum EFxType EFX_LocalVariableDeclaration, EFX_SwitchStatement, EFX_CaseStatement, + EFX_VectorInitializer, EFX_COUNT }; @@ -449,6 +450,25 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxVectorInitializer : public FxExpression +{ + FxExpression *xyz[3]; + bool isConst; // gets set to true if all element are const + +public: + FxVectorInitializer(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc); + ~FxVectorInitializer(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // @@ -1561,6 +1581,7 @@ class FxLocalVariableDeclaration : public FxExpression FName Name; FxExpression *Init; int VarFlags; + int RegCount; public: int RegNum = -1; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 5684d57754..c14a8a6e5b 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -137,7 +137,7 @@ enum REGT_MULTIREG = 8, // (e.g. a vector) 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 diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index e23fc5a879..e77c631e18 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -52,7 +52,6 @@ static const char *BuiltInTypeNames[] = "string", "vector2", "vector3", - "vector4", "name", "color", "state", @@ -622,6 +621,16 @@ static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node) out.Close(); } +static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node) +{ + ZCC_VectorInitializer *enode = (ZCC_VectorInitializer *)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; @@ -889,7 +898,8 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintFuncDeclarator, PrintDefault, PrintFlagStmt, - PrintPropertyStmt + PrintPropertyStmt, + PrintVectorInitializer, }; FString ZCC_PrintAST(ZCC_TreeNode *root) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index bbed008dd3..173ec27fc0 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -945,6 +945,7 @@ func_param_flags(X) ::= func_param_flags(A) OPTIONAL(T). { X.Int = A.Int | ZCC_O %type expr{ZCC_Expression *} %type primary{ZCC_Expression *} +%type vectorinit{ZCC_VectorInitializer*} %type unary_expr{ZCC_Expression *} %type constant{ZCC_ExprConstant *} @@ -966,29 +967,7 @@ primary(X) ::= SUPER(T). X = expr; } primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ } - -primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. -{ - NEW_AST_NODE(VectorInitializer, 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. -{ - NEW_AST_NODE(VectorInitializer, expr, A); - expr->Operation = PEX_Vector; - expr->Type = TypeVector2; - expr->X = A; - expr->Y = B; - expr->Z = nullptr; - XX = expr; -} +primary(X) ::= vectorinit(A). { X = A; /*X-overwrites-A*/ } primary(X) ::= LPAREN expr(A) RPAREN. { @@ -1039,6 +1018,30 @@ primary(X) ::= SCOPE primary(B). X = expr2; } */ + +vectorinit(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. [DOT] +{ + NEW_AST_NODE(VectorInitializer, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector3; + expr->X = A; + expr->Y = B; + expr->Z = C; + XX = expr; +} + + +vectorinit(XX) ::= LPAREN expr(A) COMMA expr(B) RPAREN. [DOT] +{ + NEW_AST_NODE(VectorInitializer, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector2; + expr->X = A; + expr->Y = B; + expr->Z = nullptr; + XX = expr; +} + /*----- Unary Expressions -----*/ unary_expr(X) ::= primary(X). diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index dc638de0f3..f1a06d5847 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1387,11 +1387,6 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n retval = TypeVector3; break; - case ZCC_Vector4: - // This has almost no use, so we really shouldn't bother. - Error(field, "vector<4> not implemented for %s", name.GetChars()); - return TypeError; - case ZCC_State: retval = TypeState; break; @@ -2710,6 +2705,15 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) return new FxConditional(condition, left, right); } + case AST_VectorInitializer: + { + auto vecini = static_cast(ast); + auto xx = ConvertNode(vecini->X); + auto yy = ConvertNode(vecini->Y); + auto zz = ConvertNode(vecini->Z); + return new FxVectorInitializer(xx, yy, zz, *ast); + } + case AST_LocalVarStmt: { auto loc = static_cast(ast); diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index ef4a2ac419..84bebff402 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -301,7 +301,8 @@ static void DoParse(int lumpnum) parser = ZCCParseAlloc(malloc); ZCCParseState state; -#if 0 // this costs a lot of time and should only be activated when it's really needed. +//#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); @@ -335,7 +336,7 @@ static void DoParse(int lumpnum) I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); } -#if 0 +#ifdef TRACE if (f != NULL) { fclose(f); diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index dafdb93e53..0889d1d378 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -120,7 +120,6 @@ enum EZCCBuiltinType ZCC_String, ZCC_Vector2, ZCC_Vector3, - ZCC_Vector4, ZCC_Name, ZCC_Color, // special types for ZDoom. From e5878f0cb289d3a23bd106891e25e7fd6a78cbc1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Oct 2016 01:39:25 +0200 Subject: [PATCH 131/471] - implemented vector operations. Vectors are now fully working as local variables. - removed mulv_kr and divv_kr instructions. The first are redundant and the second are useless. Maybe remove all other vector/const operations as well? They won't get used by the code generator. - fixed disassembly of vector multiplication and division instructions. --- src/scripting/codegeneration/codegen.cpp | 207 +++++++++++++++++++---- src/scripting/codegeneration/codegen.h | 5 +- src/scripting/vm/vmdisasm.cpp | 3 + src/scripting/vm/vmexec.h | 20 --- src/scripting/vm/vmops.h | 20 +-- 5 files changed, 193 insertions(+), 62 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 773fc4b1a4..903a0fe139 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1476,7 +1476,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx) CHECKRESOLVED(); SAFE_RESOLVE(Operand, ctx); - if (Operand->IsNumeric()) + if (Operand->IsNumeric() || Operand->IsVector()) { FxExpression *e = Operand; Operand = NULL; @@ -1530,7 +1530,7 @@ FxExpression *FxMinusSign::Resolve(FCompileContext& ctx) CHECKRESOLVED(); SAFE_RESOLVE(Operand, ctx); - if (Operand->IsNumeric()) + if (Operand->IsNumeric() || Operand->IsVector()) { if (Operand->isConstant()) { @@ -1563,6 +1563,7 @@ 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. if (ValueType->GetRegType() == REGT_INT) { @@ -1571,7 +1572,21 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) else { assert(ValueType->GetRegType() == REGT_FLOAT); - build->Emit(OP_FLOP, from.RegNum, from.RegNum, FLOP_NEG); + 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; } @@ -1610,10 +1625,10 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) CHECKRESOLVED(); SAFE_RESOLVE(Operand, ctx); - if (Operand->ValueType->GetRegType() == REGT_FLOAT /* lax */) + if (ctx.FromDecorate && Operand->IsNumeric() && Operand->ValueType->GetRegType() == REGT_FLOAT /* lax */) { // DECORATE allows floats here so cast them to int. - Operand = new FxIntCast(Operand, ctx.FromDecorate); + Operand = new FxIntCast(Operand, true); Operand = Operand->Resolve(ctx); if (Operand == NULL) { @@ -1622,7 +1637,8 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) } } - if (Operand->ValueType->GetRegType() != REGT_INT) + // Names were not blocked in DECORATE here after the scripting branch merge. Now they are again. + if (Operand->ValueType->GetRegType() != REGT_INT || Operand->ValueType == TypeName) { ScriptPosition.Message(MSG_ERROR, "Integer type expected"); delete this; @@ -1763,13 +1779,13 @@ FxExpression *FxSizeAlign::Resolve(FCompileContext& ctx) auto type = Operand->ValueType; if (Operand->isConstant()) { - ScriptPosition.Message(MSG_ERROR, "cannot determine %s of a constant", Which == 'a'? "alignment" : "size"); + ScriptPosition.Message(MSG_ERROR, "cannot determine %s of a constant", Which == TK_AlignOf? "alignment" : "size"); delete this; return NULL; } else if (!Operand->RequestAddress(nullptr)) { - ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == 'a' ? "alignment" : "size"); + ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == TK_AlignOf ? "alignment" : "size"); delete this; return NULL; } @@ -2057,7 +2073,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) + if (!Base->IsVector() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) { ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet"); delete this; @@ -2255,7 +2271,78 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) return false; } - if (left->ValueType == TypeBool && right->ValueType == TypeBool) + 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) { @@ -2361,7 +2448,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) CHECKRESOLVED(); if (!ResolveLR(ctx, true)) return NULL; - if (!IsNumeric()) + if (!IsNumeric() && !IsVector()) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; @@ -2410,6 +2497,8 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) { assert(Operator == '+' || Operator == '-'); + // allocate the result first so that the operation does not leave gaps in the register set. + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); ExpEmit op1 = left->Emit(build); ExpEmit op2 = right->Emit(build); if (Operator == '+') @@ -2422,10 +2511,20 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) assert(!op1.Konst); op1.Free(build); op2.Free(build); - if (ValueType->GetRegType() == REGT_FLOAT) + 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); - ExpEmit to(build, REGT_FLOAT); build->Emit(op2.Konst ? OP_ADDF_RK : OP_ADDF_RR, to.RegNum, op1.RegNum, op2.RegNum); return to; } @@ -2433,7 +2532,6 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) { 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; } @@ -2444,21 +2542,23 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) assert(!op1.Konst || !op2.Konst); op1.Free(build); op2.Free(build); - if (ValueType->GetRegType() == REGT_FLOAT) + if (IsVector()) { 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); + 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); - 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); + build->Emit(op1.Konst ? OP_SUB_KR : op2.Konst ? OP_SUB_RK : OP_SUB_RR, to.RegNum, op1.RegNum, op2.RegNum); return to; } } @@ -2487,7 +2587,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) if (!ResolveLR(ctx, true)) return NULL; - if (!IsNumeric()) + if (!IsNumeric() && !IsVector()) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; @@ -2552,9 +2652,33 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) { + // allocate the result first so that the operation does not leave gaps in the register set. + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); 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); + } + build->Emit(op, to.RegNum, op1.RegNum, op2.RegNum); + op1.Free(build); + op2.Free(build); + return to; + } + if (Operator == '*') { // Multiplication is commutative, so only the second operand may be constant. @@ -2568,7 +2692,6 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *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; } @@ -2576,7 +2699,6 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) { 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; } @@ -2813,7 +2935,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) return NULL; } - if (!IsNumeric() && !IsPointer() && ValueType != TypeName) + if (!IsNumeric() && !IsPointer() && !IsVector() && ValueType != TypeName) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; @@ -2866,11 +2988,13 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) 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 ? OP_EQF_R : + op1.RegType == REGT_FLOAT ? flops[op1.RegCount-1] : OP_EQA_R; op1.Free(build); if (!op2.Konst) @@ -3349,14 +3473,25 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) RESOLVE(falsex, ctx); ABORT(condition && truex && falsex); - if (truex->ValueType == TypeBool && falsex->ValueType == TypeBool) + if (truex->ValueType == falsex->ValueType) + ValueType = truex->ValueType; + else 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 + ValueType = TypeVoid; //else if (truex->ValueType != falsex->ValueType) + if (!IsNumeric() && !IsPointer() && !IsVector()) + { + ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator"); + delete this; + return false; + } + if (condition->ValueType != TypeBool) { condition = new FxBoolCast(condition); @@ -3465,7 +3600,9 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) else { assert(falseop.RegType == REGT_FLOAT); - build->Emit(OP_MOVEF, out.RegNum, falseop.RegNum, 0); + assert(falseop.RegCount == out.RegCount); + static int flops[] = { OP_MOVEF, OP_MOVEV2, OP_MOVEV3 }; + build->Emit(flops[falseop.RegNum], out.RegNum, falseop.RegNum, 0); } } } @@ -4625,6 +4762,7 @@ FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptP Variable = var; ValueType = var->ValueType; AddressRequested = false; + RegOffset = 0; } FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) @@ -4642,7 +4780,8 @@ bool FxLocalVariable::RequestAddress(bool *writable) ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { - ExpEmit ret(Variable->RegNum, Variable->ValueType->GetRegType(), false, true); + ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); + ret.RegCount = ValueType->GetRegCount(); if (AddressRequested) ret.Target = true; return ret; } @@ -4765,6 +4904,16 @@ FxExpression *FxStructMember::Resolve(FCompileContext &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 = membervar->Offset / 8; + locvar->ValueType = membervar->Type; + classx = nullptr; + delete this; + return locvar; + } else { if (!(classx->RequestAddress(&AddressWritable))) diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 30401f9077..01d63eaf8c 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -292,8 +292,10 @@ public: virtual bool RequestAddress(bool *writable); virtual PPrototype *ReturnProto(); virtual VMFunction *GetDirectFunction(); - bool IsNumeric() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } + bool IsNumeric() const { return ValueType != TypeName && ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } + bool IsInteger() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT); } bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; } + bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; }; virtual ExpEmit Emit(VMFunctionBuilder *build); @@ -1104,6 +1106,7 @@ class FxLocalVariable : public FxExpression public: FxLocalVariableDeclaration *Variable; bool AddressRequested; + int RegOffset; FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); FxExpression *Resolve(FCompileContext&); diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 563f89f280..c20083dcd8 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -117,6 +117,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 diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index e3401eb380..824cd63668 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1352,11 +1352,6 @@ begin: fc = konstf[C]; fbp = ®.f[B]; goto Do_MULV2; - OP(MULVF2_KR): - ASSERTF(a+1); ASSERTKF(B+1); ASSERTF(C); - fc = reg.f[C]; - fbp = &konstf[B]; - goto Do_MULV2; OP(DIVVF2_RR): ASSERTF(a+1); ASSERTF(B+1); ASSERTF(C); @@ -1371,11 +1366,6 @@ begin: fc = konstf[C]; fbp = ®.f[B]; goto Do_DIVV2; - OP(DIVVF2_KR): - ASSERTF(a+1); ASSERTKF(B+1); ASSERTF(C); - fc = reg.f[C]; - fbp = &konstf[B]; - goto Do_DIVV2; OP(LENV2): ASSERTF(a); ASSERTF(B+1); @@ -1488,11 +1478,6 @@ begin: fc = konstf[C]; fbp = ®.f[B]; goto Do_MULV3; - OP(MULVF3_KR): - ASSERTF(a+2); ASSERTKF(B+2); ASSERTF(C); - fc = reg.f[C]; - fbp = &konstf[B]; - goto Do_MULV3; OP(DIVVF3_RR): ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C); @@ -1508,11 +1493,6 @@ begin: fc = konstf[C]; fbp = ®.f[B]; goto Do_DIVV3; - OP(DIVVF3_KR): - ASSERTF(a+2); ASSERTKF(B+2); ASSERTF(C); - fc = reg.f[C]; - fbp = &konstf[B]; - goto Do_DIVV3; OP(LENV3): ASSERTF(a); ASSERTF(B+2); diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index ba86e2231b..e7ff19c22d 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -208,12 +208,10 @@ 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, RVRVRV), // vA = vkB * fkC -xx(MULVF2_RK, mulv2, RVRVKV), -xx(MULVF2_KR, mulv2, RVKVRV), -xx(DIVVF2_RR, divv2, RVRVRV), // vA = vkB / fkC -xx(DIVVF2_RK, divv2, RVRVKV), -xx(DIVVF2_KR, divv2, RVKVRV), +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), @@ -230,12 +228,10 @@ 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(MULVF3_RR, mulv3, RVRVRV), // vA = vkB * fkC -xx(MULVF3_RK, mulv3, RVRVKV), -xx(MULVF3_KR, mulv3, RVKVRV), -xx(DIVVF3_RR, divv3, RVRVRV), // vA = vkB / fkC -xx(DIVVF3_RK, divv3, RVRVKV), -xx(DIVVF3_KR, divv3, RVKVRV), +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), From 594a0c2008fa999a167f00883e59cf8797b92da1 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sat, 29 Oct 2016 01:30:05 +0200 Subject: [PATCH 132/471] Fixed: FxVMFunctionCall didn't check for varargs while checking argument count --- src/scripting/codegeneration/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 903a0fe139..4c048c452a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5785,7 +5785,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { bool foundvarargs = false; PType * type = nullptr; - if (ArgList->Size() + implicit > proto->ArgumentTypes.Size()) + 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; From b5222f08e8ad25064750f033150552948a494988 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Oct 2016 10:16:00 +0200 Subject: [PATCH 133/471] - implemented dot and cross products (not that I'd ever expect these to become useful in a game like Doom...) --- src/scripting/codegeneration/codegen.cpp | 70 ++++++++++++++++++++++++ src/scripting/codegeneration/codegen.h | 21 +++++++ src/scripting/zscript/zcc_compile.cpp | 9 ++- 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4c048c452a..039e428ff0 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3438,6 +3438,76 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) // //========================================================================== +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) +{ + // 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.) + 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; +} + +//========================================================================== +// +// +// +//========================================================================== + FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f) : FxExpression(EFX_Conditional, c->ScriptPosition) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 01d63eaf8c..570575bb98 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -228,6 +228,7 @@ enum EFxType 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, @@ -905,6 +906,26 @@ public: 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); +}; + //========================================================================== // // FxConditional diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f1a06d5847..294763f9b1 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2680,14 +2680,13 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_ArrayAccess: return new FxArrayElement(left, right); - // todo: These do not have representations in DECORATE and no implementation exists yet. - case PEX_Concat: - case PEX_Is: - - // vector operations will be done later. case PEX_CrossProduct: case PEX_DotProduct: + return new FxDotCross(tok, left, right); + // todo: These do not have representations in DECORATE and no implementation exists yet. + case PEX_Concat: + case PEX_Is: default: I_Error("Binary operator %d not implemented yet", op); From f5d1b1a491eb5065fb78f3b7c6c99c901d8ce19e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Oct 2016 10:43:22 +0200 Subject: [PATCH 134/471] - added vector builtins Length() and Unit(). This should complete the vector type except for use as function parameter. --- src/namedef.h | 2 + src/scripting/codegeneration/codegen.cpp | 57 ++++++++++++++++++++++++ src/scripting/codegeneration/codegen.h | 20 +++++++++ wadsrc/static/zscript.txt | 2 + 4 files changed, 81 insertions(+) diff --git a/src/namedef.h b/src/namedef.h index ea4a7b890e..a5abfa5a12 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -730,3 +730,5 @@ xx(__decorate_internal_state__) xx(__decorate_internal_float__) xx(DamageFunction) +xx(Length) +xx(Unit) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 039e428ff0..f8fd03946b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5535,6 +5535,18 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) PClass *cls; bool staticonly = false; + 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(PClassPointer))) { cls = static_cast(Self->ValueType)->ClassRestriction; @@ -6096,6 +6108,51 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) 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 diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 570575bb98..6c7dec487a 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -266,6 +266,7 @@ enum EFxType EFX_SwitchStatement, EFX_CaseStatement, EFX_VectorInitializer, + EFX_VectorBuiltin, EFX_COUNT }; @@ -1254,6 +1255,25 @@ public: 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 diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 6de64d07e5..3ab33bfd96 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -177,3 +177,5 @@ zscript/chex/chexweapons.txt zscript/chex/chexitems.txt zscript/chex/chexdecorations.txt zscript/chex/chexplayer.txt + +zscript/test2.txt From 7209f9edd6b13d108b9123d01f018c5cfea9f381 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Oct 2016 13:10:27 +0200 Subject: [PATCH 135/471] - implemented passing vectors as parameters. So far working for native functions. - removed the bogus optional value from the first A_Jump argument. A quick test with an older ZDoom revealed that this was never working - and implementing it would make things a lot more complicated, especially error checking in the code generator. - fixed: The check for insufficient parameters to a function call was missing. --- src/namedef.h | 1 + src/p_actionfunctions.cpp | 2 +- src/p_maputl.cpp | 11 ++++++ src/scripting/codegeneration/codegen.cpp | 30 +++++++++++++-- src/scripting/vm/vm.h | 4 +- src/scripting/vm/vmbuilder.cpp | 6 ++- src/scripting/vm/vmdisasm.cpp | 6 ++- src/scripting/vm/vmexec.h | 49 ++++++++++-------------- src/scripting/zscript/zcc_compile.cpp | 6 +++ 9 files changed, 78 insertions(+), 37 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index a5abfa5a12..3966c95e77 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -732,3 +732,4 @@ xx(__decorate_internal_float__) xx(DamageFunction) xx(Length) xx(Unit) +xx(A_Jump) \ No newline at end of file diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 0e96205641..9f3a088d67 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1148,7 +1148,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_DEF(maxchance); + PARAM_INT(maxchance); paramnum++; // Increment paramnum to point at the first jump target int count = numparam - paramnum; diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 04372f0eda..0a1d831d85 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -532,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/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f8fd03946b..d87e601ffd 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -334,7 +334,7 @@ PPrototype *FxExpression::ReturnProto() // //========================================================================== -static void EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const FScriptPosition &pos) +static int EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const FScriptPosition &pos) { ExpEmit where = operand->Emit(build); @@ -342,6 +342,7 @@ static void EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const { pos.Message(MSG_ERROR, "Attempted to pass a non-value"); build->Emit(OP_PARAM, 0, where.RegType, where.RegNum); + return 1; } else { @@ -350,8 +351,17 @@ static void EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const { regtype |= REGT_KONST; } + else if (where.RegCount == 2) + { + regtype |= REGT_MULTIREG2; + } + else if (where.RegCount == 3) + { + regtype |= REGT_MULTIREG3; + } build->Emit(OP_PARAM, 0, regtype, where.RegNum); where.Free(build); + return where.RegCount; } } @@ -5873,6 +5883,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) 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. @@ -5888,6 +5899,18 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& 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; + } + } + } if (failed) { @@ -5917,7 +5940,7 @@ 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); + int count = 0; (ArgList ? ArgList->Size() : 0); if (count == 1) { @@ -5928,6 +5951,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } } + count = 0; // Emit code to pass implied parameters if (Function->Variants[0].Flags & VARF_Method) { @@ -5958,7 +5982,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { for (unsigned i = 0; i < ArgList->Size(); ++i) { - EmitParameter(build, (*ArgList)[i], ScriptPosition); + count += EmitParameter(build, (*ArgList)[i], ScriptPosition); } } // Get a constant register for this function diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index c14a8a6e5b..4eb055e6ee 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -134,7 +134,9 @@ 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 = 128 // parameter was omitted diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index dd07d01008..912b958610 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -498,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) { diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index c20083dcd8..ea199612c4 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -578,8 +578,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: diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 824cd63668..9162ca9960 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -453,7 +453,7 @@ begin: } else { - switch(b & (REGT_TYPE | REGT_KONST | REGT_ADDROF)) + switch(b) { case REGT_INT: assert(C < f->NumRegD); @@ -492,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); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 294763f9b1..f2644b240d 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2017,6 +2017,7 @@ void ZCCCompiler::InitFunctions() SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags); argdefaults.Resize(argnames.Size()); auto p = f->Params; + bool hasoptionals = false; if (p != nullptr) { do @@ -2043,6 +2044,7 @@ void ZCCCompiler::InitFunctions() 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 @@ -2094,6 +2096,10 @@ void ZCCCompiler::InitFunctions() } 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); From 4dc97a6ed02f2c24fe073186a0f14b2544f1c5ac Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Oct 2016 13:42:37 +0200 Subject: [PATCH 136/471] - fixed register allocation for vector arguments to script functions. - handle 2D and 3D vectors in SetReturn. --- src/scripting/vm/vm.h | 6 ++++++ src/scripting/vm/vmbuilder.cpp | 2 +- src/scripting/vm/vmexec.h | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 4eb055e6ee..5e8a4c2a4b 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -296,6 +296,12 @@ struct VMReturn ((double *)Location)[1] = val[1]; ((double *)Location)[2] = val[2]; } + void SetVector2(const double val[2]) + { + //assert(RegType == REGT_FLOAT); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + } void SetString(const FString &val) { assert(RegType == REGT_STRING); diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 912b958610..3f6d1cbd30 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -702,7 +702,7 @@ void FFunctionBuildList::Build() 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(1); + local->RegNum = buildit.Registers[type->GetRegType()].Get(type->GetRegCount()); ctx.FunctionArgs.Push(local); } diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 9162ca9960..4b43ed8158 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1808,10 +1808,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); From 853c6f668410087ea72e78873d64be5d7a5e071f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Oct 2016 16:49:21 +0200 Subject: [PATCH 137/471] - fixed initialization of local variables with other local variables. - fixed several occurenced where vectors were treated as floats. NOTE: The entire codegen.cpp file needs to be carefully reviewed for bad use of the REGT_ constants, there's probably more places where using them has broken some type checks. - fixed: committed test version of zscript.txt instead of changed actor.txt by accident. Initialization and assignment for strings is working with this commit. --- src/scripting/codegeneration/codegen.cpp | 21 ++++++++++++++------- wadsrc/static/zscript.txt | 2 -- wadsrc/static/zscript/actor.txt | 3 ++- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d87e601ffd..37ff715dd2 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -676,7 +676,7 @@ FxExpression *FxBoolCast::Resolve(FCompileContext &ctx) delete this; return x; } - else if (basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER) + else if ((basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER) && !basex->IsVector()) { if (basex->isConstant()) { @@ -797,7 +797,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) return x; } } - else if (basex->ValueType->GetRegType() == REGT_FLOAT) + else if (basex->ValueType->GetRegType() == REGT_FLOAT && !basex->IsVector()) { if (basex->isConstant()) { @@ -875,7 +875,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(basex, ctx); - if (basex->ValueType->GetRegType() == REGT_FLOAT) + if (basex->ValueType->GetRegType() == REGT_FLOAT && !basex->IsVector()) { FxExpression *x = basex; basex = NULL; @@ -1095,11 +1095,11 @@ ExpEmit FxStringCast::Emit(VMFunctionBuilder *build) from.Free(build); ExpEmit to(build, REGT_STRING); - if (ValueType == TypeName) + if (basex->ValueType == TypeName) { build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_N2S); } - else if (ValueType == TypeSound) + else if (basex->ValueType == TypeSound) { build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_So2S); } @@ -1325,7 +1325,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) { goto basereturn; } - else if (ValueType->GetRegType() == REGT_FLOAT) + else if (ValueType->GetRegType() == REGT_FLOAT && !IsVector()) { FxExpression *x = new FxFloatCast(basex); x = x->Resolve(ctx); @@ -4867,6 +4867,7 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) } + //========================================================================== // // @@ -7671,11 +7672,17 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) } emitval.Free(build); } - else + 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(); } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 3ab33bfd96..6de64d07e5 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -177,5 +177,3 @@ zscript/chex/chexweapons.txt zscript/chex/chexitems.txt zscript/chex/chexdecorations.txt zscript/chex/chexplayer.txt - -zscript/test2.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 3630365074..18f0facd0c 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -53,6 +53,7 @@ class Actor : Thinker native return GetPointer(ptr_select1) == GetPointer(ptr_select2); } + native void SetOrigin(vector3 newpos, bool moving); native Actor GetPointer(int aaptr); native Actor SpawnMissile(Actor dest, class type, Actor owner = null); native void TraceBleed(int damage, Actor missile); @@ -296,7 +297,7 @@ class Actor : Thinker native 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 state A_Jump(int chance = 256, state label, ...); + native state A_Jump(int chance, state label, ...); native void A_CustomMissile(class missiletype, float spawnheight = 32, float spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET); native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = 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); From 78a18acf46567a1b8e22ab309f601f435cceaab4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Oct 2016 18:57:56 +0200 Subject: [PATCH 138/471] - added string handling to comparison operators. --- src/scripting/codegeneration/codegen.cpp | 276 ++++++++++++++++------- src/scripting/codegeneration/codegen.h | 2 + src/scripting/vm/vm.h | 2 +- 3 files changed, 199 insertions(+), 81 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 37ff715dd2..6b6d830686 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -676,7 +676,7 @@ FxExpression *FxBoolCast::Resolve(FCompileContext &ctx) delete this; return x; } - else if ((basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER) && !basex->IsVector()) + else if (basex->IsBoolCompat()) { if (basex->isConstant()) { @@ -797,7 +797,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) return x; } } - else if (basex->ValueType->GetRegType() == REGT_FLOAT && !basex->IsVector()) + else if (basex->IsFloat()) { if (basex->isConstant()) { @@ -875,7 +875,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(basex, ctx); - if (basex->ValueType->GetRegType() == REGT_FLOAT && !basex->IsVector()) + if (basex->IsFloat()) { FxExpression *x = basex; basex = NULL; @@ -1325,7 +1325,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) { goto basereturn; } - else if (ValueType->GetRegType() == REGT_FLOAT && !IsVector()) + else if (IsFloat()) { FxExpression *x = new FxFloatCast(basex); x = x->Resolve(ctx); @@ -1635,7 +1635,7 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) CHECKRESOLVED(); SAFE_RESOLVE(Operand, ctx); - if (ctx.FromDecorate && Operand->IsNumeric() && Operand->ValueType->GetRegType() == REGT_FLOAT /* lax */) + if (ctx.FromDecorate && Operand->IsFloat() /* lax */) { // DECORATE allows floats here so cast them to int. Operand = new FxIntCast(Operand, true); @@ -1648,7 +1648,7 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) } // Names were not blocked in DECORATE here after the scripting branch merge. Now they are again. - if (Operand->ValueType->GetRegType() != REGT_INT || Operand->ValueType == TypeName) + if (!Operand->IsInteger()) { ScriptPosition.Message(MSG_ERROR, "Integer type expected"); delete this; @@ -2281,7 +2281,51 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) return false; } - if (left->IsVector() || right->IsVector()) + 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 nullptr; + } + } + if (right->ValueType != TypeString) + { + right = new FxStringCast(right); + right = right->Resolve(ctx); + if (right == nullptr) + { + delete this; + return nullptr; + } + } + ValueType = TypeBool; + break; + + default: + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for comparison"); + delete this; + return false; + } + } + else if (left->IsVector() || right->IsVector()) { switch (Operator) { @@ -2466,7 +2510,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) } else if (left->isConstant() && right->isConstant()) { - if (ValueType->GetRegType() == REGT_FLOAT) + if (IsFloat()) { double v; double v1 = static_cast(left)->GetValue().GetFloat(); @@ -2605,7 +2649,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) } else if (left->isConstant() && right->isConstant()) { - if (ValueType->GetRegType() == REGT_FLOAT) + if (IsFloat()) { double v; double v1 = static_cast(left)->GetValue().GetFloat(); @@ -2834,7 +2878,17 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) { int v; - if (ValueType->GetRegType() == REGT_FLOAT) + 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(); @@ -2873,47 +2927,81 @@ 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 : + 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; + 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; + } } //========================================================================== @@ -2952,12 +3040,24 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) return NULL; } - if (Operator == TK_ApproxEq && ValueType->GetRegType() != REGT_FLOAT) Operator = TK_Eq; + 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->GetRegType() == REGT_FLOAT) + 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(); @@ -2989,39 +3089,55 @@ 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) + if (op1.RegType == REGT_STRING) { - swapvalues(op1, op2); - } - assert(!op1.Konst); - assert(op1.RegCount >= 1 && op1.RegCount <= 3); + 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; - 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); + 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 { - 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, op1.RegNum, op2.RegNum); - build->Emit(OP_JMP, 1); - build->Emit(OP_LI, to.RegNum, 1); - return to; + // 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, op1.RegNum, op2.RegNum); + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + return to; + } } //========================================================================== @@ -3047,7 +3163,7 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) CHECKRESOLVED(); if (!ResolveLR(ctx, false)) return NULL; - if (ValueType->GetRegType() == REGT_FLOAT && ctx.FromDecorate) + if (IsFloat() && ctx.FromDecorate) { // For DECORATE which allows floats here. ZScript does not. if (left->ValueType->GetRegType() != REGT_INT) @@ -3557,7 +3673,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) ValueType = truex->ValueType; else if (truex->ValueType == TypeBool && falsex->ValueType == TypeBool) ValueType = TypeBool; - else if (truex->ValueType->GetRegType() == REGT_INT && falsex->ValueType->GetRegType() == REGT_INT) + else if (truex->IsInteger() && falsex->IsInteger()) ValueType = TypeSInt32; else if (truex->IsNumeric() && falsex->IsNumeric()) ValueType = TypeFloat64; @@ -3565,7 +3681,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) ValueType = TypeVoid; //else if (truex->ValueType != falsex->ValueType) - if (!IsNumeric() && !IsPointer() && !IsVector()) + if ((!IsNumeric() && !IsPointer() && !IsVector()) || ValueType == TypeVoid) { ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator"); delete this; @@ -3590,7 +3706,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) return e; } - if (ValueType->GetRegType() == REGT_FLOAT) + if (IsFloat()) { if (truex->ValueType->GetRegType() != REGT_FLOAT) { @@ -3911,11 +4027,11 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx) RESOLVE(choices[i], ctx); ABORT(choices[i]); - if (choices[i]->ValueType->GetRegType() == REGT_FLOAT) + if (choices[i]->IsFloat()) { floatcount++; } - else if (choices[i]->ValueType->GetRegType() == REGT_INT && choices[i]->ValueType != TypeName) + else if (choices[i]->IsInteger()) { intcount++; } @@ -5690,7 +5806,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) failed = true; } } - else if ((*ArgList)[i]->ValueType->GetRegType() != REGT_INT) + else if (!(*ArgList)[i]->IsInteger()) { if ((*ArgList)[i]->ValueType->GetRegType() == REGT_FLOAT /* lax */) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 6c7dec487a..565da558dd 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -295,9 +295,11 @@ public: virtual PPrototype *ReturnProto(); virtual VMFunction *GetDirectFunction(); bool IsNumeric() const { return ValueType != TypeName && ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } + bool IsFloat() const { return ValueType->GetRegType() == REGT_FLOAT && ValueType->GetRegCount() == 1; } bool IsInteger() const { return ValueType != TypeName && (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); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 5e8a4c2a4b..d020b8e88a 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -921,7 +921,7 @@ 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].atag == ATAG_GENERIC || param[p].a == NULL)); FState *x = (FState *)param[p].a; #define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a; From ac1c022911662ac7f988111f3c1f0ed65cc13add Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Oct 2016 01:05:56 +0200 Subject: [PATCH 139/471] - implemented the 'is' operator (i.e. class type check.) --- src/namedef.h | 11 +- src/scripting/codegeneration/codegen.cpp | 154 +++++++++++++++++++---- src/scripting/codegeneration/codegen.h | 22 ++++ src/scripting/zscript/zcc_compile.cpp | 4 +- 4 files changed, 158 insertions(+), 33 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index 3966c95e77..2d1c3c7a70 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -673,13 +673,14 @@ xx(PlayerClass) xx(Wi_NoAutostartMap) // Decorate compatibility functions -xx(DecoRandom) -xx(DecoFRandom) -xx(DecoCallLineSpecial) -xx(DecoNameToClass) +xx(BuiltinTypeCheck) +xx(BuiltinRandom) +xx(BuiltinFRandom) +xx(BuiltinCallLineSpecial) +xx(BuiltinNameToClass) xx(BuiltinFindMultiNameState) xx(BuiltinFindSingleNameState) -xx(DecoHandleRuntimeState) +xx(BuiltinHandleRuntimeState) xx(Damage) // basic type names diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 6b6d830686..d2ca17db59 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -203,23 +203,24 @@ void ExpEmit::Reuse(VMFunctionBuilder *build) //========================================================================== // -// FindDecorateBuiltinFunction +// FindBuiltinFunction // // Returns the symbol for a decorate utility function. If not found, create -// it and install it in Actor. +// it and install it a local symbol table. // //========================================================================== +static PSymbolTable Builtins; -static PSymbol *FindDecorateBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func) +static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func) { - PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(funcname, false); + PSymbol *sym = Builtins.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); + Builtins.AddSymbol(sym); } return sym; } @@ -3615,9 +3616,6 @@ FxExpression *FxDotCross::Resolve(FCompileContext& ctx) ExpEmit FxDotCross::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.) ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); ExpEmit op1 = left->Emit(build); ExpEmit op2 = right->Emit(build); @@ -3634,6 +3632,108 @@ ExpEmit FxDotCross::Emit(VMFunctionBuilder *build) // //========================================================================== +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->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 != NULL); + 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; +} + +//========================================================================== +// +// +// +//========================================================================== + FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f) : FxExpression(EFX_Conditional, c->ScriptPosition) { @@ -4278,7 +4378,7 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx) // //========================================================================== -int DecoRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +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); @@ -4309,7 +4409,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build) { // Call DecoRandom to generate a random number. VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom); + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != NULL); @@ -4428,9 +4528,9 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) assert(choices.Size() > 0); - // Call DecoRandom to generate a random number. + // Call BuiltinRandom to generate a random number. VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom); + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != NULL); @@ -4528,7 +4628,7 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri // //========================================================================== -int DecoFRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +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); @@ -4553,9 +4653,9 @@ int DecoFRandom(VMFrameStack *stack, VMValue *param, TArray &defaultpar ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) { - // Call the DecoFRandom function to generate a floating point random number.. + // Call the BuiltinFRandom function to generate a floating point random number.. VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoFRandom, DecoFRandom); + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != NULL); @@ -4647,9 +4747,9 @@ FxExpression *FxRandom2::Resolve(FCompileContext &ctx) ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) { - // Call the DecoRandom function to generate the random number. + // Call the BuiltinRandom function to generate the random number. VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom); + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != NULL); @@ -5836,7 +5936,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) // //========================================================================== -int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +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); @@ -5885,9 +5985,9 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) } } } - // Call the DecoCallLineSpecial function to perform the desired special. + // Call the BuiltinCallLineSpecial function to perform the desired special. VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoCallLineSpecial, DecoCallLineSpecial); + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != NULL); @@ -7347,7 +7447,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) // //========================================================================== -int DecoNameToClass(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 2); assert(numret == 1); @@ -7380,9 +7480,9 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) 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. + // Call the BuiltinNameToClass function to convert from 'name' to class. VMFunction *callfunc; - PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoNameToClass, DecoNameToClass); + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != NULL); @@ -7487,7 +7587,7 @@ static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int return false; } -static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +static int BuiltinHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { PARAM_PROLOGUE; PARAM_OBJECT(stateowner, AActor); @@ -7522,7 +7622,7 @@ ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build) VMFunction *callfunc; PSymbol *sym; - sym = FindDecorateBuiltinFunction(NAME_DecoHandleRuntimeState, DecoHandleRuntimeState); + sym = FindBuiltinFunction(NAME_BuiltinHandleRuntimeState, BuiltinHandleRuntimeState); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; @@ -7702,11 +7802,11 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) if (names.Size() == 1) { - sym = FindDecorateBuiltinFunction(NAME_BuiltinFindSingleNameState, BuiltinFindSingleNameState); + sym = FindBuiltinFunction(NAME_BuiltinFindSingleNameState, BuiltinFindSingleNameState); } else { - sym = FindDecorateBuiltinFunction(NAME_BuiltinFindMultiNameState, BuiltinFindMultiNameState); + sym = FindBuiltinFunction(NAME_BuiltinFindMultiNameState, BuiltinFindMultiNameState); } assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 565da558dd..9e13d3806b 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -267,6 +267,7 @@ enum EFxType EFX_CaseStatement, EFX_VectorInitializer, EFX_VectorBuiltin, + EFX_TypeCheck, EFX_COUNT }; @@ -929,6 +930,27 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxBinaryLogical +// +//========================================================================== + +class FxTypeCheck : public FxExpression +{ +public: + FxExpression *left; + FxExpression *right; + bool EmitTail; + + FxTypeCheck(FxExpression*, FxExpression*); + ~FxTypeCheck(); + FxExpression *Resolve(FCompileContext&); + PPrototype *ReturnProto(); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxConditional diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f2644b240d..e545bd5087 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2690,9 +2690,11 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) 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: - case PEX_Is: default: I_Error("Binary operator %d not implemented yet", op); From 94410accf41dd752861f002b33502db64cbcd74d Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 30 Oct 2016 04:35:01 +0100 Subject: [PATCH 140/471] Renamed "VectorInitializer" to "VectorValue" This was really confusing for me as this is an actual vector "value" rather than an "initializer" --- src/scripting/codegeneration/codegen.cpp | 14 ++++---- src/scripting/codegeneration/codegen.h | 8 ++--- src/scripting/zscript/ast.cpp | 2 +- src/scripting/zscript/zcc-parse.lemon | 46 +++++++++++------------- src/scripting/zscript/zcc_compile.cpp | 6 ++-- src/scripting/zscript/zcc_parser.h | 4 +-- 6 files changed, 37 insertions(+), 43 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d2ca17db59..0930399025 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -446,8 +446,8 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build) // //========================================================================== -FxVectorInitializer::FxVectorInitializer(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc) - :FxExpression(EFX_VectorInitializer, sc) +FxVectorValue::FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc) + :FxExpression(EFX_VectorValue, sc) { xyz[0] = x; xyz[1] = y; @@ -456,13 +456,13 @@ FxVectorInitializer::FxVectorInitializer(FxExpression *x, FxExpression *y, FxExp ValueType = TypeVoid; // we do not know yet } -FxVectorInitializer::~FxVectorInitializer() +FxVectorValue::~FxVectorValue() { for (auto &a : xyz) SAFE_DELETE(a); } -FxExpression *FxVectorInitializer::Resolve(FCompileContext&ctx) +FxExpression *FxVectorValue::Resolve(FCompileContext&ctx) { bool fails = false; @@ -501,10 +501,10 @@ FxExpression *FxVectorInitializer::Resolve(FCompileContext&ctx) return nullptr; } ValueType = TypeVector3; - if (xyz[0]->ExprType == EFX_VectorInitializer) + if (xyz[0]->ExprType == EFX_VectorValue) { // If two vector initializers are nested, unnest them now. - auto vi = static_cast(xyz[0]); + auto vi = static_cast(xyz[0]); xyz[2] = xyz[1]; xyz[1] = vi->xyz[1]; xyz[0] = vi->xyz[0]; @@ -542,7 +542,7 @@ static ExpEmit EmitKonst(VMFunctionBuilder *build, ExpEmit &emit) return emit; } -ExpEmit FxVectorInitializer::Emit(VMFunctionBuilder *build) +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) diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 9e13d3806b..f9393d11f7 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -265,7 +265,7 @@ enum EFxType EFX_LocalVariableDeclaration, EFX_SwitchStatement, EFX_CaseStatement, - EFX_VectorInitializer, + EFX_VectorValue, EFX_VectorBuiltin, EFX_TypeCheck, EFX_COUNT @@ -463,14 +463,14 @@ public: // //========================================================================== -class FxVectorInitializer : public FxExpression +class FxVectorValue : public FxExpression { FxExpression *xyz[3]; bool isConst; // gets set to true if all element are const public: - FxVectorInitializer(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc); - ~FxVectorInitializer(); + FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc); + ~FxVectorValue(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index e77c631e18..cb0240dea8 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -623,7 +623,7 @@ static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node) static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node) { - ZCC_VectorInitializer *enode = (ZCC_VectorInitializer *)node; + ZCC_VectorValue *enode = (ZCC_VectorValue *)node; OpenExprType(out, enode->Operation); PrintNodes(out, enode->X); PrintNodes(out, enode->Y); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 173ec27fc0..b1065281c8 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -945,7 +945,6 @@ func_param_flags(X) ::= func_param_flags(A) OPTIONAL(T). { X.Int = A.Int | ZCC_O %type expr{ZCC_Expression *} %type primary{ZCC_Expression *} -%type vectorinit{ZCC_VectorInitializer*} %type unary_expr{ZCC_Expression *} %type constant{ZCC_ExprConstant *} @@ -967,8 +966,26 @@ primary(X) ::= SUPER(T). X = expr; } primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ } -primary(X) ::= vectorinit(A). { X = A; /*X-overwrites-A*/ } - +primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. [DOT] +{ + 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. { X = A; /*X-overwrites-A*/ @@ -1019,29 +1036,6 @@ primary(X) ::= SCOPE primary(B). } */ -vectorinit(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. [DOT] -{ - NEW_AST_NODE(VectorInitializer, expr, A); - expr->Operation = PEX_Vector; - expr->Type = TypeVector3; - expr->X = A; - expr->Y = B; - expr->Z = C; - XX = expr; -} - - -vectorinit(XX) ::= LPAREN expr(A) COMMA expr(B) RPAREN. [DOT] -{ - NEW_AST_NODE(VectorInitializer, expr, A); - expr->Operation = PEX_Vector; - expr->Type = TypeVector2; - expr->X = A; - expr->Y = B; - expr->Z = nullptr; - XX = expr; -} - /*----- Unary Expressions -----*/ unary_expr(X) ::= primary(X). diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e545bd5087..38754bdce8 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2712,13 +2712,13 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) return new FxConditional(condition, left, right); } - case AST_VectorInitializer: + case AST_VectorValue: { - auto vecini = static_cast(ast); + auto vecini = static_cast(ast); auto xx = ConvertNode(vecini->X); auto yy = ConvertNode(vecini->Y); auto zz = ConvertNode(vecini->Z); - return new FxVectorInitializer(xx, yy, zz, *ast); + return new FxVectorValue(xx, yy, zz, *ast); } case AST_LocalVarStmt: diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 0889d1d378..715fa0be65 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -98,7 +98,7 @@ enum EZCCTreeNodeType AST_Default, AST_FlagStmt, AST_PropertyStmt, - AST_VectorInitializer, + AST_VectorValue, NUM_AST_NODE_TYPES }; @@ -385,7 +385,7 @@ struct ZCC_ExprTrinary : ZCC_Expression ZCC_Expression *Right; }; -struct ZCC_VectorInitializer : ZCC_Expression +struct ZCC_VectorValue : ZCC_Expression { ZCC_Expression *X, *Y, *Z; }; From 8be7af41a979cbd132e559da660fde38b77242ea Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 30 Oct 2016 04:35:48 +0100 Subject: [PATCH 141/471] Don't use a struct reference for vectors as return type just like for parameters --- src/scripting/zscript/zcc_compile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 38754bdce8..6c83b5a991 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1967,7 +1967,7 @@ void ZCCCompiler::InitFunctions() do { auto type = DetermineType(c->Type(), f, f->Name, t, false, false); - if (type->IsKindOf(RUNTIME_CLASS(PStruct))) + if (type->IsKindOf(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) { // structs and classes only get passed by pointer. type = NewPointer(type); From 5643d6c6928297888e6febd87d8ba3efe719f910 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 30 Oct 2016 06:17:37 +0100 Subject: [PATCH 142/471] Make sure to use the REGT_MULTIREG flags for opcodes that need it --- src/scripting/codegeneration/codegen.cpp | 47 +++++++++++++++--------- src/scripting/vm/vm.h | 4 +- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 0930399025..75058511d1 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -335,6 +335,30 @@ PPrototype *FxExpression::ReturnProto() // //========================================================================== +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); @@ -347,20 +371,7 @@ static int EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const } else { - int regtype = where.RegType; - if (where.Konst) - { - regtype |= REGT_KONST; - } - else if (where.RegCount == 2) - { - regtype |= REGT_MULTIREG2; - } - else if (where.RegCount == 3) - { - regtype |= REGT_MULTIREG3; - } - build->Emit(OP_PARAM, 0, regtype, where.RegNum); + build->Emit(OP_PARAM, 0, EncodeRegType(where), where.RegNum); where.Free(build); return where.RegCount; } @@ -6215,9 +6226,9 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } else if (vmfunc->Proto->ReturnTypes.Size() > 0) { // Call, expecting one result - ExpEmit reg(build, vmfunc->Proto->ReturnTypes[0]->GetRegType()); + 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, reg.RegType, reg.RegNum); + build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum); return reg; } else @@ -6255,7 +6266,7 @@ bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, Ex else { ExpEmit where = arg->Emit(build); - build->Emit(OP_RET, RET_FINAL, where.RegType | (where.Konst ? REGT_KONST : 0), where.RegNum); + build->Emit(OP_RET, RET_FINAL, EncodeRegType(where), where.RegNum); where.Free(build); } reg = ExpEmit(); @@ -7319,7 +7330,7 @@ ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build) } else { - build->Emit(OP_RET, RET_FINAL, out.RegType | (out.Konst ? REGT_KONST : 0), out.RegNum); + build->Emit(OP_RET, RET_FINAL, EncodeRegType(out), out.RegNum); } } } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index d020b8e88a..92615461ec 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -291,14 +291,14 @@ 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 SetVector2(const double val[2]) { - //assert(RegType == REGT_FLOAT); + assert(RegType == (REGT_FLOAT|REGT_MULTIREG2)); ((double *)Location)[0] = val[0]; ((double *)Location)[1] = val[1]; } From 06ec6318a9dbcea64a5a487908d0c95d80856fb8 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 30 Oct 2016 06:55:16 +0100 Subject: [PATCH 143/471] Fixed: A vector value could point to garbage data after being 'unnested' --- src/scripting/codegeneration/codegen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 75058511d1..a0ccbb2c8b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -519,6 +519,7 @@ FxExpression *FxVectorValue::Resolve(FCompileContext&ctx) 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; } } From 9eeb56212b4c9736593df40d91e02c4b77b43fa8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Oct 2016 09:05:42 +0100 Subject: [PATCH 144/471] - fixed: A VM function's NumArgs value needs to count stack arguments, not logical ones, meaning that for vectors each element needs to count separately. - renamed VMFunction::Defaults to DefaultArgs to make searching easier. - let ZCCCompiler process vector defaults for function parameters. --- src/scripting/codegeneration/codegen.h | 10 ++++++- src/scripting/vm/vm.h | 2 +- src/scripting/vm/vmbuilder.cpp | 8 ++++- src/scripting/vm/vmexec.cpp | 4 +-- src/scripting/vm/vmexec.h | 4 +-- src/scripting/vm/vmframe.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 41 ++++++++++++++++++++------ 7 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index f9393d11f7..b3a5e4297e 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -466,12 +466,20 @@ public: class FxVectorValue : public FxExpression { FxExpression *xyz[3]; - bool isConst; // gets set to true if all element are const + 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); }; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 92615461ec..4109d4e794 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -643,7 +643,7 @@ public: bool Native; BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action FName Name; - TArray Defaults; + TArray DefaultArgs; class PPrototype *Proto; diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 3f6d1cbd30..e9ac38a78d 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -722,7 +722,13 @@ void FFunctionBuildList::Build() // Emit code item.Code->Emit(&buildit); buildit.MakeFunction(sfunc); - sfunc->NumArgs = item.Func->Variants[0].Proto->ArgumentTypes.Size(); + 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) { diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index e2691470ed..57ce48a95a 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -188,14 +188,14 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) const VMRegisters calleereg(callee); assert(calleefunc != NULL && !calleefunc->Native); - assert(numparam == calleefunc->NumArgs || ((int)calleefunc->Defaults.Size() == 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 < calleefunc->NumArgs; ++i) { // get all actual parameters and fill the rest from the defaults. - VMValue &p = i < numparam? params[i] : calleefunc->Defaults[i]; + VMValue &p = i < numparam? params[i] : calleefunc->DefaultArgs[i]; if (p.Type < REGT_STRING) { if (p.Type == REGT_INT) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 4b43ed8158..4b16a99d13 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -544,7 +544,7 @@ begin: FillReturns(reg, f, returns, pc+1, C); if (call->Native) { - numret = static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, returns, C); + numret = static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->DefaultArgs, B, returns, C); } else { @@ -588,7 +588,7 @@ begin: if (call->Native) { - return static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, 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 diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index bf2159fa14..c54b585e99 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -415,7 +415,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur { if (func->Native) { - return static_cast(func)->NativeCall(this, params, func->Defaults, numparams, results, numresults); + return static_cast(func)->NativeCall(this, params, func->DefaultArgs, numparams, results, numresults); } else { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6c83b5a991..78a448f7c1 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2022,7 +2022,8 @@ void ZCCCompiler::InitFunctions() { do { - VMValue vmval; // default is REGT_NIL which means 'no default value' here. + 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); @@ -2036,6 +2037,14 @@ void ZCCCompiler::InitFunctions() { type = NewPointer(type); } + else if (type == TypeVector2) + { + elementcount = 2; + } + else if (type == TypeVector3) + { + elementcount = 3; + } } if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3) { @@ -2055,7 +2064,21 @@ void ZCCCompiler::InitFunctions() if (x != nullptr) { - if (!x->isConstant()) + // 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()); } @@ -2070,22 +2093,22 @@ void ZCCCompiler::InitFunctions() switch (type->GetRegType()) { case REGT_INT: - vmval = cnst->GetValue().GetInt(); + vmval[0] = cnst->GetValue().GetInt(); break; case REGT_FLOAT: - vmval = cnst->GetValue().GetFloat(); + vmval[0] = cnst->GetValue().GetFloat(); break; case REGT_POINTER: if (type->IsKindOf(RUNTIME_CLASS(PClassPointer))) - vmval = (DObject*)cnst->GetValue().GetPointer(); + vmval[0] = (DObject*)cnst->GetValue().GetPointer(); else - vmval = cnst->GetValue().GetPointer(); + vmval[0] = cnst->GetValue().GetPointer(); break; case REGT_STRING: - vmval = cnst->GetValue().GetString(); + vmval[0] = cnst->GetValue().GetString(); break; default: @@ -2112,7 +2135,7 @@ void ZCCCompiler::InitFunctions() argflags.Push(0); argnames.Push(NAME_None); } - argdefaults.Push(vmval); + for(int i=0;i(p->SiblingNext); } while (p != f->Params); } @@ -2131,7 +2154,7 @@ void ZCCCompiler::InitFunctions() } if (sym->Variants[0].Implementation != nullptr && hasdefault) // do not copy empty default lists, they only waste space and processing time. { - sym->Variants[0].Implementation->Defaults = std::move(argdefaults); + sym->Variants[0].Implementation->DefaultArgs = std::move(argdefaults); } // todo: Check inheritance. } From f8ccda2dc84265d5e9ed48f34cd5583f4e65ec3e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Oct 2016 14:00:11 +0100 Subject: [PATCH 145/471] - scriptified A_Mushroom to test something a bit more complex. - fixed: FxMinusSign trashed local variables that were used with negation. - fixed: FxConditional only handled ints and floats, but not pointers and strings. - fixed: A 'no states in non-actors' error was triggered, even for classes without any states. --- src/CMakeLists.txt | 1 - src/d_dehacked.cpp | 8 + src/dobject.cpp | 7 + src/g_doom/a_doommisc.cpp | 1 - src/g_doom/a_fatso.cpp | 84 ------- src/info.h | 2 +- src/p_mobj.cpp | 31 +++ src/scripting/codegeneration/codegen.cpp | 292 +++++++++++++---------- src/scripting/thingdef_data.cpp | 3 +- src/scripting/zscript/zcc_compile.cpp | 8 +- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 5 +- wadsrc/static/zscript/base.txt | 8 + wadsrc/static/zscript/constants.txt | 6 + wadsrc/static/zscript/doom/fatso.txt | 55 +++++ 15 files changed, 290 insertions(+), 222 deletions(-) delete mode 100644 src/g_doom/a_fatso.cpp create mode 100644 wadsrc/static/zscript/base.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5c5fd3e34..f96bf7d368 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -838,7 +838,6 @@ set( NOT_COMPILED_SOURCE_FILES g_doom/a_archvile.cpp g_doom/a_bossbrain.cpp g_doom/a_doomweaps.cpp - g_doom/a_fatso.cpp g_doom/a_keen.cpp g_doom/a_lostsoul.cpp g_doom/a_painelemental.cpp diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 064f37c027..cc699ac47b 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1488,6 +1488,14 @@ static int PatchFrame (int frameNum) return result; } +// there is exactly one place where this is needed and we do not want to expose the state internals to ZSCRIPT. +DEFINE_ACTION_FUNCTION(AActor, isDEHState) +{ + PARAM_PROLOGUE; + PARAM_STATE(state); + ACTION_RETURN_BOOL(state != nullptr && (state->DefineFlags & SDF_DEHACKED)); +} + static int PatchSprite (int sprNum) { int result; diff --git a/src/dobject.cpp b/src/dobject.cpp index 4acb86ce40..beef73c89d 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -349,6 +349,13 @@ void DObject::Destroy () ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe; } +DEFINE_ACTION_FUNCTION(DObject, Destroy) +{ + PARAM_SELF_PROLOGUE(DObject); + self->Destroy(); + return 0; +} + //========================================================================== // // diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index df42bfa7be..29e2fc8eec 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -25,7 +25,6 @@ #include "a_archvile.cpp" #include "a_bossbrain.cpp" #include "a_doomweaps.cpp" -#include "a_fatso.cpp" #include "a_keen.cpp" #include "a_lostsoul.cpp" #include "a_painelemental.cpp" diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp deleted file mode 100644 index ea2d8f3977..0000000000 --- a/src/g_doom/a_fatso.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "vm.h" -*/ - -// -// Mancubus attack, -// firing three missiles in three different directions? -// Doesn't look like it. -// -// -// killough 9/98: a mushroom explosion effect, sorta :) -// Original idea: Linguica -// - -enum -{ - MSF_Standard = 0, - MSF_Classic = 1, - MSF_DontHurt = 2, -}; - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_DEF (spawntype, AActor) - PARAM_INT_DEF (n) - PARAM_INT_DEF (flags) - PARAM_FLOAT_DEF (vrange) - PARAM_FLOAT_DEF (hrange) - - int i, j; - - if (n == 0) - { - n = self->GetMissileDamage(0, 1); - } - if (spawntype == NULL) - { - spawntype = PClass::FindActor("FatShot"); - } - - P_RadiusAttack (self, self->target, 128, 128, self->DamageType, (flags & MSF_DontHurt) ? 0 : RADF_HURTSOURCE); - P_CheckSplash(self, 128.); - - // Now launch mushroom cloud - AActor *target = Spawn("Mapspot", self->Pos(), NO_REPLACE); // We need something to aim at. - AActor *master = (flags & MSF_DontHurt) ? (AActor*)(self->target) : self; - target->Height = self->Height; - for (i = -n; i <= n; i += 8) - { - for (j = -n; j <= n; j += 8) - { - AActor *mo; - target->SetXYZ( - self->X() + i, // Aim in many directions from source - self->Y() + j, - self->Z() + (P_AproxDistance(i,j) * vrange)); // Aim up fairly high - if ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options - (flags == 0 && (self->state->DefineFlags & SDF_DEHACKED) && (i_compatflags & COMPATF_MUSHROOM))) - { // Use old function for MBF compatibility - mo = P_OldSpawnMissile (self, master, target, spawntype); - } - else // Use normal function - { - mo = P_SpawnMissile(self, target, spawntype, master); - } - if (mo != NULL) - { // Slow it down a bit - mo->Vel *= hrange; - mo->flags &= ~MF_NOGRAVITY; // Make debris fall under gravity - } - } - } - target->Destroy(); - return 0; -} diff --git a/src/info.h b/src/info.h index 2155734ad4..ad25bdcaf0 100644 --- a/src/info.h +++ b/src/info.h @@ -67,7 +67,7 @@ enum EStateDefineFlags SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump }; -enum EStateType +enum EStateType : int // this must ensure proper alignment. { STATE_Actor, STATE_Psprite, diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 754ec516a8..3fd1be9a1e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4258,6 +4258,17 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a return actor; } +DEFINE_ACTION_FUNCTION(AActor, Spawn) +{ + PARAM_PROLOGUE; + PARAM_CLASS(type, AActor); + PARAM_FLOAT_DEF(x); + PARAM_FLOAT_DEF(y); + PARAM_FLOAT_DEF(z); + PARAM_INT_DEF(flags); + ACTION_RETURN_OBJECT(AActor::StaticSpawn(type, DVector3(x, y, z), replace_t(flags))); +} + PClassActor *ClassForSpawn(FName classname) { PClass *cls = PClass::FindClass(classname); @@ -5951,6 +5962,16 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct return th; } +DEFINE_ACTION_FUNCTION(AActor, OldSpawnMissile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(dest, AActor); + PARAM_CLASS(type, AActor); + PARAM_OBJECT_DEF(owner, AActor); + ACTION_RETURN_OBJECT(P_OldSpawnMissile(self, owner, dest, type)); +} + + //--------------------------------------------------------------------------- // // FUNC P_SpawnMissileAngle @@ -6616,6 +6637,16 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) return 0; } +DEFINE_ACTION_FUNCTION(AActor, SetXYZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + self->SetXYZ(x, y, z); + return 0; +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index a0ccbb2c8b..4fa6da73e3 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -156,7 +156,7 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) if (fail) { - pos.Message(MSG_ERROR, "All return expressions must deduce to the same type"); + pos.Message(MSG_ERROR, "Return type mismatch"); } } @@ -214,7 +214,7 @@ static PSymbolTable Builtins; static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func) { PSymbol *sym = Builtins.FindSymbol(funcname, false); - if (sym == NULL) + if (sym == nullptr) { PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname); VMNativeFunction *calldec = new VMNativeFunction(func, funcname); @@ -282,7 +282,7 @@ bool FxExpression::isConstant() const VMFunction *FxExpression::GetDirectFunction() { - return NULL; + return nullptr; } //========================================================================== @@ -387,7 +387,7 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos) { FxExpression *x; PSymbolConstNumeric *csym = dyn_cast(sym); - if (csym != NULL) + if (csym != nullptr) { if (csym->ValueType->IsA(RUNTIME_CLASS(PInt))) { @@ -400,13 +400,13 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos) else { pos.Message(MSG_ERROR, "Invalid constant '%s'\n", csym->SymbolName.GetChars()); - return NULL; + return nullptr; } } else { pos.Message(MSG_ERROR, "'%s' is not a constant\n", sym->SymbolName.GetChars()); - x = NULL; + x = nullptr; } return x; } @@ -794,7 +794,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) { FxExpression *x = basex; x->ValueType = ValueType; - basex = NULL; + basex = nullptr; delete this; return x; } @@ -833,7 +833,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) } ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } //========================================================================== @@ -891,7 +891,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) if (basex->IsFloat()) { FxExpression *x = basex; - basex = NULL; + basex = nullptr; delete this; return x; } @@ -923,7 +923,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } } @@ -982,7 +982,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx) if (basex->ValueType == TypeName) { FxExpression *x = basex; - basex = NULL; + basex = nullptr; delete this; return x; } @@ -1001,7 +1001,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Cannot convert to name"); delete this; - return NULL; + return nullptr; } } @@ -1060,7 +1060,7 @@ FxExpression *FxStringCast::Resolve(FCompileContext &ctx) if (basex->ValueType == TypeString) { FxExpression *x = basex; - basex = NULL; + basex = nullptr; delete this; return x; } @@ -1091,7 +1091,7 @@ FxExpression *FxStringCast::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Cannot convert to string"); delete this; - return NULL; + return nullptr; } } @@ -1158,7 +1158,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx) { FxExpression *x = basex; x->ValueType = TypeColor; - basex = NULL; + basex = nullptr; delete this; return x; } @@ -1177,7 +1177,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Cannot convert to color"); delete this; - return NULL; + return nullptr; } } @@ -1237,7 +1237,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx) { FxExpression *x = basex; x->ValueType = TypeSound; - basex = NULL; + basex = nullptr; delete this; return x; } @@ -1256,7 +1256,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Cannot convert to sound"); delete this; - return NULL; + return nullptr; } } @@ -1318,6 +1318,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) // first deal with the simple types if (ValueType == TypeError || basex->ValueType == TypeError) { + ScriptPosition.Message(MSG_ERROR, "Trying to cast to invalid type. This error message means that somewhere in the script compiler an error check is missing."); delete this; return nullptr; } @@ -1502,7 +1503,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx) if (Operand->IsNumeric() || Operand->IsVector()) { FxExpression *e = Operand; - Operand = NULL; + Operand = nullptr; delete this; return e; } @@ -1510,7 +1511,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } } @@ -1571,7 +1572,7 @@ FxExpression *FxMinusSign::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } } @@ -1587,7 +1588,14 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) ExpEmit from = Operand->Emit(build); assert(from.Konst == 0); assert(ValueType->GetRegCount() == from.RegCount); - // Do it in-place. + // Do it in-place, unless a local variable + if (from.Fixed) + { + ExpEmit to = ExpEmit(build, from.RegType, from.RegCount); + build->Emit(Operand->ValueType->GetMoveOp(), to.RegNum, from.RegNum); + from = to; + } + if (ValueType->GetRegType() == REGT_INT) { build->Emit(OP_NEG, from.RegNum, from.RegNum, 0); @@ -1653,10 +1661,10 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) // DECORATE allows floats here so cast them to int. Operand = new FxIntCast(Operand, true); Operand = Operand->Resolve(ctx); - if (Operand == NULL) + if (Operand == nullptr) { delete this; - return NULL; + return nullptr; } } @@ -1665,7 +1673,7 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "Integer type expected"); delete this; - return NULL; + return nullptr; } if (Operand->isConstant()) @@ -1804,13 +1812,13 @@ FxExpression *FxSizeAlign::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "cannot determine %s of a constant", Which == TK_AlignOf? "alignment" : "size"); delete this; - return NULL; + return nullptr; } else if (!Operand->RequestAddress(nullptr)) { ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == TK_AlignOf ? "alignment" : "size"); delete this; - return NULL; + return nullptr; } else { @@ -2513,7 +2521,8 @@ FxAddSub::FxAddSub(int o, FxExpression *l, FxExpression *r) FxExpression *FxAddSub::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return NULL; + if (!ResolveLR(ctx, true)) + return nullptr; if (!IsNumeric() && !IsVector()) { @@ -2652,13 +2661,14 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return NULL; + if (!ResolveLR(ctx, true)) + return nullptr; if (!IsNumeric() && !IsVector()) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } else if (left->isConstant() && right->isConstant()) { @@ -2672,7 +2682,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "Division by 0"); delete this; - return NULL; + return nullptr; } v = Operator == '*'? v1 * v2 : @@ -2693,7 +2703,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "Division by 0"); delete this; - return NULL; + return nullptr; } v = Operator == '*'? v1 * v2 : @@ -2820,7 +2830,8 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return nullptr; + if (!ResolveLR(ctx, true)) + return nullptr; if (!IsNumeric()) { @@ -2879,13 +2890,14 @@ FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r) FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return NULL; + if (!ResolveLR(ctx, true)) + return nullptr; if (!IsNumeric()) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } else if (left->isConstant() && right->isConstant()) { @@ -3038,19 +3050,20 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return NULL; + if (!ResolveLR(ctx, true)) + return nullptr; if (!left || !right) { delete this; - return NULL; + return nullptr; } if (!IsNumeric() && !IsPointer() && !IsVector() && ValueType != TypeName) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } if (Operator == TK_ApproxEq && left->ValueType->GetRegType() != REGT_FLOAT && left->ValueType->GetRegType() != REGT_STRING) @@ -3174,7 +3187,8 @@ FxBinaryInt::FxBinaryInt(int o, FxExpression *l, FxExpression *r) FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, false)) return NULL; + if (!ResolveLR(ctx, false)) + return nullptr; if (IsFloat() && ctx.FromDecorate) { @@ -3189,10 +3203,10 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) right = new FxIntCast(right, ctx.FromDecorate); right = right->Resolve(ctx); } - if (left == NULL || right == NULL) + if (left == nullptr || right == nullptr) { delete this; - return NULL; + return nullptr; } ValueType = TypeSInt32; } @@ -3201,7 +3215,7 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "Integer type expected"); delete this; - return NULL; + return nullptr; } else if (left->isConstant() && right->isConstant()) { @@ -3322,7 +3336,8 @@ FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r) FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) return NULL; + if (!ResolveLR(ctx, true)) + return nullptr; if (!left->IsNumeric() || !right->IsNumeric()) { @@ -3467,14 +3482,14 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx) else if (b_left==1) { FxExpression *x = right; - right=NULL; + right=nullptr; delete this; return x; } else if (b_right==1) { FxExpression *x = left; - left=NULL; + left=nullptr; delete this; return x; } @@ -3496,14 +3511,14 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx) else if (b_left==0) { FxExpression *x = right; - right=NULL; + right=nullptr; delete this; return x; } else if (b_right==0) { FxExpression *x = left; - left=NULL; + left=nullptr; delete this; return x; } @@ -3723,7 +3738,7 @@ ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build) PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); auto callfunc = ((PSymbolVMFunction *)sym)->Function; int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); @@ -3813,7 +3828,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) FxExpression *e = result? truex:falsex; delete (result? falsex:truex); - falsex = truex = NULL; + falsex = truex = nullptr; delete this; return e; } @@ -3867,9 +3882,22 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) ExpEmit trueop = truex->Emit(build); if (trueop.Konst) { - assert(trueop.RegType == REGT_FLOAT); - out = ExpEmit(build, REGT_FLOAT); - build->Emit(OP_LKF, out.RegNum, trueop.RegNum); + if (trueop.RegType == REGT_FLOAT) + { + out = ExpEmit(build, REGT_FLOAT); + build->Emit(OP_LKF, out.RegNum, trueop.RegNum); + } + else if (trueop.RegType == REGT_POINTER) + { + out = ExpEmit(build, REGT_POINTER); + build->Emit(OP_LKP, out.RegNum, trueop.RegNum); + } + else + { + assert(trueop.RegType == REGT_STRING); + out = ExpEmit(build, REGT_STRING); + build->Emit(OP_LKS, out.RegNum, trueop.RegNum); + } } else { @@ -3892,8 +3920,22 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) ExpEmit falseop = falsex->Emit(build); if (falseop.Konst) { - assert(falseop.RegType == REGT_FLOAT); - build->Emit(OP_LKF, out.RegNum, falseop.RegNum); + if (falseop.RegType == REGT_FLOAT) + { + out = ExpEmit(build, REGT_FLOAT); + build->Emit(OP_LKF, out.RegNum, falseop.RegNum); + } + else if (falseop.RegType == REGT_POINTER) + { + out = ExpEmit(build, REGT_POINTER); + build->Emit(OP_LKP, out.RegNum, falseop.RegNum); + } + else + { + assert(falseop.RegType == REGT_STRING); + out = ExpEmit(build, REGT_STRING); + build->Emit(OP_LKS, out.RegNum, falseop.RegNum); + } } else { @@ -3901,17 +3943,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) // returned by "true" so that only one register is returned by // this tree. falseop.Free(build); - if (falseop.RegType == REGT_INT) - { - build->Emit(OP_MOVE, out.RegNum, falseop.RegNum, 0); - } - else - { - assert(falseop.RegType == REGT_FLOAT); - assert(falseop.RegCount == out.RegCount); - static int flops[] = { OP_MOVEF, OP_MOVEV2, OP_MOVEV3 }; - build->Emit(flops[falseop.RegNum], out.RegNum, falseop.RegNum, 0); - } + build->Emit(falsex->ValueType->GetMoveOp(), out.RegNum, falseop.RegNum, 0); } } build->BackpatchToHere(truejump); @@ -3958,7 +3990,7 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return NULL; + return nullptr; } else if (val->isConstant()) { @@ -3976,7 +4008,7 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx) default: // shouldn't happen delete this; - return NULL; + return nullptr; } FxExpression *x = new FxConstant(value, ScriptPosition); delete this; @@ -4047,7 +4079,7 @@ FxExpression *FxATan2::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); delete this; - return NULL; + return nullptr; } if (yval->isConstant() && xval->isConstant()) { @@ -4151,7 +4183,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Arguments must be of type int or float"); delete this; - return NULL; + return nullptr; } } if (floatcount != 0) @@ -4230,7 +4262,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx) } } delete choices[j]; - choices[j] = NULL; + choices[j] = nullptr; choices.Delete(j); } } @@ -4329,12 +4361,12 @@ FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScrip : FxExpression(EFX_Random, pos) { EmitTail = false; - if (mi != NULL && ma != NULL) + if (mi != nullptr && ma != nullptr) { min = new FxIntCast(mi, nowarn); max = new FxIntCast(ma, nowarn); } - else min = max = NULL; + else min = max = nullptr; rng = r; ValueType = TypeSInt32; } @@ -4424,13 +4456,13 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build) PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); - if (min != NULL && max != NULL) + if (min != nullptr && max != nullptr) { EmitParameter(build, min, ScriptPosition); EmitParameter(build, max, ScriptPosition); @@ -4545,7 +4577,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); @@ -4623,9 +4655,9 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) // //========================================================================== FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos) -: FxRandom(r, NULL, NULL, pos, true) +: FxRandom(r, nullptr, nullptr, pos, true) { - if (mi != NULL && ma != NULL) + if (mi != nullptr && ma != nullptr) { min = new FxFloatCast(mi); max = new FxFloatCast(ma); @@ -4670,13 +4702,13 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); - if (min != NULL && max != NULL) + if (min != nullptr && max != nullptr) { EmitParameter(build, min, ScriptPosition); EmitParameter(build, max, ScriptPosition); @@ -4764,7 +4796,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); @@ -4896,7 +4928,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } // now check the global identifiers. - else if ((sym = ctx.FindGlobal(Identifier)) != NULL) + else if ((sym = ctx.FindGlobal(Identifier)) != nullptr) { if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) { @@ -4910,7 +4942,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } // and line specials - else if ((num = P_FindLineSpecial(Identifier, NULL, NULL))) + else if ((num = P_FindLineSpecial(Identifier, nullptr, nullptr))) { ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num); newex = new FxConstant(num, ScriptPosition); @@ -5355,25 +5387,25 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) // DECORATE allows floats here so cast them to int. index = new FxIntCast(index, ctx.FromDecorate); index = index->Resolve(ctx); - if (index == NULL) + if (index == nullptr) { delete this; - return NULL; + return nullptr; } } if (index->ValueType->GetRegType() != REGT_INT && index->ValueType != TypeName) { ScriptPosition.Message(MSG_ERROR, "Array index must be integer"); delete this; - return NULL; + return nullptr; } PArray *arraytype = dyn_cast(Array->ValueType); - if (arraytype == NULL) + if (arraytype == nullptr) { ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); delete this; - return NULL; + return nullptr; } if (index->isConstant()) { @@ -5382,7 +5414,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Array index out of bounds"); delete this; - return NULL; + return nullptr; } } @@ -5392,13 +5424,13 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) // int arrays only for now ScriptPosition.Message(MSG_ERROR, "Only numeric arrays are supported."); delete this; - return NULL; + return nullptr; } if (!Array->RequestAddress(&AddressWritable)) { ScriptPosition.Message(MSG_ERROR, "Unable to dereference array."); delete this; - return NULL; + return nullptr; } return this; } @@ -5901,12 +5933,12 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) bool failed = false; SAFE_RESOLVE_OPT(Self, ctx); - if (ArgList != NULL) + if (ArgList != nullptr) { for (unsigned i = 0; i < ArgList->Size(); i++) { (*ArgList)[i] = (*ArgList)[i]->Resolve(ctx); - if ((*ArgList)[i] == NULL) + if ((*ArgList)[i] == nullptr) { failed = true; } @@ -5934,7 +5966,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) if (failed) { delete this; - return NULL; + return nullptr; } } ValueType = TypeSInt32; @@ -5959,7 +5991,7 @@ int BuiltinCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray { 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])); + 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) @@ -5970,7 +6002,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) // fixme: This really should use the Self pointer that got passed to this class instead of just using the first argument from the function. // Once static functions are possible, or specials can be called through a member access operator this won't work anymore. build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self - if (ArgList != NULL) + if (ArgList != nullptr) { for (; i < ArgList->Size(); ++i) { @@ -6002,7 +6034,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; if (EmitTail) @@ -6144,7 +6176,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) if (failed) { delete this; - return NULL; + return nullptr; } TArray &rets = proto->ReturnTypes; if (rets.Size() > 0) @@ -6207,7 +6239,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } } // Emit code to pass explicit parameters - if (ArgList != NULL) + if (ArgList != nullptr) { for (unsigned i = 0; i < ArgList->Size(); ++i) { @@ -6311,25 +6343,25 @@ FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (ArgList == NULL || ArgList->Size() != 1) + if (ArgList == nullptr || ArgList->Size() != 1) { ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", FName(FxFlops[Index].Name).GetChars()); delete this; - return NULL; + return nullptr; } (*ArgList)[0] = (*ArgList)[0]->Resolve(ctx); - if ((*ArgList)[0] == NULL) + if ((*ArgList)[0] == nullptr) { delete this; - return NULL; + return nullptr; } if (!(*ArgList)[0]->IsNumeric()) { ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); delete this; - return NULL; + return nullptr; } if ((*ArgList)[0]->isConstant()) { @@ -6417,7 +6449,7 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx) CHECKRESOLVED(); for (unsigned i = 0; i < Expressions.Size(); ++i) { - if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx))) + if (nullptr == (Expressions[i] = Expressions[i]->Resolve(ctx))) { delete this; return nullptr; @@ -6455,7 +6487,7 @@ VMFunction *FxSequence::GetDirectFunction() { return Expressions[0]->GetDirectFunction(); } - return NULL; + return nullptr; } //========================================================================== @@ -6792,7 +6824,7 @@ FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part, WhenFalse = false_part; if (WhenTrue != nullptr) WhenTrue->NeedResult = false; if (WhenFalse != nullptr) WhenFalse->NeedResult = false; - assert(cond != NULL); + assert(cond != nullptr); } FxIfStatement::~FxIfStatement() @@ -6840,8 +6872,8 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) FxExpression *e = result ? WhenTrue : WhenFalse; delete (result ? WhenFalse : WhenTrue); - WhenTrue = WhenFalse = NULL; - if (e == NULL) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts. + WhenTrue = WhenFalse = nullptr; + if (e == nullptr) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts. delete this; return e; } @@ -6861,7 +6893,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) ExpEmit cond = Condition->Emit(build); assert(cond.RegType != REGT_STRING && !cond.Konst); - if (WhenTrue != NULL) + if (WhenTrue != nullptr) { path1 = WhenTrue; path2 = WhenFalse; @@ -6871,9 +6903,9 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) { // When there is only a false path, reverse the condition so we can // treat it as a true path. - assert(WhenFalse != NULL); + assert(WhenFalse != nullptr); path1 = WhenFalse; - path2 = NULL; + path2 = nullptr; condcheck = 0; } @@ -6900,7 +6932,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) // Evaluate first path v = path1->Emit(build); v.Free(build); - if (path2 != NULL) + if (path2 != nullptr) { size_t path1jump = build->Emit(OP_JMP, 0); // Evaluate second path @@ -7412,18 +7444,18 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to class type", basex->ValueType->DescriptiveName()); delete this; - return NULL; + return nullptr; } if (basex->isConstant()) { FName clsname = static_cast(basex)->GetValue().GetName(); - PClass *cls = NULL; + PClass *cls = nullptr; if (clsname != NAME_None) { cls = PClass::FindClass(clsname); - if (cls == NULL) + if (cls == nullptr) { /* lax */ // Since this happens in released WADs it must pass without a terminal error... :( @@ -7437,7 +7469,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { ScriptPosition.Message(MSG_ERROR, "class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); delete this; - return NULL; + return nullptr; } ScriptPosition.Message(MSG_DEBUG, "resolving '%s' as class name", clsname.GetChars()); } @@ -7474,7 +7506,7 @@ int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray &def if (!cls->IsDescendantOf(desttype)) { Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); - cls = NULL; + cls = nullptr; } ret->SetPointer(const_cast(cls), ATAG_OBJECT); return 1; @@ -7484,7 +7516,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) { if (basex->ValueType != TypeName) { - return ExpEmit(build->GetConstantAddress(NULL, ATAG_OBJECT), REGT_POINTER, true); + return ExpEmit(build->GetConstantAddress(nullptr, ATAG_OBJECT), REGT_POINTER, true); } ExpEmit clsname = basex->Emit(build); assert(!clsname.Konst); @@ -7497,7 +7529,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); @@ -7526,7 +7558,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d", ctx.Class->TypeName.GetChars(), index); delete this; - return NULL; + return nullptr; } FxExpression *x = new FxConstant(aclass->OwnedStates + index, ScriptPosition); delete this; @@ -7677,7 +7709,7 @@ FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPositi } names = MakeStateNameList(statestring); names.Insert(0, scopename); - scope = NULL; + scope = nullptr; } //========================================================================== @@ -7693,7 +7725,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) if (names[0] == NAME_None) { - scope = NULL; + scope = nullptr; } else if (names[0] == NAME_Super) { @@ -7702,27 +7734,27 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) else { scope = PClass::FindActor(names[0]); - if (scope == NULL) + if (scope == nullptr) { ScriptPosition.Message(MSG_ERROR, "Unknown class '%s' in state label", names[0].GetChars()); delete this; - return NULL; + return nullptr; } else if (!scope->IsAncestorOf(ctx.Class)) { ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars()); delete this; - return NULL; + return nullptr; } } - if (scope != NULL) + if (scope != nullptr) { - FState *destination = NULL; + FState *destination = nullptr; // If the label is class specific we can resolve it right here if (names[1] != NAME_None) { destination = scope->FindState(names.Size()-1, &names[1], false); - if (destination == NULL) + if (destination == nullptr) { ScriptPosition.Message(MSG_OPTERROR, "Unknown state jump destination"); /* lax */ @@ -7749,7 +7781,7 @@ static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMRetu { PARAM_OBJECT_AT(0, self, AActor); FState *state = self->GetClass()->FindState(numparam - 1, names); - if (state == NULL) + if (state == nullptr) { const char *dot = ""; Printf("Jump target '"); @@ -7822,7 +7854,7 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) } assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != NULL); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), names.Size() + 1, 1); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index f071614a84..6c47fabe07 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -671,7 +671,7 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_Score, TypeSInt32, VARF_Native, myoffsetof(AActor, Score))); symt.AddSymbol(new PField(NAME_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor, accuracy))); symt.AddSymbol(new PField(NAME_Stamina, TypeSInt32, VARF_Native, myoffsetof(AActor, stamina))); - symt.AddSymbol(new PField(NAME_Height, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, Height))); + symt.AddSymbol(new PField(NAME_Height, TypeFloat64, VARF_Native, myoffsetof(AActor, Height))); symt.AddSymbol(new PField(NAME_Radius, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, radius))); symt.AddSymbol(new PField(NAME_ReactionTime, TypeSInt32, VARF_Native, myoffsetof(AActor, reactiontime))); symt.AddSymbol(new PField(NAME_MeleeRange, TypeFloat64, VARF_Native, myoffsetof(AActor, meleerange))); @@ -698,6 +698,7 @@ void InitThingdef() symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos))); symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel))); symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale))); + symt.AddSymbol(new PField("CurState", TypeState, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, state))); // has to be renamed on the script side because it clashes with the same named type. symt.AddSymbol(new PField("SeeState", TypeState, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, SeeState))); symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master))); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 78a448f7c1..9e8b84163d 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1490,6 +1490,7 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) } return type; } + Error(type, "Unable to resolve %s as type.", FName(type->UserType->Id).GetChars()); return TypeError; } @@ -2186,8 +2187,8 @@ static bool CheckRandom(ZCC_Expression *duration) FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) { // We have 3 cases to consider here: - // 1. An action function without parameters. This can be called directly - // 2. An action functon with parameters or a non-action function. This needs to be wrapped into a helper function to set everything up. + // 1. A function without parameters. This can be called directly + // 2. A functon with parameters. This needs to be wrapped into a helper function to set everything up. // 3. An anonymous function. // 1. and 2. are exposed through AST_ExprFunctionCall @@ -2236,9 +2237,10 @@ void ZCCCompiler::CompileStates() { for (auto c : Classes) { + if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor))) { - Error(c->cls, "%s: States can only be defined for actors.", c->Type()->TypeName.GetChars()); + if (c->States.Size()) Error(c->cls, "%s: States can only be defined for actors.", c->Type()->TypeName.GetChars()); continue; } FString statename; // The state builder wants the label as one complete string, not separated into tokens. diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 6de64d07e5..8ea4bb114c 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,3 +1,4 @@ +zscript/base.txt zscript/constants.txt zscript/actor.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 18f0facd0c..4fc18d75de 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -53,9 +53,13 @@ class Actor : Thinker native return GetPointer(ptr_select1) == GetPointer(ptr_select2); } + native static bool isDehState(state st); native void SetOrigin(vector3 newpos, bool moving); + native void SetXYZ(vector3 newpos); native Actor GetPointer(int aaptr); + native static Actor Spawn(class type, vector3 pos = (0,0,0), int replace = NO_REPLACE); native Actor SpawnMissile(Actor dest, class type, Actor owner = null); + native Actor OldSpawnMissile(Actor dest, class type, Actor owner = null); native void TraceBleed(int damage, Actor missile); native bool CheckMeleeRange(); native int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0); @@ -228,7 +232,6 @@ class Actor : Thinker native native void A_SpawnFly(class spawntype = null); // needs special treatment for default native void A_BrainExplode(); native void A_Detonate(); - native void 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); native void A_SetFloorClip(); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt new file mode 100644 index 0000000000..bda63f059d --- /dev/null +++ b/wadsrc/static/zscript/base.txt @@ -0,0 +1,8 @@ +class Object native +{ + /*virtual*/ native void Destroy(); +} + +class Thinker : Object native +{ +} \ No newline at end of file diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index b14634e0d2..5cbbbaf9e3 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -876,3 +876,9 @@ enum EDmgFlags DMG_NO_PROTECT = 256, DMG_USEANGLE = 512, } + +enum EReplace +{ + NO_REPLACE = 0, + ALLOW_REPLACE = 1 +} diff --git a/wadsrc/static/zscript/doom/fatso.txt b/wadsrc/static/zscript/doom/fatso.txt index c477cbb447..d1a456d16a 100644 --- a/wadsrc/static/zscript/doom/fatso.txt +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -110,6 +110,12 @@ extend class Actor A_PlaySound("fatso/raiseguns", CHAN_WEAPON); } + // + // Mancubus attack, + // firing three missiles in three different directions? + // Doesn't look like it. + // + void A_FatAttack1(class spawntype = "FatShot") { if (target) @@ -163,5 +169,54 @@ extend class Actor } } } + + // + // killough 9/98: a mushroom explosion effect, sorta :) + // Original idea: Linguica + // + + void A_Mushroom(class 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(); + } + } From a652c5f259426bbc09c08f50657029a4f91fb9ae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Oct 2016 16:21:44 +0100 Subject: [PATCH 146/471] - fixed: For named functions the prototype needs to be set before the code generator starts resolving. Otherwise it will crash on incompletely set up forward declarations. --- src/scripting/vm/vmbuilder.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index e9ac38a78d..afadaaa1ed 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -673,6 +673,13 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c it.Function->ImplicitArgs = functype->GetImplicitArgs(); it.Proto = nullptr; it.FromDecorate = fromdecorate; + + // 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; } @@ -714,10 +721,13 @@ void FFunctionBuildList::Build() { assert(item.Proto != nullptr); - // Generate prototype for this anonymous function + // 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. - sfunc->Proto = NewPrototype(item.Proto->ReturnTypes, item.Func->Variants[0].Proto->ArgumentTypes); + if (sfunc->Proto == nullptr) + { + sfunc->Proto = NewPrototype(item.Proto->ReturnTypes, item.Func->Variants[0].Proto->ArgumentTypes); + } // Emit code item.Code->Emit(&buildit); From 2857fac3386194d45959faabdbe66dd194cd621a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Oct 2016 18:41:39 +0100 Subject: [PATCH 147/471] - scriptified a_archvile.cpp. - fixed the type checks for the conditional operator. --- src/CMakeLists.txt | 1 - src/g_doom/a_archvile.cpp | 160 ----------------------- src/g_doom/a_doommisc.cpp | 1 - src/p_actionfunctions.cpp | 3 +- src/p_mobj.cpp | 10 ++ src/scripting/codegeneration/codegen.cpp | 3 +- src/scripting/vm/vm.h | 15 +++ wadsrc/static/zscript/actor.txt | 7 +- wadsrc/static/zscript/constants.txt | 3 +- wadsrc/static/zscript/doom/archvile.txt | 88 +++++++++++++ 10 files changed, 120 insertions(+), 171 deletions(-) delete mode 100644 src/g_doom/a_archvile.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f96bf7d368..12df2e61cc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -835,7 +835,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_doom/a_archvile.cpp g_doom/a_bossbrain.cpp g_doom/a_doomweaps.cpp g_doom/a_keen.cpp diff --git a/src/g_doom/a_archvile.cpp b/src/g_doom/a_archvile.cpp deleted file mode 100644 index 959c5763d8..0000000000 --- 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 "vm.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_SELF_PROLOGUE(AActor); - 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_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_BODY, "vile/firestrt", 1, ATTN_NORM); - A_Fire (self, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FireCrackle) -{ - PARAM_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_BODY, "vile/firecrkl", 1, ATTN_NORM); - A_Fire (self, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Fire) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_DEF(height); - - 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_SELF_PROLOGUE(AActor); - PARAM_CLASS_DEF(fire, AActor); - - 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_SELF_PROLOGUE(AActor); - PARAM_SOUND_DEF (snd) - PARAM_INT_DEF (dmg) - PARAM_INT_DEF (blastdmg) - PARAM_INT_DEF (blastrad) - PARAM_FLOAT_DEF (thrust) - PARAM_NAME_DEF (dmgtype) - PARAM_INT_DEF (flags) - - 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_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 29e2fc8eec..31ee228f80 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -22,7 +22,6 @@ #include "vm.h" // Include all the other Doom stuff here to reduce compile time -#include "a_archvile.cpp" #include "a_bossbrain.cpp" #include "a_doomweaps.cpp" #include "a_keen.cpp" diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 9f3a088d67..4748b1708a 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1362,6 +1362,7 @@ enum XF_HURTSOURCE = 1, XF_NOTMISSILE = 4, XF_NOACTORTYPE = 1 << 3, + XF_NOSPLASH = 16, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) @@ -1412,7 +1413,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); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3fd1be9a1e..26987e6224 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6647,6 +6647,16 @@ DEFINE_ACTION_FUNCTION(AActor, SetXYZ) 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)); +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4fa6da73e3..66a7d8b41b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -345,6 +345,7 @@ static int EncodeRegType(ExpEmit reg) else if (reg.RegCount == 2) { regtype |= REGT_MULTIREG2; + } else if (reg.RegCount == 3) { @@ -3808,7 +3809,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) ValueType = TypeVoid; //else if (truex->ValueType != falsex->ValueType) - if ((!IsNumeric() && !IsPointer() && !IsVector()) || ValueType == TypeVoid) + if (ValueType->GetRegType() == REGT_NIL) { ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator"); delete this; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 4109d4e794..ca7aa6d547 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -4,6 +4,7 @@ #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 @@ -296,12 +297,25 @@ struct VMReturn ((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); @@ -1029,6 +1043,7 @@ struct AFuncDesc #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) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 4fc18d75de..83ea76cb77 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -70,6 +70,7 @@ class Actor : Thinker native native bool SetState(state st, bool nofunction = false); native void LinkToWorld(); native void UnlinkFromWorld(); + native vector3 Vec3Angle(float length, float angle, float z = 0, bool absolute = false); native void VelFromAngle(float speed = 0, float angle = 0); native bool isFriend(Actor other); @@ -209,12 +210,6 @@ class Actor : Thinker native native void A_Chase(state melee = null, state missile = null, int flags = 0); native void A_Scream(); native void A_VileChase(); - native void A_VileStart(); - native void A_VileTarget(class fire = "ArchvileFire"); - native void 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); - native void A_StartFire(); - native void A_Fire(float spawnheight = 0); - native void A_FireCrackle(); native void A_Tracer(); native void A_SkelWhoosh(); native void A_SkelFist(); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 5cbbbaf9e3..9562e3f407 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -243,7 +243,8 @@ enum EExplodeFlags { XF_HURTSOURCE = 1, XF_NOTMISSILE = 4, - XF_EXPLICITDAMAGETYPE = 1 << 3, + XF_EXPLICITDAMAGETYPE = 8, + XF_NOSPLASH = 16, }; // Flags for A_RadiusThrust diff --git a/wadsrc/static/zscript/doom/archvile.txt b/wadsrc/static/zscript/doom/archvile.txt index bdca2b05f6..0e9008570f 100644 --- a/wadsrc/static/zscript/doom/archvile.txt +++ b/wadsrc/static/zscript/doom/archvile.txt @@ -87,3 +87,91 @@ class ArchvileFire : Actor } } + +//=========================================================================== +// +// 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(); + } +} From 6ff973a06bd97dfd1c2c5191b508fdbd98f62063 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Sun, 30 Oct 2016 22:15:40 -0500 Subject: [PATCH 148/471] Modify CMPJMP to produce more compact code (as far as VC++ is concerned, anyway) --- src/scripting/vm/vmexec.cpp | 14 +++++++---- src/scripting/vm/vmexec.h | 46 ++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 57ce48a95a..af25030a9c 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -82,11 +82,17 @@ #define THROW(x) throw(EVMAbortException(x)) #define CMPJMP(test) \ - if ((test) == (a & CMP_CHECK)) { \ + pc++; \ + if (VM_UBYTE(test) == VM_UBYTE(a)) { \ assert(pc[1].op == OP_JMP); \ - pc += 1 + JMPOFS(pc+1); \ - } else { \ - pc += 1; \ + pc += JMPOFS(pc); \ + } + +#define CMPJMP_MASK(test) \ + pc++; \ + if (VM_UBYTE(test) == (VM_UBYTE(a) & CMP_CHECK)) { \ + assert(pc[1].op == OP_JMP); \ + pc += JMPOFS(pc); \ } #define GETADDR(a,o,x) \ diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 4b16a99d13..10b85ef868 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1199,88 +1199,88 @@ begin: ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP(fabs(reg.f[C] - reg.f[B]) < VM_EPSILON); + CMPJMP_MASK(fabs(reg.f[C] - reg.f[B]) < VM_EPSILON); } else { - CMPJMP(reg.f[C] == reg.f[B]); + CMPJMP_MASK(reg.f[C] == reg.f[B]); } NEXTOP; OP(EQF_K): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP(fabs(konstf[C] - reg.f[B]) < VM_EPSILON); + CMPJMP_MASK(fabs(konstf[C] - reg.f[B]) < VM_EPSILON); } else { - CMPJMP(konstf[C] == reg.f[B]); + CMPJMP_MASK(konstf[C] == reg.f[B]); } NEXTOP; OP(LTF_RR): ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP((reg.f[B] - reg.f[C]) < -VM_EPSILON); + CMPJMP_MASK((reg.f[B] - reg.f[C]) < -VM_EPSILON); } else { - CMPJMP(reg.f[B] < reg.f[C]); + CMPJMP_MASK(reg.f[B] < reg.f[C]); } NEXTOP; OP(LTF_RK): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP((reg.f[B] - konstf[C]) < -VM_EPSILON); + CMPJMP_MASK((reg.f[B] - konstf[C]) < -VM_EPSILON); } else { - CMPJMP(reg.f[B] < konstf[C]); + CMPJMP_MASK(reg.f[B] < konstf[C]); } NEXTOP; OP(LTF_KR): ASSERTKF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP((konstf[B] - reg.f[C]) < -VM_EPSILON); + CMPJMP_MASK((konstf[B] - reg.f[C]) < -VM_EPSILON); } else { - CMPJMP(konstf[B] < reg.f[C]); + CMPJMP_MASK(konstf[B] < reg.f[C]); } NEXTOP; OP(LEF_RR): ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP((reg.f[B] - reg.f[C]) <= -VM_EPSILON); + CMPJMP_MASK((reg.f[B] - reg.f[C]) <= -VM_EPSILON); } else { - CMPJMP(reg.f[B] <= reg.f[C]); + CMPJMP_MASK(reg.f[B] <= reg.f[C]); } NEXTOP; OP(LEF_RK): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP((reg.f[B] - konstf[C]) <= -VM_EPSILON); + CMPJMP_MASK((reg.f[B] - konstf[C]) <= -VM_EPSILON); } else { - CMPJMP(reg.f[B] <= konstf[C]); + CMPJMP_MASK(reg.f[B] <= konstf[C]); } NEXTOP; OP(LEF_KR): ASSERTKF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP((konstf[B] - reg.f[C]) <= -VM_EPSILON); + CMPJMP_MASK((konstf[B] - reg.f[C]) <= -VM_EPSILON); } else { - CMPJMP(konstf[B] <= reg.f[C]); + CMPJMP_MASK(konstf[B] <= reg.f[C]); } NEXTOP; @@ -1369,12 +1369,12 @@ begin: Do_EQV2: if (a & CMP_APPROX) { - CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && - fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON); + CMPJMP_MASK(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]); + CMPJMP_MASK(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1]); } NEXTOP; OP(EQV2_K): @@ -1496,13 +1496,13 @@ begin: Do_EQV3: if (a & CMP_APPROX) { - CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && - fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON && - fabs(reg.f[B+2] - fcp[2]) < VM_EPSILON); + CMPJMP_MASK(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && + fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON && + fabs(reg.f[B+2] - fcp[2]) < VM_EPSILON); } else { - CMPJMP(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1] && reg.f[B+2] == fcp[2]); + CMPJMP_MASK(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1] && reg.f[B+2] == fcp[2]); } NEXTOP; OP(EQV3_K): From e620c9bd7dc777fa733b4fbf0662506b17474807 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 31 Oct 2016 17:02:47 +0100 Subject: [PATCH 149/471] - scriptified parts of a_bossbrain.cpp. Some things cannot be done yet, the script code is there but commented out. - exported thinker iterator and drop item chain to scripting. Unlike its native counterpart the script-side iterator is wrapped into a DObject to allow proper handling for memory management. - fixed: The VMFunctionBuilder only distinguished between member and action functions but failed on static ones. - fixed: FxAssign did not add all needed type casts. Except for purely numeric types it will now wrap the expression in an FxTypeCast. Numeric handling remains unchanged for both performance reasons and not altering semantics for DECORATE. - exported all internal flags as variables to scripting. They still cannot be used in an actor definition. - make ATAG_STATE the same as ATAG_GENERIC. Since state pointers exist as actual variables they can take both values which on occasion can trigger some asserts. - gave PClass a bExported flag, so that scripts cannot see purely internal classes. Especially the types like PInt can cause problems. Todo: we need readonly references to safely expose the actor defaults. Right now some badly behaving code could overwrite them. --- src/d_dehacked.cpp | 2 +- src/dobjtype.cpp | 1 + src/dobjtype.h | 1 + src/dthinker.cpp | 38 +++ src/g_doom/a_bossbrain.cpp | 95 ------- src/p_mobj.cpp | 23 ++ src/scripting/codegeneration/codegen.cpp | 240 ++++++++++++++---- src/scripting/codegeneration/codegen.h | 25 +- src/scripting/thingdef_data.cpp | 51 +++- src/scripting/vm/vm.h | 2 +- src/scripting/vm/vmbuilder.cpp | 4 +- src/scripting/vm/vmbuilder.h | 6 +- src/scripting/vm/vmexec.h | 2 +- src/scripting/zscript/zcc_compile.cpp | 1 + wadsrc/static/zscript/actor.txt | 11 +- wadsrc/static/zscript/base.txt | 25 +- wadsrc/static/zscript/doom/bossbrain.txt | 302 +++++++++++++++++++++++ 17 files changed, 668 insertions(+), 161 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index cc699ac47b..896e174d65 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -808,8 +808,8 @@ void SetDehParams(FState *state, int codepointer) } else { - VMFunctionBuilder buildit(true); 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(numargs); diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 7eb152ebdf..57a67384a0 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2737,6 +2737,7 @@ PClass::PClass() HashNext = NULL; Defaults = NULL; bRuntimeClass = false; + bExported = false; ConstructNative = NULL; mDescriptiveName = "Class"; diff --git a/src/dobjtype.h b/src/dobjtype.h index 302352b21b..5aeefac502 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -769,6 +769,7 @@ public: 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 void (*ConstructNative)(void *); diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 114d260df7..022e147da0 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -521,6 +521,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); +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/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 1b50cb3cc6..f58e753750 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -12,103 +12,8 @@ #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_SELF_PROLOGUE(AActor); - // 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_SELF_PROLOGUE(AActor); - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - 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_SELF_PROLOGUE(AActor); - - // [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_SELF_PROLOGUE(AActor); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 26987e6224..f597b89c27 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6612,6 +6612,20 @@ 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, 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)); +} // This combines all 3 variations of the internal function DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) @@ -6657,6 +6671,15 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3Angle) 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)); +} //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 66a7d8b41b..fa5405c601 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2078,6 +2078,8 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) 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) @@ -2113,32 +2115,13 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) } // Both types are the same so this is ok. } - else if ((Base->ValueType == TypeState || Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) && Right->ValueType == TypeNullPtr) - { - // null pointers can be assigned to any other pointer - } - else if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) - { - // class pointers may be assignable so add a cast which performs a check. - Right = new FxClassTypeCast(static_cast(ValueType), Right); - SAFE_RESOLVE(Right, ctx); - } - else if (Base->ValueType == TypeString && (Right->ValueType == TypeName || Right->ValueType == TypeSound)) - { - Right = new FxStringCast(Right); - SAFE_RESOLVE(Right, ctx); - } - else if (Base->ValueType == TypeName && Right->ValueType == TypeString) - { - Right = new FxNameCast(Right); - SAFE_RESOLVE(Right, ctx); - } else { - ScriptPosition.Message(MSG_ERROR, "Assignment between incompatible types."); - delete this; - return nullptr; + // pass it to FxTypeCast for complete handling. + Right = new FxTypeCast(Right, Base->ValueType, false); + SAFE_RESOLVE(Right, ctx); } + if (!Base->RequestAddress(&AddressWritable) || !AddressWritable) { ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); @@ -3100,6 +3083,69 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) delete this; return e; } + else + { + // also simplify comparisons against zero. For these a bool cast on the other value will do just as well and create better code. + 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 = 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 = new FxBoolCast(left); + left = nullptr; + delete this; + return x->Resolve(ctx); + } + } + } Promote(ctx); ValueType = TypeBool; return this; @@ -3720,7 +3766,7 @@ int BuiltinTypeCheck(VMFrameStack *stack, VMValue *param, TArray &defau assert(numparam == 2); PARAM_POINTER_AT(0, obj, DObject); PARAM_CLASS_AT(1, cls, DObject); - ACTION_RETURN_BOOL(obj->IsKindOf(cls)); + ACTION_RETURN_BOOL(obj && obj->IsKindOf(cls)); } //========================================================================== @@ -3762,6 +3808,72 @@ ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build) // //========================================================================== +FxDynamicCast::FxDynamicCast(PClass * cls, FxExpression *r) + : FxExpression(EFX_DynamicCast, r->ScriptPosition) +{ + expr = new FxTypeCast(r, NewPointer(RUNTIME_CLASS(DObject)), true, true); + ValueType = NewPointer(cls); + CastType = cls; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxDynamicCast::~FxDynamicCast() +{ + SAFE_DELETE(expr); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(expr, ctx); + 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); + auto patch = build->Emit(OP_EQ_K, 0, check.RegNum, build->GetConstantInt(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) { @@ -5655,6 +5767,24 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) 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; @@ -5681,7 +5811,12 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) break; case NAME_Random: - if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) + // 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; @@ -5754,7 +5889,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) break; default: - // todo: Check for class type casts + ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); break; } if (func != nullptr) @@ -5762,7 +5897,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) delete this; return func->Resolve(ctx); } - ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); delete this; return nullptr; } @@ -5803,10 +5937,22 @@ FxMemberFunctionCall::~FxMemberFunctionCall() FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) { ABORT(ctx.Class); - SAFE_RESOLVE(Self, ctx); - PClass *cls; bool staticonly = 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->IsVector()) { // handle builtins: Vectors got 2: Length and Unit. @@ -5819,12 +5965,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } } - if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) - { - cls = static_cast(Self->ValueType)->ClassRestriction; - staticonly = true; - } - else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { auto ptype = static_cast(Self->ValueType)->PointedType; if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) @@ -5845,6 +5986,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } +isresolved: bool error = false; PFunction *afd = FindClassMemberFunction(cls, cls, MethodName, ScriptPosition, &error); if (error) @@ -5859,7 +6001,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return nullptr; } - if (staticonly && !(afd->Variants[0].Flags & VARF_Static)) + if (staticonly && (afd->Variants[0].Flags & VARF_Method)) { if (!ctx.Class->IsDescendantOf(cls)) { @@ -5867,11 +6009,17 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return nullptr; } - // If this is a qualified call to a parent class function, let it through (but this needs to disable virtual calls later.) + 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_Static) ? Self : nullptr; + auto self = (afd->Variants[0].Flags & VARF_Method) ? Self : nullptr; auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly); ArgList = nullptr; if (Self == self) Self = nullptr; @@ -6128,7 +6276,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) int implicit = Function->GetImplicitArgs(); // This should never happen. - if (Self == nullptr && !(Function->Variants[0].Flags & VARF_Static)) + if (Self == nullptr && (Function->Variants[0].Flags & VARF_Method)) { ScriptPosition.Message(MSG_ERROR, "Call to non-static function without a self pointer"); delete this; @@ -6200,8 +6348,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { - assert((build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= NAP) || - (!build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 1)); + assert(build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits); int count = 0; (ArgList ? ArgList->Size() : 0); if (count == 1) @@ -6225,7 +6372,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) if (Function->Variants[0].Flags & VARF_Action) { static_assert(NAP == 3, "This code needs to be updated if NAP changes"); - if (build->IsActionFunc && selfemit.RegNum == 0) // only pass this function's stateowner and stateinfo if the subfunction is run in self's context. + 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); @@ -6238,6 +6385,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } count += 2; } + selfemit.Free(build); } // Emit code to pass explicit parameters if (ArgList != nullptr) @@ -7654,7 +7802,9 @@ static int BuiltinHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build) { - assert(build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 3 && + // This code can only be called from DECORATE, not ZSCRIPT so any function going through here + // is an anoynmous one which are always marked as 'action'. + assert(build->NumImplicits >= NAP && build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits && "FxRuntimeStateIndex is only valid inside action functions"); ExpEmit out(build, REGT_POINTER); @@ -7741,7 +7891,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) delete this; return nullptr; } - else if (!scope->IsAncestorOf(ctx.Class)) + else if (!scope->IsAncestorOf(ctx.Class) && ctx.Class != RUNTIME_CLASS(AActor)) // AActor needs access to subclasses in a few places. TBD: Relax this for non-action functions? { ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars()); delete this; @@ -7827,7 +7977,7 @@ int BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, TArrayIsActionFunc) + if (build->NumImplicits == NAP) { build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // pass stateowner } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index b3a5e4297e..cfe261b39b 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -268,6 +268,7 @@ enum EFxType EFX_VectorValue, EFX_VectorBuiltin, EFX_TypeCheck, + EFX_DynamicCast, EFX_COUNT }; @@ -320,10 +321,9 @@ public: class FxIdentifier : public FxExpression { -protected: +public: FName Identifier; -public: FxIdentifier(FName i, const FScriptPosition &p); FxExpression *Resolve(FCompileContext&); }; @@ -940,7 +940,7 @@ public: //========================================================================== // -// FxBinaryLogical +// // //========================================================================== @@ -959,6 +959,25 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxDynamicCast : public FxExpression +{ + PClass *CastType; +public: + FxExpression *expr; + + FxDynamicCast(PClass*, FxExpression*); + ~FxDynamicCast(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxConditional diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 6c47fabe07..c623290daf 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -61,6 +61,39 @@ static TArray AFTable; #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 } +// internal flags. These do not get exposed to actor definitions but scripts need to be able to access them as variables. +static 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, DONTTRANSLATE, 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, NOSKIN, 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), +}; + + static FFlagDef ActorFlagDefs[]= { DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags), @@ -687,6 +720,7 @@ void InitThingdef() symt.AddSymbol(new PField("Gravity", TypeFloat64, VARF_Native, myoffsetof(AActor, Gravity))); symt.AddSymbol(new PField("DamageType", TypeName, VARF_Native, myoffsetof(AActor, DamageType))); symt.AddSymbol(new PField("FloatBobPhase", TypeUInt8, VARF_Native, myoffsetof(AActor, FloatBobPhase))); + symt.AddSymbol(new PField("tics", TypeSInt32, VARF_Native, myoffsetof(AActor, tics))); symt.AddSymbol(new PField("RipperLevel", TypeSInt32, VARF_Native, myoffsetof(AActor, RipperLevel))); symt.AddSymbol(new PField("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin))); symt.AddSymbol(new PField("RipLevelMax", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMax))); @@ -695,6 +729,7 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle))); symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch))); symt.AddSymbol(new PField("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound))); + symt.AddSymbol(new PField("DeathSound", TypeSound, VARF_Native, myoffsetof(AActor, DeathSound))); symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos))); symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel))); symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale))); @@ -706,7 +741,7 @@ void InitThingdef() symt.AddSymbol(new PField("LastHeard", TypeActor, VARF_Native, myoffsetof(AActor, LastHeard))); symt.AddSymbol(new PField("LastEnemy", TypeActor, VARF_Native, myoffsetof(AActor, lastenemy))); - // synthesize a symbol for each flag. The bounce flags are excluded on purpose. + // synthesize a symbol for each flag. for (size_t i = 0; i < countof(ActorFlagDefs); i++) { int bit = 0; @@ -714,5 +749,19 @@ void InitThingdef() while ((val >>= 1)) bit++; symt.AddSymbol(new PField(FStringf("b%s", ActorFlagDefs[i].name), (ActorFlagDefs[i].fieldsize == 4? TypeSInt32 : TypeSInt16), ActorFlagDefs[i].varflags, ActorFlagDefs[i].structoffset, bit)); } + for (size_t i = 0; i < countof(InternalActorFlagDefs); i++) + { + int bit = 0; + unsigned val = InternalActorFlagDefs[i].flagbit; + while ((val >>= 1)) bit++; + symt.AddSymbol(new PField(FStringf("b%s", InternalActorFlagDefs[i].name), (InternalActorFlagDefs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), InternalActorFlagDefs[i].varflags, InternalActorFlagDefs[i].structoffset, bit)); + } + + PSymbolTable &symt2 = RUNTIME_CLASS(DDropItem)->Symbols; + PType *TypeDropItem = NewPointer(RUNTIME_CLASS(DDropItem)); + symt2.AddSymbol(new PField("Next", TypeDropItem, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Next))); + symt2.AddSymbol(new PField("ItemName", TypeName, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Name))); + symt2.AddSymbol(new PField("Probability", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Probability))); + symt2.AddSymbol(new PField("Amount", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Amount))); } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index ca7aa6d547..811fb82e09 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -161,8 +161,8 @@ enum ATAG_SREGISTER, // pointer to a string register ATAG_AREGISTER, // pointer to an address register - ATAG_STATE, // pointer to FState 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 diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index afadaaa1ed..d2d9e7140f 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -43,7 +43,7 @@ // //========================================================================== -VMFunctionBuilder::VMFunctionBuilder(bool selfcheck) +VMFunctionBuilder::VMFunctionBuilder(int numimplicits) { NumIntConstants = 0; NumFloatConstants = 0; @@ -51,7 +51,7 @@ VMFunctionBuilder::VMFunctionBuilder(bool selfcheck) NumStringConstants = 0; MaxParam = 0; ActiveParam = 0; - IsActionFunc = selfcheck; + NumImplicits = numimplicits; } //========================================================================== diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index dcaae72518..9a97c216d2 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -23,7 +23,7 @@ public: friend class VMFunctionBuilder; }; - VMFunctionBuilder(bool checkself = false); + VMFunctionBuilder(int numimplicits); ~VMFunctionBuilder(); void MakeFunction(VMScriptFunction *func); @@ -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 diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 10b85ef868..500c30c667 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -175,7 +175,7 @@ begin: OP(LO): ASSERTA(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); - reg.a[a] = GC::ReadBarrier(*(DObject **)ptr); + reg.a[a] = *(DObject **)ptr; reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(LO_R): diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 9e8b84163d..98d847ebe2 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -508,6 +508,7 @@ void ZCCCompiler::CreateClassTypes() // We will never get here if the name is a duplicate, so we can just do the assignment. 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); c->Type()->Symbols.SetName(c->NodeName()); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 83ea76cb77..213ca8b254 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -53,6 +53,8 @@ class Actor : Thinker native return GetPointer(ptr_select1) == GetPointer(ptr_select2); } + native static /*readonly*/ Actor GetDefaultByType(class cls); + native void SetDamage(int dmg); native static bool isDehState(state st); native void SetOrigin(vector3 newpos, bool moving); native void SetXYZ(vector3 newpos); @@ -71,6 +73,7 @@ class Actor : Thinker native native void LinkToWorld(); native void UnlinkFromWorld(); 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 bool isFriend(Actor other); @@ -218,14 +221,6 @@ class Actor : Thinker native native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); native void A_KeenDie(int doortag = 666); - native void A_BrainPain(); - native void A_BrainScream(); - native void A_BrainDie(); - native void A_BrainAwake(); - native void A_BrainSpit(class spawntype = null); // needs special treatment for default - native void A_SpawnSound(); - native void A_SpawnFly(class spawntype = null); // needs special treatment for default - native void A_BrainExplode(); 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); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index bda63f059d..cca39f1e23 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -5,4 +5,27 @@ class Object native class Thinker : Object native { -} \ No newline at end of file +} + +class ThinkerIterator : Object native +{ + enum EStatnums + { + MAX_STATNUM = 127 + } + + native static ThinkerIterator Create(class type = "Actor", int statnum=MAX_STATNUM+1); + native Thinker Next(); + native void Reinit(); +} + +class DropItem : Object native +{ + /* native fields listed for reference only for now + native readonly DropItem Next; + native readonly name ItemName; // internally called 'name' which clashes with the type. + native readonly int Probability; + native readonly int Amount; + */ +} + diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 533d0fa01c..2193be9542 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -133,3 +133,305 @@ class SpawnFire : Actor 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.; + + State stt = "BossBrain::Brainexplode"; + if (stt) boom.SetState (stt); + } + 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() + { + A_Log("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) + { + AActor newmobj; + AActor fog; + AActor eye = master; // The eye is the spawnshot's master, not the target! + AActor 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; + + 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 = randon[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, null)) + { + newmobj.SetState (newmobj.SeeState); + } + if (!(newmobj.ObjectFlags & OF_EuthanizeMe)) + { + // telefrag anything in this spot + newmobj.TeleportMove (newmobj.pos, true); + } + newmobj.bBossSpawned = true; + } + } + + // remove self (i.e., cube). + Destroy (); + } + */ + + + native + void A_SpawnFly(class spawntype = null) // needs special treatment for default + ; + /* + { + sound snd; + if (spawntype != null) + { + snd = GetDefaultByType(spawntype).SeeSound; + } + else + { + spawntype = "SpawnFire"; + snd = "brain/spawn"; + } + SpawnFly(self, spawntype, snd); + } + */ + + native + void A_SpawnSound() + ; + /* + { + // travelling cube sound + A_PlaySound("brain/cube", CHAN_BODY); + SpawnFly("SpawnFire", "brain/spawn"); + } + */ +} From 7137e87b4b709fcc2675b7fef3d0c36b96e3b47f Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Sun, 30 Oct 2016 13:43:20 +0100 Subject: [PATCH 150/471] - Fixed GCC/Clang errors from recent commits. --- src/scripting/codegeneration/codegen.cpp | 28 ++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index fa5405c601..f1dfab523c 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -563,8 +563,10 @@ ExpEmit FxVectorValue::Emit(VMFunctionBuilder *build) assert(xyz[1] != nullptr); if (ValueType == TypeVector2) { - ExpEmit xval = EmitKonst(build, xyz[0]->Emit(build)); - ExpEmit yval = EmitKonst(build, xyz[1]->Emit(build)); + 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) { @@ -586,7 +588,8 @@ ExpEmit FxVectorValue::Emit(VMFunctionBuilder *build) else if (xyz[0]->ValueType == TypeVector2) // vec2+float { ExpEmit xyval = xyz[0]->Emit(build); - ExpEmit zval = EmitKonst(build, xyz[1]->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) { @@ -608,9 +611,12 @@ ExpEmit FxVectorValue::Emit(VMFunctionBuilder *build) else // 3*float { assert(xyz[2] != nullptr); - ExpEmit xval = EmitKonst(build, xyz[0]->Emit(build)); - ExpEmit yval = EmitKonst(build, xyz[1]->Emit(build)); - ExpEmit zval = EmitKonst(build, xyz[2]->Emit(build)); + 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) { @@ -2308,7 +2314,7 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) if (left == nullptr) { delete this; - return nullptr; + return false; } } if (right->ValueType != TypeString) @@ -2318,7 +2324,7 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) if (right == nullptr) { delete this; - return nullptr; + return false; } } ValueType = TypeBool; @@ -2464,7 +2470,7 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) delete this; return false; } - assert(ValueType > nullptr && ValueType < (PType*)0xfffffffffffffff); + assert(ValueType != nullptr && ValueType < (PType*)0xfffffffffffffff); if (castnumeric) { @@ -3206,7 +3212,7 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) // 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, op1.RegNum, op2.RegNum); + 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; @@ -3925,7 +3931,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator"); delete this; - return false; + return nullptr; } if (condition->ValueType != TypeBool) From 88fd47247d41fc3a46f5f41f060591b3f773003a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 1 Nov 2016 16:32:47 +0100 Subject: [PATCH 151/471] - scriptified several trivial functions from a_action.cpp. --- src/g_shared/a_action.cpp | 223 -------------------------------- src/p_mobj.cpp | 7 + src/scripting/thingdef_data.cpp | 1 + wadsrc/static/zscript/actor.txt | 35 +++-- 4 files changed, 25 insertions(+), 241 deletions(-) diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index abd58dec11..0ec388de85 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -109,71 +109,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking) return 0; } -DEFINE_ACTION_FUNCTION(AActor, A_Fall) -{ - PARAM_SELF_PROLOGUE(AActor); - A_Unblock(self, true); - return 0; -} - -//========================================================================== -// -// A_SetFloorClip -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_SetFloorClip) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 |= MF2_FLOORCLIP; - self->AdjustFloorClip (); - return 0; -} - -//========================================================================== -// -// A_UnSetFloorClip -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetFloorClip) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 &= ~MF2_FLOORCLIP; - self->Floorclip = 0; - return 0; -} - -//========================================================================== -// -// A_HideThing -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_HideThing) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->renderflags |= RF_INVISIBLE; - return 0; -} - -//========================================================================== -// -// A_UnHideThing -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_UnHideThing) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->renderflags &= ~RF_INVISIBLE; - return 0; -} - //============================================================================ // // A_FreezeDeath @@ -475,164 +410,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeQueueCorpse) return 0; } -//============================================================================ -// -// A_SetInvulnerable -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SetInvulnerable) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 |= MF2_INVULNERABLE; - return 0; -} - -//============================================================================ -// -// A_UnSetInvulnerable -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetInvulnerable) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 &= ~MF2_INVULNERABLE; - return 0; -} - -//============================================================================ -// -// A_SetReflective -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SetReflective) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 |= MF2_REFLECTIVE; - return 0; -} - -//============================================================================ -// -// A_UnSetReflective -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetReflective) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 &= ~MF2_REFLECTIVE; - return 0; -} - -//============================================================================ -// -// A_SetReflectiveInvulnerable -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SetReflectiveInvulnerable) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 |= MF2_REFLECTIVE|MF2_INVULNERABLE; - return 0; -} - -//============================================================================ -// -// A_UnSetReflectiveInvulnerable -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetReflectiveInvulnerable) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 &= ~(MF2_REFLECTIVE|MF2_INVULNERABLE); - return 0; -} - -//========================================================================== -// -// A_SetShootable -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_SetShootable) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 &= ~MF2_NONSHOOTABLE; - self->flags |= MF_SHOOTABLE; - return 0; -} - -//========================================================================== -// -// A_UnSetShootable -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_UnSetShootable) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags2 |= MF2_NONSHOOTABLE; - self->flags &= ~MF_SHOOTABLE; - return 0; -} - -//=========================================================================== -// -// A_NoGravity -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_NoGravity) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags |= MF_NOGRAVITY; - return 0; -} - -//=========================================================================== -// -// A_Gravity -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_Gravity) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags &= ~MF_NOGRAVITY; - self->Gravity = 1; - return 0; -} - -//=========================================================================== -// -// A_LowGravity -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_LowGravity) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags &= ~MF_NOGRAVITY; - self->Gravity = 1. / 8;; - return 0; -} - //=========================================================================== // // FaceMovementDirection diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f597b89c27..bd78fdcef4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4509,6 +4509,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. diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index c623290daf..b0edcb167f 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -718,6 +718,7 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_Damage, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, DamageVal))); symt.AddSymbol(new PField("visdir", TypeSInt32, VARF_Native, myoffsetof(AActor, visdir))); symt.AddSymbol(new PField("Gravity", TypeFloat64, VARF_Native, myoffsetof(AActor, Gravity))); + symt.AddSymbol(new PField("FloorClip", TypeFloat64, VARF_Native, myoffsetof(AActor, Floorclip))); symt.AddSymbol(new PField("DamageType", TypeName, VARF_Native, myoffsetof(AActor, DamageType))); symt.AddSymbol(new PField("FloatBobPhase", TypeUInt8, VARF_Native, myoffsetof(AActor, FloatBobPhase))); symt.AddSymbol(new PField("tics", TypeSInt32, VARF_Native, myoffsetof(AActor, tics))); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 213ca8b254..1e05d75a79 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -76,6 +76,7 @@ class Actor : Thinker native native vector3 Vec2OffsetZ(float x, float y, float atz, bool absolute = false); native void VelFromAngle(float speed = 0, float angle = 0); native bool isFriend(Actor other); + native void AdjustFloorClip(); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); @@ -98,7 +99,22 @@ class Actor : Thinker native // 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 = true; 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; } @@ -208,6 +224,7 @@ class Actor : Thinker native 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(); + void A_Fall() { A_NoBlocking(); } native void A_XScream(); native void A_Look(); native void A_Chase(state melee = null, state missile = null, int flags = 0); @@ -224,24 +241,6 @@ class Actor : Thinker native 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_SetFloorClip(); - native void A_UnSetFloorClip(); - native void A_HideThing(); - native void A_UnHideThing(); - native void A_SetInvulnerable(); - native void A_UnSetInvulnerable(); - native void A_SetReflective(); - native void A_UnSetReflective(); - native void A_SetReflectiveInvulnerable(); - native void A_UnSetReflectiveInvulnerable(); - native void A_SetShootable(); - native void A_UnSetShootable(); - native void A_NoGravity(); - native void A_Gravity(); - native void A_LowGravity(); - - native void A_Fall(); - native void A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); native void A_ScreamAndUnblock(); From 5e76d3af186a9ba78955e22d402feb99d0fef6f7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 00:14:08 +0100 Subject: [PATCH 152/471] - fixed BrainishExplosion and removed some unnecessary checks, the state to be set is being defined in the same file, after all... --- wadsrc/static/zscript/doom/bossbrain.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 2193be9542..641263eccb 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -162,13 +162,12 @@ extend class Actor boom.DeathSound = "misc/brainexplode"; boom.Vel.z = random[BrainScream](0, 255)/128.; - State stt = "BossBrain::Brainexplode"; - if (stt) boom.SetState (stt); + boom.SetState ("BossBrain::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; } - 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() From ff8b216167dedc041a422a3c382fef2599264aec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 10:52:14 +0100 Subject: [PATCH 153/471] SHA-1: 8852bc7278d033bbed66c51bf23aee841ee977a9 * Revert "Modify CMPJMP to produce more compact code (as far as VC++ is concerned, anyway)" This reverts commit 6ff973a06bd97dfd1c2c5191b508fdbd98f62063. This modification did not work and broke the comparisons. Actually this had three problems: * the asserts checked the wrong instruction * the mask was not applied to regular comparisons. * incrementing PC before testing does not work because 'test' references the PC. --- src/scripting/vm/vmexec.cpp | 14 ++++------- src/scripting/vm/vmexec.h | 46 ++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index af25030a9c..57ce48a95a 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -82,17 +82,11 @@ #define THROW(x) throw(EVMAbortException(x)) #define CMPJMP(test) \ - pc++; \ - if (VM_UBYTE(test) == VM_UBYTE(a)) { \ + if ((test) == (a & CMP_CHECK)) { \ assert(pc[1].op == OP_JMP); \ - pc += JMPOFS(pc); \ - } - -#define CMPJMP_MASK(test) \ - pc++; \ - if (VM_UBYTE(test) == (VM_UBYTE(a) & CMP_CHECK)) { \ - assert(pc[1].op == OP_JMP); \ - pc += JMPOFS(pc); \ + pc += 1 + JMPOFS(pc+1); \ + } else { \ + pc += 1; \ } #define GETADDR(a,o,x) \ diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 500c30c667..69f406dd81 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1199,88 +1199,88 @@ begin: ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK(fabs(reg.f[C] - reg.f[B]) < VM_EPSILON); + CMPJMP(fabs(reg.f[C] - reg.f[B]) < VM_EPSILON); } else { - CMPJMP_MASK(reg.f[C] == reg.f[B]); + CMPJMP(reg.f[C] == reg.f[B]); } NEXTOP; OP(EQF_K): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP_MASK(fabs(konstf[C] - reg.f[B]) < VM_EPSILON); + CMPJMP(fabs(konstf[C] - reg.f[B]) < VM_EPSILON); } else { - CMPJMP_MASK(konstf[C] == reg.f[B]); + CMPJMP(konstf[C] == reg.f[B]); } NEXTOP; OP(LTF_RR): ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((reg.f[B] - reg.f[C]) < -VM_EPSILON); + CMPJMP((reg.f[B] - reg.f[C]) < -VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] < reg.f[C]); + CMPJMP(reg.f[B] < reg.f[C]); } NEXTOP; OP(LTF_RK): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((reg.f[B] - konstf[C]) < -VM_EPSILON); + CMPJMP((reg.f[B] - konstf[C]) < -VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] < konstf[C]); + CMPJMP(reg.f[B] < konstf[C]); } NEXTOP; OP(LTF_KR): ASSERTKF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((konstf[B] - reg.f[C]) < -VM_EPSILON); + CMPJMP((konstf[B] - reg.f[C]) < -VM_EPSILON); } else { - CMPJMP_MASK(konstf[B] < reg.f[C]); + CMPJMP(konstf[B] < reg.f[C]); } NEXTOP; OP(LEF_RR): ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((reg.f[B] - reg.f[C]) <= -VM_EPSILON); + CMPJMP((reg.f[B] - reg.f[C]) <= -VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] <= reg.f[C]); + CMPJMP(reg.f[B] <= reg.f[C]); } NEXTOP; OP(LEF_RK): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((reg.f[B] - konstf[C]) <= -VM_EPSILON); + CMPJMP((reg.f[B] - konstf[C]) <= -VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] <= konstf[C]); + CMPJMP(reg.f[B] <= konstf[C]); } NEXTOP; OP(LEF_KR): ASSERTKF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((konstf[B] - reg.f[C]) <= -VM_EPSILON); + CMPJMP((konstf[B] - reg.f[C]) <= -VM_EPSILON); } else { - CMPJMP_MASK(konstf[B] <= reg.f[C]); + CMPJMP(konstf[B] <= reg.f[C]); } NEXTOP; @@ -1369,12 +1369,12 @@ begin: Do_EQV2: if (a & CMP_APPROX) { - CMPJMP_MASK(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && - fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON); + CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && + fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1]); + CMPJMP(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1]); } NEXTOP; OP(EQV2_K): @@ -1496,13 +1496,13 @@ begin: Do_EQV3: if (a & CMP_APPROX) { - CMPJMP_MASK(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && - fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON && - fabs(reg.f[B+2] - fcp[2]) < VM_EPSILON); + CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && + fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON && + fabs(reg.f[B+2] - fcp[2]) < VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1] && reg.f[B+2] == fcp[2]); + CMPJMP(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1] && reg.f[B+2] == fcp[2]); } NEXTOP; OP(EQV3_K): From 703aaa373e0127657cd88960c48bb330a99324fc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 10:52:14 +0100 Subject: [PATCH 154/471] SHA-1: 8852bc7278d033bbed66c51bf23aee841ee977a9 * Revert "Modify CMPJMP to produce more compact code (as far as VC++ is concerned, anyway)" This reverts commit 6ff973a06bd97dfd1c2c5191b508fdbd98f62063. This modification did not work and broke the comparisons. Actually this had three problems: * the asserts checked the wrong instruction * the mask was not applied to regular comparisons. * incrementing PC before testing does not work because 'test' references the PC. --- src/scripting/vm/vmexec.cpp | 14 ++++------- src/scripting/vm/vmexec.h | 46 ++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index af25030a9c..57ce48a95a 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -82,17 +82,11 @@ #define THROW(x) throw(EVMAbortException(x)) #define CMPJMP(test) \ - pc++; \ - if (VM_UBYTE(test) == VM_UBYTE(a)) { \ + if ((test) == (a & CMP_CHECK)) { \ assert(pc[1].op == OP_JMP); \ - pc += JMPOFS(pc); \ - } - -#define CMPJMP_MASK(test) \ - pc++; \ - if (VM_UBYTE(test) == (VM_UBYTE(a) & CMP_CHECK)) { \ - assert(pc[1].op == OP_JMP); \ - pc += JMPOFS(pc); \ + pc += 1 + JMPOFS(pc+1); \ + } else { \ + pc += 1; \ } #define GETADDR(a,o,x) \ diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 500c30c667..69f406dd81 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1199,88 +1199,88 @@ begin: ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK(fabs(reg.f[C] - reg.f[B]) < VM_EPSILON); + CMPJMP(fabs(reg.f[C] - reg.f[B]) < VM_EPSILON); } else { - CMPJMP_MASK(reg.f[C] == reg.f[B]); + CMPJMP(reg.f[C] == reg.f[B]); } NEXTOP; OP(EQF_K): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP_MASK(fabs(konstf[C] - reg.f[B]) < VM_EPSILON); + CMPJMP(fabs(konstf[C] - reg.f[B]) < VM_EPSILON); } else { - CMPJMP_MASK(konstf[C] == reg.f[B]); + CMPJMP(konstf[C] == reg.f[B]); } NEXTOP; OP(LTF_RR): ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((reg.f[B] - reg.f[C]) < -VM_EPSILON); + CMPJMP((reg.f[B] - reg.f[C]) < -VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] < reg.f[C]); + CMPJMP(reg.f[B] < reg.f[C]); } NEXTOP; OP(LTF_RK): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((reg.f[B] - konstf[C]) < -VM_EPSILON); + CMPJMP((reg.f[B] - konstf[C]) < -VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] < konstf[C]); + CMPJMP(reg.f[B] < konstf[C]); } NEXTOP; OP(LTF_KR): ASSERTKF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((konstf[B] - reg.f[C]) < -VM_EPSILON); + CMPJMP((konstf[B] - reg.f[C]) < -VM_EPSILON); } else { - CMPJMP_MASK(konstf[B] < reg.f[C]); + CMPJMP(konstf[B] < reg.f[C]); } NEXTOP; OP(LEF_RR): ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((reg.f[B] - reg.f[C]) <= -VM_EPSILON); + CMPJMP((reg.f[B] - reg.f[C]) <= -VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] <= reg.f[C]); + CMPJMP(reg.f[B] <= reg.f[C]); } NEXTOP; OP(LEF_RK): ASSERTF(B); ASSERTKF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((reg.f[B] - konstf[C]) <= -VM_EPSILON); + CMPJMP((reg.f[B] - konstf[C]) <= -VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] <= konstf[C]); + CMPJMP(reg.f[B] <= konstf[C]); } NEXTOP; OP(LEF_KR): ASSERTKF(B); ASSERTF(C); if (a & CMP_APPROX) { - CMPJMP_MASK((konstf[B] - reg.f[C]) <= -VM_EPSILON); + CMPJMP((konstf[B] - reg.f[C]) <= -VM_EPSILON); } else { - CMPJMP_MASK(konstf[B] <= reg.f[C]); + CMPJMP(konstf[B] <= reg.f[C]); } NEXTOP; @@ -1369,12 +1369,12 @@ begin: Do_EQV2: if (a & CMP_APPROX) { - CMPJMP_MASK(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && - fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON); + CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && + fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1]); + CMPJMP(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1]); } NEXTOP; OP(EQV2_K): @@ -1496,13 +1496,13 @@ begin: Do_EQV3: if (a & CMP_APPROX) { - CMPJMP_MASK(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && - fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON && - fabs(reg.f[B+2] - fcp[2]) < VM_EPSILON); + CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && + fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON && + fabs(reg.f[B+2] - fcp[2]) < VM_EPSILON); } else { - CMPJMP_MASK(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1] && reg.f[B+2] == fcp[2]); + CMPJMP(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1] && reg.f[B+2] == fcp[2]); } NEXTOP; OP(EQV3_K): From 570572fcf2f6561c920279c98df53b79a79d86b7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 11:44:48 +0100 Subject: [PATCH 155/471] - scriptified a_hereticimp.cpp. - fixed the comparison against 0 simplification which did not negate the result for '=='. --- src/CMakeLists.txt | 1 - src/g_heretic/a_hereticimp.cpp | 96 ----------------- src/scripting/codegeneration/codegen.cpp | 103 ++++++++++--------- wadsrc/static/zscript/heretic/hereticimp.txt | 79 ++++++++++++-- 4 files changed, 128 insertions(+), 151 deletions(-) delete mode 100644 src/g_heretic/a_hereticimp.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 12df2e61cc..adc90444dc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -845,7 +845,6 @@ set( NOT_COMPILED_SOURCE_FILES 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 diff --git a/src/g_heretic/a_hereticimp.cpp b/src/g_heretic/a_hereticimp.cpp deleted file mode 100644 index 39dfb049ec..0000000000 --- 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 "vm.h" -*/ - -static FRandom pr_impmsatk ("ImpMsAttack"); -static FRandom pr_imp ("ImpExplode"); - - -//---------------------------------------------------------------------------- -// -// PROC A_ImpMsAttack -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ImpMsAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - self->flags &= ~MF_SOLID; - self->flags2 |= MF2_FLOORCLIP; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpXDeath1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ImpXDeath1) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f1dfab523c..d3923b2317 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3091,64 +3091,71 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) } else { - // also simplify comparisons against zero. For these a bool cast on the other value will do just as well and create better code. - if (left->isConstant()) + // 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) { - bool leftisnull; - switch (left->ValueType->GetRegType()) + if (left->isConstant()) { - case REGT_INT: - leftisnull = static_cast(left)->GetValue().GetInt() == 0; - break; + 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_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; + 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); + } - default: - leftisnull = false; } - if (leftisnull) + if (right->isConstant()) { - FxExpression *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; + 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_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; + case REGT_POINTER: + rightisnull = static_cast(right)->GetValue().GetPointer() == nullptr; + break; - default: - rightisnull = false; - } - if (rightisnull) - { - FxExpression *x = new FxBoolCast(left); - left = nullptr; - delete this; - return x->Resolve(ctx); + 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); + } } } } diff --git a/wadsrc/static/zscript/heretic/hereticimp.txt b/wadsrc/static/zscript/heretic/hereticimp.txt index 5764094de4..34738ed566 100644 --- a/wadsrc/static/zscript/heretic/hereticimp.txt +++ b/wadsrc/static/zscript/heretic/hereticimp.txt @@ -3,6 +3,8 @@ class HereticImp : Actor { + bool extremecrash; + Default { Health 40; @@ -26,12 +28,6 @@ class HereticImp : Actor HitObituary "$OB_HERETICIMPHIT"; } - native void A_ImpMsAttack(); - native void A_ImpDeath(); - native void A_ImpXDeath1(); - native void A_ImpExplode(); - - States { Spawn: @@ -75,6 +71,77 @@ class HereticImp : Actor 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) + { + SetState ("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 ------------------------------------------------------- From 3a7f51db88e281970693c5d33ae057755620cd73 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 13:39:37 +0100 Subject: [PATCH 156/471] a_hereticimp.cpp does not exist anymore... --- src/g_heretic/a_hereticmisc.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 2d4f3497ce..2ea39a4bcb 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -24,7 +24,6 @@ #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" From eca4fba0f638a40d27f7262bad14baf4b98a4a4e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 14:15:09 +0100 Subject: [PATCH 157/471] - fixed a merge conflict which wasn't flagged by TortoiseMerge. --- src/p_actionfunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index c625bd927e..7ec8bb874d 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -994,7 +994,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) PARAM_FLOAT_DEF (volume); PARAM_BOOL_DEF (looping); PARAM_FLOAT_DEF (attenuation); - PARAM_BOOL_OPT (local) { local = false; } + PARAM_BOOL_DEF (local); if (!looping) { From ff66dc3189bb4fd5941d37affbca5a11587180af Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 15:46:15 +0100 Subject: [PATCH 158/471] - flatten FxBinaryLogical chains into a single node for more efficient processing. --- src/scripting/codegeneration/codegen.cpp | 100 ++++++++++++----------- src/scripting/codegeneration/codegen.h | 2 + 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d3923b2317..620d9feed7 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3583,9 +3583,47 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx) 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; +} + //========================================================================== // // @@ -3594,56 +3632,24 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx) 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); + TArray patchspots; + int zero = build->GetConstantInt(0); - op1.Free(build); - - if (Operator == TK_AndAnd) + for (unsigned i = 0; i < list.Size(); i++) { - 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; + 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); + return to; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index cfe261b39b..ee792e5bfd 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -910,9 +910,11 @@ public: int Operator; FxExpression *left; FxExpression *right; + TDeletingArray list; FxBinaryLogical(int, FxExpression*, FxExpression*); ~FxBinaryLogical(); + void Flatten(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); From 6aecb29995914acb5c2768ebaaba10b465be82bc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 16:05:57 +0100 Subject: [PATCH 159/471] - fixed: The VM function builder was set up with the wrong number of implicit arguments. --- src/scripting/vm/vmbuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index d2d9e7140f..41ec4b920b 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -701,7 +701,7 @@ void FFunctionBuildList::Build() FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate); // Allocate registers for the function's arguments and create local variable nodes before starting to resolve it. - VMFunctionBuilder buildit(!!(item.Func->Variants[0].Flags & VARF_Action)); + VMFunctionBuilder buildit(item.Func->GetImplicitArgs()); for(unsigned i=0;iVariants[0].Proto->ArgumentTypes.Size();i++) { auto type = item.Func->Variants[0].Proto->ArgumentTypes[i]; From a45523fb63239a4d9a35a596f0bcb7131c1a56a2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Nov 2016 13:38:40 +0100 Subject: [PATCH 160/471] - scriptified A_SpawnFly. - added support for global variables to the code generator - not the compiler, though. For the handful of entries this is needed for it may just as well be done manually. So far FLevelLocals level is the only one being exported. - fixed: The VM disassembler truncated 64 bit pointers to 15 digits because the output buffer was too small. - resolve entire FxSequences instead of aborting on the first failed entry. This allows to output all errors at once. --- src/dobjtype.cpp | 34 +++++++-- src/dobjtype.h | 4 +- src/g_level.cpp | 59 ++++++++++++++ src/g_level.h | 2 +- src/p_enemy.cpp | 7 ++ src/p_map.cpp | 11 +++ src/p_mobj.cpp | 15 ++++ src/scripting/codegeneration/codegen.cpp | 97 +++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 20 +++++ src/scripting/thingdef.cpp | 2 + src/scripting/thingdef_data.cpp | 17 ++++- src/scripting/vm/vmbuilder.h | 2 + src/scripting/vm/vmdisasm.cpp | 4 +- wadsrc/static/zscript/actor.txt | 4 + wadsrc/static/zscript/doom/bossbrain.txt | 35 +++------ 15 files changed, 274 insertions(+), 39 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 57a67384a0..53eedc4568 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2100,6 +2100,7 @@ PStruct::PStruct(FName name, PTypeBase *outer) { mDescriptiveName.Format("Struct<%s>", name.GetChars()); Size = 0; + HasNativeFields = false; } //========================================================================== @@ -2114,7 +2115,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); } } } @@ -2216,13 +2217,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. @@ -2238,6 +2239,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 + delete field; + return nullptr; + } + Fields.Push(field); + HasNativeFields = true; + return field; +} + //========================================================================== // // PStruct :: PropagateMark @@ -2286,7 +2310,7 @@ PField::PField() } PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue) - : PSymbol(name), Offset(unsigned(offset)), Type(type), Flags(flags) + : PSymbol(name), Offset(offset), Type(type), Flags(flags) { BitValue = bitvalue; if (bitvalue > -1) @@ -3085,7 +3109,7 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) { Defaults = (BYTE *)M_Realloc(Defaults, Size); memset(Defaults + oldsize, 0, Size - oldsize); - type->SetDefaultValue(Defaults, field->Offset, &SpecialInits); + type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } return field; } diff --git a/src/dobjtype.h b/src/dobjtype.h index 5aeefac502..db468870f6 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -574,7 +574,7 @@ class PField : public PSymbol public: 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; @@ -669,8 +669,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(); diff --git a/src/g_level.cpp b/src/g_level.cpp index 9e8448879f..5b0c46fa2b 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1848,6 +1848,65 @@ 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. +// +//========================================================================== + +inline int val2bit(int val) +{ + int bit = 0; + while ((val >>= 1)) bit++; + return bit; +} + +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, val2bit(LEVEL_MONSTERSTELEFRAG)); + lstruct->AddNativeField("actownspecial", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, val2bit(LEVEL_ACTOWNSPECIAL)); + lstruct->AddNativeField("sndseqtotalctrl", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, val2bit(LEVEL_SNDSEQTOTALCTRL)); + lstruct->AddNativeField("allmap", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_ALLMAP)); + lstruct->AddNativeField("missilesactivateimpact", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_MISSILESACTIVATEIMPACT)); + lstruct->AddNativeField("monsterfallingdamage", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_MONSTERFALLINGDAMAGE)); + lstruct->AddNativeField("checkswitchrange", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_CHECKSWITCHRANGE)); + lstruct->AddNativeField("polygrind", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(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 2b0de7b687..790eba3444 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -260,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/p_enemy.cpp b/src/p_enemy.cpp index 77082f3a43..8337320081 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1790,6 +1790,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 // diff --git a/src/p_map.cpp b/src/p_map.cpp index a2e83b73f4..d7bffa5895 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 diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index bd78fdcef4..08b6627679 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -990,6 +990,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 @@ -6515,6 +6524,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; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 620d9feed7..50cd7699b1 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5067,6 +5067,12 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) 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()); @@ -5303,6 +5309,72 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +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(bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = AddressWritable && !(membervar->Flags & VARF_ReadOnly); + 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; +} + + //========================================================================== // // @@ -5377,11 +5449,21 @@ FxExpression *FxStructMember::Resolve(FCompileContext &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 = membervar->Offset / 8; + locvar->RegOffset = int(membervar->Offset / 8); locvar->ValueType = membervar->Type; classx = nullptr; delete this; @@ -5816,13 +5898,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Name: case NAME_Color: case NAME_Sound: + case NAME_State: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { PType *type = MethodName == NAME_Int ? TypeSInt32 : MethodName == NAME_uInt ? TypeUInt32 : MethodName == NAME_Double ? TypeFloat64 : MethodName == NAME_Name ? TypeName : - MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; + MethodName == NAME_Color ? TypeColor : + MethodName == NAME_State? TypeState :(PType*)TypeSound; func = new FxTypeCast((*ArgList)[0], type, true, true); (*ArgList)[0] = nullptr; @@ -6615,14 +6699,19 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build) 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))) { - delete this; - return nullptr; + fail = true; } } + if (fail) + { + delete this; + return nullptr; + } return this; } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index ee792e5bfd..b118b8d5d4 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -269,6 +269,7 @@ enum EFxType EFX_VectorBuiltin, EFX_TypeCheck, EFX_DynamicCast, + EFX_GlobalVariable, EFX_COUNT }; @@ -1136,6 +1137,25 @@ public: }; +//========================================================================== +// +// FxGlobalVariaböe +// +//========================================================================== + +class FxGlobalVariable : public FxExpression +{ +public: + PField *membervar; + bool AddressRequested; + bool AddressWritable; + + FxGlobalVariable(PField*, const FScriptPosition&); + FxExpression *Resolve(FCompileContext&); + bool RequestAddress(bool *writable); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxClassMember diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 8c42e8987d..38bf2bcf6c 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -215,6 +215,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, //========================================================================== void ParseScripts(); void ParseAllDecorate(); +void G_InitLevelLocalsForScript(); void LoadActors () { @@ -223,6 +224,7 @@ void LoadActors () timer.Reset(); timer.Clock(); FScriptPosition::ResetErrorCounter(); + G_InitLevelLocalsForScript(); InitThingdef(); FScriptPosition::StrictErrors = true; ParseScripts(); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index b0edcb167f..4d18a083bc 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -673,10 +673,16 @@ void InitThingdef() qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp); } + PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); + + PStruct *sstruct = NewStruct("Sector", nullptr); + auto sptr = NewPointer(sstruct); + sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); + // Define some member variables we feel like exposing to the user PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols; PType *array5 = NewArray(TypeSInt32, 5); - PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); + symt.AddSymbol(new PField("sector", sptr, VARF_Native, myoffsetof(AActor, Sector))); 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))); @@ -725,12 +731,14 @@ void InitThingdef() symt.AddSymbol(new PField("RipperLevel", TypeSInt32, VARF_Native, myoffsetof(AActor, RipperLevel))); symt.AddSymbol(new PField("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin))); symt.AddSymbol(new PField("RipLevelMax", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMax))); + symt.AddSymbol(new PField("special2", TypeSInt32, VARF_Native, myoffsetof(AActor, special2))); 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))); symt.AddSymbol(new PField("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound))); symt.AddSymbol(new PField("DeathSound", TypeSound, VARF_Native, myoffsetof(AActor, DeathSound))); + symt.AddSymbol(new PField("SeeSound", TypeSound, VARF_Native, myoffsetof(AActor, SeeSound))); symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos))); symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel))); symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale))); @@ -761,8 +769,11 @@ void InitThingdef() PSymbolTable &symt2 = RUNTIME_CLASS(DDropItem)->Symbols; PType *TypeDropItem = NewPointer(RUNTIME_CLASS(DDropItem)); symt2.AddSymbol(new PField("Next", TypeDropItem, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Next))); - symt2.AddSymbol(new PField("ItemName", TypeName, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Name))); + symt2.AddSymbol(new PField("Name", TypeName, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Name))); symt2.AddSymbol(new PField("Probability", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Probability))); - symt2.AddSymbol(new PField("Amount", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Amount))); + symt2.AddSymbol(new PField("Amount", TypeSInt32, VARF_Native, myoffsetof(DDropItem, Amount))); + + PSymbolTable &symt3 = RUNTIME_CLASS(DObject)->Symbols; + symt3.AddSymbol(new PField("bDestroyed", TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(DObject, ObjectFlags), 5/*OF_EuthanizeMe*/)); } diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 9a97c216d2..c94d85f3cc 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -30,6 +30,8 @@ public: // Returns the constant register holding the value. int GetConstantInt(int val); + int GetConstantInt(size_t val) { return GetConstantInt(int(val)); } + int GetConstantInt(unsigned val) { return GetConstantInt(int(val)); } int GetConstantFloat(double val); int GetConstantAddress(void *ptr, VM_ATAG tag); int GetConstantString(FString str); diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index ea199612c4..239a0dc51d 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -199,7 +199,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) @@ -239,7 +239,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"); } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0b3c4d40b6..091fba4b53 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -77,6 +77,10 @@ class Actor : Thinker native native void VelFromAngle(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); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 641263eccb..cb30e886bd 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -280,13 +280,12 @@ extend class Actor } */ - /* private void SpawnFly(class spawntype, sound snd) { - AActor newmobj; - AActor fog; - AActor eye = master; // The eye is the spawnshot's master, not the target! - AActor targ = target; // Unlike other projectiles, the target is the intended destination. + 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... @@ -307,7 +306,7 @@ extend class Actor if (fog) A_PlaySound(snd, CHAN_BODY); } - class SpawnName; + class SpawnName = null; DropItem di; // di will be our drop item list iterator DropItem drop; // while drop stays as the reference point. @@ -334,7 +333,7 @@ extend class Actor } } di = drop; - n = randon[pr_spawnfly](0, n); + n = random[pr_spawnfly](0, n); while (n >= 0) { if (di.Name != 'none') @@ -385,11 +384,11 @@ extend class Actor // (if the player has made noise). newmobj.LastHeard = newmobj.Sector.SoundTarget; - if (newmobj.SeeState != null && newmobj.LookForPlayers (true, null)) + if (newmobj.SeeState != null && newmobj.LookForPlayers (true)) { newmobj.SetState (newmobj.SeeState); } - if (!(newmobj.ObjectFlags & OF_EuthanizeMe)) + if (!newmobj.bDestroyed) { // telefrag anything in this spot newmobj.TeleportMove (newmobj.pos, true); @@ -401,13 +400,8 @@ extend class Actor // remove self (i.e., cube). Destroy (); } - */ - - native - void A_SpawnFly(class spawntype = null) // needs special treatment for default - ; - /* + void A_SpawnFly(class spawntype = null) { sound snd; if (spawntype != null) @@ -419,18 +413,13 @@ extend class Actor spawntype = "SpawnFire"; snd = "brain/spawn"; } - SpawnFly(self, spawntype, snd); + SpawnFly(spawntype, snd); } - */ - - native - void A_SpawnSound() - ; - /* + + void A_SpawnSound() { // travelling cube sound A_PlaySound("brain/cube", CHAN_BODY); SpawnFly("SpawnFire", "brain/spawn"); } - */ } From 830500512516d363f5e3970864a47537c01d89b3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Nov 2016 13:39:51 +0100 Subject: [PATCH 161/471] - remove debug message. --- wadsrc/static/zscript/doom/bossbrain.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index cb30e886bd..b1aa901a33 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -189,7 +189,6 @@ extend class Actor void A_BrainDie() { - A_Log("A_BrainDie"); // [RH] If noexit, then don't end the level. if ((GetCVar("deathmatch") || GetCVar("alwaysapplydmflags")) && GetCVar("sv_noexit")) return; From 995f01f8aa3b8d7e5796f4ad6b875e98b8915419 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Nov 2016 14:23:29 +0100 Subject: [PATCH 162/471] - removed obsolete code from a_bossbrain.cpp. - fixed: divisions wasted one register for each operation due to a double allocation. - changed math operations to use less registers. There was a well-intended change to allocate the destination first, but the better approach is to first allocate the operands and free then before allocating the destination register. --- src/g_doom/a_bossbrain.cpp | 150 ----------------------- src/scripting/codegeneration/codegen.cpp | 12 +- 2 files changed, 6 insertions(+), 156 deletions(-) diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index f58e753750..5807ce1759 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -78,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_SELF_PROLOGUE(AActor); - PARAM_CLASS_DEF(spawntype, AActor); - - 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_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_BODY, "brain/cube", 1, ATTN_IDLE); - SpawnFly(self, PClass::FindActor("SpawnFire"), "brain/spawn"); - return 0; -} diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 50cd7699b1..4c26da5954 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2563,8 +2563,6 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) { assert(Operator == '+' || Operator == '-'); - // allocate the result first so that the operation does not leave gaps in the register set. - ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); ExpEmit op1 = left->Emit(build); ExpEmit op2 = right->Emit(build); if (Operator == '+') @@ -2577,6 +2575,7 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) 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); @@ -2608,6 +2607,7 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) 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); @@ -2720,7 +2720,6 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) { // allocate the result first so that the operation does not leave gaps in the register set. - ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); ExpEmit op1 = left->Emit(build); ExpEmit op2 = right->Emit(build); @@ -2740,9 +2739,10 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) { op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RR : OP_MULVF3_RR) : (ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR); } - build->Emit(op, to.RegNum, op1.RegNum, op2.RegNum); op1.Free(build); op2.Free(build); + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + build->Emit(op, to.RegNum, op1.RegNum, op2.RegNum); return to; } @@ -2756,6 +2756,7 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) 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); @@ -2777,10 +2778,10 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) 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); - 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); @@ -2790,7 +2791,6 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) { 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); From 9188dc07a7254cf3134508168cb3f7327af5bc50 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Nov 2016 14:38:18 +0100 Subject: [PATCH 163/471] - removed excess parameter from A_FadeIn. --- src/p_actionfunctions.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 7ec8bb874d..9ed20daf85 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -3398,7 +3398,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_DEF(reduce); PARAM_INT_DEF(flags); - PARAM_NAME_DEF(fontname); if (reduce == 0) From c9dad704086ac9880ab207b90634107bddd7da52 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Nov 2016 16:46:55 +0100 Subject: [PATCH 164/471] - removed the GetConstantInt overloads since it appears they are not needed. --- src/scripting/vm/vmbuilder.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index c94d85f3cc..9a97c216d2 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -30,8 +30,6 @@ public: // Returns the constant register holding the value. int GetConstantInt(int val); - int GetConstantInt(size_t val) { return GetConstantInt(int(val)); } - int GetConstantInt(unsigned val) { return GetConstantInt(int(val)); } int GetConstantFloat(double val); int GetConstantAddress(void *ptr, VM_ATAG tag); int GetConstantString(FString str); From 956304530501b82f8c96fad9c6b56bb3d2238498 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Nov 2016 00:19:36 +0100 Subject: [PATCH 165/471] - moved declaration of native fields into the respective class definitions. This bypasses a declaration in the script in favor of a simpler implementation. In order to work it is always necessary to have an offset table to map the variables to, but doing it fully on the native side only requires adding the type to the declaration. --- src/actor.h | 2 + src/dobject.cpp | 13 ++++ src/dobject.h | 25 ++++++-- src/dobjtype.cpp | 9 ++- src/g_level.cpp | 23 +++---- src/p_acs.cpp | 4 +- src/p_mobj.cpp | 108 +++++++++++++++++++++++++++++++- src/scripting/thingdef.cpp | 2 - src/scripting/thingdef_data.cpp | 108 ++++---------------------------- 9 files changed, 170 insertions(+), 124 deletions(-) diff --git a/src/actor.h b/src/actor.h index df5ef3c175..833cd2c0ab 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(); diff --git a/src/dobject.cpp b/src/dobject.cpp index beef73c89d..56d12787f4 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -62,6 +62,7 @@ ClassReg DObject::RegistrationInfo = NULL, // ParentType NULL, // Pointers &DObject::InPlaceConstructor, // ConstructNative + &DObject::InitNativeFields, sizeof(DObject), // SizeOf CLASSREG_PClass, // MetaClassNum }; @@ -344,6 +345,18 @@ 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; diff --git a/src/dobject.h b/src/dobject.h index 91a80f9d07..ea0a44a85c 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -111,6 +111,7 @@ struct ClassReg ClassReg *ParentType; const size_t *Pointers; void (*ConstructNative)(void *); + void(*InitNatives)(); unsigned int SizeOf:28; unsigned int MetaClassNum:4; @@ -147,6 +148,9 @@ protected: \ #define HAS_OBJECT_POINTERS \ static const size_t PointerOffsets[]; +#define HAS_FIELDS \ + static void InitNativeFields(); + // 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, @@ -159,13 +163,14 @@ 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) \ ClassReg cls::RegistrationInfo = {\ NULL, \ #cls, \ &cls::Super::RegistrationInfo, \ ptrs, \ create, \ + initn, \ sizeof(cls), \ cls::MetaClassNum }; \ _DECLARE_TI(cls) \ @@ -176,18 +181,27 @@ protected: \ #define IMPLEMENT_POINTY_CLASS(cls) \ _IMP_CREATE_OBJ(cls) \ - _IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor) \ + _IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor, nullptr) \ + const size_t cls::PointerOffsets[] = { + +#define IMPLEMENT_POINTY_CLASS_WITH_FIELDS(cls) \ + _IMP_CREATE_OBJ(cls) \ + _IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor, cls::InitNativeFields) \ const size_t cls::PointerOffsets[] = { #define IMPLEMENT_CLASS(cls) \ _IMP_CREATE_OBJ(cls) \ - _IMP_PCLASS(cls,NULL,cls::InPlaceConstructor) + _IMP_PCLASS(cls,nullptr,cls::InPlaceConstructor, nullptr) + +#define IMPLEMENT_CLASS_WITH_FIELDS(cls) \ + _IMP_CREATE_OBJ(cls) \ + _IMP_PCLASS(cls,nullptr,cls::InPlaceConstructor, cls::InitNativeFields) #define IMPLEMENT_ABSTRACT_CLASS(cls) \ - _IMP_PCLASS(cls,NULL,NULL) + _IMP_PCLASS(cls,nullptr,nullptr,nullptr) #define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \ - _IMP_PCLASS(cls,cls::PointerOffsets,NULL) \ + _IMP_PCLASS(cls,cls::PointerOffsets,nullptr,nullptr) \ const size_t cls::PointerOffsets[] = { enum EObjectFlags @@ -438,6 +452,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; diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 53eedc4568..631a7e6eee 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2309,13 +2309,18 @@ 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) + if (bitvalue != -1) { - if (type->IsA(RUNTIME_CLASS(PInt)) && unsigned(bitvalue) < 8 * type->Size) + 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__ diff --git a/src/g_level.cpp b/src/g_level.cpp index 5b0c46fa2b..b13a39e20b 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1856,13 +1856,6 @@ void FLevelLocals::AddScroller (int secnum) // //========================================================================== -inline int val2bit(int val) -{ - int bit = 0; - while ((val >>= 1)) bit++; - return bit; -} - void G_InitLevelLocalsForScript() { PStruct *lstruct = NewStruct("LevelLocals", nullptr); @@ -1884,14 +1877,14 @@ void G_InitLevelLocalsForScript() 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, val2bit(LEVEL_MONSTERSTELEFRAG)); - lstruct->AddNativeField("actownspecial", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, val2bit(LEVEL_ACTOWNSPECIAL)); - lstruct->AddNativeField("sndseqtotalctrl", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, val2bit(LEVEL_SNDSEQTOTALCTRL)); - lstruct->AddNativeField("allmap", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_ALLMAP)); - lstruct->AddNativeField("missilesactivateimpact", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_MISSILESACTIVATEIMPACT)); - lstruct->AddNativeField("monsterfallingdamage", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_MONSTERFALLINGDAMAGE)); - lstruct->AddNativeField("checkswitchrange", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_CHECKSWITCHRANGE)); - lstruct->AddNativeField("polygrind", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_POLYGRIND)); + 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); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index a6197e9a66..4024bc9f9f 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5389,11 +5389,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_mobj.cpp b/src/p_mobj.cpp index 08b6627679..cf0a033b31 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -131,7 +131,7 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- -IMPLEMENT_POINTY_CLASS (AActor) +IMPLEMENT_POINTY_CLASS_WITH_FIELDS (AActor) DECLARE_POINTER (target) DECLARE_POINTER (lastenemy) DECLARE_POINTER (tracer) @@ -151,6 +151,99 @@ AActor::~AActor () // Use Destroy() instead. } +extern FFlagDef InternalActorFlagDefs[]; +extern FFlagDef ActorFlagDefs[]; + +void AActor::InitNativeFields() +{ + PType *TypeActor = NewPointer(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); + + // Define the member variables we feel like exposing to the user + meta->AddNativeField(NAME_Alpha, TypeFloat64, myoffsetof(AActor, Alpha)); + meta->AddNativeField(NAME_Angle, TypeFloat64, myoffsetof(AActor, Angles.Yaw)); + meta->AddNativeField(NAME_Args, array5, myoffsetof(AActor, args)); + meta->AddNativeField(NAME_CeilingZ, TypeFloat64, myoffsetof(AActor, ceilingz), VARF_ReadOnly); + meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz), VARF_ReadOnly); + meta->AddNativeField(NAME_Health, TypeSInt32, myoffsetof(AActor, health), VARF_ReadOnly); + meta->AddNativeField(NAME_Mass, TypeSInt32, myoffsetof(AActor, Mass)); + meta->AddNativeField(NAME_Pitch, TypeFloat64, myoffsetof(AActor, Angles.Pitch)); + meta->AddNativeField(NAME_Roll, TypeFloat64, myoffsetof(AActor, Angles.Roll)); + 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_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(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_ScaleX, TypeFloat64, myoffsetof(AActor, Scale.X), VARF_Deprecated); + meta->AddNativeField(NAME_ScaleY, TypeFloat64, myoffsetof(AActor, Scale.Y), VARF_Deprecated); + 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_Height, TypeFloat64, myoffsetof(AActor, Height)); + meta->AddNativeField(NAME_Radius, TypeFloat64, myoffsetof(AActor, radius), VARF_ReadOnly); + meta->AddNativeField(NAME_ReactionTime, TypeSInt32, myoffsetof(AActor, reactiontime)); + meta->AddNativeField(NAME_MeleeRange, TypeFloat64, myoffsetof(AActor, meleerange)); + meta->AddNativeField(NAME_Speed, TypeFloat64, myoffsetof(AActor, Speed)); + meta->AddNativeField("FloatSpeed", TypeFloat64, myoffsetof(AActor, FloatSpeed)); + meta->AddNativeField("PainThreshold", TypeSInt32, myoffsetof(AActor, PainThreshold)); + meta->AddNativeField("spriteAngle", TypeFloat64, myoffsetof(AActor, SpriteAngle)); + meta->AddNativeField("spriteRotation", TypeFloat64, myoffsetof(AActor, SpriteRotation)); + meta->AddNativeField(NAME_Threshold, TypeSInt32, myoffsetof(AActor, threshold)); + meta->AddNativeField(NAME_DefThreshold, TypeSInt32, myoffsetof(AActor, DefThreshold), VARF_ReadOnly); + meta->AddNativeField(NAME_Damage, TypeSInt32, myoffsetof(AActor, DamageVal), VARF_ReadOnly); + meta->AddNativeField("visdir", TypeSInt32, myoffsetof(AActor, visdir)); + meta->AddNativeField("Gravity", TypeFloat64, myoffsetof(AActor, Gravity)); + meta->AddNativeField("FloorClip", TypeFloat64, myoffsetof(AActor, Floorclip)); + meta->AddNativeField("DamageType", TypeName, myoffsetof(AActor, DamageType)); + meta->AddNativeField("FloatBobPhase", TypeUInt8, myoffsetof(AActor, FloatBobPhase)); + meta->AddNativeField("tics", TypeSInt32, myoffsetof(AActor, tics)); + meta->AddNativeField("RipperLevel", TypeSInt32, myoffsetof(AActor, RipperLevel)); + meta->AddNativeField("RipLevelMin", TypeSInt32, myoffsetof(AActor, RipLevelMin)); + meta->AddNativeField("RipLevelMax", TypeSInt32, myoffsetof(AActor, RipLevelMax)); + meta->AddNativeField("special2", TypeSInt32, myoffsetof(AActor, special2)); + 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("AttackSound", TypeSound, myoffsetof(AActor, AttackSound)); + meta->AddNativeField("DeathSound", TypeSound, myoffsetof(AActor, DeathSound)); + meta->AddNativeField("SeeSound", TypeSound, myoffsetof(AActor, SeeSound)); + meta->AddNativeField("Pos", TypeVector3, myoffsetof(AActor, __Pos), VARF_ReadOnly); + meta->AddNativeField("Vel", TypeVector3, myoffsetof(AActor, Vel)); + meta->AddNativeField("Scale", TypeVector2, myoffsetof(AActor, Scale)); + 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("SeeState", TypeState, myoffsetof(AActor, SeeState), VARF_ReadOnly); + 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("Sector", TypeSector, myoffsetof(AActor, Sector)); + + // 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 @@ -6707,10 +6800,21 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2OffsetZ) // DropItem handling // //---------------------------------------------------------------------------- -IMPLEMENT_POINTY_CLASS(DDropItem) +IMPLEMENT_POINTY_CLASS_WITH_FIELDS(DDropItem) DECLARE_POINTER(Next) END_POINTERS +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) { if (query) diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 38bf2bcf6c..8c42e8987d 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -215,7 +215,6 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, //========================================================================== void ParseScripts(); void ParseAllDecorate(); -void G_InitLevelLocalsForScript(); void LoadActors () { @@ -224,7 +223,6 @@ void LoadActors () timer.Reset(); timer.Clock(); FScriptPosition::ResetErrorCounter(); - G_InitLevelLocalsForScript(); InitThingdef(); FScriptPosition::StrictErrors = true; ParseScripts(); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 4d18a083bc..f628dec3c1 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -62,7 +62,7 @@ static TArray AFTable; #define DEFINE_DUMMY_FLAG(name, deprec) { DEPF_UNUSED, #name, -1, 0, deprec? VARF_Deprecated:0 } // internal flags. These do not get exposed to actor definitions but scripts need to be able to access them as variables. -static FFlagDef InternalActorFlagDefs[]= +FFlagDef InternalActorFlagDefs[]= { DEFINE_FLAG(MF, INCHASE, AActor, flags), DEFINE_FLAG(MF, UNMORPHED, AActor, flags), @@ -91,10 +91,11 @@ static FFlagDef InternalActorFlagDefs[]= DEFINE_FLAG(MF6, INTRYMOVE, AActor, flags6), DEFINE_FLAG(MF7, HANDLENODELAY, AActor, flags7), DEFINE_FLAG(MF7, FLYCHEAT, AActor, flags7), + { 0xffffffff } }; -static FFlagDef ActorFlagDefs[]= +FFlagDef ActorFlagDefs[]= { DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags), DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags), @@ -328,6 +329,7 @@ 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 @@ -433,7 +435,7 @@ 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) }, @@ -634,6 +636,7 @@ static int funccmp(const void * a, const void * b) // Initialization // //========================================================================== +void G_InitLevelLocalsForScript(); void InitThingdef() { @@ -679,101 +682,14 @@ void InitThingdef() auto sptr = NewPointer(sstruct); sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); - // 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("sector", sptr, VARF_Native, myoffsetof(AActor, Sector))); - 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|VARF_Deprecated, myoffsetof(AActor, __Pos.X))); // must remain read-only! - symt.AddSymbol(new PField(NAME_Y, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, __Pos.Y))); // must remain read-only! - symt.AddSymbol(new PField(NAME_Z, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, __Pos.Z))); // must remain read-only! - symt.AddSymbol(new PField(NAME_VelX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.X))); - symt.AddSymbol(new PField(NAME_VelY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Y))); - symt.AddSymbol(new PField(NAME_VelZ, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Z))); - symt.AddSymbol(new PField(NAME_MomX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.X))); - symt.AddSymbol(new PField(NAME_MomY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Y))); - symt.AddSymbol(new PField(NAME_MomZ, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Z))); - symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native|VARF_Deprecated, myoffsetof(AActor, Scale.X))); - symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native|VARF_Deprecated, myoffsetof(AActor, Scale.Y))); - symt.AddSymbol(new PField(NAME_Score, TypeSInt32, VARF_Native, myoffsetof(AActor, Score))); - symt.AddSymbol(new PField(NAME_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor, accuracy))); - symt.AddSymbol(new PField(NAME_Stamina, TypeSInt32, VARF_Native, myoffsetof(AActor, stamina))); - symt.AddSymbol(new PField(NAME_Height, TypeFloat64, VARF_Native, myoffsetof(AActor, Height))); - symt.AddSymbol(new PField(NAME_Radius, TypeFloat64, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, radius))); - symt.AddSymbol(new PField(NAME_ReactionTime, TypeSInt32, VARF_Native, myoffsetof(AActor, reactiontime))); - symt.AddSymbol(new PField(NAME_MeleeRange, TypeFloat64, VARF_Native, myoffsetof(AActor, meleerange))); - symt.AddSymbol(new PField(NAME_Speed, TypeFloat64, VARF_Native, myoffsetof(AActor, Speed))); - symt.AddSymbol(new PField("FloatSpeed", TypeFloat64, VARF_Native, myoffsetof(AActor, FloatSpeed))); - symt.AddSymbol(new PField("PainThreshold", TypeSInt32, VARF_Native, myoffsetof(AActor, PainThreshold))); - symt.AddSymbol(new PField("spriteAngle", TypeFloat64, VARF_Native, myoffsetof(AActor, SpriteAngle))); - symt.AddSymbol(new PField("spriteRotation", TypeFloat64, VARF_Native, myoffsetof(AActor, SpriteRotation))); - symt.AddSymbol(new PField(NAME_Threshold, TypeSInt32, VARF_Native, 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("visdir", TypeSInt32, VARF_Native, myoffsetof(AActor, visdir))); - symt.AddSymbol(new PField("Gravity", TypeFloat64, VARF_Native, myoffsetof(AActor, Gravity))); - symt.AddSymbol(new PField("FloorClip", TypeFloat64, VARF_Native, myoffsetof(AActor, Floorclip))); - symt.AddSymbol(new PField("DamageType", TypeName, VARF_Native, myoffsetof(AActor, DamageType))); - symt.AddSymbol(new PField("FloatBobPhase", TypeUInt8, VARF_Native, myoffsetof(AActor, FloatBobPhase))); - symt.AddSymbol(new PField("tics", TypeSInt32, VARF_Native, myoffsetof(AActor, tics))); - symt.AddSymbol(new PField("RipperLevel", TypeSInt32, VARF_Native, myoffsetof(AActor, RipperLevel))); - symt.AddSymbol(new PField("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin))); - symt.AddSymbol(new PField("RipLevelMax", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMax))); - symt.AddSymbol(new PField("special2", TypeSInt32, VARF_Native, myoffsetof(AActor, special2))); - 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))); - symt.AddSymbol(new PField("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound))); - symt.AddSymbol(new PField("DeathSound", TypeSound, VARF_Native, myoffsetof(AActor, DeathSound))); - symt.AddSymbol(new PField("SeeSound", TypeSound, VARF_Native, myoffsetof(AActor, SeeSound))); - symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos))); - symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel))); - symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale))); - symt.AddSymbol(new PField("CurState", TypeState, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, state))); // has to be renamed on the script side because it clashes with the same named type. - symt.AddSymbol(new PField("SeeState", TypeState, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, SeeState))); - symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target))); - symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master))); - symt.AddSymbol(new PField(NAME_Tracer, TypeActor, VARF_Native, myoffsetof(AActor, tracer))); - symt.AddSymbol(new PField("LastHeard", TypeActor, VARF_Native, myoffsetof(AActor, LastHeard))); - symt.AddSymbol(new PField("LastEnemy", TypeActor, VARF_Native, myoffsetof(AActor, lastenemy))); + G_InitLevelLocalsForScript(); - // synthesize a symbol for each flag. - for (size_t i = 0; i < countof(ActorFlagDefs); i++) + FAutoSegIterator probe(CRegHead, CRegTail); + + while (*++probe != NULL) { - int bit = 0; - unsigned val = ActorFlagDefs[i].flagbit; - while ((val >>= 1)) bit++; - symt.AddSymbol(new PField(FStringf("b%s", ActorFlagDefs[i].name), (ActorFlagDefs[i].fieldsize == 4? TypeSInt32 : TypeSInt16), ActorFlagDefs[i].varflags, ActorFlagDefs[i].structoffset, bit)); + if (((ClassReg *)*probe)->InitNatives) + ((ClassReg *)*probe)->InitNatives(); } - for (size_t i = 0; i < countof(InternalActorFlagDefs); i++) - { - int bit = 0; - unsigned val = InternalActorFlagDefs[i].flagbit; - while ((val >>= 1)) bit++; - symt.AddSymbol(new PField(FStringf("b%s", InternalActorFlagDefs[i].name), (InternalActorFlagDefs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), InternalActorFlagDefs[i].varflags, InternalActorFlagDefs[i].structoffset, bit)); - } - - PSymbolTable &symt2 = RUNTIME_CLASS(DDropItem)->Symbols; - PType *TypeDropItem = NewPointer(RUNTIME_CLASS(DDropItem)); - symt2.AddSymbol(new PField("Next", TypeDropItem, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Next))); - symt2.AddSymbol(new PField("Name", TypeName, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Name))); - symt2.AddSymbol(new PField("Probability", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Probability))); - symt2.AddSymbol(new PField("Amount", TypeSInt32, VARF_Native, myoffsetof(DDropItem, Amount))); - - PSymbolTable &symt3 = RUNTIME_CLASS(DObject)->Symbols; - symt3.AddSymbol(new PField("bDestroyed", TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(DObject, ObjectFlags), 5/*OF_EuthanizeMe*/)); } From d433fb76c999bb8fabc5ab5a3d3e014b0b1d553e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Nov 2016 08:57:10 +0100 Subject: [PATCH 166/471] - completed the list of AActor exported member variables, with the exception of a few things that cannot be done yet. Note that AActor::Inventory needed to be renamed because defining this symbol within AActor would hide the global type of the same name! --- src/p_mobj.cpp | 185 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 135 insertions(+), 50 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index cf0a033b31..a567f54864 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -157,6 +157,7 @@ extern FFlagDef ActorFlagDefs[]; void AActor::InitNativeFields() { 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); @@ -164,74 +165,158 @@ void AActor::InitNativeFields() auto meta = RUNTIME_CLASS(AActor); - // Define the member variables we feel like exposing to the user - meta->AddNativeField(NAME_Alpha, TypeFloat64, myoffsetof(AActor, Alpha)); - meta->AddNativeField(NAME_Angle, TypeFloat64, myoffsetof(AActor, Angles.Yaw)); - meta->AddNativeField(NAME_Args, array5, myoffsetof(AActor, args)); - meta->AddNativeField(NAME_CeilingZ, TypeFloat64, myoffsetof(AActor, ceilingz), VARF_ReadOnly); - meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz), VARF_ReadOnly); - meta->AddNativeField(NAME_Health, TypeSInt32, myoffsetof(AActor, health), VARF_ReadOnly); - meta->AddNativeField(NAME_Mass, TypeSInt32, myoffsetof(AActor, Mass)); - meta->AddNativeField(NAME_Pitch, TypeFloat64, myoffsetof(AActor, Angles.Pitch)); - meta->AddNativeField(NAME_Roll, TypeFloat64, myoffsetof(AActor, Angles.Roll)); - 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("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_ScaleX, TypeFloat64, myoffsetof(AActor, Scale.X), VARF_Deprecated); - meta->AddNativeField(NAME_ScaleY, TypeFloat64, myoffsetof(AActor, Scale.Y), VARF_Deprecated); - 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_Height, TypeFloat64, myoffsetof(AActor, Height)); - meta->AddNativeField(NAME_Radius, TypeFloat64, myoffsetof(AActor, radius), VARF_ReadOnly); - meta->AddNativeField(NAME_ReactionTime, TypeSInt32, myoffsetof(AActor, reactiontime)); - meta->AddNativeField(NAME_MeleeRange, TypeFloat64, myoffsetof(AActor, meleerange)); meta->AddNativeField(NAME_Speed, TypeFloat64, myoffsetof(AActor, Speed)); meta->AddNativeField("FloatSpeed", TypeFloat64, myoffsetof(AActor, FloatSpeed)); - meta->AddNativeField("PainThreshold", TypeSInt32, myoffsetof(AActor, PainThreshold)); - meta->AddNativeField("spriteAngle", TypeFloat64, myoffsetof(AActor, SpriteAngle)); - meta->AddNativeField("spriteRotation", TypeFloat64, myoffsetof(AActor, SpriteRotation)); - meta->AddNativeField(NAME_Threshold, TypeSInt32, myoffsetof(AActor, threshold)); - meta->AddNativeField(NAME_DefThreshold, TypeSInt32, myoffsetof(AActor, DefThreshold), VARF_ReadOnly); - meta->AddNativeField(NAME_Damage, TypeSInt32, myoffsetof(AActor, DamageVal), VARF_ReadOnly); - meta->AddNativeField("visdir", TypeSInt32, myoffsetof(AActor, visdir)); - meta->AddNativeField("Gravity", TypeFloat64, myoffsetof(AActor, Gravity)); - meta->AddNativeField("FloorClip", TypeFloat64, myoffsetof(AActor, Floorclip)); - meta->AddNativeField("DamageType", TypeName, myoffsetof(AActor, DamageType)); - meta->AddNativeField("FloatBobPhase", TypeUInt8, myoffsetof(AActor, FloatBobPhase)); - meta->AddNativeField("tics", TypeSInt32, myoffsetof(AActor, tics)); - meta->AddNativeField("RipperLevel", TypeSInt32, myoffsetof(AActor, RipperLevel)); - meta->AddNativeField("RipLevelMin", TypeSInt32, myoffsetof(AActor, RipLevelMin)); - meta->AddNativeField("RipLevelMax", TypeSInt32, myoffsetof(AActor, RipLevelMax)); - meta->AddNativeField("special2", TypeSInt32, myoffsetof(AActor, special2)); - 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("AttackSound", TypeSound, myoffsetof(AActor, AttackSound)); - meta->AddNativeField("DeathSound", TypeSound, myoffsetof(AActor, DeathSound)); - meta->AddNativeField("SeeSound", TypeSound, myoffsetof(AActor, SeeSound)); - meta->AddNativeField("Pos", TypeVector3, myoffsetof(AActor, __Pos), VARF_ReadOnly); - meta->AddNativeField("Vel", TypeVector3, myoffsetof(AActor, Vel)); + 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("SeeState", TypeState, myoffsetof(AActor, SeeState), VARF_ReadOnly); + 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("Sector", TypeSector, myoffsetof(AActor, Sector)); + 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("TelefogSpurceType", 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++) From 157cfe3ab37e7b94fe98a19fb53e45804e62a62f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Nov 2016 09:23:29 +0100 Subject: [PATCH 167/471] - fixed: The RNG was not initialized for script calls that did not explicitly specify an RNG by name. --- src/scripting/codegeneration/codegen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4c26da5954..9cbc1c2b16 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -55,6 +55,8 @@ #include "v_text.h" #include "math/cmath.h" +extern FRandom pr_exrandom; + struct FLOP { ENamedName Name; @@ -5733,7 +5735,7 @@ FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList *a : FxExpression(EFX_FunctionCall, pos) { MethodName = methodname; - RNG = nullptr; + RNG = &pr_exrandom; ArgList = args; if (rngname != NAME_None) { From 7068070c0da0c4f28bf7b480477dca79e7ab8e94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Nov 2016 09:56:03 +0100 Subject: [PATCH 168/471] - fixed: The identifier fallback which existed for all other basic types was missing for 'state'. - added the option to put code right into the ZSCRIPT lump for smaller definitions where a file list would be too cumbersome. --- src/scripting/zscript/zcc-parse.lemon | 2 +- src/scripting/zscript/zcc_parser.cpp | 64 ++++++++++++++++++--------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index b1065281c8..9d22765fc2 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -690,7 +690,7 @@ type_name(X) ::= DOT dottable_id(A). /* 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 VECTOR2 VECTOR3 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 *} diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 84bebff402..fe6341bb34 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -179,9 +179,9 @@ static void InitTokenMap() TOKENDEF (TK_Loop, ZCC_LOOP); TOKENDEF (TK_Goto, ZCC_GOTO); TOKENDEF (TK_States, ZCC_STATES); - TOKENDEF (TK_State, ZCC_STATE); - TOKENDEF (TK_Color, ZCC_COLOR); - TOKENDEF (TK_Sound, ZCC_SOUND); + 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); @@ -206,24 +206,27 @@ static void InitTokenMap() #undef TOKENDEF #undef TOKENDEF2 -static void ParseSingleFile(const char *filename, void *parser, ZCCParseState &state) +static void ParseSingleFile(const char *filename, int lump, void *parser, ZCCParseState &state) { int tokentype; - int lump; //bool failed; ZCCToken value; FScanner sc; - lump = Wads.CheckNumForFullName(filename, true); - if (lump >= 0) + if (filename != nullptr) { - sc.OpenLumpNum(lump); - } - else - { - Printf("Could not find script lump '%s'\n", filename); - return; + lump = Wads.CheckNumForFullName(filename, true); + if (lump >= 0) + { + sc.OpenLumpNum(lump); + } + else + { + Printf("Could not find script lump '%s'\n", filename); + return; + } } + else sc.OpenLumpNum(lump); state.sc = ≻ while (sc.GetToken()) @@ -309,20 +312,39 @@ static void DoParse(int lumpnum) #endif sc.OpenLumpNum(lumpnum); - // parse all files from this list in one go. - while (sc.GetString()) + auto saved = sc.SavePos(); + bool parsed = false; + if (sc.GetToken()) { - if (Wads.GetLumpFile(sc.LumpNum) == 0) + if (sc.TokenType == TK_Class || sc.TokenType == TK_Enum || sc.TokenType == TK_Struct || sc.TokenType == TK_Const || sc.TokenType == TK_Native) { - int includefile = Wads.GetLumpFile(Wads.CheckNumForFullName(sc.String, true)); - if (includefile != 0) + if (sc.CheckToken(TK_Identifier)) { - I_FatalError("File %s is overriding core lump %s.", - Wads.GetWadFullName(includefile), sc.String); + // 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, parser, state); + ParseSingleFile(sc.String, 0, parser, state); + } } value.Int = -1; From 07c24c7e27a65d22642df3e0bcaa0b72225fbca4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Nov 2016 10:35:14 +0100 Subject: [PATCH 169/471] - use different names for different AST dumps. --- src/scripting/zscript/zcc_parser.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index fe6341bb34..26fdeec432 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -369,10 +369,10 @@ static void DoParse(int lumpnum) if (Args->CheckParm("-dumpast")) { FString ast = ZCC_PrintAST(state.TopNode); - FString filename = Wads.GetLumpFullName(lumpnum); - FString astfile = ExtractFileBase(filename, false); - astfile << ".ast"; - FILE *ff = fopen(astfile, "w"); + FString filename = Wads.GetLumpFullPath(lumpnum); + filename.ReplaceChars(":\\/?|", '.'); + filename << ".ast"; + FILE *ff = fopen(filename, "w"); if (ff != NULL) { fputs(ast.GetChars(), ff); From 407345668a5f8166c340cc4f5425abc64b4255b6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Nov 2016 15:16:56 +0100 Subject: [PATCH 170/471] - fixed: ZCCCompiler tried to process replacements too early, it can only be done after all classes have been created. --- src/scripting/zscript/zcc_compile.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 98d847ebe2..8555432c07 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -93,11 +93,6 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) name << "nodes - " << FName(cnode->NodeName); cls->TreeNodes.SetName(name); - if (cnode->Replaces != nullptr && !static_cast(cnode->Type)->SetReplacement(cnode->Replaces->Id)) - { - Warn(cnode, "Replaced type '%s' not found for %s", FName(cnode->Replaces->Id).GetChars(), cnode->Type->TypeName.GetChars()); - } - // Need to check if the class actually has a body. if (node != nullptr) do { @@ -557,7 +552,7 @@ void ZCCCompiler::CreateClassTypes() 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 + // 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) @@ -574,6 +569,12 @@ void ZCCCompiler::CreateClassTypes() 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()); + } + } } From 8ae7aae14ae88396d1806a7243da60f3b5553005 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Nov 2016 15:21:45 +0100 Subject: [PATCH 171/471] - do not delete duplicate PFields - they are better be destroyed and left to the GC. - removed two duplicate entries to the flag table. --- src/dobjtype.cpp | 2 +- src/scripting/thingdef_data.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 631a7e6eee..f1726adbf1 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2254,7 +2254,7 @@ PField *PStruct::AddNativeField(FName name, PType *type, size_t address, DWORD f if (Symbols.AddSymbol(field) == nullptr) { // name is already in use - delete field; + field->Destroy(); return nullptr; } Fields.Push(field); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index f628dec3c1..74c685ea83 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -68,14 +68,12 @@ FFlagDef InternalActorFlagDefs[]= DEFINE_FLAG(MF, UNMORPHED, AActor, flags), DEFINE_FLAG(MF2, FLY, AActor, flags2), DEFINE_FLAG(MF2, ONMOBJ, AActor, flags2), - DEFINE_FLAG(MF2, DONTTRANSLATE, 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, NOSKIN, AActor, flags4), DEFINE_FLAG(MF4, SCROLLMOVE, AActor, flags4), DEFINE_FLAG(MF4, VFRICTION, AActor, flags4), DEFINE_FLAG(MF4, BOSSSPAWNED, AActor, flags4), From b6633bc489481d514dd50e8c5bf830fe75bb43bf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 00:39:00 +0100 Subject: [PATCH 172/471] - fixed: The states parser tried to simplify the head node for random duration but it has to simplify the two value nodes separately. - added jump by index to ZScript. --- src/dobjtype.h | 1 + src/scripting/codegeneration/codegen.cpp | 29 ++++++++++++++++++++-- src/scripting/decorate/thingdef_states.cpp | 2 +- src/scripting/thingdef.cpp | 5 ++-- src/scripting/thingdef.h | 2 +- src/scripting/zscript/zcc_compile.cpp | 11 +++++--- 6 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index db468870f6..30e22e8680 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -718,6 +718,7 @@ public: }; TArray Variants; PClass *OwningClass = nullptr; + int StateCount = 0; // needed to process state indices later. unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags); int GetImplicitArgs() diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9cbc1c2b16..9e86fff8f7 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1416,6 +1416,26 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + else if (basex->IsNumeric() && basex->ValueType != TypeSound && basex->ValueType != TypeColor) + { + if (ctx.Function->SymbolName != NAME_None || !(ctx.Function->Variants[0].Flags & VARF_Action)) + { + ScriptPosition.Message(MSG_ERROR, "State jumps with index can only be used in anonymous state functions."); + delete this; + return nullptr; + } + if (ctx.Function->StateCount != 1) + { + ScriptPosition.Message(MSG_ERROR, "State jumps with index cannot be used on multistate definitions"); + delete this; + return nullptr; + } + FxExpression *x = new FxRuntimeStateIndex(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } } else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) { @@ -7859,6 +7879,12 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) delete this; return nullptr; } + else if (Index->isConstant() && static_cast(Index) < 0) + { + ScriptPosition.Message(MSG_ERROR, "State index must be positive"); + delete this; + return nullptr; + } else if (Index->ValueType->GetRegType() != REGT_INT) { // Float. Index = new FxIntCast(Index, ctx.FromDecorate); @@ -7912,8 +7938,7 @@ static int BuiltinHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build) { - // This code can only be called from DECORATE, not ZSCRIPT so any function going through here - // is an anoynmous one which are always marked as 'action'. + // This can only be called from inline state functions which must be VARF_Action. assert(build->NumImplicits >= NAP && build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits && "FxRuntimeStateIndex is only valid inside action functions"); diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index dda25f9265..59cf309386 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -322,7 +322,7 @@ do_stop: endofstate: if (ScriptCode != nullptr) { - auto funcsym = CreateAnonymousFunction(actor, nullptr, VARF_Method | VARF_Action); + auto funcsym = CreateAnonymousFunction(actor, nullptr, VARF_Method | VARF_Action, (int)statestring.Len()); state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true); } int count = bag.statedef.AddStates(&state, statestring); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 8c42e8987d..6f30f8add7 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -132,7 +132,7 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArray rets(1); TArray args; @@ -143,6 +143,7 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i SetImplicitArgs(&args, &argflags, &argnames, containingclass, flags); PFunction *sym = new PFunction(containingclass, NAME_None); // anonymous functions do not have names. + sym->StateCount = statecount; sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, flags); return sym; } @@ -201,7 +202,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, else { auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition); - auto funcsym = CreateAnonymousFunction(info, TypeSInt32, VARF_Method); + auto funcsym = CreateAnonymousFunction(info, TypeSInt32, VARF_Method, 0); defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate); } } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index b2d34231de..3511d1ee1d 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -153,7 +153,7 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag); FName CheckCastKludges(FName in); void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags); -PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); +PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags, int statecount); PFunction *FindClassMemberFunction(PClass *cls, PClass *funccls, FName name, FScriptPosition &sc, bool *error); void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 8555432c07..f296a91b6c 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2248,6 +2248,7 @@ void ZCCCompiler::CompileStates() 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) { @@ -2279,13 +2280,15 @@ void ZCCCompiler::CompileStates() // 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(Simplify(sl->Duration, &c->Type()->Symbols, true)); + 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"); } - int v1 = GetInt(func->Parameters->Value); - int v2 = GetInt(static_cast(func->Parameters->SiblingNext)->Value); + 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); @@ -2346,7 +2349,7 @@ void ZCCCompiler::CompileStates() auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); if (code != nullptr) { - auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action); + auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action, (int)sl->Frames->Len()); state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false); } } From 010fd038beed8d3c46d4a763040387462857e29a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 01:19:41 +0100 Subject: [PATCH 173/471] - scriptified A_KeenDie. - added an 'exact' parameter to FThinkerIterator's Next function. This is mainly for scripting which allows to do a lot more checks natively when running the iterator while looking for one specific class. --- src/CMakeLists.txt | 1 - src/dobject.cpp | 6 +++++ src/dthinker.cpp | 8 ++++-- src/dthinker.h | 6 ++--- src/g_doom/a_doommisc.cpp | 1 - src/g_doom/a_keen.cpp | 42 ----------------------------- src/g_shared/a_action.cpp | 3 ++- wadsrc/static/zscript/actor.txt | 3 +-- wadsrc/static/zscript/base.txt | 7 ++--- wadsrc/static/zscript/doom/keen.txt | 37 +++++++++++++++++++++++++ 10 files changed, 59 insertions(+), 55 deletions(-) delete mode 100644 src/g_doom/a_keen.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index adc90444dc..9b4985a739 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -837,7 +837,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_doom/a_bossbrain.cpp g_doom/a_doomweaps.cpp - g_doom/a_keen.cpp g_doom/a_lostsoul.cpp g_doom/a_painelemental.cpp g_doom/a_revenant.cpp diff --git a/src/dobject.cpp b/src/dobject.cpp index 56d12787f4..d057a71d39 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -369,6 +369,12 @@ DEFINE_ACTION_FUNCTION(DObject, Destroy) return 0; } +DEFINE_ACTION_FUNCTION(DObject, GetClass) +{ + PARAM_SELF_PROLOGUE(DObject); + ACTION_RETURN_OBJECT(self->GetClass()); +} + //========================================================================== // // diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 022e147da0..bacd53eee5 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -480,7 +480,7 @@ void FThinkerIterator::Reinit () m_SearchingFresh = false; } -DThinker *FThinkerIterator::Next () +DThinker *FThinkerIterator::Next (bool exact) { if (m_ParentType == NULL) { @@ -496,7 +496,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; } diff --git a/src/dthinker.h b/src/dthinker.h index 3f96472977..95985c2fb4 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/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 31ee228f80..534ed400e7 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -24,7 +24,6 @@ // Include all the other Doom stuff here to reduce compile time #include "a_bossbrain.cpp" #include "a_doomweaps.cpp" -#include "a_keen.cpp" #include "a_lostsoul.cpp" #include "a_painelemental.cpp" #include "a_revenant.cpp" diff --git a/src/g_doom/a_keen.cpp b/src/g_doom/a_keen.cpp deleted file mode 100644 index b22f141b49..0000000000 --- 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 "vm.h" -*/ - -// -// A_KeenDie -// DOOM II special, map 32. -// Uses special tag 666 by default. -// - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KeenDie) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT_DEF(doortag); - - 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_shared/a_action.cpp b/src/g_shared/a_action.cpp index 0ec388de85..e1fa9a7fab 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -105,7 +105,8 @@ void A_Unblock(AActor *self, bool drop) DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking) { PARAM_SELF_PROLOGUE(AActor); - A_Unblock(self, true); + PARAM_BOOL_DEF(drop); + A_Unblock(self, drop); return 0; } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 091fba4b53..c6175b6f10 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -227,7 +227,7 @@ class Actor : Thinker native 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(); + native void A_NoBlocking(bool drop = true); void A_Fall() { A_NoBlocking(); } native void A_XScream(); native void A_Look(); @@ -241,7 +241,6 @@ class Actor : Thinker native native void A_BossDeath(); native void A_SkullAttack(float speed = 20); native void A_BetaSkullAttack(); - native void A_KeenDie(int doortag = 666); 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); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index cca39f1e23..4564f0e86d 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -1,6 +1,7 @@ class Object native { /*virtual*/ native void Destroy(); + native class GetClass(); } class Thinker : Object native @@ -14,8 +15,8 @@ class ThinkerIterator : Object native MAX_STATNUM = 127 } - native static ThinkerIterator Create(class type = "Actor", int statnum=MAX_STATNUM+1); - native Thinker Next(); + native static ThinkerIterator Create(class type = "Actor", int statnum=MAX_STATNUM+1); + native Thinker Next(bool exact = false); native void Reinit(); } @@ -23,7 +24,7 @@ class DropItem : Object native { /* native fields listed for reference only for now native readonly DropItem Next; - native readonly name ItemName; // internally called 'name' which clashes with the type. + native readonly name Name; native readonly int Probability; native readonly int Amount; */ diff --git a/wadsrc/static/zscript/doom/keen.txt b/wadsrc/static/zscript/doom/keen.txt index a60e924eff..6d596c717a 100644 --- a/wadsrc/static/zscript/doom/keen.txt +++ b/wadsrc/static/zscript/doom/keen.txt @@ -42,3 +42,40 @@ class CommanderKeen : Actor 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); + } +} + + From 514bcfb128afa13af1fad5216ad0c50361d71690 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 01:24:52 +0100 Subject: [PATCH 174/471] Print a clearer error message if a function name is encountered without parentheses. --- src/scripting/codegeneration/codegen.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9e86fff8f7..4111805eab 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5075,7 +5075,14 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else { - ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); + 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; } From 76c34d7b2fc2d737384796d807778a41db92503d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 09:50:53 +0100 Subject: [PATCH 175/471] - block access to private and protected data for the external variabler getter functions. - fixed: The state index comparison against 0 was broken. - fixed: Resolving codegen nodes must set the strictness flag per function so that ZSCRIPT and DECORATE are done properly. --- src/p_actionfunctions.cpp | 4 ++-- src/p_setup.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/vm/vmbuilder.cpp | 3 +++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 9ed20daf85..1cfc44ae2f 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -5031,7 +5031,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()); @@ -5080,7 +5080,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))) { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index aafed854b0..11aef9d8db 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/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4111805eab..db6355f842 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7886,7 +7886,7 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) delete this; return nullptr; } - else if (Index->isConstant() && static_cast(Index) < 0) + else if (Index->isConstant() && static_cast(Index)->GetValue() < 0) { ScriptPosition.Message(MSG_ERROR, "State index must be positive"); delete this; diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 41ec4b920b..5b792e7cc7 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -713,6 +713,7 @@ void FFunctionBuildList::Build() ctx.FunctionArgs.Push(local); } + FScriptPosition::StrictErrors = !item.FromDecorate; item.Code = item.Code->Resolve(ctx); item.Proto = ctx.ReturnProto; @@ -758,4 +759,6 @@ void FFunctionBuildList::Build() fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4); fclose(dump); } + FScriptPosition::StrictErrors = false; + } \ No newline at end of file From b890f2b60892f6d2a337a5c21b6e86a46e9cc666 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 10:38:23 +0100 Subject: [PATCH 176/471] - fixed retrieval of constant for state index. --- src/scripting/codegeneration/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index db6355f842..f19e8901f3 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7886,7 +7886,7 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) delete this; return nullptr; } - else if (Index->isConstant() && static_cast(Index)->GetValue() < 0) + else if (Index->isConstant() && static_cast(Index)->GetValue().GetInt() < 0) { ScriptPosition.Message(MSG_ERROR, "State index must be positive"); delete this; From 24925c88a80e24478883a47dab8e5000e34b3e61 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 13:51:46 +0100 Subject: [PATCH 177/471] - added readonly pointers. They need to be defined with 'readonly'. These are significantly different from declaring a field readonly in that they do not disallow modification of the variable itself but what it points to. For the actor defaults this is necessary to prevent accidental modification. A readonly pointer is actually a different type than a regular pointer. - fixed code generation for dynamic cast. It was missing the jump instruction after the compare. --- src/dobjtype.cpp | 14 +++++++------- src/dobjtype.h | 5 +++-- src/scripting/codegeneration/codegen.cpp | 19 +++++++++++++++---- src/scripting/zscript/zcc-parse.lemon | 16 +++++++++++++++- src/scripting/zscript/zcc_compile.cpp | 10 +++++----- src/scripting/zscript/zcc_parser.h | 1 + wadsrc/static/zscript/actor.txt | 2 +- 7 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index f1726adbf1..1b5d3bc7ec 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1467,7 +1467,7 @@ END_POINTERS //========================================================================== PPointer::PPointer() -: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL) +: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL), IsConst(false) { mDescriptiveName = "NullPointer"; SetOps(); @@ -1479,10 +1479,10 @@ PPointer::PPointer() // //========================================================================== -PPointer::PPointer(PType *pointsat) -: PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat) +PPointer::PPointer(PType *pointsat, bool isconst) +: PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat), IsConst(isconst) { - mDescriptiveName.Format("Pointer<%s>", pointsat->DescriptiveName()); + mDescriptiveName.Format("Pointer<%s%s>", pointsat->DescriptiveName(), isconst? "readonly " : ""); SetOps(); } @@ -1570,14 +1570,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); } diff --git a/src/dobjtype.h b/src/dobjtype.h index 30e22e8680..9cf6639831 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -535,9 +535,10 @@ class PPointer : public PBasicType HAS_OBJECT_POINTERS; public: PPointer(); - PPointer(PType *pointsat); + PPointer(PType *pointsat, bool isconst = false); PType *PointedType; + bool IsConst; virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; @@ -877,7 +878,7 @@ 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); PEnum *NewEnum(FName name, PTypeBase *outer); PStruct *NewStruct(FName name, PTypeBase *outer); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f19e8901f3..39034c7521 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -241,6 +241,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source) 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))) { @@ -3852,8 +3853,7 @@ ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build) FxDynamicCast::FxDynamicCast(PClass * cls, FxExpression *r) : FxExpression(EFX_DynamicCast, r->ScriptPosition) { - expr = new FxTypeCast(r, NewPointer(RUNTIME_CLASS(DObject)), true, true); - ValueType = NewPointer(cls); + expr = r; CastType = cls; } @@ -3878,6 +3878,15 @@ 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; } @@ -3903,7 +3912,8 @@ ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build) build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); build->Emit(OP_RESULT, 0, REGT_INT, check.RegNum); - auto patch = build->Emit(OP_EQ_K, 0, check.RegNum, build->GetConstantInt(0)); + 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; @@ -5439,7 +5449,8 @@ FxStructMember::~FxStructMember() bool FxStructMember::RequestAddress(bool *writable) { AddressRequested = true; - if (writable != nullptr) *writable = AddressWritable && !(membervar->Flags & VARF_ReadOnly); + if (writable != nullptr) *writable = (AddressWritable && !(membervar->Flags & VARF_ReadOnly) && + (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast(classx->ValueType)->IsConst)); return true; } diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 9d22765fc2..666eff5a2a 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -668,6 +668,7 @@ 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) */ @@ -676,14 +677,27 @@ 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; } @@ -698,7 +712,7 @@ type_name(X) ::= DOT dottable_id(A). %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 *} diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f296a91b6c..d6bf1d7f34 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1481,16 +1481,16 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(type->UserType->Id, table); if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) { - auto type = static_cast(sym)->Type; - if (type->IsKindOf(RUNTIME_CLASS(PEnum))) + 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 (type->IsKindOf(RUNTIME_CLASS(PClass))) + if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) { - return NewPointer(type); + return NewPointer(ptype, type->isconst); } - return type; + return ptype; } Error(type, "Unable to resolve %s as type.", FName(type->UserType->Id).GetChars()); return TypeError; diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 715fa0be65..01ea0d2d07 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -310,6 +310,7 @@ struct ZCC_BasicType : ZCC_Type { EZCCBuiltinType Type; ZCC_Identifier *UserType; + bool isconst; }; struct ZCC_MapType : ZCC_Type diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c6175b6f10..fdadab53c6 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -53,7 +53,7 @@ class Actor : Thinker native return GetPointer(ptr_select1) == GetPointer(ptr_select2); } - native static /*readonly*/ Actor GetDefaultByType(class cls); + native static readonly GetDefaultByType(class cls); native void SetDamage(int dmg); native static bool isDehState(state st); native void SetOrigin(vector3 newpos, bool moving); From 98fa3d2d939d663acc1e2cf95c92dc0940f8c130 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 17:14:16 +0100 Subject: [PATCH 178/471] - added an accessor to the actor defaults. This might have been possible with less work using a function but that would have necessitated some type casts when using it on subclasses. - scriptified A_BarrelDestroy to test the above. --- src/dobjtype.cpp | 4 +- src/g_doom/a_doommisc.cpp | 18 ---- src/namedef.h | 1 + src/scripting/codegeneration/codegen.cpp | 126 ++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 6 +- src/scripting/zscript/zcc-parse.lemon | 8 ++ wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/doom/doommisc.txt | 17 +++ 8 files changed, 157 insertions(+), 24 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 1b5d3bc7ec..e3c6380622 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1508,10 +1508,10 @@ void PPointer::SetOps() 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; } //========================================================================== diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 534ed400e7..9f31782951 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -29,21 +29,3 @@ #include "a_revenant.cpp" #include "a_scriptedmarine.cpp" -// The barrel of green goop ------------------------------------------------ - -DEFINE_ACTION_FUNCTION(AActor, A_BarrelDestroy) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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/namedef.h b/src/namedef.h index 809c28a9c3..8f1a54337b 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -683,6 +683,7 @@ xx(BuiltinNameToClass) xx(BuiltinFindMultiNameState) xx(BuiltinFindSingleNameState) xx(BuiltinHandleRuntimeState) +xx(BuiltinGetDefault) xx(Damage) // basic type names diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 39034c7521..4ece6ad4ff 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5015,6 +5015,27 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) 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; @@ -5348,6 +5369,95 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +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; + +} + //========================================================================== // // @@ -5465,6 +5575,21 @@ 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); @@ -5581,7 +5706,6 @@ FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition : FxStructMember(x, mem, pos) { ExprType = EFX_ClassMember; - //if (classx->IsDefaultObject()) Readonly=true; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index b118b8d5d4..a244e519ee 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -355,12 +355,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); }; //========================================================================== diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 666eff5a2a..fc707428ea 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -224,6 +224,14 @@ 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. diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index fdadab53c6..efdeb3ef10 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -357,7 +357,6 @@ class Actor : Thinker native 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_BarrelDestroy(); native void A_QueueCorpse(); native void A_DeQueueCorpse(); native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = null); diff --git a/wadsrc/static/zscript/doom/doommisc.txt b/wadsrc/static/zscript/doom/doommisc.txt index 80e330a68e..a11c411f8c 100644 --- a/wadsrc/static/zscript/doom/doommisc.txt +++ b/wadsrc/static/zscript/doom/doommisc.txt @@ -34,6 +34,23 @@ class ExplosiveBarrel : Actor } } +extend class Actor +{ + void A_BarrelDestroy() + { + if (GetCVar("sv_barrelrespawn")) + { + Height = Default.Height; + bInvisible = true; + bSolid = false; + } + else + { + Destroy(); + } + } +} + // Bullet puff ------------------------------------------------------------- class BulletPuff : Actor From 1b77a8f491300c31096f7cc00de9f16c6ce6d8f7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 18:05:57 +0100 Subject: [PATCH 179/471] - fixed: Tacking on a return statement should only be done if the function has branches that actually reach the end. Otherwise it may interfere with return type deduction. - used the return check to optimize out unneeded jumps at the end of an if statement's first block. --- src/scripting/codegeneration/codegen.cpp | 52 +++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 5 +++ src/scripting/vm/vmbuilder.cpp | 7 ++++ src/scripting/zscript/zcc_compile.cpp | 6 +-- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4ece6ad4ff..5ab66c4c2f 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6879,6 +6879,18 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx) 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 @@ -7194,6 +7206,24 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) 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(); +} //========================================================================== // @@ -7355,17 +7385,35 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) v.Free(build); if (path2 != nullptr) { - size_t path1jump = build->Emit(OP_JMP, 0); + 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; } - build->BackpatchToHere(jumpspot); + if (jumpspot != 0xffffffff) build->BackpatchToHere(jumpspot); return ExpEmit(); } + +//========================================================================== +// +// FxIfStatement :: CheckReturn +// +//========================================================================== + +bool FxIfStatement::CheckReturn() +{ + //An if statement returns if both branches return, if present. + return (WhenTrue == nullptr || WhenTrue->CheckReturn()) && + (WhenFalse == nullptr || WhenFalse->CheckReturn()); +} + //========================================================================== // // FxLoopStatement :: Resolve diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index a244e519ee..f4426da907 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -297,6 +297,7 @@ public: virtual bool RequestAddress(bool *writable); virtual PPrototype *ReturnProto(); virtual VMFunction *GetDirectFunction(); + virtual bool CheckReturn() { return false; } bool IsNumeric() const { return ValueType != TypeName && ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } bool IsFloat() const { return ValueType->GetRegType() == REGT_FLOAT && ValueType->GetRegCount() == 1; } bool IsInteger() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT); } @@ -1390,6 +1391,7 @@ public: ExpEmit Emit(VMFunctionBuilder *build); void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); expr->NeedResult = false; } VMFunction *GetDirectFunction(); + bool CheckReturn(); }; //========================================================================== @@ -1438,6 +1440,7 @@ public: ~FxSwitchStatement(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); + bool CheckReturn(); }; //========================================================================== @@ -1476,6 +1479,7 @@ public: ~FxIfStatement(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); + bool CheckReturn(); }; //========================================================================== @@ -1589,6 +1593,7 @@ public: FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); VMFunction *GetDirectFunction(); + bool CheckReturn() { return true; } }; //========================================================================== diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 5b792e7cc7..f8451e62c8 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -715,6 +715,13 @@ void FFunctionBuildList::Build() FScriptPosition::StrictErrors = !item.FromDecorate; item.Code = item.Code->Resolve(ctx); + 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; // Make sure resolving it didn't obliterate it. diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index d6bf1d7f34..44b2f489c1 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2464,15 +2464,15 @@ FxExpression *ZCCCompiler::ConvertAST(PClass *cls, ZCC_TreeNode *ast) // 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; + //bool isreturn = false; auto node = compound->Content; if (node != nullptr) do { x->Add(ConvertNode(node)); - isreturn = node->NodeType == AST_ReturnStmt; + //isreturn = node->NodeType == AST_ReturnStmt; node = static_cast(node->SiblingNext); } while (node != compound->Content); - if (!isreturn) x->Add(new FxReturnStatement(nullptr, *ast)); + //if (!isreturn) x->Add(new FxReturnStatement(nullptr, *ast)); return x; } } From 0851d698de84259448b013050af40054619f722f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 18:15:53 +0100 Subject: [PATCH 180/471] - don't run constant state indices through the runtime checker. --- src/scripting/codegeneration/codegen.cpp | 30 +++++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 5ab66c4c2f..cfff4ef359 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1431,11 +1431,29 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return nullptr; } - FxExpression *x = new FxRuntimeStateIndex(basex); - x = x->Resolve(ctx); - basex = nullptr; - delete this; - return x; + 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(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))) @@ -8019,7 +8037,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) ABORT(ctx.Class); auto aclass = dyn_cast(ctx.Class); - // This expression type can only be used from DECORATE, so there's no need to consider the possibility of calling it from a non-actor. + // 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) From 0f9ebff3ee14cb8423c78dbbee7340e862666844 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 18:56:04 +0100 Subject: [PATCH 181/471] - fixed: The return checking code must be inside the nullptr check for item.code. --- src/scripting/vm/vmbuilder.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index f8451e62c8..aa6188f908 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -715,13 +715,6 @@ void FFunctionBuildList::Build() FScriptPosition::StrictErrors = !item.FromDecorate; item.Code = item.Code->Resolve(ctx); - 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; // Make sure resolving it didn't obliterate it. @@ -729,6 +722,14 @@ void FFunctionBuildList::Build() { assert(item.Proto != 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); + } + // 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. From b59f4e950f83602b4058fe3bfde546b1c7da164e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Nov 2016 21:02:26 +0100 Subject: [PATCH 182/471] - fixed: The return prototyxpe may only be retrieved after the return state of the function has been checked. Also made this a real error message instead of an assert because it will inevitably result in a crash if the prototype cannot be generated, making diagnostics impossible. --- src/scripting/vm/vmbuilder.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index aa6188f908..f8ca44ba6b 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -715,13 +715,10 @@ void FFunctionBuildList::Build() FScriptPosition::StrictErrors = !item.FromDecorate; item.Code = item.Code->Resolve(ctx); - item.Proto = ctx.ReturnProto; // Make sure resolving it didn't obliterate it. if (item.Code != nullptr) { - assert(item.Proto != nullptr); - if (!item.Code->CheckReturn()) { auto newcmpd = new FxCompoundStatement(item.Code->ScriptPosition); @@ -730,6 +727,13 @@ void FFunctionBuildList::Build() 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. From c9a96ed0aef5eeb2c3d851483c585c766699727e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 01:34:54 +0100 Subject: [PATCH 183/471] - fixed: CALL_ACTION always set 3 args, even for normal methods. Also moved this to a sunfunction because the macro created a lot of code. --- src/scripting/vm/vm.h | 7 +++---- src/scripting/vm/vmframe.cpp | 7 +++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 811fb82e09..3120bbd61d 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1034,10 +1034,9 @@ struct AFuncDesc //#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_GENERIC) }; \ - stack->Call(name##_VMPtr, params, countof(params), NULL, 0, NULL); \ - } +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) diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index c54b585e99..1ccf3321e1 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -491,3 +491,10 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur throw; } } + +class AActor; +void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self) +{ + VMValue params[3] = { self, self, VMValue(nullptr, ATAG_GENERIC) }; + stack->Call(vmfunc, params, vmfunc->ImplicitArgs, nullptr, 0, nullptr); +} From 0130bde07740e5717a3c7c796a3c8c06ad6a99fd Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sat, 5 Nov 2016 20:15:41 -0500 Subject: [PATCH 184/471] Do not allow DMG_FORCED to penetrate player ultimate degreelessness/buddha. --- src/p_interaction.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index b4ecc827eb..ec8b5e4955 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1254,11 +1254,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, damage = target->health - 1; } - if (!(flags & DMG_FORCED)) { // check the real player, not a voodoo doll here for invulnerability effects if ((!telefragDamage && ((player->mo->flags2 & MF2_INVULNERABLE) || - (player->cheats & CF_GODMODE))) || + (player->cheats & CF_GODMODE)) && !(flags & DMG_FORCED)) || (player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE)) //Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2. { // player is invulnerable, so don't hurt him @@ -1331,7 +1330,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // but telefragging should still do enough damage to kill the player) // Ignore players that are already dead. // [MC]Buddha2 absorbs telefrag damage, and anything else thrown their way. - if (!(flags & DMG_FORCED) && (((player->cheats & CF_BUDDHA2) || (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && !telefragDamage)) && (player->playerstate != PST_DEAD))) + if ((((player->cheats & CF_BUDDHA2) || + (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && !telefragDamage && !(flags & DMG_FORCED))) && (player->playerstate != PST_DEAD))) { // If this is a voodoo doll we need to handle the real player as well. player->mo->health = target->health = player->health = 1; From c3ae56028934cc38ce3e08e415712a4ab27c7fbf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 09:22:03 +0100 Subject: [PATCH 185/471] - scriptified two more trivial functions. --- src/p_enemy.cpp | 30 +----------------------------- wadsrc/static/zscript/actor.txt | 4 ++-- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 8337320081..20a549a511 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3061,20 +3061,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_XScream) return 0; } -//=========================================================================== -// -// A_ScreamAndUnblock -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_ScreamAndUnblock) -{ - PARAM_SELF_PROLOGUE(AActor); - CALL_ACTION(A_Scream, self); - A_Unblock(self, true); - return 0; -} - //=========================================================================== // // A_ActiveSound @@ -3086,25 +3072,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_ActiveSound) 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_SELF_PROLOGUE(AActor); - CALL_ACTION(A_ActiveSound, self); - A_Unblock(self, true); - return 0; -} - //--------------------------------------------------------------------------- // // Modifies the drop amount of this item according to the current skill's diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index efdeb3ef10..0365be6573 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -130,6 +130,8 @@ class Actor : Thinker native 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(); } void A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false) { @@ -246,8 +248,6 @@ class Actor : Thinker native native void A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); - native void A_ScreamAndUnblock(); - native void A_ActiveAndUnblock(); native void A_ActiveSound(); native void A_FastChase(); From dbde0971ef7f508161ab5851d1540921a2d76dc4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 10:28:01 +0100 Subject: [PATCH 186/471] - removed the second 'calculated' return value from the damage function call in GetMissileDamage as it is no longer needed or even code being generated for. --- src/p_mobj.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a567f54864..3ea4a25e19 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3197,14 +3197,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; } From 062574b7266a8ffcde3bf04c9d32d6e11318dcce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 11:36:12 +0100 Subject: [PATCH 187/471] - fixed damage handling in A_BetaSkullAttack. For unknown reasons this completely bypassed the normal damage function semantics and even multiplied that with a random value. - made some tests about calling script code from native functions. * scriptified A_SkullAttack to have something to test * changed the A_SkullAttack call in A_PainShootSkull. * use a macro to declare the function pointer. Using local static variable init directly results in hideous code for the need of being thread-safe (which, even if the engine was made multithreaded is not needed here.) * Importsnt node here: Apparently passing an actor pointer to the VMValue constructor results in the void * version being called, not the DObject * version. --- src/g_doom/a_doommisc.cpp | 1 - src/g_doom/a_lostsoul.cpp | 86 ---------------------- src/g_doom/a_painelemental.cpp | 10 ++- src/info.cpp | 2 +- src/p_mobj.cpp | 15 ++++ src/r_utility.cpp | 24 ++++++ src/scripting/decorate/thingdef_states.cpp | 4 +- src/scripting/thingdef_data.cpp | 5 +- src/scripting/vm/vm.h | 3 +- src/scripting/vm/vmframe.cpp | 3 +- wadsrc/static/zscript/actor.txt | 4 +- wadsrc/static/zscript/doom/lostsoul.txt | 38 ++++++++++ 12 files changed, 97 insertions(+), 98 deletions(-) delete mode 100644 src/g_doom/a_lostsoul.cpp diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 9f31782951..1df9a4e7cd 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -24,7 +24,6 @@ // Include all the other Doom stuff here to reduce compile time #include "a_bossbrain.cpp" #include "a_doomweaps.cpp" -#include "a_lostsoul.cpp" #include "a_painelemental.cpp" #include "a_revenant.cpp" #include "a_scriptedmarine.cpp" diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp deleted file mode 100644 index 1c33f47a7d..0000000000 --- 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 "vm.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_SELF_PROLOGUE(AActor); - PARAM_FLOAT_DEF(speed); - - if (speed <= 0) - speed = SKULLSPEED; - A_SkullAttack(self, speed); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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 09160ddeb6..f2db5a2402 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -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,7 +137,10 @@ 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); + { + DECLARE_VMFUNC(AActor, A_SkullAttack); + CallAction(stack, A_SkullAttack, other); + } } @@ -148,7 +151,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_PainShootSkull) PARAM_FLOAT(angle); PARAM_INT_DEF(flags); PARAM_INT_DEF(limit); - A_PainShootSkull(self, angle, spawntype, flags, limit); + A_PainShootSkull(stack, self, angle, spawntype, flags, limit); + return 0; } diff --git a/src/info.cpp b/src/info.cpp index 26bd306fa8..4705e0e533 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -68,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) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3ea4a25e19..d0c0af1f55 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6445,6 +6445,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 @@ -6850,6 +6856,14 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) return 0; } +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); @@ -6879,6 +6893,7 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2OffsetZ) PARAM_BOOL_DEF(absolute); ACTION_RETURN_VEC3(self->Vec2OffsetZ(x, y, z, absolute)); } + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/r_utility.cpp b/src/r_utility.cpp index b009912f03..1588349299 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/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 59cf309386..3b99309285 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -99,7 +99,9 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) { sc.ScriptError ("Too many arguments to %s", specname.GetChars()); } - return new FxVMFunctionCall(new FxSelf(sc), FindGlobalActionFunction("A_CallSpecial"), args, sc, false); + 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; } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 74c685ea83..8152e9977b 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -602,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; } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 3120bbd61d..abce2f5571 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1071,7 +1071,8 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); class PFunction; -PFunction *FindGlobalActionFunction(const char *name); +VMFunction *FindVMFunction(PClass *cls, const char *name); +#define DECLARE_VMFUNC(cls, name) static VMFunction *name; if (name == nullptr) name = FindVMFunction(RUNTIME_CLASS(cls), #name); diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 1ccf3321e1..f622e114d2 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -495,6 +495,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur class AActor; void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self) { - VMValue params[3] = { self, self, VMValue(nullptr, ATAG_GENERIC) }; + // 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/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0365be6573..287808b673 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -81,6 +81,8 @@ class Actor : Thinker native 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(); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); @@ -241,8 +243,6 @@ class Actor : Thinker native native void A_SkelFist(); native void A_SkelMissile(); native void A_BossDeath(); - native void A_SkullAttack(float speed = 20); - native void A_BetaSkullAttack(); 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); diff --git a/wadsrc/static/zscript/doom/lostsoul.txt b/wadsrc/static/zscript/doom/lostsoul.txt index 69574e5c7c..00158e071c 100644 --- a/wadsrc/static/zscript/doom/lostsoul.txt +++ b/wadsrc/static/zscript/doom/lostsoul.txt @@ -81,3 +81,41 @@ class BetaSkull : LostSoul 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 - Vel.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'); + } +} + + + From c354000f1ce0dfdd49aa4e1839b79e189b320bbd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 12:00:16 +0100 Subject: [PATCH 188/471] - block "" and 0 as valid state names in ZScript. There were common workarounds for the lack of a null pointer in DECORATE which no longer are supported as those and would produce errors now. --- src/scripting/codegeneration/codegen.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index cfff4ef359..f296ac6e7d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1411,7 +1411,14 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) // 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)) { - FxExpression *x = new FxMultiNameState(static_cast(basex)->GetValue().GetString(), basex->ScriptPosition); + 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; @@ -1434,7 +1441,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) if (basex->isConstant()) { int i = static_cast(basex)->GetValue().GetInt(); - if (i < 0) + if (i <= 0) { ScriptPosition.Message(MSG_ERROR, "State index must be positive"); delete this; @@ -8087,7 +8094,7 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) delete this; return nullptr; } - else if (Index->isConstant() && static_cast(Index)->GetValue().GetInt() < 0) + else if (Index->isConstant() && static_cast(Index)->GetValue().GetInt() <= 0) { ScriptPosition.Message(MSG_ERROR, "State index must be positive"); delete this; From 2ac0046cdaa0efc9ef6d5298716ede192ab76957 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 13:14:46 +0100 Subject: [PATCH 189/471] - fixed and cleaned up state index jump handling * use the function build list instead of the function to pass the info. The function is permanent so not the best place for compile-time info. * pass along the current state index which is needed to calculate the target state. --- src/dobjtype.h | 1 - src/scripting/codegeneration/codegen.cpp | 12 +++++++----- src/scripting/codegeneration/codegen.h | 6 ++++-- src/scripting/decorate/thingdef_states.cpp | 2 +- src/scripting/thingdef.cpp | 5 ++--- src/scripting/thingdef.h | 2 +- src/scripting/vm/vmbuilder.cpp | 6 ++++-- src/scripting/vm/vmbuilder.h | 4 +++- src/scripting/zscript/zcc_compile.cpp | 4 ++-- 9 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index 9cf6639831..fd8bfb60ac 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -719,7 +719,6 @@ public: }; TArray Variants; PClass *OwningClass = nullptr; - int StateCount = 0; // needed to process state indices later. unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags); int GetImplicitArgs() diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f296ac6e7d..ea61d42df2 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -93,12 +93,14 @@ static const FLOP FxFlops[] = // //========================================================================== -FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecorate) : ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate) +FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecorate, int stateindex, int statecount) + : ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount) { if (fnc != nullptr) Class = fnc->OwningClass; } -FCompileContext::FCompileContext(PClass *cls, bool fromdecorate) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate) +FCompileContext::FCompileContext(PClass *cls, bool fromdecorate) + : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0) { } @@ -1426,13 +1428,13 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) } else if (basex->IsNumeric() && basex->ValueType != TypeSound && basex->ValueType != TypeColor) { - if (ctx.Function->SymbolName != NAME_None || !(ctx.Function->Variants[0].Flags & VARF_Action)) + 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.Function->StateCount != 1) + if (ctx.StateCount != 1) { ScriptPosition.Message(MSG_ERROR, "State jumps with index cannot be used on multistate definitions"); delete this; @@ -1447,7 +1449,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return nullptr; } - FxExpression *x = new FxStateByIndex(i, ScriptPosition); + FxExpression *x = new FxStateByIndex(ctx.StateIndex + i, ScriptPosition); x = x->Resolve(ctx); basex = nullptr; delete this; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index f4426da907..3cc86d1e6d 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -73,10 +73,12 @@ struct FCompileContext PPrototype *ReturnProto; PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) PClass *Class; // The type of the owning class. - bool FromDecorate; + 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.) TDeletingArray FunctionArgs; - FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate); + FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount); FCompileContext(PClass *cls, bool fromdecorate); // only to be used to resolve constants! PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 3b99309285..d17cb5d4dd 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -324,7 +324,7 @@ do_stop: endofstate: if (ScriptCode != nullptr) { - auto funcsym = CreateAnonymousFunction(actor, nullptr, VARF_Method | VARF_Action, (int)statestring.Len()); + auto funcsym = CreateAnonymousFunction(actor, nullptr, VARF_Method | VARF_Action); state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true); } int count = bag.statedef.AddStates(&state, statestring); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 6f30f8add7..8c42e8987d 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -132,7 +132,7 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArray rets(1); TArray args; @@ -143,7 +143,6 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i SetImplicitArgs(&args, &argflags, &argnames, containingclass, flags); PFunction *sym = new PFunction(containingclass, NAME_None); // anonymous functions do not have names. - sym->StateCount = statecount; sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, flags); return sym; } @@ -202,7 +201,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, else { auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition); - auto funcsym = CreateAnonymousFunction(info, TypeSInt32, VARF_Method, 0); + auto funcsym = CreateAnonymousFunction(info, TypeSInt32, VARF_Method); defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate); } } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 3511d1ee1d..b2d34231de 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -153,7 +153,7 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag); FName CheckCastKludges(FName in); void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags); -PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags, int statecount); +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); diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index f8ca44ba6b..0d517b6ef3 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -653,7 +653,7 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc) //========================================================================== FFunctionBuildList FunctionBuildList; -VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate) +VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount) { auto func = code->GetDirectFunction(); if (func != nullptr) @@ -673,6 +673,8 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c it.Function->ImplicitArgs = functype->GetImplicitArgs(); it.Proto = nullptr; it.FromDecorate = fromdecorate; + it.StateIndex = stateindex; + it.StateCount = statecount; // set prototype for named functions. if (it.Func->SymbolName != NAME_None) @@ -698,7 +700,7 @@ void FFunctionBuildList::Build() 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); + FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate, item.StateIndex, item.StateCount); // Allocate registers for the function's arguments and create local variable nodes before starting to resolve it. VMFunctionBuilder buildit(item.Func->GetImplicitArgs()); diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 9a97c216d2..452a7882cf 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -106,13 +106,15 @@ class FFunctionBuildList PPrototype *Proto = nullptr; VMScriptFunction *Function = nullptr; FString PrintableName; + int StateIndex; + int StateCount; bool FromDecorate; }; TArray mItems; public: - VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate); + VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate = -1, int statecnt = 0); void Build(); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 44b2f489c1..f529765121 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2349,8 +2349,8 @@ void ZCCCompiler::CompileStates() auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); if (code != nullptr) { - auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action, (int)sl->Frames->Len()); - state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false); + auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action); + state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len()); } } From 398433b5e6c76bf08c89e0ac447f887a4a1cc561 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 13:20:22 +0100 Subject: [PATCH 190/471] - fixed: Explicit casts to bool were missing. --- src/scripting/codegeneration/codegen.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index ea61d42df2..b2d0b2f0ac 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6083,6 +6083,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) switch (MethodName) { + case NAME_Bool: case NAME_Int: case NAME_uInt: case NAME_Double: @@ -6092,7 +6093,9 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_State: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { - PType *type = MethodName == NAME_Int ? TypeSInt32 : + PType *type = + MethodName == NAME_Bool ? TypeBool : + MethodName == NAME_Int ? TypeSInt32 : MethodName == NAME_uInt ? TypeUInt32 : MethodName == NAME_Double ? TypeFloat64 : MethodName == NAME_Name ? TypeName : From 6414fd301b729b1ce1d418129ff41f48b6313bab Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 13:21:47 +0100 Subject: [PATCH 191/471] - let's add a 'float' cast, too, just in case. It still will cast to double, because single precision floats only can exist as memory values. --- src/scripting/codegeneration/codegen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index b2d0b2f0ac..58f73a8914 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6086,6 +6086,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Bool: case NAME_Int: case NAME_uInt: + case NAME_Float: case NAME_Double: case NAME_Name: case NAME_Color: @@ -6097,6 +6098,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) 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_Color ? TypeColor : From 647fd53a1582385c1f5b618dbba96d583eeba260 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 14:14:54 +0100 Subject: [PATCH 192/471] - fixed: An 'if' statement with only one branch may never considered to be always returning. --- src/scripting/codegeneration/codegen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 58f73a8914..61b23cc158 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7441,9 +7441,9 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) bool FxIfStatement::CheckReturn() { - //An if statement returns if both branches return, if present. - return (WhenTrue == nullptr || WhenTrue->CheckReturn()) && - (WhenFalse == nullptr || WhenFalse->CheckReturn()); + //An if statement returns if both branches return. Both branches must be present. + return WhenTrue != nullptr && WhenTrue->CheckReturn() && + WhenFalse != nullptr && WhenFalse->CheckReturn(); } //========================================================================== From 10ef430baefcf8e6ada0dcb853a2228867c5dd40 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 14:18:13 +0100 Subject: [PATCH 193/471] Revert "Do not allow DMG_FORCED to penetrate player ultimate degreelessness/buddha." This reverts commit 0130bde07740e5717a3c7c796a3c8c06ad6a99fd. This wasn't supposed to get merged, so get rid of it again. The change in semantics here is not acceptable. --- src/p_interaction.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index ec8b5e4955..b4ecc827eb 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1254,10 +1254,11 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, damage = target->health - 1; } + if (!(flags & DMG_FORCED)) { // check the real player, not a voodoo doll here for invulnerability effects if ((!telefragDamage && ((player->mo->flags2 & MF2_INVULNERABLE) || - (player->cheats & CF_GODMODE)) && !(flags & DMG_FORCED)) || + (player->cheats & CF_GODMODE))) || (player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE)) //Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2. { // player is invulnerable, so don't hurt him @@ -1330,8 +1331,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // but telefragging should still do enough damage to kill the player) // Ignore players that are already dead. // [MC]Buddha2 absorbs telefrag damage, and anything else thrown their way. - if ((((player->cheats & CF_BUDDHA2) || - (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && !telefragDamage && !(flags & DMG_FORCED))) && (player->playerstate != PST_DEAD))) + if (!(flags & DMG_FORCED) && (((player->cheats & CF_BUDDHA2) || (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && !telefragDamage)) && (player->playerstate != PST_DEAD))) { // If this is a voodoo doll we need to handle the real player as well. player->mo->health = target->health = player->health = 1; From 2583da968018947be7eeb09bbb7ebe7ed143d756 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sun, 6 Nov 2016 07:44:30 -0600 Subject: [PATCH 194/471] Do not allow DMG_FORCED to bypass ultimate degreeslessness/buddha for players. --- src/p_interaction.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index b4ecc827eb..48d13bebff 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) { From 7da4e0d03dfc68498e385ef42417db3289ae277e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Nov 2016 23:10:23 +0100 Subject: [PATCH 195/471] - removed a parsing hack for the old internal definitions. - fixed: The state cast hack for DECORATE could not properly create state constants. Instead they were passed to FxRuntimeStateIndex without resolving them to something constant. This adds proper handling of constant indices within that class. --- src/scripting/codegeneration/codegen.cpp | 24 +++++++++++++++++++---- src/scripting/decorate/thingdef_parse.cpp | 8 ++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 61b23cc158..fa9fe13c9b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -8101,11 +8101,27 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) delete this; return nullptr; } - else if (Index->isConstant() && static_cast(Index)->GetValue().GetInt() <= 0) + else if (Index->isConstant()) { - ScriptPosition.Message(MSG_ERROR, "State index must be positive"); - delete this; - return nullptr; + 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) + { + auto x = new FxConstant((FState*)nullptr, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + else + { + auto x = new FxStateByIndex(index, ScriptPosition); + delete this; + return x->Resolve(ctx); + } } else if (Index->ValueType->GetRegType() != REGT_INT) { // Float. diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index b344a12283..4308950600 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -181,15 +181,11 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c { if (sc.String[0] == 0 || sc.Compare("None")) { - x = new FxConstant((FState*)NULL, sc); + x = new FxConstant((FState*)nullptr, sc); } 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 { From b206d19df4bb32c8af1819d1b3b977c02cd7d528 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 01:10:56 +0100 Subject: [PATCH 196/471] - fixed: RegAvailability never set the number of allocated registers to more than 32. - fixed register allocation in ?: operator which was quite broken. --- src/CMakeLists.txt | 1 - src/scripting/codegeneration/codegen.cpp | 6 +++--- src/scripting/vm/vmbuilder.cpp | 12 ++++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a20d9ff0b9..d5d3e007b1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -850,7 +850,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_doom/a_bossbrain.cpp g_doom/a_doomweaps.cpp - g_doom/a_lostsoul.cpp g_doom/a_painelemental.cpp g_doom/a_revenant.cpp g_doom/a_scriptedmarine.cpp diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index fa9fe13c9b..814c47717b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4061,6 +4061,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) // 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) @@ -4073,6 +4074,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) ExpEmit trueop = truex->Emit(build); if (trueop.Konst) { + trueop.Free(build); if (trueop.RegType == REGT_FLOAT) { out = ExpEmit(build, REGT_FLOAT); @@ -4113,20 +4115,18 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) { if (falseop.RegType == REGT_FLOAT) { - out = ExpEmit(build, REGT_FLOAT); build->Emit(OP_LKF, out.RegNum, falseop.RegNum); } else if (falseop.RegType == REGT_POINTER) { - out = ExpEmit(build, REGT_POINTER); build->Emit(OP_LKP, out.RegNum, falseop.RegNum); } else { assert(falseop.RegType == REGT_STRING); - out = ExpEmit(build, REGT_STRING); build->Emit(OP_LKS, out.RegNum, falseop.RegNum); } + falseop.Free(build); } else { diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 0d517b6ef3..bb6b626e7d 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -336,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]; @@ -362,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; @@ -374,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); From dc055b74c153ca68aa2406d0111a445a24cfe7ab Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 09:54:46 +0100 Subject: [PATCH 197/471] - fixed the octal parser in strbin. Like its hex counterpart it needs to backtrack one character if it find the end of a sequence. - since ZScript already receives filtered strings, the 'T' converter for the properties should not do it again. --- src/cmdlib.cpp | 6 ++++++ src/scripting/zscript/zcc_compile.cpp | 5 +---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index 3a3d2876de..5799a23423 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/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f529765121..889cdb5fdb 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1676,13 +1676,10 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper 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 'T': // a filtered string - conv.s = strings[strings.Reserve(1)] = strbin1(GetString(exp)); - break; - case 'L': // Either a number or a list of strings if (!GetString(exp, true)) { From 208fe28042f3d2624c50c31f2185b4f336e98ec1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 11:30:41 +0100 Subject: [PATCH 198/471] - properly clear all script compiler data for a restart. --- src/scripting/codegeneration/codegen.cpp | 5 ++--- src/scripting/vm/vmbuilder.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 4 ---- src/scripting/zscript/zcc_parser.cpp | 15 +++++++-------- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 814c47717b..d3a5e0e8cf 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -213,18 +213,17 @@ void ExpEmit::Reuse(VMFunctionBuilder *build) // it and install it a local symbol table. // //========================================================================== -static PSymbolTable Builtins; static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func) { - PSymbol *sym = Builtins.FindSymbol(funcname, false); + 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; - Builtins.AddSymbol(sym); + GlobalSymbols.AddSymbol(sym); } return sym; } diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index bb6b626e7d..1544ca4a66 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -774,5 +774,5 @@ void FFunctionBuildList::Build() fclose(dump); } FScriptPosition::StrictErrors = false; - + mItems.Clear(); } \ No newline at end of file diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 889cdb5fdb..49711afb2d 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -51,8 +51,6 @@ #include "codegeneration/codegen.h" #include "vmbuilder.h" -#define DEFINING_CONST ((PSymbolConst *)(void *)1) - //========================================================================== // // ZCCCompiler :: ProcessClass @@ -714,10 +712,8 @@ bool ZCCCompiler::CompileConstant(ZCC_ConstantDef *def, PSymbolTable *sym) { assert(def->Symbol == nullptr); - def->Symbol = DEFINING_CONST; // avoid recursion ZCC_Expression *val = Simplify(def->Value, sym, true); def->Value = val; - if (def->Symbol == DEFINING_CONST) def->Symbol = nullptr; return (val->NodeType == AST_ExprConstant); } diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 26fdeec432..1f0800302f 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -199,9 +199,6 @@ static void InitTokenMap() TOKENDEF (TK_CanRaise, ZCC_CANRAISE); TOKENDEF (TK_Light, ZCC_LIGHT); TOKENDEF (TK_Extend, ZCC_EXTEND); - - ZCC_InitOperators(); - ZCC_InitConversions(); } #undef TOKENDEF #undef TOKENDEF2 @@ -293,11 +290,6 @@ parse_end: static void DoParse(int lumpnum) { - if (TokenMap.CountUsed() == 0) - { - InitTokenMap(); - } - FScanner sc; void *parser; ZCCToken value; @@ -400,6 +392,13 @@ static void DoParse(int lumpnum) void ParseScripts() { + if (TokenMap.CountUsed() == 0) + { + InitTokenMap(); + } + ZCC_InitOperators(); + ZCC_InitConversions(); + int lump, lastlump = 0; FScriptPosition::ResetErrorCounter(); while ((lump = Wads.FindLump("ZSCRIPT", &lastlump)) != -1) From 5e8c819a33abf09921f1a4ae440aed2d82f3727f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 11:53:49 +0100 Subject: [PATCH 199/471] - fixed checks in Powerup.Type property to properly deal with the differences between DECORATE and ZScript. - properly initialize Baggage everywhere it gets used. - fixed a few items with incorrect Powerup.Type settings that got flagged by the above changes. --- src/scripting/decorate/olddecorations.cpp | 1 + src/scripting/decorate/thingdef_parse.cpp | 1 + src/scripting/thingdef.h | 3 ++- src/scripting/thingdef_properties.cpp | 15 +++++++++++---- src/scripting/zscript/zcc_compile.cpp | 2 +- .../static/zscript/heretic/hereticartifacts.txt | 2 +- wadsrc/static/zscript/strife/strifeitems.txt | 8 ++++---- 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 75e49dbaa8..6ccd0051a0 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -158,6 +158,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 diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 4308950600..07da3cf573 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -1064,6 +1064,7 @@ static void ParseActor(FScanner &sc) PClassActor *info = NULL; Baggage bag; + bag.fromDecorate = true; info = ParseActorHeader(sc, &bag); sc.MustGetToken('{'); while (sc.MustGetAnyToken(), sc.TokenType != '}') diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index b2d34231de..6529059e6f 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -117,7 +117,7 @@ struct Baggage PClassActor *Info; bool DropItemSet; bool StateSet; - bool fromZScript; + bool fromDecorate; int CurrentState; int Lumpnum; FStateDefinitions statedef; @@ -132,6 +132,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); } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 6f1455e435..aa45089501 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -2422,11 +2422,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)) && !bag.fromZScript)) + 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; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 49711afb2d..981dcbc2a0 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1897,7 +1897,7 @@ void ZCCCompiler::InitDefaults() bag.Info = ti; bag.DropItemSet = false; bag.StateSet = false; - bag.fromZScript = true; + bag.fromDecorate = false; bag.CurrentState = 0; bag.Lumpnum = c->cls->SourceLump; bag.DropItemList = nullptr; diff --git a/wadsrc/static/zscript/heretic/hereticartifacts.txt b/wadsrc/static/zscript/heretic/hereticartifacts.txt index 94271c8cdd..e239748ff8 100644 --- a/wadsrc/static/zscript/heretic/hereticartifacts.txt +++ b/wadsrc/static/zscript/heretic/hereticartifacts.txt @@ -55,7 +55,7 @@ Class ArtiTomeOfPower : PowerupGiver native +FLOATBOB Inventory.PickupFlash "PickupFlash"; Inventory.Icon "ARTIPWBK"; - Powerup.Type "Weaponlevel2"; + Powerup.Type "PowerWeaponlevel2"; Inventory.PickupMessage "$TXT_ARTITOMEOFPOWER"; Tag "$TAG_ARTITOMEOFPOWER"; } diff --git a/wadsrc/static/zscript/strife/strifeitems.txt b/wadsrc/static/zscript/strife/strifeitems.txt index 3d8b4af544..cfc9394137 100644 --- a/wadsrc/static/zscript/strife/strifeitems.txt +++ b/wadsrc/static/zscript/strife/strifeitems.txt @@ -198,7 +198,7 @@ class ShadowArmor : PowerupGiver RenderStyle "Translucent"; Tag "$TAG_SHADOWARMOR"; Inventory.MaxAmount 2; - Powerup.Type "Shadow"; + Powerup.Type "PowerShadow"; Inventory.Icon "I_SHD1"; Inventory.PickupSound "misc/i_pkup"; Inventory.PickupMessage "$TXT_SHADOWARMOR"; @@ -222,7 +222,7 @@ class EnvironmentalSuit : PowerupGiver +INVENTORY.INVBAR -INVENTORY.FANCYPICKUPSOUND Inventory.MaxAmount 5; - Powerup.Type "Mask"; + Powerup.Type "PowerMask"; Tag "$TAG_ENVSUIT"; Inventory.Icon "I_MASK"; Inventory.PickupSound "misc/i_pkup"; @@ -353,7 +353,7 @@ class Targeter : PowerupGiver +INVENTORY.INVBAR -INVENTORY.FANCYPICKUPSOUND Tag "$TAG_TARGETER"; - Powerup.Type "Targeter"; + Powerup.Type "PowerTargeter"; Inventory.MaxAmount 5; Inventory.Icon "I_TARG"; Inventory.PickupSound "misc/i_pkup"; @@ -478,7 +478,7 @@ class Scanner : PowerupGiver native Inventory.MaxAmount 1; Tag "$TAG_SCANNER"; Inventory.Icon "I_PMUP"; - Powerup.Type "Scanner"; + Powerup.Type "PowerScanner"; Inventory.PickupSound "misc/i_pkup"; Inventory.PickupMessage "$TXT_SCANNER"; } From 387287008cd2dd76f055ebca11c3681278b756e1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 14:57:59 +0100 Subject: [PATCH 200/471] - fixed: Clamp was initialized with incorrect values. --- src/scripting/codegeneration/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d3a5e0e8cf..56691208f3 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6164,7 +6164,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) pass[1] = (*ArgList)[1]; pass[0] = new FxMinMax(pass, NAME_Max, ScriptPosition); pass[1] = (*ArgList)[2]; - func = new FxMinMax(*ArgList, NAME_Min, ScriptPosition); + func = new FxMinMax(pass, NAME_Min, ScriptPosition); (*ArgList)[0] = (*ArgList)[1] = (*ArgList)[2] = nullptr; } break; From e3bee84860a1079e4592d1aa246035e3c89bc181 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 20:12:06 +0100 Subject: [PATCH 201/471] - fixed: Hexen's serpent was still using "None" for 'no state', which in ZScript is done with null. --- wadsrc/static/zscript/hexen/serpent.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/hexen/serpent.txt b/wadsrc/static/zscript/hexen/serpent.txt index d8886ccb27..70fb2195a9 100644 --- a/wadsrc/static/zscript/hexen/serpent.txt +++ b/wadsrc/static/zscript/hexen/serpent.txt @@ -40,7 +40,7 @@ class Serpent : Actor SSPT H 10 A_Look; Loop; See: - SSPT HH 1 A_Chase("Melee", "None", CHF_NIGHTMAREFAST|CHF_NOPLAYACTIVE); + SSPT HH 1 A_Chase("Melee", null, CHF_NIGHTMAREFAST|CHF_NOPLAYACTIVE); SSPT H 2 A_SerpentHumpDecide; Loop; Pain: @@ -81,7 +81,7 @@ class Serpent : Actor SSPT [ 1 A_FreezeDeathChunks; Wait; Walk: - SSPT IJI 5 A_Chase("Attack", "None", CHF_NIGHTMAREFAST); + SSPT IJI 5 A_Chase("Attack", null, CHF_NIGHTMAREFAST); SSPT J 5 A_SerpentCheckForAttack; Goto Dive; Hump: From 75c20ebaa6431ca7338f2e2c3f6736f0ea96b3ab Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 21:30:08 +0100 Subject: [PATCH 202/471] - typo in Lostsoul definition. --- wadsrc/static/zscript/doom/lostsoul.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/doom/lostsoul.txt b/wadsrc/static/zscript/doom/lostsoul.txt index 00158e071c..7ef8b4cf0e 100644 --- a/wadsrc/static/zscript/doom/lostsoul.txt +++ b/wadsrc/static/zscript/doom/lostsoul.txt @@ -102,7 +102,7 @@ extend class Actor A_PlaySound(AttackSound, CHAN_VOICE); A_FaceTarget(); VelFromAngle(skullspeed); - Vel.Z = (target.pos.Z + target.Height/2 - Vel.Z) / DistanceBySpeed(target, speed); + Vel.Z = (target.pos.Z + target.Height/2 - pos.Z) / DistanceBySpeed(target, speed); } void A_BetaSkullAttack() From cf9cdeb48028c0dc53aa0dc219fbb63dc65b70e6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 23:16:25 +0100 Subject: [PATCH 203/471] - scriptified the Revenant's code. --- src/CMakeLists.txt | 1 - src/g_doom/a_doommisc.cpp | 1 - src/g_doom/a_revenant.cpp | 152 ------------------------ src/p_mobj.cpp | 56 ++++++++- wadsrc/static/zscript/actor.txt | 11 +- wadsrc/static/zscript/doom/revenant.txt | 120 +++++++++++++++++++ 6 files changed, 182 insertions(+), 159 deletions(-) delete mode 100644 src/g_doom/a_revenant.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d5d3e007b1..81f43f06b3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -851,7 +851,6 @@ set( NOT_COMPILED_SOURCE_FILES g_doom/a_bossbrain.cpp g_doom/a_doomweaps.cpp g_doom/a_painelemental.cpp - g_doom/a_revenant.cpp g_doom/a_scriptedmarine.cpp g_heretic/a_chicken.cpp g_heretic/a_dsparil.cpp diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 1df9a4e7cd..eabf887f07 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -25,6 +25,5 @@ #include "a_bossbrain.cpp" #include "a_doomweaps.cpp" #include "a_painelemental.cpp" -#include "a_revenant.cpp" #include "a_scriptedmarine.cpp" diff --git a/src/g_doom/a_revenant.cpp b/src/g_doom/a_revenant.cpp deleted file mode 100644 index 0ffaed7534..0000000000 --- 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 "vm.h" -#include "g_level.h" -*/ - -static FRandom pr_tracer ("Tracer"); -static FRandom pr_skelfist ("SkelFist"); - -// -// A_SkelMissile -// -DEFINE_ACTION_FUNCTION(AActor, A_SkelMissile) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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/p_mobj.cpp b/src/p_mobj.cpp index d0c0af1f55..21d32c2de2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1871,6 +1871,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 @@ -5424,7 +5431,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)); +} //--------------------------------------------------------------------------- // @@ -6817,6 +6837,22 @@ 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, AddZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(addz); + self->AddZ(addz); + return 0; +} + DEFINE_ACTION_FUNCTION(AActor, SetDamage) { PARAM_SELF_PROLOGUE(AActor); @@ -6856,6 +6892,14 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) 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); @@ -6894,6 +6938,16 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2OffsetZ) 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 diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 287808b673..5aa1af2930 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -54,6 +54,7 @@ class Actor : Thinker native } native static readonly GetDefaultByType(class cls); + native static float deltaangle(float ang1, float ang2); native void SetDamage(int dmg); native static bool isDehState(state st); native void SetOrigin(vector3 newpos, bool moving); @@ -62,6 +63,8 @@ class Actor : Thinker native 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 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); @@ -72,6 +75,10 @@ class Actor : Thinker native native bool SetState(state st, bool nofunction = false); 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 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); @@ -238,10 +245,6 @@ class Actor : Thinker native native void A_Chase(state melee = null, state missile = null, int flags = 0); native void A_Scream(); native void A_VileChase(); - native void A_Tracer(); - native void A_SkelWhoosh(); - native void A_SkelFist(); - native void A_SkelMissile(); 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); diff --git a/wadsrc/static/zscript/doom/revenant.txt b/wadsrc/static/zscript/doom/revenant.txt index 7fc8b8e0df..2fc35c60f2 100644 --- a/wadsrc/static/zscript/doom/revenant.txt +++ b/wadsrc/static/zscript/doom/revenant.txt @@ -120,3 +120,123 @@ class RevenantTracerSmoke : Actor 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; + } + } +} + From aac931192bebfb7e6624ec59c7f29db53619fc93 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 23:22:00 +0100 Subject: [PATCH 204/471] - fixed: Declaring a damage function must set regular damage to -1 to disable it. --- src/scripting/zscript/zcc_compile.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 981dcbc2a0..41c3cde34a 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1768,6 +1768,7 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro { auto x = ConvertNode(prop->Values); CreateDamageFunction(cls, (AActor *)bag.Info->Defaults, x, false); + ((AActor *)bag.Info->Defaults)->DamageVal = -1; return; } From 3661e479d956c0191dc3242a8eda742e2ffce836 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 7 Nov 2016 23:29:54 +0100 Subject: [PATCH 205/471] - fixed: Runtime conversion of names to classes used the wrong argument to check the class type. --- src/scripting/codegeneration/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 56691208f3..0972ed0025 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -8001,7 +8001,7 @@ int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray &def FName clsname = ENamedName(param[0].i); const PClass *cls = PClass::FindClass(clsname); - const PClass *desttype = reinterpret_cast(param[0].a); + const PClass *desttype = reinterpret_cast(param[1].a); if (!cls->IsDescendantOf(desttype)) { From 7b7b66d8b7d9462e2b59b8dc4d9601fd2520d79f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 8 Nov 2016 11:12:56 +0100 Subject: [PATCH 206/471] - added a new variable flag that allows defining variables which can only be modified by internal script code but not by external mods. Currently this is used by the NoBlockmap and NoSector flags which need special handling for changing. --- src/dobjtype.h | 1 + src/scripting/codegeneration/codegen.cpp | 64 +++++++++++++++--------- src/scripting/codegeneration/codegen.h | 18 ++++--- src/scripting/thingdef_data.cpp | 6 +-- src/scripting/vm/vmbuilder.cpp | 5 +- src/scripting/vm/vmbuilder.h | 3 +- src/scripting/zscript/zcc_compile.cpp | 8 +-- src/scripting/zscript/zcc_compile.h | 3 +- src/scripting/zscript/zcc_parser.cpp | 2 +- 9 files changed, 67 insertions(+), 43 deletions(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index fd8bfb60ac..d907feeeb9 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -30,6 +30,7 @@ enum 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. }; // Symbol information ------------------------------------------------------- diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 0972ed0025..32ee2d012e 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -53,6 +53,7 @@ #include "m_fixed.h" #include "vmbuilder.h" #include "v_text.h" +#include "w_wad.h" #include "math/cmath.h" extern FRandom pr_exrandom; @@ -93,14 +94,14 @@ static const FLOP FxFlops[] = // //========================================================================== -FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecorate, int stateindex, int statecount) - : ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount) +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) + : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1) { } @@ -164,6 +165,13 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) } } +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) @@ -307,7 +315,7 @@ FxExpression *FxExpression::Resolve(FCompileContext &ctx) // //========================================================================== -bool FxExpression::RequestAddress(bool *writable) +bool FxExpression::RequestAddress(FCompileContext &ctx, bool *writable) { if (writable != nullptr) *writable = false; return false; @@ -1178,9 +1186,19 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx) if (basex->isConstant()) { ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(V_GetColor(nullptr, constval.GetString()), ScriptPosition); - delete this; - return x; + 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; } @@ -1870,7 +1888,7 @@ FxExpression *FxSizeAlign::Resolve(FCompileContext& ctx) delete this; return nullptr; } - else if (!Operand->RequestAddress(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; @@ -1907,7 +1925,7 @@ FxPreIncrDecr::~FxPreIncrDecr() SAFE_DELETE(Base); } -bool FxPreIncrDecr::RequestAddress(bool *writable) +bool FxPreIncrDecr::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; if (writable != nullptr) *writable = AddressWritable; @@ -1933,7 +1951,7 @@ FxExpression *FxPreIncrDecr::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (!Base->RequestAddress(&AddressWritable) || !AddressWritable ) + if (!Base->RequestAddress(ctx, &AddressWritable) || !AddressWritable ) { ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); delete this; @@ -2019,7 +2037,7 @@ FxExpression *FxPostIncrDecr::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (!Base->RequestAddress(&AddressWritable) || !AddressWritable) + if (!Base->RequestAddress(ctx, &AddressWritable) || !AddressWritable) { ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); delete this; @@ -2107,7 +2125,7 @@ FxAssign::~FxAssign() } /* I don't think we should allow constructs like (a = b) = c;... -bool FxAssign::RequestAddress(bool *writable) +bool FxAssign::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; if (writable != nullptr) *writable = AddressWritable; @@ -2177,7 +2195,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) SAFE_RESOLVE(Right, ctx); } - if (!Base->RequestAddress(&AddressWritable) || !AddressWritable) + if (!Base->RequestAddress(ctx, &AddressWritable) || !AddressWritable) { ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); delete this; @@ -2188,7 +2206,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) if (Base->ExprType == EFX_StructMember || Base->ExprType == EFX_ClassMember) { auto f = static_cast(Base)->membervar; - if (f->BitValue != -1 && !(f->Flags & VARF_ReadOnly)) + if (f->BitValue != -1 && !ctx.CheckReadOnly(f->Flags)) { IsBitWrite = f->BitValue; return this; @@ -5335,10 +5353,10 @@ FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) return this; } -bool FxLocalVariable::RequestAddress(bool *writable) +bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; - if (writable != nullptr) *writable = !(Variable->VarFlags & VARF_ReadOnly); + if (writable != nullptr) *writable = !ctx.CheckReadOnly(Variable->VarFlags); return true; } @@ -5504,10 +5522,10 @@ FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos) // //========================================================================== -bool FxGlobalVariable::RequestAddress(bool *writable) +bool FxGlobalVariable::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; - if (writable != nullptr) *writable = AddressWritable && !(membervar->Flags & VARF_ReadOnly); + if (writable != nullptr) *writable = AddressWritable && !ctx.CheckReadOnly(membervar->Flags); return true; } @@ -5582,10 +5600,10 @@ FxStructMember::~FxStructMember() // //========================================================================== -bool FxStructMember::RequestAddress(bool *writable) +bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; - if (writable != nullptr) *writable = (AddressWritable && !(membervar->Flags & VARF_ReadOnly) && + if (writable != nullptr) *writable = (AddressWritable && !ctx.CheckReadOnly(membervar->Flags) && (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast(classx->ValueType)->IsConst)); return true; } @@ -5662,7 +5680,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) } else { - if (!(classx->RequestAddress(&AddressWritable))) + if (!(classx->RequestAddress(ctx, &AddressWritable))) { ScriptPosition.Message(MSG_ERROR, "unable to dereference left side of %s", membervar->SymbolName.GetChars()); delete this; @@ -5767,7 +5785,7 @@ FxArrayElement::~FxArrayElement() // //========================================================================== -bool FxArrayElement::RequestAddress(bool *writable) +bool FxArrayElement::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; if (writable != nullptr) *writable = AddressWritable; @@ -5830,7 +5848,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (!Array->RequestAddress(&AddressWritable)) + if (!Array->RequestAddress(ctx, &AddressWritable)) { ScriptPosition.Message(MSG_ERROR, "Unable to dereference array."); delete this; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 3cc86d1e6d..df0ba75948 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -76,9 +76,10 @@ struct FCompileContext 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; TDeletingArray FunctionArgs; - FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount); + 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, PSymbolTable *&symt); @@ -87,6 +88,7 @@ struct FCompileContext void HandleJumps(int token, FxExpression *handler); void CheckReturn(PPrototype *proto, FScriptPosition &pos); + bool CheckReadOnly(int flags); FxLocalVariableDeclaration *FindLocalVariable(FName name); }; @@ -296,7 +298,7 @@ public: virtual FxExpression *Resolve(FCompileContext &ctx); virtual bool isConstant() const; - virtual bool RequestAddress(bool *writable); + virtual bool RequestAddress(FCompileContext &ctx, bool *writable); virtual PPrototype *ReturnProto(); virtual VMFunction *GetDirectFunction(); virtual bool CheckReturn() { return false; } @@ -715,7 +717,7 @@ public: FxPreIncrDecr(FxExpression *base, int token); ~FxPreIncrDecr(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(bool *writable); + bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -758,7 +760,7 @@ public: FxAssign(FxExpression *base, FxExpression *right, bool ismodify = false); ~FxAssign(); FxExpression *Resolve(FCompileContext&); - //bool RequestAddress(bool *writable); + //bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Address; @@ -1157,7 +1159,7 @@ public: FxGlobalVariable(PField*, const FScriptPosition&); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(bool *writable); + bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1178,7 +1180,7 @@ public: FxStructMember(FxExpression*, PField*, const FScriptPosition&); ~FxStructMember(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(bool *writable); + bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1210,7 +1212,7 @@ public: FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(bool *writable); + bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1245,7 +1247,7 @@ public: FxArrayElement(FxExpression*, FxExpression*); ~FxArrayElement(); FxExpression *Resolve(FCompileContext&); - bool RequestAddress(bool *writable); + bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); }; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 8152e9977b..4ccc72748e 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -55,7 +55,7 @@ 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), VARF_Native } -#define DEFINE_READONLY_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 } +#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 } @@ -99,8 +99,8 @@ FFlagDef ActorFlagDefs[]= 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), diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 1544ca4a66..e5ed249b13 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -653,7 +653,7 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc) //========================================================================== FFunctionBuildList FunctionBuildList; -VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount) +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) @@ -675,6 +675,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c it.FromDecorate = fromdecorate; it.StateIndex = stateindex; it.StateCount = statecount; + it.Lump = lumpnum; // set prototype for named functions. if (it.Func->SymbolName != NAME_None) @@ -700,7 +701,7 @@ void FFunctionBuildList::Build() 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); + 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()); diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 452a7882cf..5394dec32c 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -108,13 +108,14 @@ class FFunctionBuildList 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); + VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate = -1, int statecnt = 0, int lumpnum = -1); void Build(); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 41c3cde34a..2965357dde 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -217,8 +217,8 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC // //========================================================================== -ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PSymbolTable &_outsymbols) - : Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast) +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 @@ -2146,7 +2146,7 @@ void ZCCCompiler::InitFunctions() 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); + 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. @@ -2344,7 +2344,7 @@ void ZCCCompiler::CompileStates() if (code != nullptr) { auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action); - state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len()); + state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len(), Lump); } } diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 4ad72769a4..c901fc42ea 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -78,7 +78,7 @@ struct ZCC_ConstantWork class ZCCCompiler { public: - ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PSymbolTable &outsymbols); + ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PSymbolTable &outsymbols, int lumpnum); ~ZCCCompiler(); int Compile(); @@ -149,6 +149,7 @@ private: PSymbolTable *GlobalTreeNodes; PSymbolTable *OutputSymbols; ZCC_AST &AST; + int Lump; }; void ZCC_InitConversions(); diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 1f0800302f..c84b72c666 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -374,7 +374,7 @@ static void DoParse(int lumpnum) PSymbolTable symtable; symtable.SetName("Global_Node"); - ZCCCompiler cc(state, NULL, symtable, GlobalSymbols); + ZCCCompiler cc(state, NULL, symtable, GlobalSymbols, lumpnum); cc.Compile(); if (FScriptPosition::ErrorCounter > 0) From 701ffb868b45ddf7fe21acb0f9af9237b201f5ec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 8 Nov 2016 22:36:44 +0100 Subject: [PATCH 207/471] - fixed: The first argument of string-based ACS specials was missing a string to name cast. --- src/scripting/codegeneration/codegen.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 32ee2d012e..63302d600a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6409,7 +6409,16 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) } else if (Special < 0 && i == 0) { - if ((*ArgList)[i]->ValueType != TypeName) + 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; From 0b3585c83f35e84510b1db22d8723b9a2be178df Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sat, 5 Nov 2016 17:08:54 +0100 Subject: [PATCH 208/471] Separate the pointer list from the implement macro --- src/b_bot.cpp | 16 +++-- src/d_dehacked.cpp | 8 ++- src/decallib.cpp | 8 ++- src/dobject.h | 14 ++-- src/dobjtype.cpp | 70 +++++++++++++------- src/dsectoreffect.cpp | 8 ++- src/fragglescript/t_prepro.cpp | 6 +- src/fragglescript/t_script.cpp | 103 ++++++++++++++++-------------- src/fragglescript/t_variable.cpp | 8 ++- src/g_hexen/a_spike.cpp | 8 ++- src/g_shared/a_action.cpp | 6 +- src/g_shared/a_decals.cpp | 10 +-- src/g_shared/a_flashfader.cpp | 8 ++- src/g_shared/a_morph.cpp | 8 ++- src/g_shared/a_movingcamera.cpp | 26 +++++--- src/g_shared/a_pickups.cpp | 8 ++- src/g_shared/a_quake.cpp | 8 ++- src/g_shared/a_soundsequence.cpp | 6 +- src/g_shared/a_weaponpiece.cpp | 7 +- src/g_shared/a_weapons.cpp | 12 ++-- src/g_shared/hudmessages.cpp | 8 ++- src/g_shared/sbarinfo.cpp | 10 +-- src/g_shared/shared_sbar.cpp | 10 +-- src/info.cpp | 6 +- src/intermission/intermission.cpp | 7 +- src/m_cheat.cpp | 6 +- src/menu/menu.cpp | 8 ++- src/p_acs.cpp | 30 +++++---- src/p_floor.cpp | 10 +-- src/p_mobj.cpp | 34 +++++----- src/p_pillar.cpp | 10 +-- src/p_pspr.cpp | 8 ++- src/p_pusher.cpp | 7 +- src/p_scroll.cpp | 11 ++-- src/p_user.cpp | 10 +-- src/po_man.cpp | 8 ++- src/r_data/r_interpolate.cpp | 9 ++- src/s_sndseq.cpp | 22 ++++--- src/scripting/vm/vmframe.cpp | 7 +- 39 files changed, 341 insertions(+), 228 deletions(-) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index c4d702c8ec..dee20d2957 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -16,13 +16,15 @@ #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_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/d_dehacked.cpp b/src/d_dehacked.cpp index 896e174d65..4e2b326ff7 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -231,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_POINTY_CLASS(ADehackedPickup) + +IMPLEMENT_POINTERS_START(ADehackedPickup) + IMPLEMENT_POINTER(RealPickup) +IMPLEMENT_POINTERS_END TArray TouchedActors; diff --git a/src/decallib.cpp b/src/decallib.cpp index fc7e465dc6..2f74925162 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_POINTY_CLASS(DDecalThinker) + +IMPLEMENT_POINTERS_START(DDecalThinker) + IMPLEMENT_POINTER(TheDecal) +IMPLEMENT_POINTERS_END void DDecalThinker::Serialize(FSerializer &arc) { diff --git a/src/dobject.h b/src/dobject.h index ea0a44a85c..620bc8af34 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -151,11 +151,6 @@ protected: \ #define HAS_FIELDS \ static void InitNativeFields(); -// 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 }; - #if defined(_MSC_VER) # pragma section(".creg$u",read) # define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo; @@ -182,12 +177,10 @@ protected: \ #define IMPLEMENT_POINTY_CLASS(cls) \ _IMP_CREATE_OBJ(cls) \ _IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor, nullptr) \ - const size_t cls::PointerOffsets[] = { #define IMPLEMENT_POINTY_CLASS_WITH_FIELDS(cls) \ _IMP_CREATE_OBJ(cls) \ _IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor, cls::InitNativeFields) \ - const size_t cls::PointerOffsets[] = { #define IMPLEMENT_CLASS(cls) \ _IMP_CREATE_OBJ(cls) \ @@ -202,7 +195,12 @@ protected: \ #define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \ _IMP_PCLASS(cls,cls::PointerOffsets,nullptr,nullptr) \ - 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 }; enum EObjectFlags { diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index e3c6380622..f9f987a42f 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -188,8 +188,10 @@ PClassClass::PClassClass() /* PType ******************************************************************/ IMPLEMENT_ABSTRACT_POINTY_CLASS(PType) - DECLARE_POINTER(HashNext) -END_POINTERS + +IMPLEMENT_POINTERS_START(PType) + IMPLEMENT_POINTER(HashNext) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -643,8 +645,10 @@ IMPLEMENT_ABSTRACT_CLASS(PCompoundType) /* PNamedType *************************************************************/ IMPLEMENT_ABSTRACT_POINTY_CLASS(PNamedType) - DECLARE_POINTER(Outer) -END_POINTERS + +IMPLEMENT_POINTERS_START(PNamedType) + IMPLEMENT_POINTER(Outer) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1457,8 +1461,10 @@ bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons /* PPointer ***************************************************************/ IMPLEMENT_POINTY_CLASS(PPointer) - DECLARE_POINTER(PointedType) -END_POINTERS + +IMPLEMENT_POINTERS_START(PPointer) + IMPLEMENT_POINTER(PointedType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1586,8 +1592,10 @@ PPointer *NewPointer(PType *type, bool isconst) /* PClassPointer **********************************************************/ IMPLEMENT_POINTY_CLASS(PClassPointer) - DECLARE_POINTER(ClassRestriction) -END_POINTERS + +IMPLEMENT_POINTERS_START(PClassPointer) + IMPLEMENT_POINTER(ClassRestriction) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1665,8 +1673,10 @@ PClassPointer *NewClassPointer(PClass *restrict) /* PEnum ******************************************************************/ IMPLEMENT_POINTY_CLASS(PEnum) - DECLARE_POINTER(ValueType) -END_POINTERS + +IMPLEMENT_POINTERS_START(PEnum) + IMPLEMENT_POINTER(ValueType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1716,8 +1726,10 @@ PEnum *NewEnum(FName name, PTypeBase *outer) /* PArray *****************************************************************/ IMPLEMENT_POINTY_CLASS(PArray) - DECLARE_POINTER(ElementType) -END_POINTERS + +IMPLEMENT_POINTERS_START(PArray) + IMPLEMENT_POINTER(ElementType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1913,8 +1925,10 @@ PVector *NewVector(unsigned int size) /* PDynArray **************************************************************/ IMPLEMENT_POINTY_CLASS(PDynArray) - DECLARE_POINTER(ElementType) -END_POINTERS + +IMPLEMENT_POINTERS_START(PDynArray) + IMPLEMENT_POINTER(ElementType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -1994,9 +2008,11 @@ PDynArray *NewDynArray(PType *type) /* PMap *******************************************************************/ IMPLEMENT_POINTY_CLASS(PMap) - DECLARE_POINTER(KeyType) - DECLARE_POINTER(ValueType) -END_POINTERS + +IMPLEMENT_POINTERS_START(PMap) + IMPLEMENT_POINTER(KeyType) + IMPLEMENT_POINTER(ValueType) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -2486,8 +2502,10 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra /* PClass *****************************************************************/ IMPLEMENT_POINTY_CLASS(PClass) - DECLARE_POINTER(ParentClass) -END_POINTERS + +IMPLEMENT_POINTERS_START(PClass) + IMPLEMENT_POINTER(ParentClass) +IMPLEMENT_POINTERS_END //========================================================================== // @@ -3407,12 +3425,18 @@ IMPLEMENT_ABSTRACT_CLASS(PSymbol); IMPLEMENT_CLASS(PSymbolConst); IMPLEMENT_CLASS(PSymbolConstNumeric); IMPLEMENT_CLASS(PSymbolConstString); + IMPLEMENT_POINTY_CLASS(PSymbolType) - DECLARE_POINTER(Type) -END_POINTERS + +IMPLEMENT_POINTERS_START(PSymbolType) + IMPLEMENT_POINTER(Type) +IMPLEMENT_POINTERS_END + IMPLEMENT_POINTY_CLASS(PSymbolVMFunction) - DECLARE_POINTER(Function) -END_POINTERS + +IMPLEMENT_POINTERS_START(PSymbolVMFunction) + IMPLEMENT_POINTER(Function) +IMPLEMENT_POINTERS_END IMPLEMENT_CLASS(PSymbolTreeNode) //========================================================================== diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 815b49dc47..7b29dbf051 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -71,9 +71,11 @@ void DSectorEffect::Serialize(FSerializer &arc) arc("sector", m_Sector); } -IMPLEMENT_POINTY_CLASS (DMover) - DECLARE_POINTER(interpolation) -END_POINTERS +IMPLEMENT_POINTY_CLASS(DMover) + +IMPLEMENT_POINTERS_START(DMover) + IMPLEMENT_POINTER(interpolation) +IMPLEMENT_POINTERS_END DMover::DMover () { diff --git a/src/fragglescript/t_prepro.cpp b/src/fragglescript/t_prepro.cpp index 619b6d570e..2c667878d4 100644 --- a/src/fragglescript/t_prepro.cpp +++ b/src/fragglescript/t_prepro.cpp @@ -72,8 +72,10 @@ //========================================================================== IMPLEMENT_POINTY_CLASS(DFsSection) - DECLARE_POINTER(next) -END_POINTERS + +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 f1376b7eb3..f14cbe25fb 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]) \ //========================================================================== // @@ -100,29 +100,31 @@ 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_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 //========================================================================== // @@ -268,11 +270,13 @@ 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_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_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 125f32367d..895602f537 100644 --- a/src/fragglescript/t_variable.cpp +++ b/src/fragglescript/t_variable.cpp @@ -180,9 +180,11 @@ AActor* actorvalue(const svalue_t &svalue) //========================================================================== IMPLEMENT_POINTY_CLASS(DFsVariable) - DECLARE_POINTER (next) - DECLARE_POINTER (actor) -END_POINTERS + +IMPLEMENT_POINTERS_START(DFsVariable) + IMPLEMENT_POINTER(next) + IMPLEMENT_POINTER(actor) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp index 3f5f4d2e83..faf3c3083e 100644 --- a/src/g_hexen/a_spike.cpp +++ b/src/g_hexen/a_spike.cpp @@ -31,9 +31,11 @@ public: TObjPtr DirtClump; }; -IMPLEMENT_POINTY_CLASS (AThrustFloor) - DECLARE_POINTER (DirtClump) -END_POINTERS +IMPLEMENT_POINTY_CLASS(AThrustFloor) + +IMPLEMENT_POINTERS_START(AThrustFloor) + IMPLEMENT_POINTER(DirtClump) +IMPLEMENT_POINTERS_END void AThrustFloor::Serialize(FSerializer &arc) { diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index e1fa9a7fab..4925e3c25e 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -305,8 +305,10 @@ private: }; IMPLEMENT_POINTY_CLASS(DCorpsePointer) - DECLARE_POINTER(Corpse) -END_POINTERS + +IMPLEMENT_POINTERS_START(DCorpsePointer) + IMPLEMENT_POINTER(Corpse) +IMPLEMENT_POINTERS_END CUSTOM_CVAR(Int, sv_corpsequeuesize, 64, CVAR_ARCHIVE|CVAR_SERVERINFO) { diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index e02ab1a52d..b06191607e 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -58,10 +58,12 @@ static int ImpactCount; CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE) -IMPLEMENT_POINTY_CLASS (DBaseDecal) - DECLARE_POINTER(WallPrev) - DECLARE_POINTER(WallNext) -END_POINTERS +IMPLEMENT_POINTY_CLASS(DBaseDecal) + +IMPLEMENT_POINTERS_START(DBaseDecal) + IMPLEMENT_POINTER(WallPrev) + IMPLEMENT_POINTER(WallNext) +IMPLEMENT_POINTERS_END IMPLEMENT_CLASS (DImpactDecal) diff --git a/src/g_shared/a_flashfader.cpp b/src/g_shared/a_flashfader.cpp index 71673e5c7d..61b305f447 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_POINTY_CLASS(DFlashFader) + +IMPLEMENT_POINTERS_START(DFlashFader) + IMPLEMENT_POINTER(ForWho) +IMPLEMENT_POINTERS_END DFlashFader::DFlashFader () { diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 46ae5cac7b..3323a0a4c7 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -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_POINTY_CLASS(AMorphedMonster) + +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 76f128b15a..e60c940369 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_POINTY_CLASS(AInterpolationPoint) + +IMPLEMENT_POINTERS_START(AInterpolationPoint) + IMPLEMENT_POINTER(Next) +IMPLEMENT_POINTERS_END void AInterpolationPoint::Serialize(FSerializer &arc) { @@ -176,10 +178,12 @@ protected: int HoldTime; }; -IMPLEMENT_POINTY_CLASS (APathFollower) - DECLARE_POINTER (PrevNode) - DECLARE_POINTER (CurrNode) -END_POINTERS +IMPLEMENT_POINTY_CLASS(APathFollower) + +IMPLEMENT_POINTERS_START(APathFollower) + IMPLEMENT_POINTER(PrevNode) + IMPLEMENT_POINTER(CurrNode) +IMPLEMENT_POINTERS_END void APathFollower::Serialize(FSerializer &arc) { @@ -592,9 +596,11 @@ protected: TObjPtr Activator; }; -IMPLEMENT_POINTY_CLASS (AMovingCamera) - DECLARE_POINTER (Activator) -END_POINTERS +IMPLEMENT_POINTY_CLASS(AMovingCamera) + +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 ae7516d173..155878bacd 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -470,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_POINTY_CLASS(AInventory) + +IMPLEMENT_POINTERS_START(AInventory) + IMPLEMENT_POINTER(Owner) +IMPLEMENT_POINTERS_END //=========================================================================== // diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 98e505b2b9..1a0c6a0fd6 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_POINTY_CLASS(DEarthquake) + +IMPLEMENT_POINTERS_START(DEarthquake) + IMPLEMENT_POINTER(m_Spot) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/g_shared/a_soundsequence.cpp b/src/g_shared/a_soundsequence.cpp index f09b5b7adc..3741a39142 100644 --- a/src/g_shared/a_soundsequence.cpp +++ b/src/g_shared/a_soundsequence.cpp @@ -81,8 +81,10 @@ public: }; IMPLEMENT_POINTY_CLASS(ASoundSequenceSlot) - DECLARE_POINTER(Sequence) -END_POINTERS + +IMPLEMENT_POINTERS_START(ASoundSequenceSlot) + IMPLEMENT_POINTER(Sequence) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp index aefce18c1c..4b0a6dcbf3 100644 --- a/src/g_shared/a_weaponpiece.cpp +++ b/src/g_shared/a_weaponpiece.cpp @@ -24,10 +24,11 @@ void AWeaponHolder::Serialize(FSerializer &arc) ("pieceweapon", PieceWeapon); } +IMPLEMENT_POINTY_CLASS(AWeaponPiece) -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 7e6aefb7a0..ec5e32be8a 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -21,11 +21,13 @@ #define BONUSADD 6 -IMPLEMENT_POINTY_CLASS (AWeapon) - DECLARE_POINTER (Ammo1) - DECLARE_POINTER (Ammo2) - DECLARE_POINTER (SisterWeapon) -END_POINTERS +IMPLEMENT_POINTY_CLASS(AWeapon) + +IMPLEMENT_POINTERS_START(AWeapon) + IMPLEMENT_POINTER(Ammo1) + IMPLEMENT_POINTER(Ammo2) + IMPLEMENT_POINTER(SisterWeapon) +IMPLEMENT_POINTERS_END FString WeaponSection; TArray KeyConfWeapons; diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index b86cf64175..783d1624d9 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -44,9 +44,11 @@ EXTERN_CVAR(Int, con_scaletext) int active_con_scaletext(); -IMPLEMENT_POINTY_CLASS (DHUDMessage) - DECLARE_POINTER(Next) -END_POINTERS +IMPLEMENT_POINTY_CLASS(DHUDMessage) + +IMPLEMENT_POINTERS_START(DHUDMessage) + IMPLEMENT_POINTER(Next) +IMPLEMENT_POINTERS_END IMPLEMENT_CLASS (DHUDMessageFadeOut) IMPLEMENT_CLASS (DHUDMessageFadeInOut) diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 2e764a4035..d0cd2defcb 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -1532,10 +1532,12 @@ private: }; IMPLEMENT_POINTY_CLASS(DSBarInfo) - DECLARE_POINTER(ammo1) - DECLARE_POINTER(ammo2) - DECLARE_POINTER(armor) -END_POINTERS + +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_sbar.cpp b/src/g_shared/shared_sbar.cpp index 191b097d2e..524ec4f1fc 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -63,10 +63,12 @@ #define POWERUPICONSIZE 32 IMPLEMENT_POINTY_CLASS(DBaseStatusBar) - DECLARE_POINTER(Messages[0]) - DECLARE_POINTER(Messages[1]) - DECLARE_POINTER(Messages[2]) -END_POINTERS + +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/info.cpp b/src/info.cpp index 4705e0e533..12753b21b9 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -154,8 +154,10 @@ int GetSpriteIndex(const char * spritename, bool add) } IMPLEMENT_POINTY_CLASS(PClassActor) - DECLARE_POINTER(DropItems) -END_POINTERS + +IMPLEMENT_POINTERS_START(PClassActor) + IMPLEMENT_POINTER(DropItems) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index ba4566e9d9..527062bb62 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -59,9 +59,12 @@ IMPLEMENT_CLASS(DIntermissionScreenFader) IMPLEMENT_CLASS(DIntermissionScreenText) IMPLEMENT_CLASS(DIntermissionScreenCast) IMPLEMENT_CLASS(DIntermissionScreenScroller) + IMPLEMENT_POINTY_CLASS(DIntermissionController) - DECLARE_POINTER(mScreen) -END_POINTERS + +IMPLEMENT_POINTERS_START(DIntermissionController) + IMPLEMENT_POINTER(mScreen) +IMPLEMENT_POINTERS_END extern int NoWipe; diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 7c110a52c9..7348f5881e 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -1034,8 +1034,10 @@ public: }; IMPLEMENT_POINTY_CLASS(DSuicider) - DECLARE_POINTER(Pawn) -END_POINTERS + +IMPLEMENT_POINTERS_START(DSuicider) + IMPLEMENT_POINTER(Pawn) +IMPLEMENT_POINTERS_END void cht_Suicide (player_t *plyr) { diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 7e938230e7..c4e0a4d985 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_POINTY_CLASS(DMenu) + +IMPLEMENT_POINTERS_START(DMenu) + IMPLEMENT_POINTER(mParentMenu) +IMPLEMENT_POINTERS_END DMenu::DMenu(DMenu *parent) { diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 4024bc9f9f..1fac7e8fee 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1369,9 +1369,11 @@ private: DPlaneWatcher() {} }; -IMPLEMENT_POINTY_CLASS (DPlaneWatcher) - DECLARE_POINTER (Activator) -END_POINTERS +IMPLEMENT_POINTY_CLASS(DPlaneWatcher) + +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, @@ -2858,10 +2860,12 @@ void FBehavior::StaticStopMyScripts (AActor *actor) //---- The ACS Interpreter ----// -IMPLEMENT_POINTY_CLASS (DACSThinker) - DECLARE_POINTER(LastScript) - DECLARE_POINTER(Scripts) -END_POINTERS +IMPLEMENT_POINTY_CLASS(DACSThinker) + +IMPLEMENT_POINTERS_START(DACSThinker) + IMPLEMENT_POINTER(LastScript) + IMPLEMENT_POINTER(Scripts) +IMPLEMENT_POINTERS_END TObjPtr DACSThinker::ActiveThinker; @@ -2987,11 +2991,13 @@ void DACSThinker::StopScriptsFor (AActor *actor) } } -IMPLEMENT_POINTY_CLASS (DLevelScript) - DECLARE_POINTER(next) - DECLARE_POINTER(prev) - DECLARE_POINTER(activator) -END_POINTERS +IMPLEMENT_POINTY_CLASS(DLevelScript) + +IMPLEMENT_POINTERS_START(DLevelScript) + IMPLEMENT_POINTER(next) + IMPLEMENT_POINTER(prev) + IMPLEMENT_POINTER(activator) +IMPLEMENT_POINTERS_END //========================================================================== // diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 62479e3404..23fdc7575c 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -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_POINTY_CLASS(DElevator) + +IMPLEMENT_POINTERS_START(DElevator) + IMPLEMENT_POINTER(m_Interp_Floor) + IMPLEMENT_POINTER(m_Interp_Ceiling) +IMPLEMENT_POINTERS_END DElevator::DElevator () { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 21d32c2de2..f36760856c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -132,18 +132,20 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- IMPLEMENT_POINTY_CLASS_WITH_FIELDS (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_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 () { @@ -6953,9 +6955,12 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) // DropItem handling // //---------------------------------------------------------------------------- + IMPLEMENT_POINTY_CLASS_WITH_FIELDS(DDropItem) - DECLARE_POINTER(Next) -END_POINTERS + +IMPLEMENT_POINTERS_START(DDropItem) + IMPLEMENT_POINTER(Next) +IMPLEMENT_POINTERS_END void DDropItem::InitNativeFields() { @@ -6967,7 +6972,6 @@ void DDropItem::InitNativeFields() meta->AddNativeField("Amount", TypeSInt32, myoffsetof(DDropItem, Amount)); } - void PrintMiscActorInfo(AActor *query) { if (query) diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index a55bd5cdb8..52078daadb 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_POINTY_CLASS(DPillar) + +IMPLEMENT_POINTERS_START(DPillar) + IMPLEMENT_POINTER(m_Interp_Floor) + IMPLEMENT_POINTER(m_Interp_Ceiling) +IMPLEMENT_POINTERS_END DPillar::DPillar () { diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index bb39083da9..b2e59ade40 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -100,9 +100,11 @@ static const FGenericButtons ButtonChecks[] = //------------------------------------------------------------------------ IMPLEMENT_POINTY_CLASS(DPSprite) - DECLARE_POINTER(Caller) - DECLARE_POINTER(Next) -END_POINTERS + +IMPLEMENT_POINTERS_START(DPSprite) + IMPLEMENT_POINTER(Caller) + IMPLEMENT_POINTER(Next) +IMPLEMENT_POINTERS_END //------------------------------------------------------------------------ // diff --git a/src/p_pusher.cpp b/src/p_pusher.cpp index 38c9c9720f..d211f1c3c9 100644 --- a/src/p_pusher.cpp +++ b/src/p_pusher.cpp @@ -74,10 +74,11 @@ protected: friend bool PIT_PushThing (AActor *thing); }; +IMPLEMENT_POINTY_CLASS(DPusher) -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 f2ece8b3de..3918bc072d 100644 --- a/src/p_scroll.cpp +++ b/src/p_scroll.cpp @@ -73,12 +73,13 @@ private: } }; +IMPLEMENT_POINTY_CLASS(DScroller) -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_user.cpp b/src/p_user.cpp index cd791623b5..0efe422a3d 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -622,10 +622,12 @@ void player_t::SendPitchLimits() const // //=========================================================================== -IMPLEMENT_POINTY_CLASS (APlayerPawn) - DECLARE_POINTER(InvFirst) - DECLARE_POINTER(InvSel) -END_POINTERS +IMPLEMENT_POINTY_CLASS(APlayerPawn) + +IMPLEMENT_POINTERS_START(APlayerPawn) + IMPLEMENT_POINTER(InvFirst) + IMPLEMENT_POINTER(InvSel) +IMPLEMENT_POINTERS_END IMPLEMENT_CLASS (APlayerChunk) diff --git a/src/po_man.cpp b/src/po_man.cpp index c779a8049d..c80e72992b 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_POINTY_CLASS(DPolyAction) + +IMPLEMENT_POINTERS_START(DPolyAction) + IMPLEMENT_POINTER(m_Interpolation) +IMPLEMENT_POINTERS_END DPolyAction::DPolyAction () { diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp index c944f0fa5f..fdb8affc67 100644 --- a/src/r_data/r_interpolate.cpp +++ b/src/r_data/r_interpolate.cpp @@ -162,9 +162,12 @@ public: //========================================================================== IMPLEMENT_ABSTRACT_POINTY_CLASS(DInterpolation) -DECLARE_POINTER(Next) -DECLARE_POINTER(Prev) -END_POINTERS + +IMPLEMENT_POINTERS_START(DInterpolation) + IMPLEMENT_POINTER(Next) + IMPLEMENT_POINTER(Prev) +IMPLEMENT_POINTERS_END + IMPLEMENT_CLASS(DSectorPlaneInterpolation) IMPLEMENT_CLASS(DSectorScrollInterpolation) IMPLEMENT_CLASS(DWallScrollInterpolation) diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index 3b39965ff6..baf33fd0cb 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_POINTY_CLASS(DSeqNode) + +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_POINTY_CLASS(DSeqActorNode) + +IMPLEMENT_POINTERS_START(DSeqActorNode) + IMPLEMENT_POINTER(m_Actor) +IMPLEMENT_POINTERS_END void DSeqActorNode::Serialize(FSerializer &arc) { diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index f622e114d2..22728749cb 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -36,8 +36,11 @@ IMPLEMENT_CLASS(VMException) IMPLEMENT_ABSTRACT_POINTY_CLASS(VMFunction) - DECLARE_POINTER(Proto) -END_POINTERS + +IMPLEMENT_POINTERS_START(VMFunction) + IMPLEMENT_POINTER(Proto) +IMPLEMENT_POINTERS_END + IMPLEMENT_CLASS(VMScriptFunction) IMPLEMENT_CLASS(VMNativeFunction) From bb2d61de508e9c33657185a86853bcbc31843667 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sat, 5 Nov 2016 18:27:14 +0100 Subject: [PATCH 209/471] Replaced the many implement macros with a single one that takes arguments instead --- src/b_bot.cpp | 2 +- src/c_dispatch.cpp | 4 +- src/d_dehacked.cpp | 2 +- src/decallib.cpp | 11 ++-- src/dobject.h | 41 +++++-------- src/dobjgc.cpp | 3 +- src/dobjtype.cpp | 73 +++++++++++------------ src/dsectoreffect.cpp | 10 ++-- src/dthinker.cpp | 4 +- src/fragglescript/t_func.cpp | 4 +- src/fragglescript/t_prepro.cpp | 2 +- src/fragglescript/t_script.cpp | 6 +- src/fragglescript/t_variable.cpp | 2 +- src/g_doom/a_scriptedmarine.cpp | 2 +- src/g_heretic/a_chicken.cpp | 2 +- src/g_heretic/a_hereticartifacts.cpp | 6 +- src/g_heretic/a_hereticweaps.cpp | 21 ++++--- src/g_heretic/a_ironlich.cpp | 2 +- src/g_hexen/a_boostarmor.cpp | 2 +- src/g_hexen/a_clericflame.cpp | 2 +- src/g_hexen/a_clericholy.cpp | 4 +- src/g_hexen/a_clericstaff.cpp | 2 +- src/g_hexen/a_fighteraxe.cpp | 2 +- src/g_hexen/a_fighterplayer.cpp | 6 +- src/g_hexen/a_fighterquietus.cpp | 2 +- src/g_hexen/a_flechette.cpp | 14 ++--- src/g_hexen/a_healingradius.cpp | 2 +- src/g_hexen/a_heresiarch.cpp | 10 ++-- src/g_hexen/a_hexenspecialdecs.cpp | 6 +- src/g_hexen/a_magecone.cpp | 2 +- src/g_hexen/a_magelightning.cpp | 4 +- src/g_hexen/a_magestaff.cpp | 4 +- src/g_hexen/a_pig.cpp | 2 +- src/g_hexen/a_spike.cpp | 2 +- src/g_hexen/a_summon.cpp | 2 +- src/g_hexen/a_teleportother.cpp | 4 +- src/g_level.cpp | 2 +- src/g_raven/a_artitele.cpp | 2 +- src/g_raven/a_minotaur.cpp | 4 +- src/g_shared/a_action.cpp | 6 +- src/g_shared/a_armor.cpp | 11 ++-- src/g_shared/a_artifacts.cpp | 54 ++++++++--------- src/g_shared/a_bridge.cpp | 4 +- src/g_shared/a_camera.cpp | 4 +- src/g_shared/a_debris.cpp | 2 +- src/g_shared/a_decals.cpp | 6 +- src/g_shared/a_fastprojectile.cpp | 3 +- src/g_shared/a_flashfader.cpp | 2 +- src/g_shared/a_fountain.cpp | 2 +- src/g_shared/a_hatetarget.cpp | 2 +- src/g_shared/a_keys.cpp | 2 +- src/g_shared/a_lightning.cpp | 2 +- src/g_shared/a_mapmarker.cpp | 2 +- src/g_shared/a_morph.cpp | 4 +- src/g_shared/a_movingcamera.cpp | 10 ++-- src/g_shared/a_pickups.cpp | 27 ++++----- src/g_shared/a_puzzleitems.cpp | 4 +- src/g_shared/a_quake.cpp | 2 +- src/g_shared/a_randomspawner.cpp | 2 +- src/g_shared/a_secrettrigger.cpp | 2 +- src/g_shared/a_sectoraction.cpp | 25 ++++---- src/g_shared/a_setcolor.cpp | 4 +- src/g_shared/a_skies.cpp | 12 ++-- src/g_shared/a_soundenvironment.cpp | 2 +- src/g_shared/a_soundsequence.cpp | 4 +- src/g_shared/a_spark.cpp | 2 +- src/g_shared/a_specialspot.cpp | 5 +- src/g_shared/a_waterzone.cpp | 2 +- src/g_shared/a_weaponpiece.cpp | 6 +- src/g_shared/a_weapons.cpp | 6 +- src/g_shared/hudmessages.cpp | 8 +-- src/g_shared/sbarinfo.cpp | 2 +- src/g_shared/shared_sbar.cpp | 2 +- src/g_strife/a_coin.cpp | 2 +- src/g_strife/a_loremaster.cpp | 2 +- src/g_strife/a_programmer.cpp | 2 +- src/g_strife/a_rebels.cpp | 2 +- src/g_strife/a_spectral.cpp | 2 +- src/g_strife/a_strifeitems.cpp | 28 ++++----- src/g_strife/a_strifestuff.cpp | 6 +- src/g_strife/a_strifeweapons.cpp | 6 +- src/g_strife/strife_sbar.cpp | 2 +- src/info.cpp | 2 +- src/intermission/intermission.cpp | 13 ++-- src/m_argv.cpp | 2 +- src/m_cheat.cpp | 2 +- src/menu/colorpickermenu.cpp | 2 +- src/menu/joystickmenu.cpp | 2 +- src/menu/listmenu.cpp | 2 +- src/menu/loadsavemenu.cpp | 6 +- src/menu/menu.cpp | 2 +- src/menu/menuinput.cpp | 2 +- src/menu/messagebox.cpp | 10 ++-- src/menu/optionmenu.cpp | 7 +-- src/menu/optionmenuitems.h | 2 +- src/menu/playermenu.cpp | 2 +- src/menu/readthis.cpp | 2 +- src/menu/videomenu.cpp | 2 +- src/p_acs.cpp | 6 +- src/p_buildmap.cpp | 2 +- src/p_ceiling.cpp | 2 +- src/p_conversation.cpp | 2 +- src/p_doors.cpp | 4 +- src/p_floor.cpp | 11 ++-- src/p_lights.cpp | 16 ++--- src/p_mobj.cpp | 4 +- src/p_pillar.cpp | 2 +- src/p_plats.cpp | 2 +- src/p_pspr.cpp | 2 +- src/p_pusher.cpp | 2 +- src/p_scroll.cpp | 2 +- src/p_spec.cpp | 4 +- src/p_switch.cpp | 2 +- src/p_teleport.cpp | 2 +- src/p_user.cpp | 6 +- src/po_man.cpp | 10 ++-- src/posix/sdl/sdlvideo.cpp | 3 +- src/r_data/r_interpolate.cpp | 10 ++-- src/s_advsound.cpp | 4 +- src/s_sndseq.cpp | 8 +-- src/scripting/decorate/olddecorations.cpp | 3 +- src/scripting/vm/vmframe.cpp | 8 +-- src/v_video.cpp | 8 +-- src/win32/fb_d3d9.cpp | 2 +- src/win32/fb_ddraw.cpp | 2 +- src/win32/win32video.cpp | 2 +- 126 files changed, 365 insertions(+), 388 deletions(-) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index dee20d2957..42b34f1df7 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -15,7 +15,7 @@ #include "serializer.h" #include "d_player.h" -IMPLEMENT_POINTY_CLASS(DBot) +IMPLEMENT_CLASS(DBot, false, true, false) IMPLEMENT_POINTERS_START(DBot) IMPLEMENT_POINTER(dest) diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index c3fc9bae11..e7ccc89228 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) void DWaitingCommand::Serialize(FSerializer &arc) { @@ -225,7 +225,7 @@ void DWaitingCommand::Tick () } } -IMPLEMENT_CLASS (DStoredCommand) +IMPLEMENT_CLASS(DStoredCommand, false, false, false) DStoredCommand::DStoredCommand () { diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 4e2b326ff7..afaf7001b5 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -231,7 +231,7 @@ DehInfo deh = // from the original actor's defaults. The original actor is then changed to // spawn the new class. -IMPLEMENT_POINTY_CLASS(ADehackedPickup) +IMPLEMENT_CLASS(ADehackedPickup, false, true, false) IMPLEMENT_POINTERS_START(ADehackedPickup) IMPLEMENT_POINTER(RealPickup) diff --git a/src/decallib.cpp b/src/decallib.cpp index 2f74925162..6264970628 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -119,7 +119,7 @@ protected: DDecalThinker () : DThinker (STAT_DECALTHINKER) {} }; -IMPLEMENT_POINTY_CLASS(DDecalThinker) +IMPLEMENT_CLASS(DDecalThinker, false, true, false) IMPLEMENT_POINTERS_START(DDecalThinker) IMPLEMENT_POINTER(TheDecal) @@ -1153,7 +1153,7 @@ FDecalAnimator::~FDecalAnimator () { } -IMPLEMENT_CLASS (DDecalFader) +IMPLEMENT_CLASS(DDecalFader, false, false, false) void DDecalFader::Serialize(FSerializer &arc) { @@ -1202,7 +1202,7 @@ DThinker *FDecalFaderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const return fader; } -IMPLEMENT_CLASS (DDecalStretcher) +IMPLEMENT_CLASS(DDecalStretcher, false, false, false) void DDecalStretcher::Serialize(FSerializer &arc) { @@ -1290,7 +1290,7 @@ void DDecalStretcher::Tick () } } -IMPLEMENT_CLASS (DDecalSlider) +IMPLEMENT_CLASS(DDecalSlider, false, false, false) void DDecalSlider::Serialize(FSerializer &arc) { @@ -1370,8 +1370,7 @@ FDecalAnimator *FDecalLib::FindAnimator (const char *name) return NULL; } - -IMPLEMENT_CLASS (DDecalColorer) +IMPLEMENT_CLASS(DDecalColorer, false, false, false) void DDecalColorer::Serialize(FSerializer &arc) { diff --git a/src/dobject.h b/src/dobject.h index 620bc8af34..dd0d40772e 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -158,9 +158,9 @@ protected: \ # define _DECLARE_TI(cls) ClassReg * const cls::RegistrationInfoPtr __attribute__((section(SECTION_CREG))) = &cls::RegistrationInfo; #endif -#define _IMP_PCLASS(cls,ptrs,create, initn) \ +#define _IMP_PCLASS(cls, ptrs, create, initn) \ ClassReg cls::RegistrationInfo = {\ - NULL, \ + nullptr, \ #cls, \ &cls::Super::RegistrationInfo, \ ptrs, \ @@ -171,30 +171,9 @@ protected: \ _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_POINTY_CLASS(cls) \ - _IMP_CREATE_OBJ(cls) \ - _IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor, nullptr) \ - -#define IMPLEMENT_POINTY_CLASS_WITH_FIELDS(cls) \ - _IMP_CREATE_OBJ(cls) \ - _IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor, cls::InitNativeFields) \ - -#define IMPLEMENT_CLASS(cls) \ - _IMP_CREATE_OBJ(cls) \ - _IMP_PCLASS(cls,nullptr,cls::InPlaceConstructor, nullptr) - -#define IMPLEMENT_CLASS_WITH_FIELDS(cls) \ - _IMP_CREATE_OBJ(cls) \ - _IMP_PCLASS(cls,nullptr,cls::InPlaceConstructor, cls::InitNativeFields) - -#define IMPLEMENT_ABSTRACT_CLASS(cls) \ - _IMP_PCLASS(cls,nullptr,nullptr,nullptr) - -#define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \ - _IMP_PCLASS(cls,cls::PointerOffsets,nullptr,nullptr) \ +#define IMPLEMENT_CLASS(cls, isabstract, ptrs, fields) \ + _X_CONSTRUCTOR_##isabstract##(cls) \ + _IMP_PCLASS(cls, _X_POINTERS_##ptrs##(cls), _X_ABSTRACT_##isabstract##(cls), _X_FIELDS_##fields##(cls)) // 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. @@ -202,6 +181,16 @@ protected: \ #define IMPLEMENT_POINTER(field) (size_t)&((ThisClass*)1)->field - 1, #define IMPLEMENT_POINTERS_END ~(size_t)0 }; +// 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 + enum EObjectFlags { // GC flags diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index 28715a0ecc..fa59392d57 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -125,7 +125,8 @@ public: int PolyNum; int SideNum; }; -IMPLEMENT_CLASS(DSectorMarker) + +IMPLEMENT_CLASS(DSectorMarker, false, false, false) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index f9f987a42f..9d30229669 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -93,8 +93,8 @@ static const size_t TheEnd = ~(size_t)0; // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(PErrorType) -IMPLEMENT_CLASS(PVoidType) +IMPLEMENT_CLASS(PErrorType, false, false, false) +IMPLEMENT_CLASS(PVoidType, false, false, false) void DumpTypeTable() { @@ -141,7 +141,7 @@ void DumpTypeTable() /* PClassType *************************************************************/ -IMPLEMENT_CLASS(PClassType) +IMPLEMENT_CLASS(PClassType, false, false, false) //========================================================================== // @@ -169,7 +169,7 @@ void PClassType::Derive(PClass *newclass) /* PClassClass ************************************************************/ -IMPLEMENT_CLASS(PClassClass) +IMPLEMENT_CLASS(PClassClass, false, false, false) //========================================================================== // @@ -187,7 +187,7 @@ PClassClass::PClassClass() /* PType ******************************************************************/ -IMPLEMENT_ABSTRACT_POINTY_CLASS(PType) +IMPLEMENT_CLASS(PType, true, true, false) IMPLEMENT_POINTERS_START(PType) IMPLEMENT_POINTER(HashNext) @@ -614,7 +614,7 @@ void PType::StaticInit() /* PBasicType *************************************************************/ -IMPLEMENT_ABSTRACT_CLASS(PBasicType) +IMPLEMENT_CLASS(PBasicType, true, false, false) //========================================================================== // @@ -640,11 +640,11 @@ PBasicType::PBasicType(unsigned int size, unsigned int align) /* PCompoundType **********************************************************/ -IMPLEMENT_ABSTRACT_CLASS(PCompoundType) +IMPLEMENT_CLASS(PCompoundType, true, false, false) /* PNamedType *************************************************************/ -IMPLEMENT_ABSTRACT_POINTY_CLASS(PNamedType) +IMPLEMENT_CLASS(PNamedType, true, true, false) IMPLEMENT_POINTERS_START(PNamedType) IMPLEMENT_POINTER(Outer) @@ -692,7 +692,7 @@ FString PNamedType::QualifiedName() const /* PInt *******************************************************************/ -IMPLEMENT_CLASS(PInt) +IMPLEMENT_CLASS(PInt, false, false, false) //========================================================================== // @@ -931,7 +931,7 @@ double PInt::GetValueFloat(void *addr) const /* PBool ******************************************************************/ -IMPLEMENT_CLASS(PBool) +IMPLEMENT_CLASS(PBool, false, false, false) //========================================================================== // @@ -952,7 +952,7 @@ PBool::PBool() /* PFloat *****************************************************************/ -IMPLEMENT_CLASS(PFloat) +IMPLEMENT_CLASS(PFloat, false, false, false) //========================================================================== // @@ -1202,7 +1202,7 @@ void PFloat::SetOps() /* PString ****************************************************************/ -IMPLEMENT_CLASS(PString) +IMPLEMENT_CLASS(PString, false, false, false) //========================================================================== // @@ -1299,7 +1299,7 @@ void PString::DestroyValue(void *addr) const /* PName ******************************************************************/ -IMPLEMENT_CLASS(PName) +IMPLEMENT_CLASS(PName, false, false, false) //========================================================================== // @@ -1349,7 +1349,7 @@ bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PSound *****************************************************************/ -IMPLEMENT_CLASS(PSound) +IMPLEMENT_CLASS(PSound, false, false, false) //========================================================================== // @@ -1399,7 +1399,7 @@ bool PSound::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PColor *****************************************************************/ -IMPLEMENT_CLASS(PColor) +IMPLEMENT_CLASS(PColor, false, false, false) //========================================================================== // @@ -1416,7 +1416,7 @@ PColor::PColor() /* PStatePointer **********************************************************/ -IMPLEMENT_CLASS(PStatePointer) +IMPLEMENT_CLASS(PStatePointer, false, false, false) //========================================================================== // @@ -1460,7 +1460,7 @@ bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons /* PPointer ***************************************************************/ -IMPLEMENT_POINTY_CLASS(PPointer) +IMPLEMENT_CLASS(PPointer, false, true, false) IMPLEMENT_POINTERS_START(PPointer) IMPLEMENT_POINTER(PointedType) @@ -1591,7 +1591,7 @@ PPointer *NewPointer(PType *type, bool isconst) /* PClassPointer **********************************************************/ -IMPLEMENT_POINTY_CLASS(PClassPointer) +IMPLEMENT_CLASS(PClassPointer, false, true, false) IMPLEMENT_POINTERS_START(PClassPointer) IMPLEMENT_POINTER(ClassRestriction) @@ -1672,7 +1672,7 @@ PClassPointer *NewClassPointer(PClass *restrict) /* PEnum ******************************************************************/ -IMPLEMENT_POINTY_CLASS(PEnum) +IMPLEMENT_CLASS(PEnum, false, true, false) IMPLEMENT_POINTERS_START(PEnum) IMPLEMENT_POINTER(ValueType) @@ -1725,7 +1725,7 @@ PEnum *NewEnum(FName name, PTypeBase *outer) /* PArray *****************************************************************/ -IMPLEMENT_POINTY_CLASS(PArray) +IMPLEMENT_CLASS(PArray, false, true, false) IMPLEMENT_POINTERS_START(PArray) IMPLEMENT_POINTER(ElementType) @@ -1874,7 +1874,7 @@ PArray *NewArray(PType *type, unsigned int count) /* PVector ****************************************************************/ -IMPLEMENT_CLASS(PVector) +IMPLEMENT_CLASS(PVector, false, false, false) //========================================================================== // @@ -1924,7 +1924,7 @@ PVector *NewVector(unsigned int size) /* PDynArray **************************************************************/ -IMPLEMENT_POINTY_CLASS(PDynArray) +IMPLEMENT_CLASS(PDynArray, false, true, false) IMPLEMENT_POINTERS_START(PDynArray) IMPLEMENT_POINTER(ElementType) @@ -2007,7 +2007,7 @@ PDynArray *NewDynArray(PType *type) /* PMap *******************************************************************/ -IMPLEMENT_POINTY_CLASS(PMap) +IMPLEMENT_CLASS(PMap, false, true, false) IMPLEMENT_POINTERS_START(PMap) IMPLEMENT_POINTER(KeyType) @@ -2091,7 +2091,7 @@ PMap *NewMap(PType *keytype, PType *valuetype) /* PStruct ****************************************************************/ -IMPLEMENT_CLASS(PStruct) +IMPLEMENT_CLASS(PStruct, false, false, false) //========================================================================== // @@ -2312,7 +2312,7 @@ PStruct *NewStruct(FName name, PTypeBase *outer) /* PField *****************************************************************/ -IMPLEMENT_CLASS(PField) +IMPLEMENT_CLASS(PField, false, false, false) //========================================================================== // @@ -2357,7 +2357,7 @@ PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue /* PPrototype *************************************************************/ -IMPLEMENT_CLASS(PPrototype) +IMPLEMENT_CLASS(PPrototype, false, false, false) //========================================================================== // @@ -2443,7 +2443,7 @@ PPrototype *NewPrototype(const TArray &rettypes, const TArray /* PFunction **************************************************************/ -IMPLEMENT_CLASS(PFunction) +IMPLEMENT_CLASS(PFunction, false, false, false) //========================================================================== // @@ -2501,7 +2501,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra /* PClass *****************************************************************/ -IMPLEMENT_POINTY_CLASS(PClass) +IMPLEMENT_CLASS(PClass, false, true, false) IMPLEMENT_POINTERS_START(PClass) IMPLEMENT_POINTER(ParentClass) @@ -3420,24 +3420,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) +IMPLEMENT_CLASS(PTypeBase, true, false, false); +IMPLEMENT_CLASS(PSymbol, true, false, false); +IMPLEMENT_CLASS(PSymbolConst, false, false, false); +IMPLEMENT_CLASS(PSymbolConstNumeric, false, false, false); +IMPLEMENT_CLASS(PSymbolConstString, false, false, false); +IMPLEMENT_CLASS(PSymbolTreeNode, false, false, false) +IMPLEMENT_CLASS(PSymbolType, false, true, false) IMPLEMENT_POINTERS_START(PSymbolType) IMPLEMENT_POINTER(Type) IMPLEMENT_POINTERS_END -IMPLEMENT_POINTY_CLASS(PSymbolVMFunction) +IMPLEMENT_CLASS(PSymbolVMFunction, false, true, false) IMPLEMENT_POINTERS_START(PSymbolVMFunction) IMPLEMENT_POINTER(Function) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(PSymbolTreeNode) //========================================================================== // diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 7b29dbf051..e07f9eace4 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) DSectorEffect::DSectorEffect () : DThinker(STAT_SECTOREFFECT) @@ -71,7 +71,7 @@ void DSectorEffect::Serialize(FSerializer &arc) arc("sector", m_Sector); } -IMPLEMENT_POINTY_CLASS(DMover) +IMPLEMENT_CLASS(DMover, false, true, false) IMPLEMENT_POINTERS_START(DMover) IMPLEMENT_POINTER(interpolation) @@ -108,9 +108,7 @@ void DMover::StopInterpolation(bool force) } } - - -IMPLEMENT_CLASS (DMovingFloor) +IMPLEMENT_CLASS(DMovingFloor, false, false, false) DMovingFloor::DMovingFloor () { @@ -123,7 +121,7 @@ DMovingFloor::DMovingFloor (sector_t *sector) interpolation = sector->SetInterpolation(sector_t::FloorMove, true); } -IMPLEMENT_CLASS (DMovingCeiling) +IMPLEMENT_CLASS(DMovingCeiling, false, false, false) DMovingCeiling::DMovingCeiling () { diff --git a/src/dthinker.cpp b/src/dthinker.cpp index bacd53eee5..246b9ed2c1 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -47,7 +47,7 @@ extern cycle_t BotSupportCycles; extern cycle_t ActionCycles; extern int BotWTG; -IMPLEMENT_CLASS (DThinker) +IMPLEMENT_CLASS(DThinker, false, false, false) DThinker *NextToThink; @@ -538,7 +538,7 @@ public: } }; -IMPLEMENT_CLASS(DThinkerIterator); +IMPLEMENT_CLASS(DThinkerIterator, false, false, false); DEFINE_ACTION_FUNCTION(DThinkerIterator, Create) { PARAM_PROLOGUE; diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 6d31023724..737376ecbb 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) void DLightLevel::Serialize(FSerializer &arc) { diff --git a/src/fragglescript/t_prepro.cpp b/src/fragglescript/t_prepro.cpp index 2c667878d4..0a3ec6a0de 100644 --- a/src/fragglescript/t_prepro.cpp +++ b/src/fragglescript/t_prepro.cpp @@ -71,7 +71,7 @@ // //========================================================================== -IMPLEMENT_POINTY_CLASS(DFsSection) +IMPLEMENT_CLASS(DFsSection, false, true, false) IMPLEMENT_POINTERS_START(DFsSection) IMPLEMENT_POINTER(next) diff --git a/src/fragglescript/t_script.cpp b/src/fragglescript/t_script.cpp index f14cbe25fb..326cad621f 100644 --- a/src/fragglescript/t_script.cpp +++ b/src/fragglescript/t_script.cpp @@ -99,7 +99,7 @@ AActor *trigger_obj; // //========================================================================== -IMPLEMENT_POINTY_CLASS(DFsScript) +IMPLEMENT_CLASS(DFsScript, false, true, false) IMPLEMENT_POINTERS_START(DFsScript) IMPLEMENT_POINTER(parent) @@ -269,7 +269,7 @@ void DFsScript::ParseScript(char *position) // //========================================================================== -IMPLEMENT_POINTY_CLASS(DRunningScript) +IMPLEMENT_CLASS(DRunningScript, false, true, false) IMPLEMENT_POINTERS_START(DRunningScript) IMPLEMENT_POINTER(prev) @@ -380,7 +380,7 @@ void DRunningScript::Serialize(FSerializer &arc) // //========================================================================== -IMPLEMENT_POINTY_CLASS(DFraggleThinker) +IMPLEMENT_CLASS(DFraggleThinker, false, true, false) IMPLEMENT_POINTERS_START(DFraggleThinker) IMPLEMENT_POINTER(RunningScripts) diff --git a/src/fragglescript/t_variable.cpp b/src/fragglescript/t_variable.cpp index 895602f537..cebf0160c3 100644 --- a/src/fragglescript/t_variable.cpp +++ b/src/fragglescript/t_variable.cpp @@ -179,7 +179,7 @@ AActor* actorvalue(const svalue_t &svalue) // //========================================================================== -IMPLEMENT_POINTY_CLASS(DFsVariable) +IMPLEMENT_CLASS(DFsVariable, false, true, false) IMPLEMENT_POINTERS_START(DFsVariable) IMPLEMENT_POINTER(next) diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 4bf8283425..1342713955 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -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) void AScriptedMarine::Serialize(FSerializer &arc) { diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp index 883eac353f..762d105945 100644 --- a/src/g_heretic/a_chicken.cpp +++ b/src/g_heretic/a_chicken.cpp @@ -29,7 +29,7 @@ public: void MorphPlayerThink (); }; -IMPLEMENT_CLASS(AChickenPlayer) +IMPLEMENT_CLASS(AChickenPlayer, false, false, false) void AChickenPlayer::MorphPlayerThink () { diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index eceb2cfe15..9078d09405 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -17,8 +17,7 @@ public: bool Use (bool pickup); }; - -IMPLEMENT_CLASS (AArtiTomeOfPower) +IMPLEMENT_CLASS(AArtiTomeOfPower, false, false, false) bool AArtiTomeOfPower::Use (bool pickup) { @@ -64,8 +63,7 @@ public: bool Use (bool pickup); }; - -IMPLEMENT_CLASS (AArtiTimeBomb) +IMPLEMENT_CLASS(AArtiTimeBomb, false, false, false) bool AArtiTimeBomb::Use (bool pickup) { diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 51d759640b..b32056374f 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -358,7 +358,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AMaceFX4) +IMPLEMENT_CLASS(AMaceFX4, false, false, false) int AMaceFX4::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -726,7 +726,7 @@ void ABlasterFX1::Effect () } } -IMPLEMENT_CLASS(ABlasterFX1) +IMPLEMENT_CLASS(ABlasterFX1, 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) int ARipper::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -828,7 +828,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AHornRodFX2) +IMPLEMENT_CLASS(AHornRodFX2, 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) 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) void ARainTracker::Serialize(FSerializer &arc) { @@ -1158,8 +1158,8 @@ public: void EndPowerup (); }; -IMPLEMENT_CLASS (APhoenixRod) -IMPLEMENT_CLASS (APhoenixRodPowered) +IMPLEMENT_CLASS(APhoenixRod, false, false, false) +IMPLEMENT_CLASS(APhoenixRodPowered, 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) 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) int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) { diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index e2e1cb0214..3870219d9b 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -22,7 +22,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AWhirlwind) +IMPLEMENT_CLASS(AWhirlwind, false, false, false) int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype) { diff --git a/src/g_hexen/a_boostarmor.cpp b/src/g_hexen/a_boostarmor.cpp index 3234174f36..77fbf3dbd4 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) bool AArtiBoostArmor::Use (bool pickup) { diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp index 56267b8e6e..c0c6cb3ede 100644 --- a/src/g_hexen/a_clericflame.cpp +++ b/src/g_hexen/a_clericflame.cpp @@ -33,7 +33,7 @@ public: void Effect (); }; -IMPLEMENT_CLASS (ACFlameMissile) +IMPLEMENT_CLASS(ACFlameMissile, false, false, false) void ACFlameMissile::BeginPlay () { diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index b87bd3986c..931c75e893 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -58,11 +58,11 @@ public: BYTE CHolyCount; }; -IMPLEMENT_CLASS (ACWeapWraithverge) +IMPLEMENT_CLASS(ACWeapWraithverge, false, false, false) // Holy Spirit -------------------------------------------------------------- -IMPLEMENT_CLASS (AHolySpirit) +IMPLEMENT_CLASS(AHolySpirit, false, false, false) bool AHolySpirit::Slam(AActor *thing) { diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index a0e6b94c66..940a878844 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -25,7 +25,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (ACStaffMissile) +IMPLEMENT_CLASS(ACStaffMissile, false, false, false) int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index 696dda019d..89e3170120 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -38,7 +38,7 @@ public: FState *GetAtkState (bool hold); }; -IMPLEMENT_CLASS (AFWeapAxe) +IMPLEMENT_CLASS(AFWeapAxe, false, false, false) FState *AFWeapAxe::GetUpState () { diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index 020cec78e5..7e18f9c283 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -11,9 +11,9 @@ #include "vm.h" */ -IMPLEMENT_CLASS (AFighterWeapon) -IMPLEMENT_CLASS (AClericWeapon) -IMPLEMENT_CLASS (AMageWeapon) +IMPLEMENT_CLASS(AFighterWeapon, false, false, false) +IMPLEMENT_CLASS(AClericWeapon, false, false, false) +IMPLEMENT_CLASS(AMageWeapon, false, false, false) static FRandom pr_fpatk ("FPunchAttack"); diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index 6a4daabb23..c000a9fafc 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -59,7 +59,7 @@ public: int DoSpecialDamage(AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AFSwordMissile) +IMPLEMENT_CLASS(AFSwordMissile, false, false, false) int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype) { diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index bc13d5cf77..3da16db9ca 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -24,7 +24,7 @@ DECLARE_ACTION(A_CheckThrowBomb) // Poison Bag Artifact (Flechette) ------------------------------------------ -IMPLEMENT_CLASS (AArtiPoisonBag) +IMPLEMENT_CLASS(AArtiPoisonBag, 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) bool AArtiPoisonBag1::Use (bool pickup) { @@ -60,7 +60,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiPoisonBag2) +IMPLEMENT_CLASS(AArtiPoisonBag2, 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) bool AArtiPoisonBag3::Use (bool pickup) { @@ -136,7 +136,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiPoisonBagGiver) +IMPLEMENT_CLASS(AArtiPoisonBagGiver, 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) bool AArtiPoisonBagShooter::Use (bool pickup) { @@ -296,7 +296,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS (APoisonCloud) +IMPLEMENT_CLASS(APoisonCloud, false, false, false) void APoisonCloud::BeginPlay () { diff --git a/src/g_hexen/a_healingradius.cpp b/src/g_hexen/a_healingradius.cpp index c381f39643..3d4eef0aea 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) bool AArtiHealingRadius::Use (bool pickup) { diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index 03ffcc5d61..964fdd44f2 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -72,7 +72,7 @@ public: void Die (AActor *source, AActor *inflictor, int dmgflags); }; -IMPLEMENT_CLASS (AHeresiarch) +IMPLEMENT_CLASS(AHeresiarch, false, false, false) void AHeresiarch::Serialize(FSerializer &arc) { @@ -122,7 +122,7 @@ public: } }; -IMPLEMENT_CLASS (ASorcBall) +IMPLEMENT_CLASS(ASorcBall, 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) // Second ball (blue) - generates the shield -------------------------------- @@ -156,7 +156,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS (ASorcBall2) +IMPLEMENT_CLASS(ASorcBall2, 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) // Sorcerer spell 1 (The burning, bouncing head thing) ---------------------- diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index 866fc83722..cad6f617d7 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -39,7 +39,7 @@ public: void HitFloor (); }; -IMPLEMENT_CLASS (APottery1) +IMPLEMENT_CLASS(APottery1, false, false, false) void APottery1::HitFloor () { @@ -136,7 +136,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS (AZCorpseLynchedNoHeart) +IMPLEMENT_CLASS(AZCorpseLynchedNoHeart, false, false, false) void AZCorpseLynchedNoHeart::PostBeginPlay () { @@ -344,7 +344,7 @@ public: void Activate (AActor *activator); }; -IMPLEMENT_CLASS (AZBell) +IMPLEMENT_CLASS(AZBell, false, false, false) void AZBell::Activate (AActor *activator) { diff --git a/src/g_hexen/a_magecone.cpp b/src/g_hexen/a_magecone.cpp index 57e68c16f8..b2dd969b71 100644 --- a/src/g_hexen/a_magecone.cpp +++ b/src/g_hexen/a_magecone.cpp @@ -32,7 +32,7 @@ public: int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AFrostMissile) +IMPLEMENT_CLASS(AFrostMissile, false, false, false) int AFrostMissile::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 192fd03e01..039755ff50 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -34,7 +34,7 @@ public: int SpecialMissileHit (AActor *victim); }; -IMPLEMENT_CLASS(ALightning) +IMPLEMENT_CLASS(ALightning, 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) int ALightningZap::SpecialMissileHit (AActor *thing) { diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index 710af81982..2660117c39 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -56,7 +56,7 @@ public: BYTE MStaffCount; }; -IMPLEMENT_CLASS (AMWeapBloodscourge) +IMPLEMENT_CLASS(AMWeapBloodscourge, 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) int AMageStaffFX2::SpecialMissileHit (AActor *victim) { diff --git a/src/g_hexen/a_pig.cpp b/src/g_hexen/a_pig.cpp index cafcbcda3f..c12a9f50ac 100644 --- a/src/g_hexen/a_pig.cpp +++ b/src/g_hexen/a_pig.cpp @@ -27,7 +27,7 @@ public: void MorphPlayerThink (); }; -IMPLEMENT_CLASS (APigPlayer) +IMPLEMENT_CLASS(APigPlayer, false, false, false) void APigPlayer::MorphPlayerThink () { diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp index faf3c3083e..1559467db1 100644 --- a/src/g_hexen/a_spike.cpp +++ b/src/g_hexen/a_spike.cpp @@ -31,7 +31,7 @@ public: TObjPtr DirtClump; }; -IMPLEMENT_POINTY_CLASS(AThrustFloor) +IMPLEMENT_CLASS(AThrustFloor, false, true, false) IMPLEMENT_POINTERS_START(AThrustFloor) IMPLEMENT_POINTER(DirtClump) diff --git a/src/g_hexen/a_summon.cpp b/src/g_hexen/a_summon.cpp index e1b2bae096..e98c523520 100644 --- a/src/g_hexen/a_summon.cpp +++ b/src/g_hexen/a_summon.cpp @@ -21,7 +21,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiDarkServant) +IMPLEMENT_CLASS(AArtiDarkServant, false, false, false) //============================================================================ // diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp index 99d6876a51..68ba73bc4b 100644 --- a/src/g_hexen/a_teleportother.cpp +++ b/src/g_hexen/a_teleportother.cpp @@ -34,7 +34,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (AArtiTeleportOther) +IMPLEMENT_CLASS(AArtiTeleportOther, 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) static void TeloSpawn (AActor *source, const char *type) { diff --git a/src/g_level.cpp b/src/g_level.cpp index b13a39e20b..e377d70f63 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) void DAutosaver::Tick () { diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp index 9a43f8518d..0910e5f230 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) bool AArtiTeleport::Use (bool pickup) { diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index 209afc9f42..c906234c85 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -31,7 +31,7 @@ void P_MinotaurSlam (AActor *source, AActor *target); DECLARE_ACTION(A_MinotaurLook) -IMPLEMENT_CLASS(AMinotaur) +IMPLEMENT_CLASS(AMinotaur, false, false, false) void AMinotaur::Tick () { @@ -72,7 +72,7 @@ int AMinotaur::DoSpecialDamage (AActor *target, int damage, FName damagetype) // Minotaur Friend ---------------------------------------------------------- -IMPLEMENT_CLASS(AMinotaurFriend) +IMPLEMENT_CLASS(AMinotaurFriend, false, false, false) void AMinotaurFriend::BeginPlay () { diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index 4925e3c25e..20ab4aad08 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -29,7 +29,7 @@ public: void Deactivate (AActor *activator); }; -IMPLEMENT_CLASS (ASwitchableDecoration) +IMPLEMENT_CLASS(ASwitchableDecoration, 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) //---------------------------------------------------------------------------- // @@ -304,7 +304,7 @@ private: DCorpsePointer () {} }; -IMPLEMENT_POINTY_CLASS(DCorpsePointer) +IMPLEMENT_CLASS(DCorpsePointer, false, true, false) IMPLEMENT_POINTERS_START(DCorpsePointer) IMPLEMENT_POINTER(Corpse) diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 50472e51d0..b1935bd1d4 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) +IMPLEMENT_CLASS(ABasicArmor, false, false, false) +IMPLEMENT_CLASS(ABasicArmorPickup, false, false, false) +IMPLEMENT_CLASS(ABasicArmorBonus, false, false, false) +IMPLEMENT_CLASS(AHexenArmor, false, false, false) //=========================================================================== // diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 7e4970e040..97771021de 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) // Powerup-Giver ------------------------------------------------------------- -IMPLEMENT_CLASS(PClassPowerupGiver) +IMPLEMENT_CLASS(PClassPowerupGiver, 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) //=========================================================================== // @@ -513,7 +513,7 @@ int APowerInvulnerable::AlterWeaponSprite (visstyle_t *vis) // Strength (aka Berserk) Powerup -------------------------------------------- -IMPLEMENT_CLASS (APowerStrength) +IMPLEMENT_CLASS(APowerStrength, false, false, false) //=========================================================================== // @@ -578,7 +578,7 @@ PalEntry APowerStrength::GetBlend () // Invisibility Powerup ------------------------------------------------------ -IMPLEMENT_CLASS (APowerInvisibility) +IMPLEMENT_CLASS(APowerInvisibility, 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) //=========================================================================== // @@ -820,7 +820,7 @@ void APowerIronFeet::DoEffect () // Strife Environment Suit Powerup ------------------------------------------- -IMPLEMENT_CLASS (APowerMask) +IMPLEMENT_CLASS(APowerMask, false, false, false) //=========================================================================== // @@ -857,7 +857,7 @@ void APowerMask::DoEffect () // Light-Amp Powerup --------------------------------------------------------- -IMPLEMENT_CLASS (APowerLightAmp) +IMPLEMENT_CLASS(APowerLightAmp, false, false, false) //=========================================================================== // @@ -899,7 +899,7 @@ void APowerLightAmp::EndEffect () // Torch Powerup ------------------------------------------------------------- -IMPLEMENT_CLASS (APowerTorch) +IMPLEMENT_CLASS(APowerTorch, 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) //=========================================================================== // @@ -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) //=========================================================================== // @@ -1193,7 +1193,7 @@ public: void Tick (); }; -IMPLEMENT_CLASS (APlayerSpeedTrail) +IMPLEMENT_CLASS(APlayerSpeedTrail, false, false, false) //=========================================================================== // @@ -1216,7 +1216,7 @@ void APlayerSpeedTrail::Tick () // Speed Powerup ------------------------------------------------------------- -IMPLEMENT_CLASS (APowerSpeed) +IMPLEMENT_CLASS(APowerSpeed, false, false, false) //=========================================================================== // @@ -1303,11 +1303,11 @@ void APowerSpeed::DoEffect () // Minotaur (aka Dark Servant) powerup --------------------------------------- -IMPLEMENT_CLASS (APowerMinotaur) +IMPLEMENT_CLASS(APowerMinotaur, false, false, false) // Targeter powerup --------------------------------------------------------- -IMPLEMENT_CLASS (APowerTargeter) +IMPLEMENT_CLASS(APowerTargeter, false, false, false) void APowerTargeter::Travelled () { @@ -1422,7 +1422,7 @@ void APowerTargeter::PositionAccuracy () // Frightener Powerup -------------------------------- -IMPLEMENT_CLASS (APowerFrightener) +IMPLEMENT_CLASS(APowerFrightener, false, false, false) //=========================================================================== // @@ -1458,7 +1458,7 @@ void APowerFrightener::EndEffect () // Buddha Powerup -------------------------------- -IMPLEMENT_CLASS (APowerBuddha) +IMPLEMENT_CLASS(APowerBuddha, false, false, false) //=========================================================================== // @@ -1494,11 +1494,11 @@ void APowerBuddha::EndEffect () // Scanner powerup ---------------------------------------------------------- -IMPLEMENT_CLASS (APowerScanner) +IMPLEMENT_CLASS(APowerScanner, false, false, false) // Time freezer powerup ----------------------------------------------------- -IMPLEMENT_CLASS( APowerTimeFreezer) +IMPLEMENT_CLASS( APowerTimeFreezer, false, false, false) //=========================================================================== // @@ -1625,7 +1625,7 @@ void APowerTimeFreezer::EndEffect() // Damage powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerDamage) +IMPLEMENT_CLASS(APowerDamage, 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) #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) //=========================================================================== // @@ -1800,7 +1800,7 @@ void APowerDrain::EndEffect( ) // Regeneration rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerRegeneration) +IMPLEMENT_CLASS(APowerRegeneration, false, false, false) //=========================================================================== // @@ -1822,7 +1822,7 @@ void APowerRegeneration::DoEffect() // High jump rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerHighJump) +IMPLEMENT_CLASS(APowerHighJump, false, false, false) //=========================================================================== // @@ -1860,7 +1860,7 @@ void APowerHighJump::EndEffect( ) // Double firing speed rune --------------------------------------------- -IMPLEMENT_CLASS(APowerDoubleFiringSpeed) +IMPLEMENT_CLASS(APowerDoubleFiringSpeed, false, false, false) //=========================================================================== // @@ -1898,7 +1898,7 @@ void APowerDoubleFiringSpeed::EndEffect( ) // Morph powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerMorph) +IMPLEMENT_CLASS(APowerMorph, false, false, false) //=========================================================================== // @@ -2002,7 +2002,7 @@ void APowerMorph::EndEffect( ) // Infinite Ammo Powerup ----------------------------------------------------- -IMPLEMENT_CLASS(APowerInfiniteAmmo) +IMPLEMENT_CLASS(APowerInfiniteAmmo, false, false, false) //=========================================================================== // diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 3cd7ee1725..6409a07099 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -41,7 +41,7 @@ public: void Destroy(); }; -IMPLEMENT_CLASS(ACustomBridge) +IMPLEMENT_CLASS(ACustomBridge, false, false, false) void ACustomBridge::BeginPlay () { @@ -156,7 +156,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(AInvisibleBridge) +IMPLEMENT_CLASS(AInvisibleBridge, false, false, false) void AInvisibleBridge::BeginPlay () { diff --git a/src/g_shared/a_camera.cpp b/src/g_shared/a_camera.cpp index fb3d81533c..a29b4b81da 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) void ASecurityCamera::Serialize(FSerializer &arc) { @@ -124,7 +124,7 @@ protected: DAngle MaxPitchChange; }; -IMPLEMENT_CLASS (AAimingCamera) +IMPLEMENT_CLASS(AAimingCamera, 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 895c3b170a..9624ff5d66 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) // Dirt stuff diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index b06191607e..5347664f53 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -58,14 +58,14 @@ static int ImpactCount; CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE) -IMPLEMENT_POINTY_CLASS(DBaseDecal) +IMPLEMENT_CLASS(DBaseDecal, false, true, false) IMPLEMENT_POINTERS_START(DBaseDecal) IMPLEMENT_POINTER(WallPrev) IMPLEMENT_POINTER(WallNext) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS (DImpactDecal) +IMPLEMENT_CLASS(DImpactDecal, false, false, false) DBaseDecal::DBaseDecal () : DThinker(STAT_DECAL), @@ -746,7 +746,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS (ADecal) +IMPLEMENT_CLASS(ADecal, false, false, false) void ADecal::BeginPlay () { diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index 82349c1a71..a0774a6f6f 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) //---------------------------------------------------------------------------- diff --git a/src/g_shared/a_flashfader.cpp b/src/g_shared/a_flashfader.cpp index 61b305f447..8406ec2996 100644 --- a/src/g_shared/a_flashfader.cpp +++ b/src/g_shared/a_flashfader.cpp @@ -3,7 +3,7 @@ #include "d_player.h" #include "serializer.h" -IMPLEMENT_POINTY_CLASS(DFlashFader) +IMPLEMENT_CLASS(DFlashFader, false, true, false) IMPLEMENT_POINTERS_START(DFlashFader) IMPLEMENT_POINTER(ForWho) diff --git a/src/g_shared/a_fountain.cpp b/src/g_shared/a_fountain.cpp index 970bd8aaa8..bd415e729b 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) void AParticleFountain::PostBeginPlay () { diff --git a/src/g_shared/a_hatetarget.cpp b/src/g_shared/a_hatetarget.cpp index 4d0d9a8e7c..361ccb1f26 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) void AHateTarget::BeginPlay() { diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index 2d2b5be87f..07685be31b 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) bool AKey::HandlePickup (AInventory *item) { diff --git a/src/g_shared/a_lightning.cpp b/src/g_shared/a_lightning.cpp index 3eaedffc9c..0fe3683da4 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) DLightningThinker::DLightningThinker () : DThinker (STAT_LIGHTNING) diff --git a/src/g_shared/a_mapmarker.cpp b/src/g_shared/a_mapmarker.cpp index f8d7128c35..3c4d99b30b 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) void AMapMarker::BeginPlay () { diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 3323a0a4c7..9ce33e12da 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) int AMorphProjectile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -650,7 +650,7 @@ void AMorphProjectile::Serialize(FSerializer &arc) // Morphed Monster (you must subclass this to do something useful) --------- -IMPLEMENT_POINTY_CLASS(AMorphedMonster) +IMPLEMENT_CLASS(AMorphedMonster, false, true, false) IMPLEMENT_POINTERS_START(AMorphedMonster) IMPLEMENT_POINTER(UnmorphedMe) diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index e60c940369..89a1193cc4 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -66,7 +66,7 @@ public: TObjPtr Next; }; -IMPLEMENT_POINTY_CLASS(AInterpolationPoint) +IMPLEMENT_CLASS(AInterpolationPoint, false, true, false) IMPLEMENT_POINTERS_START(AInterpolationPoint) IMPLEMENT_POINTER(Next) @@ -135,7 +135,7 @@ public: void Tick () {} // Does absolutely nothing itself }; -IMPLEMENT_CLASS (AInterpolationSpecial) +IMPLEMENT_CLASS(AInterpolationSpecial, false, false, false) /* == PathFollower: something that follows a camera path @@ -178,7 +178,7 @@ protected: int HoldTime; }; -IMPLEMENT_POINTY_CLASS(APathFollower) +IMPLEMENT_CLASS(APathFollower, false, true, false) IMPLEMENT_POINTERS_START(APathFollower) IMPLEMENT_POINTER(PrevNode) @@ -480,7 +480,7 @@ protected: bool Interpolate (); }; -IMPLEMENT_CLASS (AActorMover) +IMPLEMENT_CLASS(AActorMover, false, false, false) void AActorMover::BeginPlay() { @@ -596,7 +596,7 @@ protected: TObjPtr Activator; }; -IMPLEMENT_POINTY_CLASS(AMovingCamera) +IMPLEMENT_CLASS(AMovingCamera, false, true, false) IMPLEMENT_POINTERS_START(AMovingCamera) IMPLEMENT_POINTER(Activator) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 155878bacd..2b7fcb79a2 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -24,7 +24,7 @@ static FRandom pr_restore ("RestorePos"); -IMPLEMENT_CLASS(PClassInventory) +IMPLEMENT_CLASS(PClassInventory, false, false, false) PClassInventory::PClassInventory() { @@ -71,7 +71,7 @@ void PClassInventory::Finalize(FStateDefinitions &statedef) ((AActor*)Defaults)->flags |= MF_SPECIAL; } -IMPLEMENT_CLASS(PClassAmmo) +IMPLEMENT_CLASS(PClassAmmo, false, false, false) PClassAmmo::PClassAmmo() { @@ -87,7 +87,7 @@ void PClassAmmo::DeriveData(PClass *newclass) newc->DropAmount = DropAmount; } -IMPLEMENT_CLASS (AAmmo) +IMPLEMENT_CLASS(AAmmo, false, false, false) //=========================================================================== // @@ -470,7 +470,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) int AInventory::StaticLastMessageTic; const char *AInventory::StaticLastMessage; -IMPLEMENT_POINTY_CLASS(AInventory) +IMPLEMENT_CLASS(AInventory, false, true, false) IMPLEMENT_POINTERS_START(AInventory) IMPLEMENT_POINTER(Owner) @@ -1354,7 +1354,7 @@ bool AInventory::DrawPowerup (int x, int y) /* AArtifact implementation */ /***************************************************************************/ -IMPLEMENT_CLASS (APowerupGiver) +IMPLEMENT_CLASS(APowerupGiver, false, false, false) //=========================================================================== // @@ -1644,8 +1644,8 @@ void AInventory::DetachFromOwner () { } -IMPLEMENT_CLASS(AStateProvider) -IMPLEMENT_CLASS (ACustomInventory) +IMPLEMENT_CLASS(AStateProvider, false, false, false) +IMPLEMENT_CLASS(ACustomInventory, false, false, false) //=========================================================================== // @@ -1690,7 +1690,7 @@ bool ACustomInventory::TryPickup (AActor *&toucher) return useok; } -IMPLEMENT_CLASS(PClassHealth) +IMPLEMENT_CLASS(PClassHealth, false, false, false) //=========================================================================== // @@ -1719,7 +1719,7 @@ void PClassHealth::DeriveData(PClass *newclass) newc->LowHealthMessage = LowHealthMessage; } -IMPLEMENT_CLASS (AHealth) +IMPLEMENT_CLASS(AHealth, false, false, false) //=========================================================================== // @@ -1762,7 +1762,7 @@ bool AHealth::TryPickup (AActor *&other) return false; } -IMPLEMENT_CLASS (AHealthPickup) +IMPLEMENT_CLASS(AHealthPickup, false, false, false) //=========================================================================== // @@ -2015,9 +2015,8 @@ void ABackpackItem::DetachFromOwner () // //=========================================================================== -IMPLEMENT_CLASS(ABackpackItem) - -IMPLEMENT_CLASS (AMapRevealer) +IMPLEMENT_CLASS(ABackpackItem, false, false, false) +IMPLEMENT_CLASS(AMapRevealer, false, false, false) //=========================================================================== // @@ -2042,7 +2041,7 @@ bool AMapRevealer::TryPickup (AActor *&toucher) // //=========================================================================== -IMPLEMENT_CLASS(AScoreItem) +IMPLEMENT_CLASS(AScoreItem, false, false, false) //=========================================================================== // diff --git a/src/g_shared/a_puzzleitems.cpp b/src/g_shared/a_puzzleitems.cpp index 233066edc7..ba3f90dc80 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) 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) bool APuzzleItem::HandlePickup (AInventory *item) { diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 1a0c6a0fd6..d2a2e5e5b0 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -14,7 +14,7 @@ static FRandom pr_quake ("Quake"); -IMPLEMENT_POINTY_CLASS(DEarthquake) +IMPLEMENT_CLASS(DEarthquake, false, true, false) IMPLEMENT_POINTERS_START(DEarthquake) IMPLEMENT_POINTER(m_Spot) diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index 3ab67425d2..ca85a13490 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -231,4 +231,4 @@ class ARandomSpawner : public AActor }; -IMPLEMENT_CLASS (ARandomSpawner) +IMPLEMENT_CLASS(ARandomSpawner, false, false, false) diff --git a/src/g_shared/a_secrettrigger.cpp b/src/g_shared/a_secrettrigger.cpp index 286ea50113..7128565715 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) void ASecretTrigger::PostBeginPlay () { diff --git a/src/g_shared/a_sectoraction.cpp b/src/g_shared/a_sectoraction.cpp index 38435e16be..88e504aa95 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) bool ASecActHitFakeFloor::DoTriggerAction (AActor *triggerer, int activationType) diff --git a/src/g_shared/a_setcolor.cpp b/src/g_shared/a_setcolor.cpp index 4e27257560..579c577065 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) class AFadeSetter : public AActor { @@ -30,4 +30,4 @@ class AFadeSetter : public AActor }; -IMPLEMENT_CLASS(AFadeSetter) +IMPLEMENT_CLASS(AFadeSetter, false, false, false) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 89c785e3ef..f58779387b 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) // 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) void ASkyCamCompat::BeginPlay() { @@ -98,7 +98,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS (ASkyPicker) +IMPLEMENT_CLASS(ASkyPicker, 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) void AStackPoint::BeginPlay () { @@ -160,7 +160,7 @@ public: void Destroy (); }; -IMPLEMENT_CLASS (ASectorSilencer) +IMPLEMENT_CLASS(ASectorSilencer, false, false, false) void ASectorSilencer::BeginPlay () { @@ -184,7 +184,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS (ASectorFlagSetter) +IMPLEMENT_CLASS(ASectorFlagSetter, false, false, false) void ASectorFlagSetter::BeginPlay () { diff --git a/src/g_shared/a_soundenvironment.cpp b/src/g_shared/a_soundenvironment.cpp index ba01711573..6d381dbe58 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) void ASoundEnvironment::PostBeginPlay () { diff --git a/src/g_shared/a_soundsequence.cpp b/src/g_shared/a_soundsequence.cpp index 3741a39142..01453fc9c2 100644 --- a/src/g_shared/a_soundsequence.cpp +++ b/src/g_shared/a_soundsequence.cpp @@ -80,7 +80,7 @@ public: TObjPtr Sequence; }; -IMPLEMENT_POINTY_CLASS(ASoundSequenceSlot) +IMPLEMENT_CLASS(ASoundSequenceSlot, false, true, false) IMPLEMENT_POINTERS_START(ASoundSequenceSlot) IMPLEMENT_POINTER(Sequence) @@ -111,7 +111,7 @@ public: void MarkPrecacheSounds () const; }; -IMPLEMENT_CLASS (ASoundSequence) +IMPLEMENT_CLASS(ASoundSequence, false, false, false) //========================================================================== // diff --git a/src/g_shared/a_spark.cpp b/src/g_shared/a_spark.cpp index 4bc9dc4c48..ce61480682 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) void ASpark::Activate (AActor *activator) { diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index c47116f794..1011fcb92a 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -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) +IMPLEMENT_CLASS(ASpecialSpot, false, false, false) TObjPtr DSpotState::SpotState; //---------------------------------------------------------------------------- diff --git a/src/g_shared/a_waterzone.cpp b/src/g_shared/a_waterzone.cpp index 50fc6825b1..65cdf96f6d 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) void AWaterZone::PostBeginPlay () { diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp index 4b0a6dcbf3..68c631d9bd 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) +IMPLEMENT_CLASS(AWeaponHolder, false, false, false) void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) { @@ -24,7 +24,7 @@ void AWeaponHolder::Serialize(FSerializer &arc) ("pieceweapon", PieceWeapon); } -IMPLEMENT_POINTY_CLASS(AWeaponPiece) +IMPLEMENT_CLASS(AWeaponPiece, false, true, false) IMPLEMENT_POINTERS_START(AWeaponPiece) IMPLEMENT_POINTER(FullWeapon) diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index ec5e32be8a..adaf4c9e36 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -21,7 +21,7 @@ #define BONUSADD 6 -IMPLEMENT_POINTY_CLASS(AWeapon) +IMPLEMENT_CLASS(AWeapon, false, true, false) IMPLEMENT_POINTERS_START(AWeapon) IMPLEMENT_POINTER(Ammo1) @@ -38,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) PClassWeapon::PClassWeapon() { @@ -791,7 +791,7 @@ FState *AWeapon::GetStateForButtonName (FName button) /* Weapon giver ***********************************************************/ -IMPLEMENT_CLASS(AWeaponGiver) +IMPLEMENT_CLASS(AWeaponGiver, false, false, false) void AWeaponGiver::Serialize(FSerializer &arc) { diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index 783d1624d9..947f68ae4d 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -44,15 +44,15 @@ EXTERN_CVAR(Int, con_scaletext) int active_con_scaletext(); -IMPLEMENT_POINTY_CLASS(DHUDMessage) +IMPLEMENT_CLASS(DHUDMessage, false, true, false) IMPLEMENT_POINTERS_START(DHUDMessage) IMPLEMENT_POINTER(Next) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS (DHUDMessageFadeOut) -IMPLEMENT_CLASS (DHUDMessageFadeInOut) -IMPLEMENT_CLASS (DHUDMessageTypeOnFadeOut) +IMPLEMENT_CLASS(DHUDMessageFadeOut, false, false, false) +IMPLEMENT_CLASS(DHUDMessageFadeInOut, false, false, false) +IMPLEMENT_CLASS(DHUDMessageTypeOnFadeOut, 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 d0cd2defcb..7675865adc 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -1531,7 +1531,7 @@ private: SBarInfoMainBlock *lastPopup; }; -IMPLEMENT_POINTY_CLASS(DSBarInfo) +IMPLEMENT_CLASS(DSBarInfo, false, true, false) IMPLEMENT_POINTERS_START(DSBarInfo) IMPLEMENT_POINTER(ammo1) diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 524ec4f1fc..abf48c6a16 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -62,7 +62,7 @@ #define XHAIRPICKUPSIZE (2+XHAIRSHRINKSIZE) #define POWERUPICONSIZE 32 -IMPLEMENT_POINTY_CLASS(DBaseStatusBar) +IMPLEMENT_CLASS(DBaseStatusBar, false, true, false) IMPLEMENT_POINTERS_START(DBaseStatusBar) IMPLEMENT_POINTER(Messages[0]) diff --git a/src/g_strife/a_coin.cpp b/src/g_strife/a_coin.cpp index 5848164bde..281c979213 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) const char *ACoin::PickupMessage () { diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp index 5043245903..4bb2fec0e6 100644 --- a/src/g_strife/a_loremaster.cpp +++ b/src/g_strife/a_loremaster.cpp @@ -17,7 +17,7 @@ public: int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS (ALoreShot) +IMPLEMENT_CLASS(ALoreShot, false, false, false) int ALoreShot::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp index b46b47e70d..70310eef2b 100644 --- a/src/g_strife/a_programmer.cpp +++ b/src/g_strife/a_programmer.cpp @@ -23,7 +23,7 @@ public: PalEntry GetBlend (); }; -IMPLEMENT_CLASS (AProgLevelEnder) +IMPLEMENT_CLASS(AProgLevelEnder, false, false, false) //============================================================================ // diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index e460dd91aa..bef34d03ba 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -47,7 +47,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS (ATeleporterBeacon) +IMPLEMENT_CLASS(ATeleporterBeacon, false, false, false) bool ATeleporterBeacon::Use (bool pickup) { diff --git a/src/g_strife/a_spectral.cpp b/src/g_strife/a_spectral.cpp index b348e54dc9..d1dff1fb17 100644 --- a/src/g_strife/a_spectral.cpp +++ b/src/g_strife/a_spectral.cpp @@ -16,7 +16,7 @@ public: void Touch (AActor *toucher); }; -IMPLEMENT_CLASS (ASpectralMonster) +IMPLEMENT_CLASS(ASpectralMonster, false, false, false) void ASpectralMonster::Touch (AActor *toucher) { diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index 6cda8a0fcf..f937da570d 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -19,7 +19,7 @@ */ // Degnin Ore --------------------------------------------------------------- -IMPLEMENT_CLASS(ADegninOre) +IMPLEMENT_CLASS(ADegninOre, false, false, false) DEFINE_ACTION_FUNCTION(AActor, A_RemoveForceField) { @@ -75,7 +75,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS (AHealthTraining) +IMPLEMENT_CLASS(AHealthTraining, 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) bool AScanner::Use (bool pickup) { @@ -130,7 +130,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS (APrisonPass) +IMPLEMENT_CLASS(APrisonPass, 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) // Sound the alarm! --------------------------------------------------------- @@ -175,7 +175,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS (ARaiseAlarm) +IMPLEMENT_CLASS(ARaiseAlarm, 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) bool AOpenDoor222::TryPickup (AActor *&toucher) { @@ -228,7 +228,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS (ACloseDoor222) +IMPLEMENT_CLASS(ACloseDoor222, 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) bool AOpenDoor224::TryPickup (AActor *&toucher) { @@ -287,7 +287,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS (AAmmoFillup) +IMPLEMENT_CLASS(AAmmoFillup, 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) 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) 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) 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) bool ASlideshowStarter::TryPickup (AActor *&toucher) { diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index ef60b77e7e..f4a724bc45 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -72,7 +72,7 @@ public: int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AForceFieldGuard) +IMPLEMENT_CLASS(AForceFieldGuard, false, false, false) int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) { @@ -197,7 +197,7 @@ public: void Die (AActor *source, AActor *inflictor, int dmgflags); }; -IMPLEMENT_CLASS (APowerCoupling) +IMPLEMENT_CLASS(APowerCoupling, false, false, false) void APowerCoupling::Die (AActor *source, AActor *inflictor, int dmgflags) { @@ -239,7 +239,7 @@ public: } }; -IMPLEMENT_CLASS (AMeat) +IMPLEMENT_CLASS(AMeat, false, false, false) //========================================================================== // diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 41ceff087a..ec153d675c 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -184,7 +184,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (APoisonBolt) +IMPLEMENT_CLASS(APoisonBolt, false, false, false) int APoisonBolt::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -607,7 +607,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS (APhosphorousFire) +IMPLEMENT_CLASS(APhosphorousFire, false, false, false) int APhosphorousFire::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -734,7 +734,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade) // The Almighty Sigil! ------------------------------------------------------ -IMPLEMENT_CLASS(ASigil) +IMPLEMENT_CLASS(ASigil, false, false, false) //============================================================================ // diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 122846a82b..3d00897778 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -851,7 +851,7 @@ private: double ItemFlash; }; -IMPLEMENT_CLASS(DStrifeStatusBar); +IMPLEMENT_CLASS(DStrifeStatusBar, false, false, false); DBaseStatusBar *CreateStrifeStatusBar () { diff --git a/src/info.cpp b/src/info.cpp index 12753b21b9..3e14d7fed7 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -153,7 +153,7 @@ int GetSpriteIndex(const char * spritename, bool add) return (lastindex = (int)sprites.Push (temp)); } -IMPLEMENT_POINTY_CLASS(PClassActor) +IMPLEMENT_CLASS(PClassActor, false, true, false) IMPLEMENT_POINTERS_START(PClassActor) IMPLEMENT_POINTER(DropItems) diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 527062bb62..94288bfdfd 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -54,13 +54,12 @@ FIntermissionDescriptorList IntermissionDescriptors; -IMPLEMENT_CLASS(DIntermissionScreen) -IMPLEMENT_CLASS(DIntermissionScreenFader) -IMPLEMENT_CLASS(DIntermissionScreenText) -IMPLEMENT_CLASS(DIntermissionScreenCast) -IMPLEMENT_CLASS(DIntermissionScreenScroller) - -IMPLEMENT_POINTY_CLASS(DIntermissionController) +IMPLEMENT_CLASS(DIntermissionScreen, false, false, false) +IMPLEMENT_CLASS(DIntermissionScreenFader, false, false, false) +IMPLEMENT_CLASS(DIntermissionScreenText, false, false, false) +IMPLEMENT_CLASS(DIntermissionScreenCast, false, false, false) +IMPLEMENT_CLASS(DIntermissionScreenScroller, false, false, false) +IMPLEMENT_CLASS(DIntermissionController, false, true, false) IMPLEMENT_POINTERS_START(DIntermissionController) IMPLEMENT_POINTER(mScreen) diff --git a/src/m_argv.cpp b/src/m_argv.cpp index 5d4aa97a34..924c9dd5c6 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) //=========================================================================== // diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 7348f5881e..94c1ef3df7 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -1033,7 +1033,7 @@ public: } }; -IMPLEMENT_POINTY_CLASS(DSuicider) +IMPLEMENT_CLASS(DSuicider, false, true, false) IMPLEMENT_POINTERS_START(DSuicider) IMPLEMENT_POINTER(Pawn) diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp index affcf7c9f1..110ed2c3ea 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) CCMD(undocolorpic) { diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 174b45d4be..8e05391a69 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) //============================================================================= // diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index bcb61d6eb4..645636dadb 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) //============================================================================= // diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 99c34ab3e4..69976726e1 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) TArray DLoadSaveMenu::SaveGames; int DLoadSaveMenu::LastSaved = -1; @@ -934,7 +934,7 @@ public: }; -IMPLEMENT_CLASS(DSaveMenu) +IMPLEMENT_CLASS(DSaveMenu, false, false, false) //============================================================================= @@ -1102,7 +1102,7 @@ public: bool MenuEvent (int mkey, bool fromcontroller); }; -IMPLEMENT_CLASS(DLoadMenu) +IMPLEMENT_CLASS(DLoadMenu, false, false, false) //============================================================================= diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index c4e0a4d985..6717ffcf2a 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -91,7 +91,7 @@ static bool MenuEnabled = true; // //============================================================================ -IMPLEMENT_POINTY_CLASS(DMenu) +IMPLEMENT_CLASS(DMenu, false, true, false) IMPLEMENT_POINTERS_START(DMenu) IMPLEMENT_POINTER(mParentMenu) diff --git a/src/menu/menuinput.cpp b/src/menu/menuinput.cpp index 39d7a8c0bf..12ef4525d7 100644 --- a/src/menu/menuinput.cpp +++ b/src/menu/menuinput.cpp @@ -44,7 +44,7 @@ // [TP] New #includes #include "v_text.h" -IMPLEMENT_ABSTRACT_CLASS(DTextEnterMenu) +IMPLEMENT_CLASS(DTextEnterMenu, true, false, false) #define INPUTGRID_WIDTH 13 #define INPUTGRID_HEIGHT 5 diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index a72a377407..7915f44b30 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -73,7 +73,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DMessageBoxMenu) +IMPLEMENT_CLASS(DMessageBoxMenu, false, false, false) //============================================================================= // @@ -365,7 +365,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuitMenu) +IMPLEMENT_CLASS(DQuitMenu, false, false, false) //============================================================================= // @@ -458,7 +458,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DEndGameMenu) +IMPLEMENT_CLASS(DEndGameMenu, false, false, false) //============================================================================= // @@ -536,7 +536,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuickSaveMenu) +IMPLEMENT_CLASS(DQuickSaveMenu, false, false, false) //============================================================================= // @@ -632,7 +632,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuickLoadMenu) +IMPLEMENT_CLASS(DQuickLoadMenu, false, false, false) //============================================================================= // diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index efea7d9107..46bbae6655 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) //============================================================================= // @@ -579,7 +578,7 @@ public: } }; -IMPLEMENT_CLASS(DGameplayMenu) +IMPLEMENT_CLASS(DGameplayMenu, false, false, false) class DCompatibilityMenu : public DOptionMenu { @@ -601,4 +600,4 @@ public: } }; -IMPLEMENT_CLASS(DCompatibilityMenu) +IMPLEMENT_CLASS(DCompatibilityMenu, false, false, false) diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index 0fadeca374..2d3c8c25f6 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) #endif //============================================================================= diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index ce542c2f2c..bc22c8e12a 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) //============================================================================= // diff --git a/src/menu/readthis.cpp b/src/menu/readthis.cpp index 0aa3c2fcd2..ce03ec84bb 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) //============================================================================= // diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index b1b4d792fd..6fec9ce6db 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) //============================================================================= diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 1fac7e8fee..dc646da180 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1369,7 +1369,7 @@ private: DPlaneWatcher() {} }; -IMPLEMENT_POINTY_CLASS(DPlaneWatcher) +IMPLEMENT_CLASS(DPlaneWatcher, false, true, false) IMPLEMENT_POINTERS_START(DPlaneWatcher) IMPLEMENT_POINTER(Activator) @@ -2860,7 +2860,7 @@ void FBehavior::StaticStopMyScripts (AActor *actor) //---- The ACS Interpreter ----// -IMPLEMENT_POINTY_CLASS(DACSThinker) +IMPLEMENT_CLASS(DACSThinker, false, true, false) IMPLEMENT_POINTERS_START(DACSThinker) IMPLEMENT_POINTER(LastScript) @@ -2991,7 +2991,7 @@ void DACSThinker::StopScriptsFor (AActor *actor) } } -IMPLEMENT_POINTY_CLASS(DLevelScript) +IMPLEMENT_CLASS(DLevelScript, false, true, false) IMPLEMENT_POINTERS_START(DLevelScript) IMPLEMENT_POINTER(next) diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index 7e65bf05df..ce2221ca14 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) void ACustomSprite::BeginPlay () { diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 29b0c50950..53100f9caf 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -38,7 +38,7 @@ // //============================================================================ -IMPLEMENT_CLASS (DCeiling) +IMPLEMENT_CLASS(DCeiling, false, false, false) DCeiling::DCeiling () { diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 0bc2b98a87..ad434b535b 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) 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 33e37218d7..568e880586 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -45,7 +45,7 @@ // //============================================================================ -IMPLEMENT_CLASS (DDoor) +IMPLEMENT_CLASS(DDoor, 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) DAnimatedDoor::DAnimatedDoor () { diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 23fdc7575c..a89330b2ae 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) DFloor::DFloor () { @@ -815,7 +815,7 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed) // //========================================================================== -IMPLEMENT_POINTY_CLASS(DElevator) +IMPLEMENT_CLASS(DElevator, false, true, false) IMPLEMENT_POINTERS_START(DElevator) IMPLEMENT_POINTER(m_Interp_Floor) @@ -1105,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) +IMPLEMENT_CLASS(DFloorWaggle, false, false, false) +IMPLEMENT_CLASS(DCeilingWaggle, false, false, false) DWaggleBase::DWaggleBase () { diff --git a/src/p_lights.cpp b/src/p_lights.cpp index fb3ab339e4..c2c2127a26 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) DLighting::DLighting () { @@ -191,7 +191,7 @@ DLighting::DLighting (sector_t *sector) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DFireFlicker) +IMPLEMENT_CLASS(DFireFlicker, 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) DFlicker::DFlicker () { @@ -334,7 +334,7 @@ void EV_StartLightFlickering (int tag, int upper, int lower) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DLightFlash) +IMPLEMENT_CLASS(DLightFlash, 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) DStrobe::DStrobe () { @@ -667,7 +667,7 @@ void EV_LightChange (int tag, int value) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DGlow) +IMPLEMENT_CLASS(DGlow, false, false, false) DGlow::DGlow () { @@ -736,7 +736,7 @@ DGlow::DGlow (sector_t *sector) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS (DGlow2) +IMPLEMENT_CLASS(DGlow2, 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) DPhased::DPhased () { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f36760856c..3cc961d846 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -131,7 +131,7 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- -IMPLEMENT_POINTY_CLASS_WITH_FIELDS (AActor) +IMPLEMENT_CLASS(AActor, false, true, true) IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(target) @@ -6956,7 +6956,7 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) // //---------------------------------------------------------------------------- -IMPLEMENT_POINTY_CLASS_WITH_FIELDS(DDropItem) +IMPLEMENT_CLASS(DDropItem, false, true, true) IMPLEMENT_POINTERS_START(DDropItem) IMPLEMENT_POINTER(Next) diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index 52078daadb..fecfbd024d 100644 --- a/src/p_pillar.cpp +++ b/src/p_pillar.cpp @@ -40,7 +40,7 @@ #include "serializer.h" #include "r_data/r_interpolate.h" -IMPLEMENT_POINTY_CLASS(DPillar) +IMPLEMENT_CLASS(DPillar, false, true, false) IMPLEMENT_POINTERS_START(DPillar) IMPLEMENT_POINTER(m_Interp_Floor) diff --git a/src/p_plats.cpp b/src/p_plats.cpp index 868f471383..3bd7089166 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) DPlat::DPlat () { diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index b2e59ade40..b64bb22a74 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -99,7 +99,7 @@ static const FGenericButtons ButtonChecks[] = // //------------------------------------------------------------------------ -IMPLEMENT_POINTY_CLASS(DPSprite) +IMPLEMENT_CLASS(DPSprite, false, true, false) IMPLEMENT_POINTERS_START(DPSprite) IMPLEMENT_POINTER(Caller) diff --git a/src/p_pusher.cpp b/src/p_pusher.cpp index d211f1c3c9..250e8ee3de 100644 --- a/src/p_pusher.cpp +++ b/src/p_pusher.cpp @@ -74,7 +74,7 @@ protected: friend bool PIT_PushThing (AActor *thing); }; -IMPLEMENT_POINTY_CLASS(DPusher) +IMPLEMENT_CLASS(DPusher, false, true, false) IMPLEMENT_POINTERS_START(DPusher) IMPLEMENT_POINTER(m_Source) diff --git a/src/p_scroll.cpp b/src/p_scroll.cpp index 3918bc072d..67f6499d61 100644 --- a/src/p_scroll.cpp +++ b/src/p_scroll.cpp @@ -73,7 +73,7 @@ private: } }; -IMPLEMENT_POINTY_CLASS(DScroller) +IMPLEMENT_CLASS(DScroller, false, true, false) IMPLEMENT_POINTERS_START(DScroller) IMPLEMENT_POINTER(m_Interpolations[0]) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index dc878bc335..e9ac494197 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) void DLightTransfer::Serialize(FSerializer &arc) { @@ -750,7 +750,7 @@ protected: BYTE Flags; }; -IMPLEMENT_CLASS (DWallLightTransfer) +IMPLEMENT_CLASS(DWallLightTransfer, false, false, false) void DWallLightTransfer::Serialize(FSerializer &arc) { diff --git a/src/p_switch.cpp b/src/p_switch.cpp index c60b0fdcda..027b5d99d2 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) DActiveButton::DActiveButton () { diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index f65e2f4028..85ee8a1c83 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) void ATeleportFog::PostBeginPlay () { diff --git a/src/p_user.cpp b/src/p_user.cpp index 0efe422a3d..266d216bb0 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -508,7 +508,7 @@ int player_t::GetSpawnClass() // //=========================================================================== -IMPLEMENT_CLASS(PClassPlayerPawn) +IMPLEMENT_CLASS(PClassPlayerPawn, false, false, false) PClassPlayerPawn::PClassPlayerPawn() { @@ -622,14 +622,14 @@ void player_t::SendPitchLimits() const // //=========================================================================== -IMPLEMENT_POINTY_CLASS(APlayerPawn) +IMPLEMENT_CLASS(APlayerPawn, false, true, false) IMPLEMENT_POINTERS_START(APlayerPawn) IMPLEMENT_POINTER(InvFirst) IMPLEMENT_POINTER(InvSel) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS (APlayerChunk) +IMPLEMENT_CLASS(APlayerChunk, false, false, false) void APlayerPawn::Serialize(FSerializer &arc) { diff --git a/src/po_man.cpp b/src/po_man.cpp index c80e72992b..3261e34f32 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -172,7 +172,7 @@ static FPolyNode *FreePolyNodes; // //========================================================================== -IMPLEMENT_POINTY_CLASS(DPolyAction) +IMPLEMENT_CLASS(DPolyAction, false, true, false) IMPLEMENT_POINTERS_START(DPolyAction) IMPLEMENT_POINTER(m_Interpolation) @@ -240,7 +240,7 @@ void DPolyAction::StopInterpolation () // //========================================================================== -IMPLEMENT_CLASS (DRotatePoly) +IMPLEMENT_CLASS(DRotatePoly, false, false, false) DRotatePoly::DRotatePoly () { @@ -257,7 +257,7 @@ DRotatePoly::DRotatePoly (int polyNum) // //========================================================================== -IMPLEMENT_CLASS (DMovePoly) +IMPLEMENT_CLASS(DMovePoly, false, false, false) DMovePoly::DMovePoly () { @@ -284,7 +284,7 @@ DMovePoly::DMovePoly (int polyNum) // //========================================================================== -IMPLEMENT_CLASS(DMovePolyTo) +IMPLEMENT_CLASS(DMovePolyTo, false, false, false) DMovePolyTo::DMovePolyTo() { @@ -309,7 +309,7 @@ DMovePolyTo::DMovePolyTo(int polyNum) // //========================================================================== -IMPLEMENT_CLASS (DPolyDoor) +IMPLEMENT_CLASS(DPolyDoor, false, false, false) DPolyDoor::DPolyDoor () { diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index 04c3a3f2ef..29b7415616 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) struct MiniModeInfo { diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp index fdb8affc67..911127f07b 100644 --- a/src/r_data/r_interpolate.cpp +++ b/src/r_data/r_interpolate.cpp @@ -161,17 +161,17 @@ public: // //========================================================================== -IMPLEMENT_ABSTRACT_POINTY_CLASS(DInterpolation) +IMPLEMENT_CLASS(DInterpolation, true, true, false) IMPLEMENT_POINTERS_START(DInterpolation) IMPLEMENT_POINTER(Next) IMPLEMENT_POINTER(Prev) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(DSectorPlaneInterpolation) -IMPLEMENT_CLASS(DSectorScrollInterpolation) -IMPLEMENT_CLASS(DWallScrollInterpolation) -IMPLEMENT_CLASS(DPolyobjInterpolation) +IMPLEMENT_CLASS(DSectorPlaneInterpolation, false, false, false) +IMPLEMENT_CLASS(DSectorScrollInterpolation, false, false, false) +IMPLEMENT_CLASS(DWallScrollInterpolation, false, false, false) +IMPLEMENT_CLASS(DPolyobjInterpolation, false, false, false) //========================================================================== // diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 0db9365c20..1aedcb1fb1 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) //========================================================================== // @@ -2470,7 +2470,7 @@ public: virtual void PostBeginPlay(); }; -IMPLEMENT_CLASS(AMusicChanger) +IMPLEMENT_CLASS(AMusicChanger, false, false, false) bool AMusicChanger::DoTriggerAction (AActor *triggerer, int activationType) { diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index baf33fd0cb..449baa4d6b 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -285,7 +285,7 @@ void DSeqNode::SerializeSequences (FSerializer &arc) arc("sndseqlisthead", SequenceListHead); } -IMPLEMENT_POINTY_CLASS(DSeqNode) +IMPLEMENT_CLASS(DSeqNode, false, true, false) IMPLEMENT_POINTERS_START(DSeqNode) IMPLEMENT_POINTER(m_ChildSeqNode) @@ -429,7 +429,7 @@ FName DSeqNode::GetSequenceName () const return Sequences[m_Sequence]->SeqName; } -IMPLEMENT_POINTY_CLASS(DSeqActorNode) +IMPLEMENT_CLASS(DSeqActorNode, false, true, false) IMPLEMENT_POINTERS_START(DSeqActorNode) IMPLEMENT_POINTER(m_Actor) @@ -441,7 +441,7 @@ void DSeqActorNode::Serialize(FSerializer &arc) arc("actor", m_Actor); } -IMPLEMENT_CLASS (DSeqPolyNode) +IMPLEMENT_CLASS(DSeqPolyNode, false, false, false) void DSeqPolyNode::Serialize(FSerializer &arc) { @@ -449,7 +449,7 @@ void DSeqPolyNode::Serialize(FSerializer &arc) arc("poly", m_Poly); } -IMPLEMENT_CLASS (DSeqSectorNode) +IMPLEMENT_CLASS(DSeqSectorNode, false, false, false) void DSeqSectorNode::Serialize(FSerializer &arc) { diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 6ccd0051a0..63ae447cfd 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -95,7 +95,8 @@ public: // The special was already executed by TryPickup, so do nothing here } }; -IMPLEMENT_CLASS (AFakeInventory) + +IMPLEMENT_CLASS(AFakeInventory, false, false, false) // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 22728749cb..3070c1b4d7 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -34,15 +34,15 @@ #include #include "vm.h" -IMPLEMENT_CLASS(VMException) -IMPLEMENT_ABSTRACT_POINTY_CLASS(VMFunction) +IMPLEMENT_CLASS(VMException, false, false, false) +IMPLEMENT_CLASS(VMFunction, true, true, false) IMPLEMENT_POINTERS_START(VMFunction) IMPLEMENT_POINTER(Proto) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(VMScriptFunction) -IMPLEMENT_CLASS(VMNativeFunction) +IMPLEMENT_CLASS(VMScriptFunction, false, false, false) +IMPLEMENT_CLASS(VMNativeFunction, false, false, false) VMScriptFunction::VMScriptFunction(FName name) { diff --git a/src/v_video.cpp b/src/v_video.cpp index b1f1ced9cf..f79f31b1c7 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) +IMPLEMENT_CLASS(DFrameBuffer, true, 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) // 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) class FPaletteTester : public FTexture { diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 10ab11c729..a79ef1a3f3 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) struct D3DFB::PackedTexture { diff --git a/src/win32/fb_ddraw.cpp b/src/win32/fb_ddraw.cpp index 7cc6037865..dcd6d37a95 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) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/win32/win32video.cpp b/src/win32/win32video.cpp index 8eb2349ec2..b8aded5c1b 100644 --- a/src/win32/win32video.cpp +++ b/src/win32/win32video.cpp @@ -78,7 +78,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS(BaseWinFB) +IMPLEMENT_CLASS(BaseWinFB, true, false, false) typedef IDirect3D9 *(WINAPI *DIRECT3DCREATE9FUNC)(UINT SDKVersion); typedef HRESULT (WINAPI *DIRECTDRAWCREATEFUNC)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter); From ad19e439a6ea1a6adf38d8489cd1c356fbcf15fe Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Tue, 1 Nov 2016 04:58:10 +0100 Subject: [PATCH 210/471] Implement a general and easy-to-use way of overriding native virtual functions --- src/dobject.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/dobject.h b/src/dobject.h index dd0d40772e..fb631c91cd 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -125,8 +125,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) \ @@ -151,6 +151,34 @@ protected: \ #define HAS_FIELDS \ static void InitNativeFields(); +// 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) }; + #if defined(_MSC_VER) # pragma section(".creg$u",read) # define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo; @@ -576,6 +604,52 @@ protected: } }; +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; + } +}; + +template +ClassReg DVMObject::RegistrationInfo = +{ + nullptr, + DVMObject::FormatClassName(), + &DVMObject::Super::RegistrationInfo, + nullptr, + DVMObject::InPlaceConstructor, + nullptr, + sizeof(DVMObject), + DVMObject::MetaClassNum +}; +template _DECLARE_TI(DVMObject) + // 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. From 33e2c74642192ca8bacd5f763a37fb0593c54258 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 6 Nov 2016 11:28:01 +0100 Subject: [PATCH 211/471] Provide a way to expose a native class to zscript for virtual functions overriding --- src/dobject.cpp | 17 +++++++++-------- src/dobject.h | 11 ++++++++--- src/dobjtype.cpp | 8 ++++++-- src/dobjtype.h | 1 + 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/dobject.cpp b/src/dobject.cpp index d057a71d39..e21d07526c 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -57,14 +57,15 @@ ClassReg DObject::RegistrationInfo = { - NULL, // MyClass - "DObject", // Name - NULL, // ParentType - NULL, // Pointers - &DObject::InPlaceConstructor, // ConstructNative - &DObject::InitNativeFields, - 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) diff --git a/src/dobject.h b/src/dobject.h index fb631c91cd..24ba4997c1 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -109,6 +109,7 @@ struct ClassReg PClass *MyClass; const char *Name; ClassReg *ParentType; + ClassReg *VMExport; const size_t *Pointers; void (*ConstructNative)(void *); void(*InitNatives)(); @@ -186,11 +187,12 @@ protected: \ # define _DECLARE_TI(cls) ClassReg * const cls::RegistrationInfoPtr __attribute__((section(SECTION_CREG))) = &cls::RegistrationInfo; #endif -#define _IMP_PCLASS(cls, ptrs, create, initn) \ +#define _IMP_PCLASS(cls, ptrs, create, initn, vmexport) \ ClassReg cls::RegistrationInfo = {\ nullptr, \ #cls, \ &cls::Super::RegistrationInfo, \ + vmexport, \ ptrs, \ create, \ initn, \ @@ -199,9 +201,9 @@ protected: \ _DECLARE_TI(cls) \ PClass *cls::StaticType() const { return RegistrationInfo.MyClass; } -#define IMPLEMENT_CLASS(cls, isabstract, ptrs, fields) \ +#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)) + _IMP_PCLASS(cls, _X_POINTERS_##ptrs##(cls), _X_ABSTRACT_##isabstract##(cls), _X_FIELDS_##fields##(cls), _X_VMEXPORT_##vmexport##(cls)) // 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. @@ -218,6 +220,8 @@ protected: \ #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 { @@ -643,6 +647,7 @@ ClassReg DVMObject::RegistrationInfo = DVMObject::FormatClassName(), &DVMObject::Super::RegistrationInfo, nullptr, + nullptr, DVMObject::InPlaceConstructor, nullptr, sizeof(DVMObject), diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 9d30229669..89b9986cc2 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2847,7 +2847,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(); } @@ -2855,10 +2855,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; } diff --git a/src/dobjtype.h b/src/dobjtype.h index d907feeeb9..e1f95a8282 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -769,6 +769,7 @@ public: // 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; From 7dbc4710f1e7bce2af53f9e6b9212e0f9e6d375e Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 6 Nov 2016 19:43:19 +0100 Subject: [PATCH 212/471] Add the new argument to all uses of the implement macro --- src/b_bot.cpp | 2 +- src/c_dispatch.cpp | 4 +- src/d_dehacked.cpp | 2 +- src/decallib.cpp | 10 ++-- src/dobjgc.cpp | 2 +- src/dobjtype.cpp | 72 +++++++++++------------ src/dsectoreffect.cpp | 8 +-- src/dthinker.cpp | 4 +- src/fragglescript/t_func.cpp | 2 +- src/fragglescript/t_prepro.cpp | 2 +- src/fragglescript/t_script.cpp | 6 +- src/fragglescript/t_variable.cpp | 2 +- src/g_doom/a_scriptedmarine.cpp | 2 +- src/g_heretic/a_chicken.cpp | 2 +- src/g_heretic/a_hereticartifacts.cpp | 4 +- src/g_heretic/a_hereticweaps.cpp | 20 +++---- src/g_heretic/a_ironlich.cpp | 2 +- src/g_hexen/a_boostarmor.cpp | 2 +- src/g_hexen/a_clericflame.cpp | 2 +- src/g_hexen/a_clericholy.cpp | 4 +- src/g_hexen/a_clericstaff.cpp | 2 +- src/g_hexen/a_fighteraxe.cpp | 2 +- src/g_hexen/a_fighterplayer.cpp | 6 +- src/g_hexen/a_fighterquietus.cpp | 2 +- src/g_hexen/a_flechette.cpp | 14 ++--- src/g_hexen/a_healingradius.cpp | 2 +- src/g_hexen/a_heresiarch.cpp | 10 ++-- src/g_hexen/a_hexenspecialdecs.cpp | 6 +- src/g_hexen/a_magecone.cpp | 2 +- src/g_hexen/a_magelightning.cpp | 4 +- src/g_hexen/a_magestaff.cpp | 4 +- src/g_hexen/a_pig.cpp | 2 +- src/g_hexen/a_spike.cpp | 2 +- src/g_hexen/a_summon.cpp | 2 +- src/g_hexen/a_teleportother.cpp | 4 +- src/g_level.cpp | 2 +- src/g_raven/a_artitele.cpp | 2 +- src/g_raven/a_minotaur.cpp | 4 +- src/g_shared/a_action.cpp | 6 +- src/g_shared/a_armor.cpp | 10 ++-- src/g_shared/a_artifacts.cpp | 54 ++++++++--------- src/g_shared/a_bridge.cpp | 4 +- src/g_shared/a_camera.cpp | 4 +- src/g_shared/a_debris.cpp | 2 +- src/g_shared/a_decals.cpp | 6 +- src/g_shared/a_fastprojectile.cpp | 2 +- src/g_shared/a_flashfader.cpp | 2 +- src/g_shared/a_fountain.cpp | 2 +- src/g_shared/a_hatetarget.cpp | 2 +- src/g_shared/a_keys.cpp | 2 +- src/g_shared/a_lightning.cpp | 2 +- src/g_shared/a_mapmarker.cpp | 2 +- src/g_shared/a_morph.cpp | 4 +- src/g_shared/a_movingcamera.cpp | 10 ++-- src/g_shared/a_pickups.cpp | 26 ++++---- src/g_shared/a_puzzleitems.cpp | 4 +- src/g_shared/a_quake.cpp | 2 +- src/g_shared/a_randomspawner.cpp | 2 +- src/g_shared/a_secrettrigger.cpp | 2 +- src/g_shared/a_sectoraction.cpp | 24 ++++---- src/g_shared/a_setcolor.cpp | 4 +- src/g_shared/a_skies.cpp | 12 ++-- src/g_shared/a_soundenvironment.cpp | 2 +- src/g_shared/a_soundsequence.cpp | 4 +- src/g_shared/a_spark.cpp | 2 +- src/g_shared/a_specialspot.cpp | 4 +- src/g_shared/a_waterzone.cpp | 2 +- src/g_shared/a_weaponpiece.cpp | 6 +- src/g_shared/a_weapons.cpp | 6 +- src/g_shared/hudmessages.cpp | 8 +-- src/g_shared/sbarinfo.cpp | 2 +- src/g_shared/shared_sbar.cpp | 2 +- src/g_strife/a_coin.cpp | 2 +- src/g_strife/a_loremaster.cpp | 2 +- src/g_strife/a_programmer.cpp | 2 +- src/g_strife/a_rebels.cpp | 2 +- src/g_strife/a_spectral.cpp | 2 +- src/g_strife/a_strifeitems.cpp | 28 ++++----- src/g_strife/a_strifestuff.cpp | 6 +- src/g_strife/a_strifeweapons.cpp | 6 +- src/g_strife/strife_sbar.cpp | 2 +- src/info.cpp | 2 +- src/intermission/intermission.cpp | 12 ++-- src/m_argv.cpp | 2 +- src/m_cheat.cpp | 2 +- src/menu/colorpickermenu.cpp | 2 +- src/menu/joystickmenu.cpp | 2 +- src/menu/listmenu.cpp | 2 +- src/menu/loadsavemenu.cpp | 6 +- src/menu/menu.cpp | 2 +- src/menu/menuinput.cpp | 2 +- src/menu/messagebox.cpp | 10 ++-- src/menu/optionmenu.cpp | 6 +- src/menu/optionmenuitems.h | 2 +- src/menu/playermenu.cpp | 2 +- src/menu/readthis.cpp | 2 +- src/menu/videomenu.cpp | 2 +- src/p_acs.cpp | 6 +- src/p_buildmap.cpp | 2 +- src/p_ceiling.cpp | 2 +- src/p_conversation.cpp | 2 +- src/p_doors.cpp | 4 +- src/p_floor.cpp | 10 ++-- src/p_lights.cpp | 16 ++--- src/p_mobj.cpp | 4 +- src/p_pillar.cpp | 2 +- src/p_plats.cpp | 2 +- src/p_pspr.cpp | 2 +- src/p_pusher.cpp | 2 +- src/p_scroll.cpp | 2 +- src/p_spec.cpp | 4 +- src/p_switch.cpp | 2 +- src/p_teleport.cpp | 2 +- src/p_user.cpp | 6 +- src/po_man.cpp | 10 ++-- src/posix/sdl/sdlvideo.cpp | 2 +- src/r_data/r_interpolate.cpp | 10 ++-- src/s_advsound.cpp | 4 +- src/s_sndseq.cpp | 8 +-- src/scripting/decorate/olddecorations.cpp | 2 +- src/scripting/vm/vmframe.cpp | 8 +-- src/v_video.cpp | 8 +-- src/win32/fb_d3d9.cpp | 2 +- src/win32/fb_ddraw.cpp | 2 +- src/win32/win32video.cpp | 2 +- 125 files changed, 346 insertions(+), 346 deletions(-) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 42b34f1df7..93d71092d7 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -15,7 +15,7 @@ #include "serializer.h" #include "d_player.h" -IMPLEMENT_CLASS(DBot, false, true, false) +IMPLEMENT_CLASS(DBot, false, true, false, false) IMPLEMENT_POINTERS_START(DBot) IMPLEMENT_POINTER(dest) diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index e7ccc89228..71aeea0faa 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -187,7 +187,7 @@ static const char *KeyConfCommands[] = // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(DWaitingCommand, false, false, false) +IMPLEMENT_CLASS(DWaitingCommand, false, false, false, false) void DWaitingCommand::Serialize(FSerializer &arc) { @@ -225,7 +225,7 @@ void DWaitingCommand::Tick () } } -IMPLEMENT_CLASS(DStoredCommand, false, false, false) +IMPLEMENT_CLASS(DStoredCommand, false, false, false, false) DStoredCommand::DStoredCommand () { diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index afaf7001b5..8258a656ea 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -231,7 +231,7 @@ DehInfo deh = // from the original actor's defaults. The original actor is then changed to // spawn the new class. -IMPLEMENT_CLASS(ADehackedPickup, false, true, false) +IMPLEMENT_CLASS(ADehackedPickup, false, true, false, false) IMPLEMENT_POINTERS_START(ADehackedPickup) IMPLEMENT_POINTER(RealPickup) diff --git a/src/decallib.cpp b/src/decallib.cpp index 6264970628..970bd7458c 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -119,7 +119,7 @@ protected: DDecalThinker () : DThinker (STAT_DECALTHINKER) {} }; -IMPLEMENT_CLASS(DDecalThinker, false, true, false) +IMPLEMENT_CLASS(DDecalThinker, false, true, false, false) IMPLEMENT_POINTERS_START(DDecalThinker) IMPLEMENT_POINTER(TheDecal) @@ -1153,7 +1153,7 @@ FDecalAnimator::~FDecalAnimator () { } -IMPLEMENT_CLASS(DDecalFader, false, false, false) +IMPLEMENT_CLASS(DDecalFader, false, false, false, false) void DDecalFader::Serialize(FSerializer &arc) { @@ -1202,7 +1202,7 @@ DThinker *FDecalFaderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const return fader; } -IMPLEMENT_CLASS(DDecalStretcher, false, false, false) +IMPLEMENT_CLASS(DDecalStretcher, false, false, false, false) void DDecalStretcher::Serialize(FSerializer &arc) { @@ -1290,7 +1290,7 @@ void DDecalStretcher::Tick () } } -IMPLEMENT_CLASS(DDecalSlider, false, false, false) +IMPLEMENT_CLASS(DDecalSlider, false, false, false, false) void DDecalSlider::Serialize(FSerializer &arc) { @@ -1370,7 +1370,7 @@ FDecalAnimator *FDecalLib::FindAnimator (const char *name) return NULL; } -IMPLEMENT_CLASS(DDecalColorer, false, false, false) +IMPLEMENT_CLASS(DDecalColorer, false, false, false, false) void DDecalColorer::Serialize(FSerializer &arc) { diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index fa59392d57..fa8723e902 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -126,7 +126,7 @@ public: int SideNum; }; -IMPLEMENT_CLASS(DSectorMarker, false, false, false) +IMPLEMENT_CLASS(DSectorMarker, false, false, false, false) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 89b9986cc2..71bfd542bd 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -93,8 +93,8 @@ static const size_t TheEnd = ~(size_t)0; // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(PErrorType, false, false, false) -IMPLEMENT_CLASS(PVoidType, false, false, false) +IMPLEMENT_CLASS(PErrorType, false, false, false, false) +IMPLEMENT_CLASS(PVoidType, false, false, false, false) void DumpTypeTable() { @@ -141,7 +141,7 @@ void DumpTypeTable() /* PClassType *************************************************************/ -IMPLEMENT_CLASS(PClassType, false, false, false) +IMPLEMENT_CLASS(PClassType, false, false, false, false) //========================================================================== // @@ -169,7 +169,7 @@ void PClassType::Derive(PClass *newclass) /* PClassClass ************************************************************/ -IMPLEMENT_CLASS(PClassClass, false, false, false) +IMPLEMENT_CLASS(PClassClass, false, false, false, false) //========================================================================== // @@ -187,7 +187,7 @@ PClassClass::PClassClass() /* PType ******************************************************************/ -IMPLEMENT_CLASS(PType, true, true, false) +IMPLEMENT_CLASS(PType, true, true, false, false) IMPLEMENT_POINTERS_START(PType) IMPLEMENT_POINTER(HashNext) @@ -614,7 +614,7 @@ void PType::StaticInit() /* PBasicType *************************************************************/ -IMPLEMENT_CLASS(PBasicType, true, false, false) +IMPLEMENT_CLASS(PBasicType, true, false, false, false) //========================================================================== // @@ -640,11 +640,11 @@ PBasicType::PBasicType(unsigned int size, unsigned int align) /* PCompoundType **********************************************************/ -IMPLEMENT_CLASS(PCompoundType, true, false, false) +IMPLEMENT_CLASS(PCompoundType, true, false, false, false) /* PNamedType *************************************************************/ -IMPLEMENT_CLASS(PNamedType, true, true, false) +IMPLEMENT_CLASS(PNamedType, true, true, false, false) IMPLEMENT_POINTERS_START(PNamedType) IMPLEMENT_POINTER(Outer) @@ -692,7 +692,7 @@ FString PNamedType::QualifiedName() const /* PInt *******************************************************************/ -IMPLEMENT_CLASS(PInt, false, false, false) +IMPLEMENT_CLASS(PInt, false, false, false, false) //========================================================================== // @@ -931,7 +931,7 @@ double PInt::GetValueFloat(void *addr) const /* PBool ******************************************************************/ -IMPLEMENT_CLASS(PBool, false, false, false) +IMPLEMENT_CLASS(PBool, false, false, false, false) //========================================================================== // @@ -952,7 +952,7 @@ PBool::PBool() /* PFloat *****************************************************************/ -IMPLEMENT_CLASS(PFloat, false, false, false) +IMPLEMENT_CLASS(PFloat, false, false, false, false) //========================================================================== // @@ -1202,7 +1202,7 @@ void PFloat::SetOps() /* PString ****************************************************************/ -IMPLEMENT_CLASS(PString, false, false, false) +IMPLEMENT_CLASS(PString, false, false, false, false) //========================================================================== // @@ -1299,7 +1299,7 @@ void PString::DestroyValue(void *addr) const /* PName ******************************************************************/ -IMPLEMENT_CLASS(PName, false, false, false) +IMPLEMENT_CLASS(PName, false, false, false, false) //========================================================================== // @@ -1349,7 +1349,7 @@ bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PSound *****************************************************************/ -IMPLEMENT_CLASS(PSound, false, false, false) +IMPLEMENT_CLASS(PSound, false, false, false, false) //========================================================================== // @@ -1399,7 +1399,7 @@ bool PSound::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PColor *****************************************************************/ -IMPLEMENT_CLASS(PColor, false, false, false) +IMPLEMENT_CLASS(PColor, false, false, false, false) //========================================================================== // @@ -1416,7 +1416,7 @@ PColor::PColor() /* PStatePointer **********************************************************/ -IMPLEMENT_CLASS(PStatePointer, false, false, false) +IMPLEMENT_CLASS(PStatePointer, false, false, false, false) //========================================================================== // @@ -1460,7 +1460,7 @@ bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons /* PPointer ***************************************************************/ -IMPLEMENT_CLASS(PPointer, false, true, false) +IMPLEMENT_CLASS(PPointer, false, true, false, false) IMPLEMENT_POINTERS_START(PPointer) IMPLEMENT_POINTER(PointedType) @@ -1591,7 +1591,7 @@ PPointer *NewPointer(PType *type, bool isconst) /* PClassPointer **********************************************************/ -IMPLEMENT_CLASS(PClassPointer, false, true, false) +IMPLEMENT_CLASS(PClassPointer, false, true, false, false) IMPLEMENT_POINTERS_START(PClassPointer) IMPLEMENT_POINTER(ClassRestriction) @@ -1672,7 +1672,7 @@ PClassPointer *NewClassPointer(PClass *restrict) /* PEnum ******************************************************************/ -IMPLEMENT_CLASS(PEnum, false, true, false) +IMPLEMENT_CLASS(PEnum, false, true, false, false) IMPLEMENT_POINTERS_START(PEnum) IMPLEMENT_POINTER(ValueType) @@ -1725,7 +1725,7 @@ PEnum *NewEnum(FName name, PTypeBase *outer) /* PArray *****************************************************************/ -IMPLEMENT_CLASS(PArray, false, true, false) +IMPLEMENT_CLASS(PArray, false, true, false, false) IMPLEMENT_POINTERS_START(PArray) IMPLEMENT_POINTER(ElementType) @@ -1874,7 +1874,7 @@ PArray *NewArray(PType *type, unsigned int count) /* PVector ****************************************************************/ -IMPLEMENT_CLASS(PVector, false, false, false) +IMPLEMENT_CLASS(PVector, false, false, false, false) //========================================================================== // @@ -1924,7 +1924,7 @@ PVector *NewVector(unsigned int size) /* PDynArray **************************************************************/ -IMPLEMENT_CLASS(PDynArray, false, true, false) +IMPLEMENT_CLASS(PDynArray, false, true, false, false) IMPLEMENT_POINTERS_START(PDynArray) IMPLEMENT_POINTER(ElementType) @@ -2007,7 +2007,7 @@ PDynArray *NewDynArray(PType *type) /* PMap *******************************************************************/ -IMPLEMENT_CLASS(PMap, false, true, false) +IMPLEMENT_CLASS(PMap, false, true, false, false) IMPLEMENT_POINTERS_START(PMap) IMPLEMENT_POINTER(KeyType) @@ -2091,7 +2091,7 @@ PMap *NewMap(PType *keytype, PType *valuetype) /* PStruct ****************************************************************/ -IMPLEMENT_CLASS(PStruct, false, false, false) +IMPLEMENT_CLASS(PStruct, false, false, false, false) //========================================================================== // @@ -2312,7 +2312,7 @@ PStruct *NewStruct(FName name, PTypeBase *outer) /* PField *****************************************************************/ -IMPLEMENT_CLASS(PField, false, false, false) +IMPLEMENT_CLASS(PField, false, false, false, false) //========================================================================== // @@ -2357,7 +2357,7 @@ PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue /* PPrototype *************************************************************/ -IMPLEMENT_CLASS(PPrototype, false, false, false) +IMPLEMENT_CLASS(PPrototype, false, false, false, false) //========================================================================== // @@ -2443,7 +2443,7 @@ PPrototype *NewPrototype(const TArray &rettypes, const TArray /* PFunction **************************************************************/ -IMPLEMENT_CLASS(PFunction, false, false, false) +IMPLEMENT_CLASS(PFunction, false, false, false, false) //========================================================================== // @@ -2501,7 +2501,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra /* PClass *****************************************************************/ -IMPLEMENT_CLASS(PClass, false, true, false) +IMPLEMENT_CLASS(PClass, false, true, false, false) IMPLEMENT_POINTERS_START(PClass) IMPLEMENT_POINTER(ParentClass) @@ -3424,19 +3424,19 @@ CCMD(typetable) // Symbol tables ------------------------------------------------------------ -IMPLEMENT_CLASS(PTypeBase, true, false, false); -IMPLEMENT_CLASS(PSymbol, true, false, false); -IMPLEMENT_CLASS(PSymbolConst, false, false, false); -IMPLEMENT_CLASS(PSymbolConstNumeric, false, false, false); -IMPLEMENT_CLASS(PSymbolConstString, false, false, false); -IMPLEMENT_CLASS(PSymbolTreeNode, false, false, false) -IMPLEMENT_CLASS(PSymbolType, false, true, false) +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) +IMPLEMENT_CLASS(PSymbolVMFunction, false, true, false, false) IMPLEMENT_POINTERS_START(PSymbolVMFunction) IMPLEMENT_POINTER(Function) diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index e07f9eace4..700a407fd7 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -31,7 +31,7 @@ #include "serializer.h" #include "doomstat.h" -IMPLEMENT_CLASS(DSectorEffect, false, false, false) +IMPLEMENT_CLASS(DSectorEffect, false, false, false, false) DSectorEffect::DSectorEffect () : DThinker(STAT_SECTOREFFECT) @@ -71,7 +71,7 @@ void DSectorEffect::Serialize(FSerializer &arc) arc("sector", m_Sector); } -IMPLEMENT_CLASS(DMover, false, true, false) +IMPLEMENT_CLASS(DMover, false, true, false, false) IMPLEMENT_POINTERS_START(DMover) IMPLEMENT_POINTER(interpolation) @@ -108,7 +108,7 @@ void DMover::StopInterpolation(bool force) } } -IMPLEMENT_CLASS(DMovingFloor, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(DMovingCeiling, false, false, false, false) DMovingCeiling::DMovingCeiling () { diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 246b9ed2c1..9c87c46b45 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -47,7 +47,7 @@ extern cycle_t BotSupportCycles; extern cycle_t ActionCycles; extern int BotWTG; -IMPLEMENT_CLASS(DThinker, false, false, false) +IMPLEMENT_CLASS(DThinker, false, false, false, false) DThinker *NextToThink; @@ -538,7 +538,7 @@ public: } }; -IMPLEMENT_CLASS(DThinkerIterator, false, false, false); +IMPLEMENT_CLASS(DThinkerIterator, false, false, false, false); DEFINE_ACTION_FUNCTION(DThinkerIterator, Create) { PARAM_PROLOGUE; diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 737376ecbb..ddc1a4bd42 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -1785,7 +1785,7 @@ public: void Destroy() { Super::Destroy(); m_Sector->lightingdata=NULL; } }; -IMPLEMENT_CLASS(DLightLevel, false, false, false) +IMPLEMENT_CLASS(DLightLevel, false, false, false, false) void DLightLevel::Serialize(FSerializer &arc) { diff --git a/src/fragglescript/t_prepro.cpp b/src/fragglescript/t_prepro.cpp index 0a3ec6a0de..2129df54f7 100644 --- a/src/fragglescript/t_prepro.cpp +++ b/src/fragglescript/t_prepro.cpp @@ -71,7 +71,7 @@ // //========================================================================== -IMPLEMENT_CLASS(DFsSection, false, true, false) +IMPLEMENT_CLASS(DFsSection, false, true, false, false) IMPLEMENT_POINTERS_START(DFsSection) IMPLEMENT_POINTER(next) diff --git a/src/fragglescript/t_script.cpp b/src/fragglescript/t_script.cpp index 326cad621f..a401226236 100644 --- a/src/fragglescript/t_script.cpp +++ b/src/fragglescript/t_script.cpp @@ -99,7 +99,7 @@ AActor *trigger_obj; // //========================================================================== -IMPLEMENT_CLASS(DFsScript, false, true, false) +IMPLEMENT_CLASS(DFsScript, false, true, false, false) IMPLEMENT_POINTERS_START(DFsScript) IMPLEMENT_POINTER(parent) @@ -269,7 +269,7 @@ void DFsScript::ParseScript(char *position) // //========================================================================== -IMPLEMENT_CLASS(DRunningScript, false, true, false) +IMPLEMENT_CLASS(DRunningScript, false, true, false, false) IMPLEMENT_POINTERS_START(DRunningScript) IMPLEMENT_POINTER(prev) @@ -380,7 +380,7 @@ void DRunningScript::Serialize(FSerializer &arc) // //========================================================================== -IMPLEMENT_CLASS(DFraggleThinker, false, true, false) +IMPLEMENT_CLASS(DFraggleThinker, false, true, false, false) IMPLEMENT_POINTERS_START(DFraggleThinker) IMPLEMENT_POINTER(RunningScripts) diff --git a/src/fragglescript/t_variable.cpp b/src/fragglescript/t_variable.cpp index cebf0160c3..23d24b78a7 100644 --- a/src/fragglescript/t_variable.cpp +++ b/src/fragglescript/t_variable.cpp @@ -179,7 +179,7 @@ AActor* actorvalue(const svalue_t &svalue) // //========================================================================== -IMPLEMENT_CLASS(DFsVariable, false, true, false) +IMPLEMENT_CLASS(DFsVariable, false, true, false, false) IMPLEMENT_POINTERS_START(DFsVariable) IMPLEMENT_POINTER(next) diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 1342713955..da2c7f7910 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -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, false, false, false) +IMPLEMENT_CLASS(AScriptedMarine, false, false, false, false) void AScriptedMarine::Serialize(FSerializer &arc) { diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp index 762d105945..fa26f73158 100644 --- a/src/g_heretic/a_chicken.cpp +++ b/src/g_heretic/a_chicken.cpp @@ -29,7 +29,7 @@ public: void MorphPlayerThink (); }; -IMPLEMENT_CLASS(AChickenPlayer, false, false, false) +IMPLEMENT_CLASS(AChickenPlayer, false, false, false, false) void AChickenPlayer::MorphPlayerThink () { diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index 9078d09405..169d0e7714 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -17,7 +17,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiTomeOfPower, false, false, false) +IMPLEMENT_CLASS(AArtiTomeOfPower, false, false, false, false) bool AArtiTomeOfPower::Use (bool pickup) { @@ -63,7 +63,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiTimeBomb, false, false, false) +IMPLEMENT_CLASS(AArtiTimeBomb, false, false, false, false) bool AArtiTimeBomb::Use (bool pickup) { diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index b32056374f..38991b87db 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -358,7 +358,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AMaceFX4, false, false, false) +IMPLEMENT_CLASS(AMaceFX4, false, false, false, false) int AMaceFX4::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -726,7 +726,7 @@ void ABlasterFX1::Effect () } } -IMPLEMENT_CLASS(ABlasterFX1, false, false, false) +IMPLEMENT_CLASS(ABlasterFX1, false, false, false, false) // Ripper ------------------------------------------------------------------- @@ -738,7 +738,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(ARipper, false, false, false) +IMPLEMENT_CLASS(ARipper, false, false, false, false) int ARipper::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -828,7 +828,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AHornRodFX2, false, false, false) +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, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(ARainTracker, false, false, false, false) void ARainTracker::Serialize(FSerializer &arc) { @@ -1158,8 +1158,8 @@ public: void EndPowerup (); }; -IMPLEMENT_CLASS(APhoenixRod, false, false, false) -IMPLEMENT_CLASS(APhoenixRodPowered, false, false, false) +IMPLEMENT_CLASS(APhoenixRod, false, false, false, false) +IMPLEMENT_CLASS(APhoenixRodPowered, false, false, false, false) void APhoenixRodPowered::EndPowerup () { @@ -1177,7 +1177,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(APhoenixFX1, false, false, false) +IMPLEMENT_CLASS(APhoenixFX1, false, false, false, false) int APhoenixFX1::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -1198,7 +1198,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(APhoenixFX2, false, false, false) +IMPLEMENT_CLASS(APhoenixFX2, false, false, false, false) int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) { diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index 3870219d9b..8068c251bc 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -22,7 +22,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AWhirlwind, false, false, false) +IMPLEMENT_CLASS(AWhirlwind, false, false, false, false) int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype) { diff --git a/src/g_hexen/a_boostarmor.cpp b/src/g_hexen/a_boostarmor.cpp index 77fbf3dbd4..1323af8a53 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, false, false, false) +IMPLEMENT_CLASS(AArtiBoostArmor, false, false, false, false) bool AArtiBoostArmor::Use (bool pickup) { diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp index c0c6cb3ede..f0e9c16b24 100644 --- a/src/g_hexen/a_clericflame.cpp +++ b/src/g_hexen/a_clericflame.cpp @@ -33,7 +33,7 @@ public: void Effect (); }; -IMPLEMENT_CLASS(ACFlameMissile, false, false, false) +IMPLEMENT_CLASS(ACFlameMissile, false, false, false, false) void ACFlameMissile::BeginPlay () { diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index 931c75e893..d09c3f6aa7 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -58,11 +58,11 @@ public: BYTE CHolyCount; }; -IMPLEMENT_CLASS(ACWeapWraithverge, false, false, false) +IMPLEMENT_CLASS(ACWeapWraithverge, false, false, false, false) // Holy Spirit -------------------------------------------------------------- -IMPLEMENT_CLASS(AHolySpirit, false, false, false) +IMPLEMENT_CLASS(AHolySpirit, false, false, false, false) bool AHolySpirit::Slam(AActor *thing) { diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index 940a878844..a4050a1efb 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -25,7 +25,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(ACStaffMissile, false, false, false) +IMPLEMENT_CLASS(ACStaffMissile, false, false, false, false) int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index 89e3170120..4260f4eb41 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -38,7 +38,7 @@ public: FState *GetAtkState (bool hold); }; -IMPLEMENT_CLASS(AFWeapAxe, false, false, false) +IMPLEMENT_CLASS(AFWeapAxe, false, false, false, false) FState *AFWeapAxe::GetUpState () { diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index 7e18f9c283..ff4348520a 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -11,9 +11,9 @@ #include "vm.h" */ -IMPLEMENT_CLASS(AFighterWeapon, false, false, false) -IMPLEMENT_CLASS(AClericWeapon, false, false, false) -IMPLEMENT_CLASS(AMageWeapon, false, false, false) +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"); diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index c000a9fafc..c900794ed0 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -59,7 +59,7 @@ public: int DoSpecialDamage(AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AFSwordMissile, false, false, false) +IMPLEMENT_CLASS(AFSwordMissile, false, false, false, false) int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype) { diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index 3da16db9ca..3358428874 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -24,7 +24,7 @@ DECLARE_ACTION(A_CheckThrowBomb) // Poison Bag Artifact (Flechette) ------------------------------------------ -IMPLEMENT_CLASS(AArtiPoisonBag, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBag1, false, false, false, false) bool AArtiPoisonBag1::Use (bool pickup) { @@ -60,7 +60,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBag2, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBag2, false, false, false, false) bool AArtiPoisonBag2::Use (bool pickup) { @@ -85,7 +85,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBag3, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBag3, false, false, false, false) bool AArtiPoisonBag3::Use (bool pickup) { @@ -136,7 +136,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBagGiver, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBagGiver, false, false, false, false) bool AArtiPoisonBagGiver::Use (bool pickup) { @@ -167,7 +167,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBagShooter, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBagShooter, false, false, false, false) bool AArtiPoisonBagShooter::Use (bool pickup) { @@ -296,7 +296,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(APoisonCloud, false, false, false) +IMPLEMENT_CLASS(APoisonCloud, false, false, false, false) void APoisonCloud::BeginPlay () { diff --git a/src/g_hexen/a_healingradius.cpp b/src/g_hexen/a_healingradius.cpp index 3d4eef0aea..25efbc3ca4 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, false, false, false) +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 964fdd44f2..32ad9ab696 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -72,7 +72,7 @@ public: void Die (AActor *source, AActor *inflictor, int dmgflags); }; -IMPLEMENT_CLASS(AHeresiarch, false, false, false) +IMPLEMENT_CLASS(AHeresiarch, false, false, false, false) void AHeresiarch::Serialize(FSerializer &arc) { @@ -122,7 +122,7 @@ public: } }; -IMPLEMENT_CLASS(ASorcBall, false, false, false) +IMPLEMENT_CLASS(ASorcBall, false, false, false, false) // First ball (purple) - fires projectiles ---------------------------------- @@ -140,7 +140,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS(ASorcBall1, false, false, false) +IMPLEMENT_CLASS(ASorcBall1, false, false, false, false) // Second ball (blue) - generates the shield -------------------------------- @@ -156,7 +156,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS(ASorcBall2, false, false, false) +IMPLEMENT_CLASS(ASorcBall2, false, false, false, false) // Third ball (green) - summons Bishops ------------------------------------- @@ -172,7 +172,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS(ASorcBall3, false, false, false) +IMPLEMENT_CLASS(ASorcBall3, false, false, false, false) // Sorcerer spell 1 (The burning, bouncing head thing) ---------------------- diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index cad6f617d7..6d441ba57c 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -39,7 +39,7 @@ public: void HitFloor (); }; -IMPLEMENT_CLASS(APottery1, false, false, false) +IMPLEMENT_CLASS(APottery1, false, false, false, false) void APottery1::HitFloor () { @@ -136,7 +136,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS(AZCorpseLynchedNoHeart, false, false, false) +IMPLEMENT_CLASS(AZCorpseLynchedNoHeart, false, false, false, false) void AZCorpseLynchedNoHeart::PostBeginPlay () { @@ -344,7 +344,7 @@ public: void Activate (AActor *activator); }; -IMPLEMENT_CLASS(AZBell, false, false, false) +IMPLEMENT_CLASS(AZBell, false, false, false, false) void AZBell::Activate (AActor *activator) { diff --git a/src/g_hexen/a_magecone.cpp b/src/g_hexen/a_magecone.cpp index b2dd969b71..f2b97fcd9e 100644 --- a/src/g_hexen/a_magecone.cpp +++ b/src/g_hexen/a_magecone.cpp @@ -32,7 +32,7 @@ public: int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AFrostMissile, false, false, false) +IMPLEMENT_CLASS(AFrostMissile, false, false, false, false) int AFrostMissile::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 039755ff50..7e11b64ed4 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -34,7 +34,7 @@ public: int SpecialMissileHit (AActor *victim); }; -IMPLEMENT_CLASS(ALightning, false, false, false) +IMPLEMENT_CLASS(ALightning, false, false, false, false) int ALightning::SpecialMissileHit (AActor *thing) { @@ -87,7 +87,7 @@ public: int SpecialMissileHit (AActor *thing); }; -IMPLEMENT_CLASS(ALightningZap, false, false, false) +IMPLEMENT_CLASS(ALightningZap, false, false, false, false) int ALightningZap::SpecialMissileHit (AActor *thing) { diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index 2660117c39..acef2e5cdc 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -56,7 +56,7 @@ public: BYTE MStaffCount; }; -IMPLEMENT_CLASS(AMWeapBloodscourge, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(AMageStaffFX2, false, false, false, false) int AMageStaffFX2::SpecialMissileHit (AActor *victim) { diff --git a/src/g_hexen/a_pig.cpp b/src/g_hexen/a_pig.cpp index c12a9f50ac..a0a0cc844b 100644 --- a/src/g_hexen/a_pig.cpp +++ b/src/g_hexen/a_pig.cpp @@ -27,7 +27,7 @@ public: void MorphPlayerThink (); }; -IMPLEMENT_CLASS(APigPlayer, false, false, false) +IMPLEMENT_CLASS(APigPlayer, false, false, false, false) void APigPlayer::MorphPlayerThink () { diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp index 1559467db1..9b2cb5d6e2 100644 --- a/src/g_hexen/a_spike.cpp +++ b/src/g_hexen/a_spike.cpp @@ -31,7 +31,7 @@ public: TObjPtr DirtClump; }; -IMPLEMENT_CLASS(AThrustFloor, false, true, false) +IMPLEMENT_CLASS(AThrustFloor, false, true, false, false) IMPLEMENT_POINTERS_START(AThrustFloor) IMPLEMENT_POINTER(DirtClump) diff --git a/src/g_hexen/a_summon.cpp b/src/g_hexen/a_summon.cpp index e98c523520..7c0746c915 100644 --- a/src/g_hexen/a_summon.cpp +++ b/src/g_hexen/a_summon.cpp @@ -21,7 +21,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiDarkServant, false, false, false) +IMPLEMENT_CLASS(AArtiDarkServant, false, false, false, false) //============================================================================ // diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp index 68ba73bc4b..4eeba53f99 100644 --- a/src/g_hexen/a_teleportother.cpp +++ b/src/g_hexen/a_teleportother.cpp @@ -34,7 +34,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiTeleportOther, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(ATelOtherFX1, false, false, false, false) static void TeloSpawn (AActor *source, const char *type) { diff --git a/src/g_level.cpp b/src/g_level.cpp index e377d70f63..9a955a03ed 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -903,7 +903,7 @@ public: void Tick (); }; -IMPLEMENT_CLASS(DAutosaver, false, false, false) +IMPLEMENT_CLASS(DAutosaver, false, false, false, false) void DAutosaver::Tick () { diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp index 0910e5f230..35387df450 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, false, false, false) +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 c906234c85..36946ba871 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -31,7 +31,7 @@ void P_MinotaurSlam (AActor *source, AActor *target); DECLARE_ACTION(A_MinotaurLook) -IMPLEMENT_CLASS(AMinotaur, false, false, false) +IMPLEMENT_CLASS(AMinotaur, false, false, false, false) void AMinotaur::Tick () { @@ -72,7 +72,7 @@ int AMinotaur::DoSpecialDamage (AActor *target, int damage, FName damagetype) // Minotaur Friend ---------------------------------------------------------- -IMPLEMENT_CLASS(AMinotaurFriend, false, false, false) +IMPLEMENT_CLASS(AMinotaurFriend, false, false, false, false) void AMinotaurFriend::BeginPlay () { diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index 20ab4aad08..61be39a0e0 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -29,7 +29,7 @@ public: void Deactivate (AActor *activator); }; -IMPLEMENT_CLASS(ASwitchableDecoration, false, false, false) +IMPLEMENT_CLASS(ASwitchableDecoration, false, false, false, false) void ASwitchableDecoration::Activate (AActor *activator) { @@ -50,7 +50,7 @@ public: void Deactivate (AActor *activator) {} }; -IMPLEMENT_CLASS(ASwitchingDecoration, false, false, false) +IMPLEMENT_CLASS(ASwitchingDecoration, false, false, false, false) //---------------------------------------------------------------------------- // @@ -304,7 +304,7 @@ private: DCorpsePointer () {} }; -IMPLEMENT_CLASS(DCorpsePointer, false, true, false) +IMPLEMENT_CLASS(DCorpsePointer, false, true, false, false) IMPLEMENT_POINTERS_START(DCorpsePointer) IMPLEMENT_POINTER(Corpse) diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index b1935bd1d4..636441a9db 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -8,11 +8,11 @@ #include "d_player.h" #include "serializer.h" -IMPLEMENT_CLASS(AArmor, false, false, false) -IMPLEMENT_CLASS(ABasicArmor, false, false, false) -IMPLEMENT_CLASS(ABasicArmorPickup, false, false, false) -IMPLEMENT_CLASS(ABasicArmorBonus, false, false, false) -IMPLEMENT_CLASS(AHexenArmor, false, false, false) +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 97771021de..7cf05613ab 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, false, false, false) +IMPLEMENT_CLASS(APowerup, false, false, false, false) // Powerup-Giver ------------------------------------------------------------- -IMPLEMENT_CLASS(PClassPowerupGiver, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(APowerInvulnerable, false, false, false, false) //=========================================================================== // @@ -513,7 +513,7 @@ int APowerInvulnerable::AlterWeaponSprite (visstyle_t *vis) // Strength (aka Berserk) Powerup -------------------------------------------- -IMPLEMENT_CLASS(APowerStrength, false, false, false) +IMPLEMENT_CLASS(APowerStrength, false, false, false, false) //=========================================================================== // @@ -578,7 +578,7 @@ PalEntry APowerStrength::GetBlend () // Invisibility Powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerInvisibility, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(APowerIronFeet, false, false, false, false) //=========================================================================== // @@ -820,7 +820,7 @@ void APowerIronFeet::DoEffect () // Strife Environment Suit Powerup ------------------------------------------- -IMPLEMENT_CLASS(APowerMask, false, false, false) +IMPLEMENT_CLASS(APowerMask, false, false, false, false) //=========================================================================== // @@ -857,7 +857,7 @@ void APowerMask::DoEffect () // Light-Amp Powerup --------------------------------------------------------- -IMPLEMENT_CLASS(APowerLightAmp, false, false, false) +IMPLEMENT_CLASS(APowerLightAmp, false, false, false, false) //=========================================================================== // @@ -899,7 +899,7 @@ void APowerLightAmp::EndEffect () // Torch Powerup ------------------------------------------------------------- -IMPLEMENT_CLASS(APowerTorch, false, false, false) +IMPLEMENT_CLASS(APowerTorch, false, false, false, false) //=========================================================================== // @@ -962,7 +962,7 @@ void APowerTorch::DoEffect () // Flight (aka Wings of Wrath) powerup --------------------------------------- -IMPLEMENT_CLASS(APowerFlight, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(APowerWeaponLevel2, false, false, false, false) //=========================================================================== // @@ -1193,7 +1193,7 @@ public: void Tick (); }; -IMPLEMENT_CLASS(APlayerSpeedTrail, false, false, false) +IMPLEMENT_CLASS(APlayerSpeedTrail, false, false, false, false) //=========================================================================== // @@ -1216,7 +1216,7 @@ void APlayerSpeedTrail::Tick () // Speed Powerup ------------------------------------------------------------- -IMPLEMENT_CLASS(APowerSpeed, false, false, false) +IMPLEMENT_CLASS(APowerSpeed, false, false, false, false) //=========================================================================== // @@ -1303,11 +1303,11 @@ void APowerSpeed::DoEffect () // Minotaur (aka Dark Servant) powerup --------------------------------------- -IMPLEMENT_CLASS(APowerMinotaur, false, false, false) +IMPLEMENT_CLASS(APowerMinotaur, false, false, false, false) // Targeter powerup --------------------------------------------------------- -IMPLEMENT_CLASS(APowerTargeter, false, false, false) +IMPLEMENT_CLASS(APowerTargeter, false, false, false, false) void APowerTargeter::Travelled () { @@ -1422,7 +1422,7 @@ void APowerTargeter::PositionAccuracy () // Frightener Powerup -------------------------------- -IMPLEMENT_CLASS(APowerFrightener, false, false, false) +IMPLEMENT_CLASS(APowerFrightener, false, false, false, false) //=========================================================================== // @@ -1458,7 +1458,7 @@ void APowerFrightener::EndEffect () // Buddha Powerup -------------------------------- -IMPLEMENT_CLASS(APowerBuddha, false, false, false) +IMPLEMENT_CLASS(APowerBuddha, false, false, false, false) //=========================================================================== // @@ -1494,11 +1494,11 @@ void APowerBuddha::EndEffect () // Scanner powerup ---------------------------------------------------------- -IMPLEMENT_CLASS(APowerScanner, false, false, false) +IMPLEMENT_CLASS(APowerScanner, false, false, false, false) // Time freezer powerup ----------------------------------------------------- -IMPLEMENT_CLASS( APowerTimeFreezer, false, false, false) +IMPLEMENT_CLASS( APowerTimeFreezer, false, false, false, false) //=========================================================================== // @@ -1625,7 +1625,7 @@ void APowerTimeFreezer::EndEffect() // Damage powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerDamage, false, false, false) +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, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(APowerDrain, false, false, false, false) //=========================================================================== // @@ -1800,7 +1800,7 @@ void APowerDrain::EndEffect( ) // Regeneration rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerRegeneration, false, false, false) +IMPLEMENT_CLASS(APowerRegeneration, false, false, false, false) //=========================================================================== // @@ -1822,7 +1822,7 @@ void APowerRegeneration::DoEffect() // High jump rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerHighJump, false, false, false) +IMPLEMENT_CLASS(APowerHighJump, false, false, false, false) //=========================================================================== // @@ -1860,7 +1860,7 @@ void APowerHighJump::EndEffect( ) // Double firing speed rune --------------------------------------------- -IMPLEMENT_CLASS(APowerDoubleFiringSpeed, false, false, false) +IMPLEMENT_CLASS(APowerDoubleFiringSpeed, false, false, false, false) //=========================================================================== // @@ -1898,7 +1898,7 @@ void APowerDoubleFiringSpeed::EndEffect( ) // Morph powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerMorph, false, false, false) +IMPLEMENT_CLASS(APowerMorph, false, false, false, false) //=========================================================================== // @@ -2002,7 +2002,7 @@ void APowerMorph::EndEffect( ) // Infinite Ammo Powerup ----------------------------------------------------- -IMPLEMENT_CLASS(APowerInfiniteAmmo, false, false, false) +IMPLEMENT_CLASS(APowerInfiniteAmmo, false, false, false, false) //=========================================================================== // diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 6409a07099..ab0df27e14 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -41,7 +41,7 @@ public: void Destroy(); }; -IMPLEMENT_CLASS(ACustomBridge, false, false, false) +IMPLEMENT_CLASS(ACustomBridge, false, false, false, false) void ACustomBridge::BeginPlay () { @@ -156,7 +156,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(AInvisibleBridge, false, false, false) +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 a29b4b81da..ae34c3cbc3 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, false, false, false) +IMPLEMENT_CLASS(ASecurityCamera, false, false, false, false) void ASecurityCamera::Serialize(FSerializer &arc) { @@ -124,7 +124,7 @@ protected: DAngle MaxPitchChange; }; -IMPLEMENT_CLASS(AAimingCamera, false, false, false) +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 9624ff5d66..3be3c22409 100644 --- a/src/g_shared/a_debris.cpp +++ b/src/g_shared/a_debris.cpp @@ -25,7 +25,7 @@ public: } }; -IMPLEMENT_CLASS(AGlassShard, false, false, false) +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 5347664f53..06563f9954 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -58,14 +58,14 @@ static int ImpactCount; CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE) -IMPLEMENT_CLASS(DBaseDecal, false, true, false) +IMPLEMENT_CLASS(DBaseDecal, false, true, false, false) IMPLEMENT_POINTERS_START(DBaseDecal) IMPLEMENT_POINTER(WallPrev) IMPLEMENT_POINTER(WallNext) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(DImpactDecal, false, false, false) +IMPLEMENT_CLASS(DImpactDecal, false, false, false, false) DBaseDecal::DBaseDecal () : DThinker(STAT_DECAL), @@ -746,7 +746,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(ADecal, false, false, false) +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 a0774a6f6f..ffca8a8fad 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -7,7 +7,7 @@ #include "b_bot.h" #include "p_checkposition.h" -IMPLEMENT_CLASS(AFastProjectile, false, false, false) +IMPLEMENT_CLASS(AFastProjectile, false, false, false, false) //---------------------------------------------------------------------------- diff --git a/src/g_shared/a_flashfader.cpp b/src/g_shared/a_flashfader.cpp index 8406ec2996..8602f7a864 100644 --- a/src/g_shared/a_flashfader.cpp +++ b/src/g_shared/a_flashfader.cpp @@ -3,7 +3,7 @@ #include "d_player.h" #include "serializer.h" -IMPLEMENT_CLASS(DFlashFader, false, true, false) +IMPLEMENT_CLASS(DFlashFader, false, true, false, false) IMPLEMENT_POINTERS_START(DFlashFader) IMPLEMENT_POINTER(ForWho) diff --git a/src/g_shared/a_fountain.cpp b/src/g_shared/a_fountain.cpp index bd415e729b..e89745fc79 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, false, false, false) +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 361ccb1f26..7d25bdb31d 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, false, false, false) +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 07685be31b..69fbe48afb 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, false, false, false) +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 0fe3683da4..f00560fc80 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, false, false, false) +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 3c4d99b30b..d874042c5f 100644 --- a/src/g_shared/a_mapmarker.cpp +++ b/src/g_shared/a_mapmarker.cpp @@ -51,7 +51,7 @@ // //-------------------------------------------------------------------------- -IMPLEMENT_CLASS(AMapMarker, false, false, false) +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 9ce33e12da..506f18b2ff 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, false, false, false) +IMPLEMENT_CLASS(AMorphProjectile, false, false, false, false) int AMorphProjectile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -650,7 +650,7 @@ void AMorphProjectile::Serialize(FSerializer &arc) // Morphed Monster (you must subclass this to do something useful) --------- -IMPLEMENT_CLASS(AMorphedMonster, false, true, false) +IMPLEMENT_CLASS(AMorphedMonster, false, true, false, false) IMPLEMENT_POINTERS_START(AMorphedMonster) IMPLEMENT_POINTER(UnmorphedMe) diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index 89a1193cc4..030f5d3683 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -66,7 +66,7 @@ public: TObjPtr Next; }; -IMPLEMENT_CLASS(AInterpolationPoint, false, true, false) +IMPLEMENT_CLASS(AInterpolationPoint, false, true, false, false) IMPLEMENT_POINTERS_START(AInterpolationPoint) IMPLEMENT_POINTER(Next) @@ -135,7 +135,7 @@ public: void Tick () {} // Does absolutely nothing itself }; -IMPLEMENT_CLASS(AInterpolationSpecial, false, false, false) +IMPLEMENT_CLASS(AInterpolationSpecial, false, false, false, false) /* == PathFollower: something that follows a camera path @@ -178,7 +178,7 @@ protected: int HoldTime; }; -IMPLEMENT_CLASS(APathFollower, false, true, false) +IMPLEMENT_CLASS(APathFollower, false, true, false, false) IMPLEMENT_POINTERS_START(APathFollower) IMPLEMENT_POINTER(PrevNode) @@ -480,7 +480,7 @@ protected: bool Interpolate (); }; -IMPLEMENT_CLASS(AActorMover, false, false, false) +IMPLEMENT_CLASS(AActorMover, false, false, false, false) void AActorMover::BeginPlay() { @@ -596,7 +596,7 @@ protected: TObjPtr Activator; }; -IMPLEMENT_CLASS(AMovingCamera, false, true, false) +IMPLEMENT_CLASS(AMovingCamera, false, true, false, false) IMPLEMENT_POINTERS_START(AMovingCamera) IMPLEMENT_POINTER(Activator) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 2b7fcb79a2..223a2f75f8 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -24,7 +24,7 @@ static FRandom pr_restore ("RestorePos"); -IMPLEMENT_CLASS(PClassInventory, false, false, false) +IMPLEMENT_CLASS(PClassInventory, false, false, false, false) PClassInventory::PClassInventory() { @@ -71,7 +71,7 @@ void PClassInventory::Finalize(FStateDefinitions &statedef) ((AActor*)Defaults)->flags |= MF_SPECIAL; } -IMPLEMENT_CLASS(PClassAmmo, false, false, false) +IMPLEMENT_CLASS(PClassAmmo, false, false, false, false) PClassAmmo::PClassAmmo() { @@ -87,7 +87,7 @@ void PClassAmmo::DeriveData(PClass *newclass) newc->DropAmount = DropAmount; } -IMPLEMENT_CLASS(AAmmo, false, false, false) +IMPLEMENT_CLASS(AAmmo, false, false, false, false) //=========================================================================== // @@ -470,7 +470,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) int AInventory::StaticLastMessageTic; const char *AInventory::StaticLastMessage; -IMPLEMENT_CLASS(AInventory, false, true, false) +IMPLEMENT_CLASS(AInventory, false, true, false, false) IMPLEMENT_POINTERS_START(AInventory) IMPLEMENT_POINTER(Owner) @@ -1354,7 +1354,7 @@ bool AInventory::DrawPowerup (int x, int y) /* AArtifact implementation */ /***************************************************************************/ -IMPLEMENT_CLASS(APowerupGiver, false, false, false) +IMPLEMENT_CLASS(APowerupGiver, false, false, false, false) //=========================================================================== // @@ -1644,8 +1644,8 @@ void AInventory::DetachFromOwner () { } -IMPLEMENT_CLASS(AStateProvider, false, false, false) -IMPLEMENT_CLASS(ACustomInventory, false, false, false) +IMPLEMENT_CLASS(AStateProvider, false, false, false, false) +IMPLEMENT_CLASS(ACustomInventory, false, false, false, false) //=========================================================================== // @@ -1690,7 +1690,7 @@ bool ACustomInventory::TryPickup (AActor *&toucher) return useok; } -IMPLEMENT_CLASS(PClassHealth, false, false, false) +IMPLEMENT_CLASS(PClassHealth, false, false, false, false) //=========================================================================== // @@ -1719,7 +1719,7 @@ void PClassHealth::DeriveData(PClass *newclass) newc->LowHealthMessage = LowHealthMessage; } -IMPLEMENT_CLASS(AHealth, false, false, false) +IMPLEMENT_CLASS(AHealth, false, false, false, false) //=========================================================================== // @@ -1762,7 +1762,7 @@ bool AHealth::TryPickup (AActor *&other) return false; } -IMPLEMENT_CLASS(AHealthPickup, false, false, false) +IMPLEMENT_CLASS(AHealthPickup, false, false, false, false) //=========================================================================== // @@ -2015,8 +2015,8 @@ void ABackpackItem::DetachFromOwner () // //=========================================================================== -IMPLEMENT_CLASS(ABackpackItem, false, false, false) -IMPLEMENT_CLASS(AMapRevealer, false, false, false) +IMPLEMENT_CLASS(ABackpackItem, false, false, false, false) +IMPLEMENT_CLASS(AMapRevealer, false, false, false, false) //=========================================================================== // @@ -2041,7 +2041,7 @@ bool AMapRevealer::TryPickup (AActor *&toucher) // //=========================================================================== -IMPLEMENT_CLASS(AScoreItem, false, false, false) +IMPLEMENT_CLASS(AScoreItem, false, false, false, false) //=========================================================================== // diff --git a/src/g_shared/a_puzzleitems.cpp b/src/g_shared/a_puzzleitems.cpp index ba3f90dc80..d243dc73cb 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, false, false, false) +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, false, false, false) +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 d2a2e5e5b0..80a53ee080 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -14,7 +14,7 @@ static FRandom pr_quake ("Quake"); -IMPLEMENT_CLASS(DEarthquake, false, true, false) +IMPLEMENT_CLASS(DEarthquake, false, true, false, false) IMPLEMENT_POINTERS_START(DEarthquake) IMPLEMENT_POINTER(m_Spot) diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index ca85a13490..2b2c82956c 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -231,4 +231,4 @@ class ARandomSpawner : public AActor }; -IMPLEMENT_CLASS(ARandomSpawner, false, false, false) +IMPLEMENT_CLASS(ARandomSpawner, false, false, false, false) diff --git a/src/g_shared/a_secrettrigger.cpp b/src/g_shared/a_secrettrigger.cpp index 7128565715..372cef07d8 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, false, false, false) +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 88e504aa95..61a69b1b39 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, false, false, false) +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, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(ASecActExit, false, false, false, false) bool ASecActExit::DoTriggerAction (AActor *triggerer, int activationType) @@ -181,7 +181,7 @@ 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, false, false, false) +IMPLEMENT_CLASS(ASecActHitFloor, false, false, false, false) bool ASecActHitFloor::DoTriggerAction (AActor *triggerer, int activationType) @@ -199,7 +199,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActHitCeil, false, false, false) +IMPLEMENT_CLASS(ASecActHitCeil, false, false, false, false) bool ASecActHitCeil::DoTriggerAction (AActor *triggerer, int activationType) @@ -218,7 +218,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActUse, false, false, false) +IMPLEMENT_CLASS(ASecActUse, false, false, false, false) bool ASecActUse::DoTriggerAction (AActor *triggerer, int activationType) @@ -237,7 +237,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActUseWall, false, false, false) +IMPLEMENT_CLASS(ASecActUseWall, false, false, false, false) bool ASecActUseWall::DoTriggerAction (AActor *triggerer, int activationType) @@ -255,7 +255,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEyesDive, false, false, false) +IMPLEMENT_CLASS(ASecActEyesDive, false, false, false, false) bool ASecActEyesDive::DoTriggerAction (AActor *triggerer, int activationType) @@ -273,7 +273,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEyesSurface, false, false, false) +IMPLEMENT_CLASS(ASecActEyesSurface, false, false, false, false) bool ASecActEyesSurface::DoTriggerAction (AActor *triggerer, int activationType) @@ -291,7 +291,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEyesBelowC, false, false, false) +IMPLEMENT_CLASS(ASecActEyesBelowC, false, false, false, false) bool ASecActEyesBelowC::DoTriggerAction (AActor *triggerer, int activationType) @@ -309,7 +309,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEyesAboveC, false, false, false) +IMPLEMENT_CLASS(ASecActEyesAboveC, false, false, false, false) bool ASecActEyesAboveC::DoTriggerAction (AActor *triggerer, int activationType) @@ -327,7 +327,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActHitFakeFloor, false, false, false) +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 579c577065..585b9fcf61 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, false, false, false) +IMPLEMENT_CLASS(AColorSetter, false, false, false, false) class AFadeSetter : public AActor { @@ -30,4 +30,4 @@ class AFadeSetter : public AActor }; -IMPLEMENT_CLASS(AFadeSetter, false, false, false) +IMPLEMENT_CLASS(AFadeSetter, false, false, false, false) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index f58779387b..148a452e0c 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, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(ASkyCamCompat, false, false, false, false) void ASkyCamCompat::BeginPlay() { @@ -98,7 +98,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS(ASkyPicker, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(AStackPoint, false, false, false, false) void AStackPoint::BeginPlay () { @@ -160,7 +160,7 @@ public: void Destroy (); }; -IMPLEMENT_CLASS(ASectorSilencer, false, false, false) +IMPLEMENT_CLASS(ASectorSilencer, false, false, false, false) void ASectorSilencer::BeginPlay () { @@ -184,7 +184,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(ASectorFlagSetter, false, false, false) +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 6d381dbe58..8e5cb133b5 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, false, false, false) +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 01453fc9c2..25380a4c73 100644 --- a/src/g_shared/a_soundsequence.cpp +++ b/src/g_shared/a_soundsequence.cpp @@ -80,7 +80,7 @@ public: TObjPtr Sequence; }; -IMPLEMENT_CLASS(ASoundSequenceSlot, false, true, false) +IMPLEMENT_CLASS(ASoundSequenceSlot, false, true, false, false) IMPLEMENT_POINTERS_START(ASoundSequenceSlot) IMPLEMENT_POINTER(Sequence) @@ -111,7 +111,7 @@ public: void MarkPrecacheSounds () const; }; -IMPLEMENT_CLASS(ASoundSequence, false, false, false) +IMPLEMENT_CLASS(ASoundSequence, false, false, false, false) //========================================================================== // diff --git a/src/g_shared/a_spark.cpp b/src/g_shared/a_spark.cpp index ce61480682..654ad710b1 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, false, false, false) +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 1011fcb92a..86d0b5e8a3 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -45,8 +45,8 @@ static FRandom pr_spot ("SpecialSpot"); static FRandom pr_spawnmace ("SpawnMace"); -IMPLEMENT_CLASS(DSpotState, false, false, false) -IMPLEMENT_CLASS(ASpecialSpot, false, false, false) +IMPLEMENT_CLASS(DSpotState, false, false, false, false) +IMPLEMENT_CLASS(ASpecialSpot, false, false, false, false) TObjPtr DSpotState::SpotState; //---------------------------------------------------------------------------- diff --git a/src/g_shared/a_waterzone.cpp b/src/g_shared/a_waterzone.cpp index 65cdf96f6d..556d08d7a6 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, false, false, false) +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 68c631d9bd..7aa9591e9b 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, false, false, false) -IMPLEMENT_CLASS(AWeaponHolder, false, false, false) +IMPLEMENT_CLASS(PClassWeaponPiece, false, false, false, false) +IMPLEMENT_CLASS(AWeaponHolder, false, false, false, false) void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) { @@ -24,7 +24,7 @@ void AWeaponHolder::Serialize(FSerializer &arc) ("pieceweapon", PieceWeapon); } -IMPLEMENT_CLASS(AWeaponPiece, false, true, false) +IMPLEMENT_CLASS(AWeaponPiece, false, true, false, false) IMPLEMENT_POINTERS_START(AWeaponPiece) IMPLEMENT_POINTER(FullWeapon) diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index adaf4c9e36..9063c6c2c7 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -21,7 +21,7 @@ #define BONUSADD 6 -IMPLEMENT_CLASS(AWeapon, false, true, false) +IMPLEMENT_CLASS(AWeapon, false, true, false, false) IMPLEMENT_POINTERS_START(AWeapon) IMPLEMENT_POINTER(Ammo1) @@ -38,7 +38,7 @@ TMap Weapons_hton; static int ntoh_cmp(const void *a, const void *b); -IMPLEMENT_CLASS(PClassWeapon, false, false, false) +IMPLEMENT_CLASS(PClassWeapon, false, false, false, false) PClassWeapon::PClassWeapon() { @@ -791,7 +791,7 @@ FState *AWeapon::GetStateForButtonName (FName button) /* Weapon giver ***********************************************************/ -IMPLEMENT_CLASS(AWeaponGiver, false, false, false) +IMPLEMENT_CLASS(AWeaponGiver, false, false, false, false) void AWeaponGiver::Serialize(FSerializer &arc) { diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index 947f68ae4d..e9370ae793 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -44,15 +44,15 @@ EXTERN_CVAR(Int, con_scaletext) int active_con_scaletext(); -IMPLEMENT_CLASS(DHUDMessage, false, true, false) +IMPLEMENT_CLASS(DHUDMessage, false, true, false, false) IMPLEMENT_POINTERS_START(DHUDMessage) IMPLEMENT_POINTER(Next) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(DHUDMessageFadeOut, false, false, false) -IMPLEMENT_CLASS(DHUDMessageFadeInOut, false, false, false) -IMPLEMENT_CLASS(DHUDMessageTypeOnFadeOut, false, false, false) +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 7675865adc..3041013119 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -1531,7 +1531,7 @@ private: SBarInfoMainBlock *lastPopup; }; -IMPLEMENT_CLASS(DSBarInfo, false, true, false) +IMPLEMENT_CLASS(DSBarInfo, false, true, false, false) IMPLEMENT_POINTERS_START(DSBarInfo) IMPLEMENT_POINTER(ammo1) diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index abf48c6a16..4bc15d4bf6 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -62,7 +62,7 @@ #define XHAIRPICKUPSIZE (2+XHAIRSHRINKSIZE) #define POWERUPICONSIZE 32 -IMPLEMENT_CLASS(DBaseStatusBar, false, true, false) +IMPLEMENT_CLASS(DBaseStatusBar, false, true, false, false) IMPLEMENT_POINTERS_START(DBaseStatusBar) IMPLEMENT_POINTER(Messages[0]) diff --git a/src/g_strife/a_coin.cpp b/src/g_strife/a_coin.cpp index 281c979213..87c4619d3c 100644 --- a/src/g_strife/a_coin.cpp +++ b/src/g_strife/a_coin.cpp @@ -6,7 +6,7 @@ // Coin --------------------------------------------------------------------- -IMPLEMENT_CLASS(ACoin, false, false, false) +IMPLEMENT_CLASS(ACoin, false, false, false, false) const char *ACoin::PickupMessage () { diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp index 4bb2fec0e6..0f1bef7cca 100644 --- a/src/g_strife/a_loremaster.cpp +++ b/src/g_strife/a_loremaster.cpp @@ -17,7 +17,7 @@ public: int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS(ALoreShot, false, false, false) +IMPLEMENT_CLASS(ALoreShot, false, false, false, false) int ALoreShot::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp index 70310eef2b..c00e7fb011 100644 --- a/src/g_strife/a_programmer.cpp +++ b/src/g_strife/a_programmer.cpp @@ -23,7 +23,7 @@ public: PalEntry GetBlend (); }; -IMPLEMENT_CLASS(AProgLevelEnder, false, false, false) +IMPLEMENT_CLASS(AProgLevelEnder, false, false, false, false) //============================================================================ // diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index bef34d03ba..7f21886bf2 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -47,7 +47,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(ATeleporterBeacon, false, false, false) +IMPLEMENT_CLASS(ATeleporterBeacon, false, false, false, false) bool ATeleporterBeacon::Use (bool pickup) { diff --git a/src/g_strife/a_spectral.cpp b/src/g_strife/a_spectral.cpp index d1dff1fb17..c7012accff 100644 --- a/src/g_strife/a_spectral.cpp +++ b/src/g_strife/a_spectral.cpp @@ -16,7 +16,7 @@ public: void Touch (AActor *toucher); }; -IMPLEMENT_CLASS(ASpectralMonster, false, false, false) +IMPLEMENT_CLASS(ASpectralMonster, false, false, false, false) void ASpectralMonster::Touch (AActor *toucher) { diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index f937da570d..c1b9d75d61 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -19,7 +19,7 @@ */ // Degnin Ore --------------------------------------------------------------- -IMPLEMENT_CLASS(ADegninOre, false, false, false) +IMPLEMENT_CLASS(ADegninOre, false, false, false, false) DEFINE_ACTION_FUNCTION(AActor, A_RemoveForceField) { @@ -75,7 +75,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS(AHealthTraining, false, false, false) +IMPLEMENT_CLASS(AHealthTraining, false, false, false, false) bool AHealthTraining::TryPickup (AActor *&toucher) { @@ -105,7 +105,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AScanner, false, false, false) +IMPLEMENT_CLASS(AScanner, false, false, false, false) bool AScanner::Use (bool pickup) { @@ -130,7 +130,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS(APrisonPass, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(ADummyStrifeItem, false, false, false, false) // Sound the alarm! --------------------------------------------------------- @@ -175,7 +175,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS(ARaiseAlarm, false, false, false) +IMPLEMENT_CLASS(ARaiseAlarm, false, false, false, false) bool ARaiseAlarm::TryPickup (AActor *&toucher) { @@ -209,7 +209,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS(AOpenDoor222, false, false, false) +IMPLEMENT_CLASS(AOpenDoor222, false, false, false, false) bool AOpenDoor222::TryPickup (AActor *&toucher) { @@ -228,7 +228,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS(ACloseDoor222, false, false, false) +IMPLEMENT_CLASS(ACloseDoor222, false, false, false, false) bool ACloseDoor222::TryPickup (AActor *&toucher) { @@ -262,7 +262,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS(AOpenDoor224, false, false, false) +IMPLEMENT_CLASS(AOpenDoor224, false, false, false, false) bool AOpenDoor224::TryPickup (AActor *&toucher) { @@ -287,7 +287,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS(AAmmoFillup, false, false, false) +IMPLEMENT_CLASS(AAmmoFillup, false, false, false, false) bool AAmmoFillup::TryPickup (AActor *&toucher) { @@ -325,7 +325,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS(AHealthFillup, false, false, false) +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, false, false, false) +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, false, false, false) +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, false, false, false) +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 f4a724bc45..1580f127f4 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -72,7 +72,7 @@ public: int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AForceFieldGuard, false, false, false) +IMPLEMENT_CLASS(AForceFieldGuard, false, false, false, false) int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) { @@ -197,7 +197,7 @@ public: void Die (AActor *source, AActor *inflictor, int dmgflags); }; -IMPLEMENT_CLASS(APowerCoupling, false, false, false) +IMPLEMENT_CLASS(APowerCoupling, false, false, false, false) void APowerCoupling::Die (AActor *source, AActor *inflictor, int dmgflags) { @@ -239,7 +239,7 @@ public: } }; -IMPLEMENT_CLASS(AMeat, false, false, false) +IMPLEMENT_CLASS(AMeat, false, false, false, false) //========================================================================== // diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index ec153d675c..3e9eb69b6c 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -184,7 +184,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(APoisonBolt, false, false, false) +IMPLEMENT_CLASS(APoisonBolt, false, false, false, false) int APoisonBolt::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -607,7 +607,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(APhosphorousFire, false, false, false) +IMPLEMENT_CLASS(APhosphorousFire, false, false, false, false) int APhosphorousFire::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -734,7 +734,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade) // The Almighty Sigil! ------------------------------------------------------ -IMPLEMENT_CLASS(ASigil, false, false, false) +IMPLEMENT_CLASS(ASigil, false, false, false, false) //============================================================================ // diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 3d00897778..73e31e6765 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -851,7 +851,7 @@ private: double ItemFlash; }; -IMPLEMENT_CLASS(DStrifeStatusBar, false, false, false); +IMPLEMENT_CLASS(DStrifeStatusBar, false, false, false, false); DBaseStatusBar *CreateStrifeStatusBar () { diff --git a/src/info.cpp b/src/info.cpp index 3e14d7fed7..09d0905f6c 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -153,7 +153,7 @@ int GetSpriteIndex(const char * spritename, bool add) return (lastindex = (int)sprites.Push (temp)); } -IMPLEMENT_CLASS(PClassActor, false, true, false) +IMPLEMENT_CLASS(PClassActor, false, true, false, false) IMPLEMENT_POINTERS_START(PClassActor) IMPLEMENT_POINTER(DropItems) diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 94288bfdfd..be8f58e19f 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -54,12 +54,12 @@ FIntermissionDescriptorList IntermissionDescriptors; -IMPLEMENT_CLASS(DIntermissionScreen, false, false, false) -IMPLEMENT_CLASS(DIntermissionScreenFader, false, false, false) -IMPLEMENT_CLASS(DIntermissionScreenText, false, false, false) -IMPLEMENT_CLASS(DIntermissionScreenCast, false, false, false) -IMPLEMENT_CLASS(DIntermissionScreenScroller, false, false, false) -IMPLEMENT_CLASS(DIntermissionController, false, true, false) +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) diff --git a/src/m_argv.cpp b/src/m_argv.cpp index 924c9dd5c6..7d82ed834c 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, false, false, false) +IMPLEMENT_CLASS(DArgs, false, false, false, false) //=========================================================================== // diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 94c1ef3df7..c53192ee7b 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -1033,7 +1033,7 @@ public: } }; -IMPLEMENT_CLASS(DSuicider, false, true, false) +IMPLEMENT_CLASS(DSuicider, false, true, false, false) IMPLEMENT_POINTERS_START(DSuicider) IMPLEMENT_POINTER(Pawn) diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp index 110ed2c3ea..639c6bbef3 100644 --- a/src/menu/colorpickermenu.cpp +++ b/src/menu/colorpickermenu.cpp @@ -331,7 +331,7 @@ public: } }; -IMPLEMENT_CLASS(DColorPickerMenu, true, false, false) +IMPLEMENT_CLASS(DColorPickerMenu, true, false, false, false) CCMD(undocolorpic) { diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 8e05391a69..cca13ad44c 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, false, false, false) +IMPLEMENT_CLASS(DJoystickConfigMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index 645636dadb..7fdd0c5bcf 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, false, false, false) +IMPLEMENT_CLASS(DListMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 69976726e1..6d543228c4 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -119,7 +119,7 @@ public: }; -IMPLEMENT_CLASS(DLoadSaveMenu, false, false, false) +IMPLEMENT_CLASS(DLoadSaveMenu, false, false, false, false) TArray DLoadSaveMenu::SaveGames; int DLoadSaveMenu::LastSaved = -1; @@ -934,7 +934,7 @@ public: }; -IMPLEMENT_CLASS(DSaveMenu, false, false, false) +IMPLEMENT_CLASS(DSaveMenu, false, false, false, false) //============================================================================= @@ -1102,7 +1102,7 @@ public: bool MenuEvent (int mkey, bool fromcontroller); }; -IMPLEMENT_CLASS(DLoadMenu, false, false, false) +IMPLEMENT_CLASS(DLoadMenu, false, false, false, false) //============================================================================= diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 6717ffcf2a..6648c32b4f 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -91,7 +91,7 @@ static bool MenuEnabled = true; // //============================================================================ -IMPLEMENT_CLASS(DMenu, false, true, false) +IMPLEMENT_CLASS(DMenu, false, true, false, false) IMPLEMENT_POINTERS_START(DMenu) IMPLEMENT_POINTER(mParentMenu) diff --git a/src/menu/menuinput.cpp b/src/menu/menuinput.cpp index 12ef4525d7..c33e9fed28 100644 --- a/src/menu/menuinput.cpp +++ b/src/menu/menuinput.cpp @@ -44,7 +44,7 @@ // [TP] New #includes #include "v_text.h" -IMPLEMENT_CLASS(DTextEnterMenu, true, false, false) +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 7915f44b30..de8fa10272 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -73,7 +73,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DMessageBoxMenu, false, false, false) +IMPLEMENT_CLASS(DMessageBoxMenu, false, false, false, false) //============================================================================= // @@ -365,7 +365,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuitMenu, false, false, false) +IMPLEMENT_CLASS(DQuitMenu, false, false, false, false) //============================================================================= // @@ -458,7 +458,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DEndGameMenu, false, false, false) +IMPLEMENT_CLASS(DEndGameMenu, false, false, false, false) //============================================================================= // @@ -536,7 +536,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuickSaveMenu, false, false, false) +IMPLEMENT_CLASS(DQuickSaveMenu, false, false, false, false) //============================================================================= // @@ -632,7 +632,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuickLoadMenu, false, false, false) +IMPLEMENT_CLASS(DQuickLoadMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index 46bbae6655..1631c3d4b6 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -64,7 +64,7 @@ void M_DrawConText (int color, int x, int y, const char *str) TAG_DONE); } -IMPLEMENT_CLASS(DOptionMenu, false, false, false) +IMPLEMENT_CLASS(DOptionMenu, false, false, false, false) //============================================================================= // @@ -578,7 +578,7 @@ public: } }; -IMPLEMENT_CLASS(DGameplayMenu, false, false, false) +IMPLEMENT_CLASS(DGameplayMenu, false, false, false, false) class DCompatibilityMenu : public DOptionMenu { @@ -600,4 +600,4 @@ public: } }; -IMPLEMENT_CLASS(DCompatibilityMenu, false, false, false) +IMPLEMENT_CLASS(DCompatibilityMenu, false, false, false, false) diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index 2d3c8c25f6..e83f4ada41 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -399,7 +399,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DEnterKey, true, false, false) +IMPLEMENT_CLASS(DEnterKey, true, false, false, false) #endif //============================================================================= diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index bc22c8e12a..e32c7dd618 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -526,7 +526,7 @@ public: void Drawer (); }; -IMPLEMENT_CLASS(DPlayerMenu, false, false, false) +IMPLEMENT_CLASS(DPlayerMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/readthis.cpp b/src/menu/readthis.cpp index ce03ec84bb..0dfc47e736 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, false, false, false) +IMPLEMENT_CLASS(DReadThisMenu, false, false, false, false) //============================================================================= // diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 6fec9ce6db..37f59149e6 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -183,7 +183,7 @@ public: } }; -IMPLEMENT_CLASS(DVideoModeMenu, false, false, false) +IMPLEMENT_CLASS(DVideoModeMenu, false, false, false, false) //============================================================================= diff --git a/src/p_acs.cpp b/src/p_acs.cpp index dc646da180..da8f76d7f1 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1369,7 +1369,7 @@ private: DPlaneWatcher() {} }; -IMPLEMENT_CLASS(DPlaneWatcher, false, true, false) +IMPLEMENT_CLASS(DPlaneWatcher, false, true, false, false) IMPLEMENT_POINTERS_START(DPlaneWatcher) IMPLEMENT_POINTER(Activator) @@ -2860,7 +2860,7 @@ void FBehavior::StaticStopMyScripts (AActor *actor) //---- The ACS Interpreter ----// -IMPLEMENT_CLASS(DACSThinker, false, true, false) +IMPLEMENT_CLASS(DACSThinker, false, true, false, false) IMPLEMENT_POINTERS_START(DACSThinker) IMPLEMENT_POINTER(LastScript) @@ -2991,7 +2991,7 @@ void DACSThinker::StopScriptsFor (AActor *actor) } } -IMPLEMENT_CLASS(DLevelScript, false, true, false) +IMPLEMENT_CLASS(DLevelScript, false, true, false, false) IMPLEMENT_POINTERS_START(DLevelScript) IMPLEMENT_POINTER(next) diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index ce2221ca14..b3526c60d5 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -865,7 +865,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(ACustomSprite, false, false, false) +IMPLEMENT_CLASS(ACustomSprite, false, false, false, false) void ACustomSprite::BeginPlay () { diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 53100f9caf..d22dd6371d 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -38,7 +38,7 @@ // //============================================================================ -IMPLEMENT_CLASS(DCeiling, false, false, false) +IMPLEMENT_CLASS(DCeiling, false, false, false, false) DCeiling::DCeiling () { diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index ad434b535b..5b37268b8d 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -1103,7 +1103,7 @@ public: }; -IMPLEMENT_CLASS(DConversationMenu, true, false, false) +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 568e880586..542308fa6f 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -45,7 +45,7 @@ // //============================================================================ -IMPLEMENT_CLASS(DDoor, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(DAnimatedDoor, false, false, false, false) DAnimatedDoor::DAnimatedDoor () { diff --git a/src/p_floor.cpp b/src/p_floor.cpp index a89330b2ae..7b5ff5cc93 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -64,7 +64,7 @@ static void StartFloorSound (sector_t *sec) // //========================================================================== -IMPLEMENT_CLASS(DFloor, false, false, false) +IMPLEMENT_CLASS(DFloor, false, false, false, false) DFloor::DFloor () { @@ -815,7 +815,7 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed) // //========================================================================== -IMPLEMENT_CLASS(DElevator, false, true, false) +IMPLEMENT_CLASS(DElevator, false, true, false, false) IMPLEMENT_POINTERS_START(DElevator) IMPLEMENT_POINTER(m_Interp_Floor) @@ -1105,9 +1105,9 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag) // //========================================================================== -IMPLEMENT_CLASS(DWaggleBase, false, false, false) -IMPLEMENT_CLASS(DFloorWaggle, false, false, false) -IMPLEMENT_CLASS(DCeilingWaggle, false, false, false) +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_lights.cpp b/src/p_lights.cpp index c2c2127a26..c44a22d4b1 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -173,7 +173,7 @@ private: // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DLighting, false, false, false) +IMPLEMENT_CLASS(DLighting, false, false, false, false) DLighting::DLighting () { @@ -191,7 +191,7 @@ DLighting::DLighting (sector_t *sector) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DFireFlicker, false, false, false) +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, false, false, false) +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, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(DStrobe, false, false, false, false) DStrobe::DStrobe () { @@ -667,7 +667,7 @@ void EV_LightChange (int tag, int value) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DGlow, false, false, false) +IMPLEMENT_CLASS(DGlow, false, false, false, false) DGlow::DGlow () { @@ -736,7 +736,7 @@ DGlow::DGlow (sector_t *sector) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DGlow2, false, false, false) +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, false, false, false) +IMPLEMENT_CLASS(DPhased, false, false, false, false) DPhased::DPhased () { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3cc961d846..0fb8794cf3 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -131,7 +131,7 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(AActor, false, true, true) +IMPLEMENT_CLASS(AActor, false, true, true, false) IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(target) @@ -6956,7 +6956,7 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) // //---------------------------------------------------------------------------- -IMPLEMENT_CLASS(DDropItem, false, true, true) +IMPLEMENT_CLASS(DDropItem, false, true, true, false) IMPLEMENT_POINTERS_START(DDropItem) IMPLEMENT_POINTER(Next) diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index fecfbd024d..27eb13ec5b 100644 --- a/src/p_pillar.cpp +++ b/src/p_pillar.cpp @@ -40,7 +40,7 @@ #include "serializer.h" #include "r_data/r_interpolate.h" -IMPLEMENT_CLASS(DPillar, false, true, false) +IMPLEMENT_CLASS(DPillar, false, true, false, false) IMPLEMENT_POINTERS_START(DPillar) IMPLEMENT_POINTER(m_Interp_Floor) diff --git a/src/p_plats.cpp b/src/p_plats.cpp index 3bd7089166..9924a0f9ce 100644 --- a/src/p_plats.cpp +++ b/src/p_plats.cpp @@ -35,7 +35,7 @@ static FRandom pr_doplat ("DoPlat"); -IMPLEMENT_CLASS(DPlat, false, false, false) +IMPLEMENT_CLASS(DPlat, false, false, false, false) DPlat::DPlat () { diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index b64bb22a74..d279a180cc 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -99,7 +99,7 @@ static const FGenericButtons ButtonChecks[] = // //------------------------------------------------------------------------ -IMPLEMENT_CLASS(DPSprite, false, true, false) +IMPLEMENT_CLASS(DPSprite, false, true, false, false) IMPLEMENT_POINTERS_START(DPSprite) IMPLEMENT_POINTER(Caller) diff --git a/src/p_pusher.cpp b/src/p_pusher.cpp index 250e8ee3de..f2f982a7fa 100644 --- a/src/p_pusher.cpp +++ b/src/p_pusher.cpp @@ -74,7 +74,7 @@ protected: friend bool PIT_PushThing (AActor *thing); }; -IMPLEMENT_CLASS(DPusher, false, true, false) +IMPLEMENT_CLASS(DPusher, false, true, false, false) IMPLEMENT_POINTERS_START(DPusher) IMPLEMENT_POINTER(m_Source) diff --git a/src/p_scroll.cpp b/src/p_scroll.cpp index 67f6499d61..f44eac25a9 100644 --- a/src/p_scroll.cpp +++ b/src/p_scroll.cpp @@ -73,7 +73,7 @@ private: } }; -IMPLEMENT_CLASS(DScroller, false, true, false) +IMPLEMENT_CLASS(DScroller, false, true, false, false) IMPLEMENT_POINTERS_START(DScroller) IMPLEMENT_POINTER(m_Interpolations[0]) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index e9ac494197..e687d5724f 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -660,7 +660,7 @@ protected: short LastLight; }; -IMPLEMENT_CLASS(DLightTransfer, false, false, false) +IMPLEMENT_CLASS(DLightTransfer, false, false, false, false) void DLightTransfer::Serialize(FSerializer &arc) { @@ -750,7 +750,7 @@ protected: BYTE Flags; }; -IMPLEMENT_CLASS(DWallLightTransfer, false, false, false) +IMPLEMENT_CLASS(DWallLightTransfer, false, false, false, false) void DWallLightTransfer::Serialize(FSerializer &arc) { diff --git a/src/p_switch.cpp b/src/p_switch.cpp index 027b5d99d2..2d5423f084 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, false, false, false) +IMPLEMENT_CLASS(DActiveButton, false, false, false, false) DActiveButton::DActiveButton () { diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index 85ee8a1c83..01595ff659 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, false, false, false) +IMPLEMENT_CLASS(ATeleportFog, false, false, false, false) void ATeleportFog::PostBeginPlay () { diff --git a/src/p_user.cpp b/src/p_user.cpp index 266d216bb0..0b7d9c3545 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -508,7 +508,7 @@ int player_t::GetSpawnClass() // //=========================================================================== -IMPLEMENT_CLASS(PClassPlayerPawn, false, false, false) +IMPLEMENT_CLASS(PClassPlayerPawn, false, false, false, false) PClassPlayerPawn::PClassPlayerPawn() { @@ -622,14 +622,14 @@ void player_t::SendPitchLimits() const // //=========================================================================== -IMPLEMENT_CLASS(APlayerPawn, false, true, false) +IMPLEMENT_CLASS(APlayerPawn, false, true, false, false) IMPLEMENT_POINTERS_START(APlayerPawn) IMPLEMENT_POINTER(InvFirst) IMPLEMENT_POINTER(InvSel) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(APlayerChunk, false, false, false) +IMPLEMENT_CLASS(APlayerChunk, false, false, false, false) void APlayerPawn::Serialize(FSerializer &arc) { diff --git a/src/po_man.cpp b/src/po_man.cpp index 3261e34f32..4e304daa8b 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -172,7 +172,7 @@ static FPolyNode *FreePolyNodes; // //========================================================================== -IMPLEMENT_CLASS(DPolyAction, false, true, false) +IMPLEMENT_CLASS(DPolyAction, false, true, false, false) IMPLEMENT_POINTERS_START(DPolyAction) IMPLEMENT_POINTER(m_Interpolation) @@ -240,7 +240,7 @@ void DPolyAction::StopInterpolation () // //========================================================================== -IMPLEMENT_CLASS(DRotatePoly, false, false, false) +IMPLEMENT_CLASS(DRotatePoly, false, false, false, false) DRotatePoly::DRotatePoly () { @@ -257,7 +257,7 @@ DRotatePoly::DRotatePoly (int polyNum) // //========================================================================== -IMPLEMENT_CLASS(DMovePoly, false, false, false) +IMPLEMENT_CLASS(DMovePoly, false, false, false, false) DMovePoly::DMovePoly () { @@ -284,7 +284,7 @@ DMovePoly::DMovePoly (int polyNum) // //========================================================================== -IMPLEMENT_CLASS(DMovePolyTo, false, false, false) +IMPLEMENT_CLASS(DMovePolyTo, false, false, false, false) DMovePolyTo::DMovePolyTo() { @@ -309,7 +309,7 @@ DMovePolyTo::DMovePolyTo(int polyNum) // //========================================================================== -IMPLEMENT_CLASS(DPolyDoor, false, false, false) +IMPLEMENT_CLASS(DPolyDoor, false, false, false, false) DPolyDoor::DPolyDoor () { diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index 29b7415616..a1e6056ca7 100644 --- a/src/posix/sdl/sdlvideo.cpp +++ b/src/posix/sdl/sdlvideo.cpp @@ -79,7 +79,7 @@ private: SDLFB () {} }; -IMPLEMENT_CLASS(SDLFB, false, false, false) +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 911127f07b..c98adb47b7 100644 --- a/src/r_data/r_interpolate.cpp +++ b/src/r_data/r_interpolate.cpp @@ -161,17 +161,17 @@ public: // //========================================================================== -IMPLEMENT_CLASS(DInterpolation, true, true, false) +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) -IMPLEMENT_CLASS(DSectorScrollInterpolation, false, false, false) -IMPLEMENT_CLASS(DWallScrollInterpolation, false, false, false) -IMPLEMENT_CLASS(DPolyobjInterpolation, false, false, false) +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/s_advsound.cpp b/src/s_advsound.cpp index 1aedcb1fb1..c68df5f3c8 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -2213,7 +2213,7 @@ private: int NextCheck; }; -IMPLEMENT_CLASS(AAmbientSound, false, false, false) +IMPLEMENT_CLASS(AAmbientSound, false, false, false, false) //========================================================================== // @@ -2470,7 +2470,7 @@ public: virtual void PostBeginPlay(); }; -IMPLEMENT_CLASS(AMusicChanger, false, false, false) +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 449baa4d6b..1bed35ed5b 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -285,7 +285,7 @@ void DSeqNode::SerializeSequences (FSerializer &arc) arc("sndseqlisthead", SequenceListHead); } -IMPLEMENT_CLASS(DSeqNode, false, true, false) +IMPLEMENT_CLASS(DSeqNode, false, true, false, false) IMPLEMENT_POINTERS_START(DSeqNode) IMPLEMENT_POINTER(m_ChildSeqNode) @@ -429,7 +429,7 @@ FName DSeqNode::GetSequenceName () const return Sequences[m_Sequence]->SeqName; } -IMPLEMENT_CLASS(DSeqActorNode, false, true, false) +IMPLEMENT_CLASS(DSeqActorNode, false, true, false, false) IMPLEMENT_POINTERS_START(DSeqActorNode) IMPLEMENT_POINTER(m_Actor) @@ -441,7 +441,7 @@ void DSeqActorNode::Serialize(FSerializer &arc) arc("actor", m_Actor); } -IMPLEMENT_CLASS(DSeqPolyNode, false, false, false) +IMPLEMENT_CLASS(DSeqPolyNode, false, false, false, false) void DSeqPolyNode::Serialize(FSerializer &arc) { @@ -449,7 +449,7 @@ void DSeqPolyNode::Serialize(FSerializer &arc) arc("poly", m_Poly); } -IMPLEMENT_CLASS(DSeqSectorNode, false, false, false) +IMPLEMENT_CLASS(DSeqSectorNode, false, false, false, false) void DSeqSectorNode::Serialize(FSerializer &arc) { diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 63ae447cfd..d1b79328f9 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -96,7 +96,7 @@ public: } }; -IMPLEMENT_CLASS(AFakeInventory, false, false, false) +IMPLEMENT_CLASS(AFakeInventory, false, false, false, false) // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 3070c1b4d7..3a593861c1 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -34,15 +34,15 @@ #include #include "vm.h" -IMPLEMENT_CLASS(VMException, false, false, false) -IMPLEMENT_CLASS(VMFunction, true, true, false) +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) -IMPLEMENT_CLASS(VMNativeFunction, false, false, false) +IMPLEMENT_CLASS(VMScriptFunction, false, false, false, false) +IMPLEMENT_CLASS(VMNativeFunction, false, false, false, false) VMScriptFunction::VMScriptFunction(FName name) { diff --git a/src/v_video.cpp b/src/v_video.cpp index f79f31b1c7..e3954385a8 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -69,8 +69,8 @@ int active_con_scale(); FRenderer *Renderer; -IMPLEMENT_CLASS(DCanvas, true, false, false) -IMPLEMENT_CLASS(DFrameBuffer, true, false, false) +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_CLASS(DDummyFrameBuffer, true, false, false) +IMPLEMENT_CLASS(DDummyFrameBuffer, true, false, false, false) // SimpleCanvas is not really abstract, but this macro does not // try to generate a CreateNew() function. -IMPLEMENT_CLASS(DSimpleCanvas, true, false, false) +IMPLEMENT_CLASS(DSimpleCanvas, true, false, false, false) class FPaletteTester : public FTexture { diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index a79ef1a3f3..6d162bbec0 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -91,7 +91,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_CLASS(D3DFB, false, false, false) +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 dcd6d37a95..bd5a4db230 100644 --- a/src/win32/fb_ddraw.cpp +++ b/src/win32/fb_ddraw.cpp @@ -61,7 +61,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_CLASS(DDrawFB, false, false, false) +IMPLEMENT_CLASS(DDrawFB, false, false, false, false) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/win32/win32video.cpp b/src/win32/win32video.cpp index b8aded5c1b..d7c5d5bf5b 100644 --- a/src/win32/win32video.cpp +++ b/src/win32/win32video.cpp @@ -78,7 +78,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_CLASS(BaseWinFB, true, false, false) +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); From 26dc0c6df21e2e9f792b79149c51e13960ae8582 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 6 Nov 2016 11:40:17 +0100 Subject: [PATCH 213/471] TODO: Find a better place to insert the classes in the hierarchy --- src/scripting/zscript/zcc_compile.cpp | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 2965357dde..421b27fb19 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -51,6 +51,8 @@ #include "codegeneration/codegen.h" #include "vmbuilder.h" +#define DEFAULTS_VMEXPORT ((BYTE *)(void *)1) + //========================================================================== // // ZCCCompiler :: ProcessClass @@ -498,6 +500,26 @@ void ZCCCompiler::CreateClassTypes() } 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. c->cls->Type = parent->FindClassTentative(c->NodeName()); } @@ -1887,6 +1909,16 @@ void ZCCCompiler::InitDefaults() { // 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; + static_cast(ti->ParentClass)->InitializeNativeDefaults(); + ti->ParentClass->ParentClass->DeriveData(ti->ParentClass); + } + ti->InitializeNativeDefaults(); ti->ParentClass->DeriveData(ti); @@ -2239,6 +2271,20 @@ void ZCCCompiler::CompileStates() 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)); From fb2a843c031b0e2d36ad4043b9f412dda826ec99 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Mon, 7 Nov 2016 00:30:26 +0100 Subject: [PATCH 214/471] Test on a few methods/classes --- src/actor.h | 4 ++++ src/dobject.h | 30 ++++++++++++++++++++++++++++++ src/dthinker.cpp | 2 +- src/dthinker.h | 4 ++++ src/p_mobj.cpp | 2 +- src/p_user.cpp | 2 +- 6 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/actor.h b/src/actor.h index 833cd2c0ab..6f5ba46a32 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1419,6 +1419,10 @@ public: }; +VMEXPORT_NATIVES_START(AActor, DThinker) + VMEXPORT_NATIVES_FUNC(DropInventory) +VMEXPORT_NATIVES_END(AActor) + class FActorIterator { public: diff --git a/src/dobject.h b/src/dobject.h index 24ba4997c1..183d17dd24 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -608,6 +608,8 @@ protected: } }; +class AInventory;// + template class DVMObject : public T { @@ -638,6 +640,23 @@ private: { new((EInPlace *)mem) DVMObject; } + +public: + void Destroy() + { + Printf("Destroy\n"); + ExportedNatives::Get()->Destroy(this); + } + void Tick() + { + Printf("Tick\n"); + ExportedNatives::Get()->Tick(this); + } + AInventory *DropInventory(AInventory *item) + { + Printf("DropInventory\n"); + return ExportedNatives::Get()->DropInventory(this, item); + } }; template @@ -655,6 +674,17 @@ ClassReg DVMObject::RegistrationInfo = }; template _DECLARE_TI(DVMObject) +//Initial list +VMEXPORTED_NATIVES_START + VMEXPORTED_NATIVES_FUNC(Destroy) + VMEXPORTED_NATIVES_FUNC(Tick) + VMEXPORTED_NATIVES_FUNC(DropInventory) +VMEXPORTED_NATIVES_END + +VMEXPORT_NATIVES_START(DObject, void) + VMEXPORT_NATIVES_FUNC(Destroy) +VMEXPORT_NATIVES_END(DObject) + // 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/dthinker.cpp b/src/dthinker.cpp index 9c87c46b45..912b5642ef 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -47,7 +47,7 @@ extern cycle_t BotSupportCycles; extern cycle_t ActionCycles; extern int BotWTG; -IMPLEMENT_CLASS(DThinker, false, false, false, false) +IMPLEMENT_CLASS(DThinker, false, false, false, true) DThinker *NextToThink; diff --git a/src/dthinker.h b/src/dthinker.h index 95985c2fb4..e1020544cf 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -108,6 +108,10 @@ private: DThinker *NextThinker, *PrevThinker; }; +VMEXPORT_NATIVES_START(DThinker, DObject) + VMEXPORT_NATIVES_FUNC(Tick) +VMEXPORT_NATIVES_END(DThinker) + class FThinkerIterator { protected: diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 0fb8794cf3..7c973351fa 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -131,7 +131,7 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(AActor, false, true, true, false) +IMPLEMENT_CLASS(AActor, false, true, true, true) IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(target) diff --git a/src/p_user.cpp b/src/p_user.cpp index 0b7d9c3545..f4e52ac2f8 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -622,7 +622,7 @@ void player_t::SendPitchLimits() const // //=========================================================================== -IMPLEMENT_CLASS(APlayerPawn, false, true, false, false) +IMPLEMENT_CLASS(APlayerPawn, false, true, false, true) IMPLEMENT_POINTERS_START(APlayerPawn) IMPLEMENT_POINTER(InvFirst) From 5151547df0be103b17a563af40bb9f8f5145ffa9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 9 Nov 2016 20:28:46 +0100 Subject: [PATCH 215/471] - fixed: String comparisons with constants did not work. --- src/scripting/codegeneration/codegen.cpp | 5 +++++ src/scripting/zscript/zcc_compile.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 63302d600a..af92bf72fc 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3251,10 +3251,15 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) 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 diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 421b27fb19..7e895d0493 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -497,6 +497,8 @@ void ZCCCompiler::CreateClassTypes() 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 { From e0bd6a2c0ad96f91984f2020611a957e1b13c8e0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 10 Nov 2016 13:37:38 +0100 Subject: [PATCH 216/471] - fixed a memory leak in the compiler. - removed test Printfs. --- src/CMakeLists.txt | 1 - src/dobject.h | 3 - src/g_pch.h | 1 + .../codegeneration/functioncalls.cpp | 76 ------------------- src/scripting/zscript/zcc_compile.cpp | 4 + src/scripting/zscript/zcc_compile.h | 2 + 6 files changed, 7 insertions(+), 80 deletions(-) delete mode 100644 src/scripting/codegeneration/functioncalls.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 81f43f06b3..8b75d7b62a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1247,7 +1247,6 @@ set (PCH_SOURCES scripting/thingdef_data.cpp scripting/thingdef_properties.cpp scripting/codegeneration/codegen.cpp - scripting/codegeneration/functioncalls.cpp scripting/decorate/olddecorations.cpp scripting/decorate/thingdef_exp.cpp scripting/decorate/thingdef_parse.cpp diff --git a/src/dobject.h b/src/dobject.h index 183d17dd24..3c4b23248d 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -644,17 +644,14 @@ private: public: void Destroy() { - Printf("Destroy\n"); ExportedNatives::Get()->Destroy(this); } void Tick() { - Printf("Tick\n"); ExportedNatives::Get()->Tick(this); } AInventory *DropInventory(AInventory *item) { - Printf("DropInventory\n"); return ExportedNatives::Get()->DropInventory(this, item); } }; diff --git a/src/g_pch.h b/src/g_pch.h index 3f44cf9b54..a22649815a 100644 --- a/src/g_pch.h +++ b/src/g_pch.h @@ -18,3 +18,4 @@ #include #include #include +#include diff --git a/src/scripting/codegeneration/functioncalls.cpp b/src/scripting/codegeneration/functioncalls.cpp deleted file mode 100644 index ca2b437e70..0000000000 --- a/src/scripting/codegeneration/functioncalls.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#if 0 -/* -** cg_functioncall.cpp -** -**--------------------------------------------------------------------------- -** 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 "doomtype.h" -#include "codegen.h" -#include "thingdef.h" -#include "zscript/zcc_parser.h" - -// just some rough concepts for now... - - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *ConvertFunctionCall(ZCC_Expression *function, FArgumentList *args, PClass *cls, FScriptPosition &sc) -{ - - switch(function->NodeType) - { - case AST_ExprID: - return new FxFunctionCall( ConvertSimpleFunctionCall(static_cast(function), args, cls, sc); - - case AST_ExprMemberAccess: - return ConvertMemberCall(fcall); - - case AST_ExprBinary: - // Array access syntax is wrapped into a ZCC_ExprBinary object. - break; - - default: - break; - } - Error(fcall, "Invalid function identifier"); - return new FxNop(*fcall); // return something so that we can continue -} - - - assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. - auto fname = static_cast(fcall->Function)->Identifier; - return new FxFunctionCall(nullptr, fname, ConvertNodeList(fcall->Parameters), *ast); - -#endif \ No newline at end of file diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 7e895d0493..0d99ee5c2e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2839,10 +2839,14 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } else if (args->Size() == 1) { + auto arg = (*args)[0]; + (*args)[0] = nullptr; + delete args; return new FxReturnStatement((*args)[0], *ast); } else { + delete args; Error(ast, "Return with multiple values not implemented yet."); return new FxReturnStatement(nullptr, *ast); } diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index c901fc42ea..2e38d68d29 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -1,6 +1,8 @@ #ifndef ZCC_COMPILE_H #define ZCC_COMPILE_H +#include + struct Baggage; struct FPropertyInfo; class AActor; From a60bdc2bfb5130a937bce69f6e0e7786d4dc2ad3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 10 Nov 2016 15:13:31 +0100 Subject: [PATCH 217/471] use a memory arena for allocating code generation nodes. - Since the number of small allocations here is extremely high this will help a lot to prevent fragmentation and since most nodes are collected up front and this is done when no large resources are being loaded it won't cause heap spikes. let Emit methods delete FxExpression arrays when they are done. - For some reason the deletion process does not work 100%, there are always some nodes left behind and so far I haven't found them. This ensures that these arrays do not live any longer than needed. --- src/memarena.cpp | 11 +- src/memarena.h | 3 +- src/scripting/codegeneration/codegen.cpp | 276 +++++++++++---------- src/scripting/codegeneration/codegen.h | 36 ++- src/scripting/decorate/thingdef_exp.cpp | 34 +-- src/scripting/decorate/thingdef_states.cpp | 16 +- src/scripting/vm/vmbuilder.cpp | 1 + src/scripting/zscript/zcc_compile.cpp | 34 +-- src/scripting/zscript/zcc_compile.h | 2 +- 9 files changed, 209 insertions(+), 204 deletions(-) diff --git a/src/memarena.cpp b/src/memarena.cpp index b15fb12ea0..e6e9edd6e7 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 73dbb59323..cc0c8f148f 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/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index af92bf72fc..316ae4246f 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -57,6 +57,7 @@ #include "math/cmath.h" extern FRandom pr_exrandom; +FMemArena FxAlloc(65536); struct FLOP { @@ -483,7 +484,9 @@ FxVectorValue::FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, FxVectorValue::~FxVectorValue() { for (auto &a : xyz) + { SAFE_DELETE(a); + } } FxExpression *FxVectorValue::Resolve(FCompileContext&ctx) @@ -3721,6 +3724,8 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) 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; } @@ -4362,6 +4367,7 @@ FxMinMax::FxMinMax(TArray &expr, FName type, const FScriptPositio for (unsigned i = 0; i < expr.Size(); ++i) { choices[i] = expr[i]; + expr[i] = nullptr; } } @@ -4713,10 +4719,12 @@ FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, if (floaty) { choices[index] = new FxFloatCast(expr[index]); + expr[index] = nullptr; } else { choices[index] = new FxIntCast(expr[index], nowarn); + expr[index] = nullptr; } } @@ -5218,6 +5226,11 @@ FxMemberIdentifier::FxMemberIdentifier(FxExpression *left, FName name, const FSc ExprType = EFX_MemberIdentifier; } +FxMemberIdentifier::~FxMemberIdentifier() +{ + SAFE_DELETE(Object); +} + //========================================================================== // // @@ -5277,6 +5290,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) return nullptr; } auto x = isclass? new FxClassMember(Object, vsym, ScriptPosition) : new FxStructMember(Object, vsym, ScriptPosition); + Object = nullptr; delete this; return x->Resolve(ctx); } @@ -5313,6 +5327,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); } auto x = new FxStructMember(Object, vsym, ScriptPosition); + Object = nullptr; delete this; return x->Resolve(ctx); } @@ -5942,12 +5957,12 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) // //========================================================================== -FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos) +FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos) : FxExpression(EFX_FunctionCall, pos) { MethodName = methodname; RNG = &pr_exrandom; - ArgList = args; + ArgList = std::move(args); if (rngname != NAME_None) { switch (MethodName) @@ -5976,7 +5991,6 @@ FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList *a FxFunctionCall::~FxFunctionCall() { - SAFE_DELETE(ArgList); } //========================================================================== @@ -5985,9 +5999,9 @@ FxFunctionCall::~FxFunctionCall() // //========================================================================== -static bool CheckArgSize(FName fname, FArgumentList *args, int min, int max, FScriptPosition &sc) +static bool CheckArgSize(FName fname, FArgumentList &args, int min, int max, FScriptPosition &sc) { - int s = args ? args->Size() : 0; + 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); @@ -6030,7 +6044,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } auto self = !(afd->Variants[0].Flags & VARF_Static)? new FxSelf(ScriptPosition) : nullptr; auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, false); - ArgList = nullptr; delete this; return x->Resolve(ctx); } @@ -6040,7 +6053,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) if (MethodName == FxFlops[i].Name) { FxExpression *x = new FxFlopFunctionCall(i, ArgList, ScriptPosition); - ArgList = nullptr; delete this; return x->Resolve(ctx); } @@ -6059,7 +6071,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } if (special != 0 && min >= 0) { - int paramcount = ArgList? ArgList->Size() : 0; + int paramcount = ArgList.Size(); if (paramcount < min) { ScriptPosition.Message(MSG_ERROR, "Not enough parameters for '%s' (expected %d, got %d)", @@ -6076,7 +6088,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } FxExpression *self = (ctx.Function && ctx.Function->Variants[0].Flags & VARF_Method) ? new FxSelf(ScriptPosition) : nullptr; FxExpression *x = new FxActionSpecialCall(self, special, ArgList, ScriptPosition); - ArgList = nullptr; delete this; return x->Resolve(ctx); } @@ -6086,8 +6097,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { - FxExpression *x = new FxDynamicCast(cls, (*ArgList)[0]); - (*ArgList)[0] = nullptr; + FxExpression *x = new FxDynamicCast(cls, ArgList[0]); + ArgList[0] = nullptr; delete this; return x->Resolve(ctx); } @@ -6126,29 +6137,29 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) MethodName == NAME_Color ? TypeColor : MethodName == NAME_State? TypeState :(PType*)TypeSound; - func = new FxTypeCast((*ArgList)[0], type, true, true); - (*ArgList)[0] = nullptr; + 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) + 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; + 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; + func = new FxFRandom(RNG, ArgList[0], ArgList[1], ScriptPosition); + ArgList[0] = ArgList[1] = nullptr; } break; @@ -6156,16 +6167,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_FRandomPick: if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition)) { - func = new FxRandomPick(RNG, *ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); - for (auto &i : *ArgList) i = nullptr; + 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; + func = new FxRandom2(RNG, ArgList.Size() == 0? nullptr : ArgList[0], ScriptPosition, ctx.FromDecorate); + if (ArgList.Size() > 0) ArgList[0] = nullptr; } break; @@ -6173,8 +6183,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Max: if (CheckArgSize(MethodName, ArgList, 2, -1, ScriptPosition)) { - func = new FxMinMax(*ArgList, MethodName, ScriptPosition); - for (auto &i : *ArgList) i = nullptr; + func = new FxMinMax(ArgList, MethodName, ScriptPosition); } break; @@ -6183,20 +6192,20 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { TArray pass; pass.Resize(2); - pass[0] = (*ArgList)[0]; - pass[1] = (*ArgList)[1]; + pass[0] = ArgList[0]; + pass[1] = ArgList[1]; pass[0] = new FxMinMax(pass, NAME_Max, ScriptPosition); - pass[1] = (*ArgList)[2]; + pass[1] = ArgList[2]; func = new FxMinMax(pass, NAME_Min, ScriptPosition); - (*ArgList)[0] = (*ArgList)[1] = (*ArgList)[2] = nullptr; + 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; + func = new FxAbs(ArgList[0]); + ArgList[0] = nullptr; } break; @@ -6204,8 +6213,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) 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; + func = MethodName == NAME_ATan2 ? new FxATan2(ArgList[0], ArgList[1], ScriptPosition) : new FxATan2(ArgList[1], ArgList[0], ScriptPosition); + ArgList[0] = ArgList[1] = nullptr; } break; @@ -6229,12 +6238,12 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) // //========================================================================== -FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos) +FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &args, const FScriptPosition &pos) : FxExpression(EFX_MemberFunctionCall, pos) { Self = self; MethodName = methodname; - ArgList = args; + ArgList = std::move(args); } //========================================================================== @@ -6246,7 +6255,6 @@ FxMemberFunctionCall::FxMemberFunctionCall(FxExpression *self, FName methodname, FxMemberFunctionCall::~FxMemberFunctionCall() { SAFE_DELETE(Self); - SAFE_DELETE(ArgList); } //========================================================================== @@ -6342,7 +6350,6 @@ isresolved: // 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); - ArgList = nullptr; if (Self == self) Self = nullptr; delete this; return x->Resolve(ctx); @@ -6358,12 +6365,12 @@ isresolved: // //========================================================================== -FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgumentList *args, const FScriptPosition &pos) +FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgumentList &args, const FScriptPosition &pos) : FxExpression(EFX_ActionSpecialCall, pos) { Self = self; Special = special; - ArgList = args; + ArgList = std::move(args); EmitTail = false; } @@ -6376,7 +6383,6 @@ FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgum FxActionSpecialCall::~FxActionSpecialCall() { SAFE_DELETE(Self); - SAFE_DELETE(ArgList); } //========================================================================== @@ -6403,51 +6409,48 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) bool failed = false; SAFE_RESOLVE_OPT(Self, ctx); - if (ArgList != nullptr) + for (unsigned i = 0; i < ArgList.Size(); i++) { - for (unsigned i = 0; i < ArgList->Size(); i++) + ArgList[i] = ArgList[i]->Resolve(ctx); + if (ArgList[i] == nullptr) { - (*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 (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) + else if (!ArgList[i]->IsInteger()) { - delete this; - return nullptr; + 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; } @@ -6481,30 +6484,27 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) // fixme: This really should use the Self pointer that got passed to this class instead of just using the first argument from the function. // Once static functions are possible, or specials can be called through a member access operator this won't work anymore. build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self - if (ArgList != nullptr) + for (; i < ArgList.Size(); ++i) { - for (; i < ArgList->Size(); ++i) + FxExpression *argex = ArgList[i]; + if (Special < 0 && i == 0) { - 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()) { - assert(argex->ValueType == TypeName); - assert(argex->isConstant()); - build->EmitParamInt(-static_cast(argex)->GetValue().GetName()); + build->EmitParamInt(static_cast(argex)->GetValue().GetInt()); } 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); - } + ExpEmit arg(argex->Emit(build)); + build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum); + arg.Free(build); } } } @@ -6515,6 +6515,8 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; + ArgList.Clear(); + ArgList.ShrinkToFit(); if (EmitTail) { @@ -6536,12 +6538,12 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) // //========================================================================== -FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool novirtual) +FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual) : FxExpression(EFX_VMFunctionCall, pos) { Self = self; Function = func; - ArgList = args; + ArgList = std::move(args); EmitTail = false; NoVirtual = novirtual; } @@ -6554,7 +6556,6 @@ FxVMFunctionCall::FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumen FxVMFunctionCall::~FxVMFunctionCall() { - SAFE_DELETE(ArgList); } //========================================================================== @@ -6581,7 +6582,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction() // 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 ? ArgList->Size() : 0) == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) + if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) { return Function->Variants[0].Implementation; } @@ -6613,18 +6614,18 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } - if (ArgList != nullptr) + if (ArgList.Size() > 0) { bool foundvarargs = false; PType * type = nullptr; - if (argtypes.Last() != nullptr && ArgList->Size() + implicit > argtypes.Size()) + 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++) + 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) @@ -6634,12 +6635,12 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } assert(type != nullptr); - FxExpression *x = new FxTypeCast((*ArgList)[i], type, false); + FxExpression *x = new FxTypeCast(ArgList[i], type, false); x = x->Resolve(ctx); failed |= (x == nullptr); - (*ArgList)[i] = x; + ArgList[i] = x; } - int numargs = ArgList->Size() + implicit; + int numargs = ArgList.Size() + implicit; if ((unsigned)numargs < argtypes.Size() && argtypes[numargs] != nullptr) { auto flags = Function->Variants[0].ArgFlags[numargs]; @@ -6679,13 +6680,15 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { assert(build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits); - int count = 0; (ArgList ? ArgList->Size() : 0); + int count = 0; if (count == 1) { ExpEmit reg; if (CheckEmitCast(build, EmitTail, reg)) { + ArgList.Clear(); + ArgList.ShrinkToFit(); return reg; } } @@ -6718,13 +6721,13 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) selfemit.Free(build); } // Emit code to pass explicit parameters - if (ArgList != nullptr) + for (unsigned i = 0; i < ArgList.Size(); ++i) { - for (unsigned i = 0; i < ArgList->Size(); ++i) - { - count += EmitParameter(build, (*ArgList)[i], ScriptPosition); - } + count += EmitParameter(build, ArgList[i], ScriptPosition); } + ArgList.Clear(); + ArgList.ShrinkToFit(); + // Get a constant register for this function VMFunction *vmfunc = Function->Variants[0].Implementation; int funcaddr = build->GetConstantAddress(vmfunc, ATAG_OBJECT); @@ -6766,7 +6769,7 @@ bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, Ex funcname == NAME___decorate_internal_state__ || funcname == NAME___decorate_internal_float__) { - FxExpression *arg = (*ArgList)[0]; + FxExpression *arg = ArgList[0]; if (returnit) { if (arg->isConstant() && @@ -6799,12 +6802,12 @@ bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, Ex // //========================================================================== -FxFlopFunctionCall::FxFlopFunctionCall(size_t index, FArgumentList *args, const FScriptPosition &pos) +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 = args; + ArgList = std::move(args); } //========================================================================== @@ -6815,44 +6818,43 @@ FxFlopFunctionCall::FxFlopFunctionCall(size_t index, FArgumentList *args, const FxFlopFunctionCall::~FxFlopFunctionCall() { - SAFE_DELETE(ArgList); } FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (ArgList == nullptr || ArgList->Size() != 1) + 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) + ArgList[0] = ArgList[0]->Resolve(ctx); + if (ArgList[0] == nullptr) { delete this; return nullptr; } - if (!(*ArgList)[0]->IsNumeric()) + if (!ArgList[0]->IsNumeric()) { ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); delete this; return nullptr; } - if ((*ArgList)[0]->isConstant()) + if (ArgList[0]->isConstant()) { - double v = static_cast((*ArgList)[0])->GetValue().GetFloat(); + 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) + if (ArgList[0]->ValueType->GetRegType() == REGT_INT) { - (*ArgList)[0] = new FxFloatCast((*ArgList)[0]); + ArgList[0] = new FxFloatCast(ArgList[0]); } ValueType = TypeFloat64; return this; @@ -6865,10 +6867,12 @@ FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx) ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) { - ExpEmit v = (*ArgList)[0]->Emit(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; } @@ -7081,17 +7085,16 @@ bool FxCompoundStatement::CheckLocalVariable(FName name) // //========================================================================== -FxSwitchStatement::FxSwitchStatement(FxExpression *cond, FArgumentList *content, const FScriptPosition &pos) +FxSwitchStatement::FxSwitchStatement(FxExpression *cond, FArgumentList &content, const FScriptPosition &pos) : FxExpression(EFX_SwitchStatement, pos) { Condition = new FxIntCast(cond, false); - Content = content; + Content = std::move(content); } FxSwitchStatement::~FxSwitchStatement() { SAFE_DELETE(Condition); - SAFE_DELETE(Content); } FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) @@ -7099,7 +7102,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(Condition, ctx); - if (Content == nullptr || Content->Size() == 0) + if (Content.Size() == 0) { ScriptPosition.Message(MSG_WARNING, "Empty switch statement"); if (Condition->isConstant()) @@ -7117,7 +7120,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) } } - for (auto &line : *Content) + 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) @@ -7130,7 +7133,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) if (Condition->isConstant()) { ScriptPosition.Message(MSG_WARNING, "Case expression is constant"); - auto &content = *Content; + auto &content = Content; int defaultindex = -1; int defaultbreak = -1; int caseindex = -1; @@ -7182,7 +7185,7 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) int mincase = INT_MAX; int maxcase = INT_MIN; - for (auto line : *Content) + for (auto line : Content) { if (line->ExprType == EFX_CaseStatement) { @@ -7227,7 +7230,7 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) size_t DefaultAddress = build->Emit(OP_JMP, 0); TArray BreakAddresses; - for (auto line : *Content) + for (auto line : Content) { switch (line->ExprType) { @@ -7266,6 +7269,8 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) { build->BackpatchToHere(addr); } + Content.Clear(); + Content.ShrinkToFit(); return ExpEmit(); } @@ -7278,14 +7283,14 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) bool FxSwitchStatement::CheckReturn() { //A switch statement returns when it contains no breaks and ends with a return - for (auto line : *Content) + 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(); + return Content.Size() > 0 && Content.Last()->CheckReturn(); } //========================================================================== @@ -8414,6 +8419,8 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), names.Size() + 1, 1); build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); + names.Clear(); + names.ShrinkToFit(); return dest; } @@ -8433,6 +8440,11 @@ FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false); } +FxLocalVariableDeclaration::~FxLocalVariableDeclaration() +{ + SAFE_DELETE(Init); +} + FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index df0ba75948..46d419051e 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -56,6 +56,8 @@ class VMFunctionBuilder; class FxJumpStatement; +extern FMemArena FxAlloc; + //========================================================================== // // @@ -317,6 +319,14 @@ public: 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) {} }; //========================================================================== @@ -347,6 +357,7 @@ class FxMemberIdentifier : public FxIdentifier public: FxMemberIdentifier(FxExpression *obj, FName i, const FScriptPosition &p); + ~FxMemberIdentifier(); FxExpression *Resolve(FCompileContext&); }; @@ -1264,11 +1275,11 @@ class FxFunctionCall : public FxExpression { FName MethodName; FRandom *RNG; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos); + FxFunctionCall(FName methodname, FName rngname, FArgumentList &args, const FScriptPosition &pos); ~FxFunctionCall(); FxExpression *Resolve(FCompileContext&); }; @@ -1284,11 +1295,11 @@ class FxMemberFunctionCall : public FxExpression { FxExpression *Self; FName MethodName; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos); + FxMemberFunctionCall(FxExpression *self, FName methodname, FArgumentList &args, const FScriptPosition &pos); ~FxMemberFunctionCall(); FxExpression *Resolve(FCompileContext&); }; @@ -1305,11 +1316,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(); @@ -1325,11 +1336,11 @@ 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); @@ -1366,10 +1377,10 @@ class FxVMFunctionCall : public FxExpression bool NoVirtual; FxExpression *Self; PFunction *Function; - FArgumentList *ArgList; + FArgumentList ArgList; public: - FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList *args, const FScriptPosition &pos, bool novirtual); + FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual); ~FxVMFunctionCall(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); @@ -1429,7 +1440,7 @@ public: class FxSwitchStatement : public FxExpression { FxExpression *Condition; - FArgumentList *Content; + FArgumentList Content; struct CaseAddr { @@ -1440,7 +1451,7 @@ class FxSwitchStatement : public FxExpression TArray CaseAddresses; public: - FxSwitchStatement(FxExpression *cond, FArgumentList *content, const FScriptPosition &pos); + FxSwitchStatement(FxExpression *cond, FArgumentList &content, const FScriptPosition &pos); ~FxSwitchStatement(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); @@ -1714,6 +1725,7 @@ 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); diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index c63677e0cf..7e4c3b3987 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -482,7 +482,6 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) else if (sc.CheckToken(TK_Identifier)) { FName identifier = FName(sc.String); - FArgumentList *args; PFunction *func; switch (identifier) @@ -503,18 +502,12 @@ 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(new FxSelf(sc), func, args, sc, false); } } @@ -536,26 +529,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(identifier, NAME_None, args, sc); + while (sc.CheckToken(',')); + sc.MustGetToken(')'); } - catch (...) - { - delete args; - throw; - } - break; + return new FxFunctionCall(identifier, NAME_None, args, sc); } } else diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index d17cb5d4dd..e3cb74c328 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -75,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 @@ -84,7 +84,7 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) { while (i < 5) { - args->Push(new FxIntCast(ParseExpression(sc, bag.Info), true)); + args.Push(new FxIntCast(ParseExpression(sc, bag.Info), true)); i++; if (!sc.CheckToken (',')) break; } @@ -571,13 +571,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(new FxSelf(sc), afd, args->Size() > 0 ? args : NULL, sc, false); - 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); diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index e5ed249b13..acb67e2f54 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -776,4 +776,5 @@ void FFunctionBuildList::Build() } FScriptPosition::StrictErrors = false; mItems.Clear(); + FxAlloc.FreeAllBlocks(); } \ No newline at end of file diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 0d99ee5c2e..7db62d6fb5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2239,7 +2239,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) if (fc->Parameters == nullptr && !(afd->Variants[0].Flags & VARF_Virtual)) { // We can use this function directly without wrapping it in a caller. - return new FxVMFunctionCall(new FxSelf(*af), afd, nullptr, *af, false); + return new FxVMFunctionCall(new FxSelf(*af), afd, FArgumentList(), *af, false); } } else @@ -2563,16 +2563,17 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // - 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(fcall->Parameters), *ast); + 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(fcall->Parameters), *ast); + return new FxMemberFunctionCall(ConvertNode(ema->Left), ema->Right, ConvertNodeList(args, fcall->Parameters), *ast); } case AST_ExprBinary: @@ -2582,7 +2583,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) 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(fcall->Parameters), *ast); + 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. @@ -2832,21 +2833,20 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_ReturnStmt: { auto ret = static_cast(ast); - FArgumentList *args = ConvertNodeList(ret->Values); - if (args->Size() == 0) + FArgumentList args; + ConvertNodeList(args, ret->Values); + if (args.Size() == 0) { return new FxReturnStatement(nullptr, *ast); } - else if (args->Size() == 1) + else if (args.Size() == 1) { - auto arg = (*args)[0]; - (*args)[0] = nullptr; - delete args; - return new FxReturnStatement((*args)[0], *ast); + auto arg = args[0]; + args[0] = nullptr; + return new FxReturnStatement(arg, *ast); } else { - delete args; Error(ast, "Return with multiple values not implemented yet."); return new FxReturnStatement(nullptr, *ast); } @@ -2893,7 +2893,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) { // The switch content is wrapped into a compound statement which needs to be unraveled here. auto cmpnd = static_cast(swtch->Content); - return new FxSwitchStatement(ConvertNode(swtch->Condition), ConvertNodeList(cmpnd->Content), *ast); + FArgumentList args; + return new FxSwitchStatement(ConvertNode(swtch->Condition), ConvertNodeList(args, cmpnd->Content), *ast); } } @@ -2922,17 +2923,16 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } -FArgumentList *ZCCCompiler::ConvertNodeList(ZCC_TreeNode *head) +FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *head) { - FArgumentList *list = new FArgumentList; if (head != nullptr) { auto node = head; do { - list->Push(ConvertNode(node)); + args.Push(ConvertNode(node)); node = node->SiblingNext; } while (node != head); } - return list; + return args; } \ No newline at end of file diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 2e38d68d29..2e8840a467 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -144,7 +144,7 @@ private: FxExpression *ConvertAST(PClass *cclass, ZCC_TreeNode *ast); FxExpression *ConvertNode(ZCC_TreeNode *node); - FArgumentList *ConvertNodeList(ZCC_TreeNode *head); + FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head); DObject *Outer; PClass *ConvertClass; // class type to be used when resoving symbold while converting an AST From 15ddf70f58721314d71e1cd051eb09a92182b087 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Nov 2016 09:27:52 +0100 Subject: [PATCH 218/471] - typo --- src/p_mobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7c973351fa..3205067b83 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -310,7 +310,7 @@ void AActor::InitNativeFields() meta->AddNativeField("DeathType", TypeName, myoffsetof(AActor, DeathType)); meta->AddNativeField("DamageFactor", TypeFloat64, myoffsetof(AActor, DamageFactor)); meta->AddNativeField("DamageMultiply", TypeFloat64, myoffsetof(AActor, DamageMultiply)); - meta->AddNativeField("TelefogSpurceType", TypeActorClass, myoffsetof(AActor, TeleFogSourceType)); + 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); From 65299312813c91dbcd856ce113e55f6c97c3d05f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Nov 2016 14:40:32 +0100 Subject: [PATCH 219/471] fixed and completed the special field init code. Strings can now be used as class members, and so can structs which contain strings. - made 'DamageMultiply' an actor property and moved the initialization of ConversationRoot to the property handler for the compiler to get this stuff out of the type classes. - consolidate default initialization into one function which performs all the required setup. The original implementation did this when adding the fields but that cannot work because at that time no defaults have been created yet. - fixed: When deriving a class the child class's defaults also must initialize the copied parent fields with special initialization. This part was completely missing. - removed DECORATE code for parsing native classes because it's no longer needed. --- src/dobjtype.cpp | 66 +++++++++++++++++------ src/dobjtype.h | 9 +++- src/info.cpp | 29 ---------- src/info.h | 1 - src/scripting/decorate/thingdef_parse.cpp | 38 ++----------- src/scripting/thingdef.h | 2 - src/scripting/thingdef_properties.cpp | 9 ++++ src/scripting/zscript/zcc_compile.cpp | 10 +++- wadsrc/static/zscript/actor.txt | 3 +- 9 files changed, 81 insertions(+), 86 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 71bfd542bd..0e17299cd7 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2778,14 +2778,14 @@ 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; bExported = false; - ConstructNative = NULL; + ConstructNative = nullptr; mDescriptiveName = "Class"; PClass::AllClasses.Push(this); @@ -2969,10 +2969,7 @@ DObject *PClass::CreateNew() const ConstructNative (mem); ((DObject *)mem)->SetClass (const_cast(this)); - if (Defaults != NULL) - { - InitializeSpecials(mem); - } + InitializeSpecials(mem); return (DObject *)mem; } @@ -3037,16 +3034,52 @@ void PClass::Derive(PClass *newclass) { newclass->ParentClass = this; newclass->ConstructNative = ConstructNative; + newclass->Symbols.SetParentTable(&this->Symbols); + newclass->InitializeDefaults(); +} - // 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); + } + } + } } //========================================================================== @@ -3136,7 +3169,6 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) { Defaults = (BYTE *)M_Realloc(Defaults, Size); memset(Defaults + oldsize, 0, Size - oldsize); - type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } return field; } diff --git a/src/dobjtype.h b/src/dobjtype.h index e1f95a8282..62860d0bde 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -137,6 +137,13 @@ struct PSymbolTable // Frees all symbols from this table. void ReleaseSymbols(); + typedef TMap MapType; + + MapType::Iterator GetIterator() + { + return MapType::Iterator(Symbols); + } + // add a name to help debugging. #ifdef _DEBUG FString name; @@ -147,7 +154,6 @@ struct PSymbolTable private: - typedef TMap MapType; PSymbolTable *ParentSymbolTable; MapType Symbols; @@ -761,6 +767,7 @@ 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(); virtual void DeriveData(PClass *newclass) {} static void StaticInit(); diff --git a/src/info.cpp b/src/info.cpp index 09d0905f6c..83b455fb4b 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -355,35 +355,6 @@ size_t PClassActor::PropagateMark() return Super::PropagateMark(); } -//========================================================================== -// -// PClassActor :: InitializeNativeDefaults -// -// This is used by DECORATE to assign ActorInfos to internal classes -// -//========================================================================== - -void PClassActor::InitializeNativeDefaults() -{ - assert(Defaults == NULL); - Defaults = (BYTE *)M_Malloc(Size); - if (ParentClass->Defaults != NULL) - { - memcpy(Defaults, ParentClass->Defaults, ParentClass->Size); - if (Size > ParentClass->Size) - { - memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size); - } - } - else - { - 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; - } -} - //========================================================================== // // PClassActor :: SetReplacement diff --git a/src/info.h b/src/info.h index ad25bdcaf0..6aee02bedb 100644 --- a/src/info.h +++ b/src/info.h @@ -234,7 +234,6 @@ 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); diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 07da3cf573..baa662047c 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -875,7 +875,7 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) // Starts a new actor definition // //========================================================================== -PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native) +PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName) { PClassActor *replacee = NULL; PClassActor *ti = NULL; @@ -908,36 +908,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par 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 = DecoDerivedClass(sc, parent, typeName); ti->Replacee = ti->Replacement = NULL; ti->DoomEdNum = -1; @@ -1025,12 +996,13 @@ 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); diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 6529059e6f..2c13d8eb7d 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -164,8 +164,6 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, // //========================================================================== -PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native); - void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod); FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant); diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index aa45089501..45d78557c0 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -652,6 +652,15 @@ DEFINE_PROPERTY(damage, X, Actor) CreateDamageFunction(bag.Info, defaults, id, true); } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(damagemultiply, F, Actor) +{ + PROP_FLOAT_PARM(dmgm, 0); + defaults->DamageMultiply = dmgm; +} + //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 7db62d6fb5..a2e2262f28 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1917,13 +1917,19 @@ void ZCCCompiler::InitDefaults() if (ti->ParentClass->Defaults == DEFAULTS_VMEXPORT) { ti->ParentClass->Defaults = nullptr; - static_cast(ti->ParentClass)->InitializeNativeDefaults(); + ti->ParentClass->InitializeDefaults(); ti->ParentClass->ParentClass->DeriveData(ti->ParentClass); } - ti->InitializeNativeDefaults(); + 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 diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5aa1af2930..c70ab28a19 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -23,7 +23,8 @@ class Actor : Thinker native FloatBobPhase -1; // randomly initialize by default Gravity 1; Friction 1; - DamageFactor 1.0; + 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; From 5e8c8b80c9ee796d06b8d0fd628d706fc75e7b6c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Nov 2016 14:51:36 +0100 Subject: [PATCH 220/471] - removed bogus token paste operator. --- src/dobject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dobject.h b/src/dobject.h index 3c4b23248d..22ebf13050 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -176,7 +176,7 @@ protected: \ ExportedNatives(ExportedNatives&&) = delete; #define VMEXPORT_NATIVES_FUNC(func) \ - template ret func(void *ptr, args ... arglist) { return static_cast(ptr)->object::##func(arglist...); } + template ret func(void *ptr, args ... arglist) { return static_cast(ptr)->object::func(arglist...); } #define VMEXPORT_NATIVES_END(cls) }; From 8d01ba77339b2fdbcde36077929c106c6591e787 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Fri, 11 Nov 2016 15:22:53 +0100 Subject: [PATCH 221/471] - Fixed Clang errors with delayed templates on. --- src/dobject.h | 11 ++++++----- src/scripting/zscript/zcc_compile.cpp | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index 22ebf13050..d6bae3dad1 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -36,6 +36,7 @@ #include #include "doomtype.h" +#include "i_system.h" class PClass; @@ -202,8 +203,8 @@ protected: \ PClass *cls::StaticType() const { return RegistrationInfo.MyClass; } #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)) + _X_CONSTRUCTOR_##isabstract(cls) \ + _IMP_PCLASS(cls, _X_POINTERS_##ptrs(cls), _X_ABSTRACT_##isabstract(cls), _X_FIELDS_##fields(cls), _X_VMEXPORT_##vmexport(cls)) // 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. @@ -644,15 +645,15 @@ private: public: void Destroy() { - ExportedNatives::Get()->Destroy(this); + ExportedNatives::Get()->template Destroy(this); } void Tick() { - ExportedNatives::Get()->Tick(this); + ExportedNatives::Get()->template Tick(this); } AInventory *DropInventory(AInventory *item) { - return ExportedNatives::Get()->DropInventory(this, item); + return ExportedNatives::Get()->template DropInventory(this, item); } }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index a2e2262f28..7d338cc699 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2244,8 +2244,9 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) { if (fc->Parameters == nullptr && !(afd->Variants[0].Flags & VARF_Virtual)) { + FArgumentList argumentlist; // We can use this function directly without wrapping it in a caller. - return new FxVMFunctionCall(new FxSelf(*af), afd, FArgumentList(), *af, false); + return new FxVMFunctionCall(new FxSelf(*af), afd, argumentlist, *af, false); } } else From a1aceaf04fb3e427b2c8bd9074ab4dcb1e4ff21d Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Fri, 11 Nov 2016 16:01:09 +0100 Subject: [PATCH 222/471] Fixed the remaining errors with GCC --- src/dobject.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index d6bae3dad1..60668ceec1 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -609,6 +609,13 @@ protected: } }; +//Initial list +VMEXPORTED_NATIVES_START + VMEXPORTED_NATIVES_FUNC(Destroy) + VMEXPORTED_NATIVES_FUNC(Tick) + VMEXPORTED_NATIVES_FUNC(DropInventory) +VMEXPORTED_NATIVES_END + class AInventory;// template @@ -672,13 +679,6 @@ ClassReg DVMObject::RegistrationInfo = }; template _DECLARE_TI(DVMObject) -//Initial list -VMEXPORTED_NATIVES_START - VMEXPORTED_NATIVES_FUNC(Destroy) - VMEXPORTED_NATIVES_FUNC(Tick) - VMEXPORTED_NATIVES_FUNC(DropInventory) -VMEXPORTED_NATIVES_END - VMEXPORT_NATIVES_START(DObject, void) VMEXPORT_NATIVES_FUNC(Destroy) VMEXPORT_NATIVES_END(DObject) From 72e77a6c657ee5ed7b8c762723692fb21c6d53c2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Nov 2016 20:05:07 +0100 Subject: [PATCH 223/471] - implemented handling for virtual function. Syntax-wise I chose to make it as strict as possible to reduce the chance of errors: Virtual base functions must be declared with the 'virtual' keyword, and overrides in child classes with the 'override' keyword. This way any mismatch in parameters that otherwise would cause silent failure will outright produce a compile error. --- src/d_dehacked.cpp | 1 - src/dobjtype.cpp | 88 +++++++++++++++++++----- src/dobjtype.h | 9 ++- src/sc_man_scanner.re | 1 + src/sc_man_tokens.h | 1 + src/scripting/codegeneration/codegen.cpp | 76 ++++++++++++++------ src/scripting/vm/vm.h | 2 + src/scripting/vm/vmdisasm.cpp | 1 + src/scripting/vm/vmexec.h | 9 +++ src/scripting/vm/vmops.h | 1 + src/scripting/zscript/zcc-parse.lemon | 2 + src/scripting/zscript/zcc_compile.cpp | 72 +++++++++++++++++-- src/scripting/zscript/zcc_parser.cpp | 2 + src/scripting/zscript/zcc_parser.h | 2 + wadsrc/static/zscript/base.txt | 2 +- 15 files changed, 222 insertions(+), 47 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 8258a656ea..eef9b137a3 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3030,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/dobjtype.cpp b/src/dobjtype.cpp index 0e17299cd7..b7e666fc1b 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -156,14 +156,14 @@ 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; } @@ -3030,12 +3030,14 @@ 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->InitializeDefaults(); + newclass->TypeName = name; + newclass->mDescriptiveName.Format("Class<%s>", name.GetChars()); } //========================================================================== @@ -3082,6 +3084,18 @@ void PClass::InitializeDefaults() } } +//========================================================================== +// +// PClass :: DeriveData +// +// Copies inheritable data to the child class. +// +//========================================================================== + +void PClass::DeriveData(PClass *newclass) +{ +} + //========================================================================== // // PClass :: CreateDerivedClass @@ -3126,11 +3140,10 @@ 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; type->Size = size; - type->bRuntimeClass = true; - type->mDescriptiveName.Format("Class<%s>", name.GetChars()); - Derive(type); + Derive(type, name); + type->InitializeDefaults(); + type->Virtuals = Virtuals; DeriveData(type); if (!notnew) { @@ -3178,8 +3191,7 @@ 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. // //========================================================================== @@ -3201,17 +3213,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; - type->ConstructNative = ConstructNative; + Derive(type, name); type->Size = TentativeClass; - type->bRuntimeClass = true; - type->mDescriptiveName.Format("Class<%s>", name.GetChars()); - type->Symbols.SetParentTable(&Symbols); 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 diff --git a/src/dobjtype.h b/src/dobjtype.h index 62860d0bde..7746dce29a 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -31,6 +31,7 @@ enum 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 ------------------------------------------------------- @@ -756,7 +757,7 @@ 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: @@ -768,8 +769,9 @@ public: 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(); @@ -782,6 +784,7 @@ public: BYTE *Defaults; bool bRuntimeClass; // class was defined at run-time, not compile-time bool bExported; // This type has been declared in a script + TArray Virtuals; // virtual function table void (*ConstructNative)(void *); @@ -838,7 +841,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 }; diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index bc0a4b2e24..194582d73d 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -168,6 +168,7 @@ 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); } 'stop' { RET(TK_Stop); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 2b93c9ac2a..801d02be3d 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -105,6 +105,7 @@ 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'") diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 316ae4246f..49b1d6baef 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6693,12 +6693,16 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } } + 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); - ExpEmit selfemit = Self->Emit(build); + selfemit = Self->Emit(build); assert(selfemit.RegType == REGT_POINTER); build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); count += 1; @@ -6718,8 +6722,9 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } count += 2; } - selfemit.Free(build); + if (staticcall) selfemit.Free(build); } + else staticcall = true; // Emit code to pass explicit parameters for (unsigned i = 0; i < ArgList.Size(); ++i) { @@ -6729,27 +6734,56 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) ArgList.ShrinkToFit(); // 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(), vmfunc->Proto->ReturnTypes[0]->GetRegCount()); - build->Emit(OP_CALL_K, funcaddr, count, 1); - build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum); - return reg; + 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 - { // Call, expecting no results - build->Emit(OP_CALL_K, funcaddr, count, 0); - return ExpEmit(); + { + 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(); + } + + } } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index abce2f5571..6c7878a9a0 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -655,7 +655,9 @@ class VMFunction : public DObject HAS_OBJECT_POINTERS; public: bool Native; + bool Final = false; // cannot be overridden BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action + int VirtualIndex = -1; FName Name; TArray DefaultArgs; diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 239a0dc51d..49c929f053 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -84,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 diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 69f406dd81..a6eda2a249 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -525,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); diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index e7ff19c22d..368f143bdf 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -82,6 +82,7 @@ xx(PARAM, param, __BCP), // push parameter encoded in BC for function call (B=r 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) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index fc707428ea..6caef777e1 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -905,6 +905,8 @@ 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) ::= CONST(T). { X.Int = ZCC_FuncConst; X.SourceLoc = T.SourceLoc; } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 7d338cc699..6c837cead5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1258,7 +1258,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel 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; + 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) { @@ -1894,6 +1894,7 @@ void ZCCCompiler::InitDefaults() 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 { @@ -1989,6 +1990,16 @@ void ZCCCompiler::InitFunctions() 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(); @@ -2030,13 +2041,32 @@ void ZCCCompiler::InitFunctions() 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 ((f->Flags & (ZCC_Action | ZCC_Static)) == (ZCC_Action | ZCC_Static)) + + 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++) { - Error(f, "%s: Action and Static on the same function is not allowed.", FName(f->Name).GetChars()); + 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) { @@ -2193,7 +2223,41 @@ void ZCCCompiler::InitFunctions() { sym->Variants[0].Implementation->DefaultArgs = std::move(argdefaults); } - // todo: Check inheritance. + + 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); + } + } } } } diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index c84b72c666..098a38d823 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -123,6 +123,8 @@ static void InitTokenMap() 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); diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 01ea0d2d07..ec8bd956a6 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -33,6 +33,8 @@ enum ZCC_FuncConst = 1 << 10, ZCC_Abstract = 1 << 11, ZCC_Extension = 1 << 12, + ZCC_Virtual = 1 << 13, + ZCC_Override = 1 << 14, }; // Function parameter modifiers diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 4564f0e86d..33c1c61352 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -1,6 +1,6 @@ class Object native { - /*virtual*/ native void Destroy(); + virtual native void Destroy(); native class GetClass(); } From 924096694e700b7d8c9678ae8484487487ece845 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Nov 2016 21:52:08 +0100 Subject: [PATCH 224/471] - implemented super calls and proper dispatch of scripted virtual overrides for Destroy. --- src/dobject.cpp | 1 + src/dobject.h | 30 +++++++++++++++++-- src/scripting/codegeneration/codegen.cpp | 38 ++++++++++++++++++++++-- src/scripting/codegeneration/codegen.h | 18 +++++++++++ src/scripting/zscript/zcc_compile.cpp | 10 +++++++ 5 files changed, 93 insertions(+), 4 deletions(-) diff --git a/src/dobject.cpp b/src/dobject.cpp index e21d07526c..6fa7d53175 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -366,6 +366,7 @@ void DObject::Destroy () DEFINE_ACTION_FUNCTION(DObject, Destroy) { PARAM_SELF_PROLOGUE(DObject); + self->VMSuperCall(); self->Destroy(); return 0; } diff --git a/src/dobject.h b/src/dobject.h index 60668ceec1..d5e11a04cb 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -235,7 +235,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, @@ -244,6 +243,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; @@ -498,6 +499,11 @@ public: void SerializeUserVars(FSerializer &arc); virtual void Serialize(FSerializer &arc); + void VMSuperCall() + { + ObjectFlags |= OF_SuperCall; + } + void ClearClass() { Class = NULL; @@ -652,7 +658,27 @@ private: public: void Destroy() { - ExportedNatives::Get()->template Destroy(this); + if (ObjectFlags & OF_SuperCall) + { + 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(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); + } } void Tick() { diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 49b1d6baef..dfe02404b5 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1350,7 +1350,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) // first deal with the simple types if (ValueType == TypeError || basex->ValueType == TypeError) { - ScriptPosition.Message(MSG_ERROR, "Trying to cast to invalid type. This error message means that somewhere in the script compiler an error check is missing."); + ScriptPosition.Message(MSG_ERROR, "Trying to cast to invalid type."); delete this; return nullptr; } @@ -5433,6 +5433,25 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +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; +} + //========================================================================== // // @@ -6268,6 +6287,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) ABORT(ctx.Class); PClass *cls; bool staticonly = false; + bool novirtual = false; if (Self->ExprType == EFX_Identifier) { @@ -6282,6 +6302,15 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } 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. @@ -6349,7 +6378,7 @@ isresolved: // 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); + auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly|novirtual); if (Self == self) Self = nullptr; delete this; return x->Resolve(ctx); @@ -6971,6 +7000,11 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx) { fail = true; } + if (Expressions[i]->ValueType == TypeError) + { + ScriptPosition.Message(MSG_ERROR, "Invalid statement"); + fail = true; + } } if (fail) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 46d419051e..d5f812d528 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -276,6 +276,7 @@ enum EFxType EFX_TypeCheck, EFX_DynamicCast, EFX_GlobalVariable, + EFX_Super, EFX_COUNT }; @@ -1241,6 +1242,23 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxSuper +// +//========================================================================== + +class FxSuper : public FxSelf +{ +public: + FxSuper(const FScriptPosition&pos) + : FxSelf(pos) + { + ExprType = EFX_Super; + } + FxExpression *Resolve(FCompileContext&); +}; + //========================================================================== // // FxArrayElement diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6c837cead5..f52e0e0627 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2898,6 +2898,16 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) 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); From a5f9eb5be1f885346d1fa00a8edb1b6d0489b4b6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Nov 2016 22:14:29 +0100 Subject: [PATCH 225/471] - Scriptified Heretic's knight. --- src/CMakeLists.txt | 1 - src/g_heretic/a_hereticmisc.cpp | 1 - src/g_heretic/a_knight.cpp | 70 ------------------------ src/p_mobj.cpp | 9 +++ src/scripting/codegeneration/codegen.cpp | 2 +- wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/heretic/knight.txt | 49 +++++++++++++++-- 7 files changed, 55 insertions(+), 78 deletions(-) delete mode 100644 src/g_heretic/a_knight.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8b75d7b62a..9f5b0346c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -857,7 +857,6 @@ set( NOT_COMPILED_SOURCE_FILES g_heretic/a_hereticartifacts.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 diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 2ea39a4bcb..c6192b8e23 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -26,7 +26,6 @@ #include "a_hereticartifacts.cpp" #include "a_hereticweaps.cpp" #include "a_ironlich.cpp" -#include "a_knight.cpp" #include "a_wizard.cpp" diff --git a/src/g_heretic/a_knight.cpp b/src/g_heretic/a_knight.cpp deleted file mode 100644 index a3125f77d4..0000000000 --- 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 "vm.h" -*/ - -static FRandom pr_dripblood ("DripBlood"); -static FRandom pr_knightatk ("KnightAttack"); - -//---------------------------------------------------------------------------- -// -// PROC A_DripBlood -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_DripBlood) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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/p_mobj.cpp b/src/p_mobj.cpp index 3205067b83..400fe8c746 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6077,6 +6077,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) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index dfe02404b5..5e212dfe3c 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7000,7 +7000,7 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx) { fail = true; } - if (Expressions[i]->ValueType == TypeError) + else if (Expressions[i]->ValueType == TypeError) { ScriptPosition.Message(MSG_ERROR, "Invalid statement"); fail = true; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c70ab28a19..0baac6bf0a 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -63,6 +63,7 @@ class Actor : Thinker native native Actor GetPointer(int aaptr); 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 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); diff --git a/wadsrc/static/zscript/heretic/knight.txt b/wadsrc/static/zscript/heretic/knight.txt index 1eb341859b..01b7252c60 100644 --- a/wadsrc/static/zscript/heretic/knight.txt +++ b/wadsrc/static/zscript/heretic/knight.txt @@ -22,8 +22,6 @@ class Knight : Actor HitObituary "$OB_BONEKNIGHTHIT"; DropItem "CrossbowAmmo", 84, 5; } - - native void A_KnightAttack (); States { @@ -56,6 +54,34 @@ class Knight : Actor 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"); + } + } } @@ -116,8 +142,6 @@ class RedAxe : KnightAxe Damage 7; } - native void A_DripBlood (); - States { Spawn: @@ -127,5 +151,20 @@ class RedAxe : KnightAxe 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; + } } - From 14a9c13113982870410856bb7faf8d6633208d4f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Nov 2016 23:32:13 +0100 Subject: [PATCH 226/471] - scriptified Heretic's wizard. --- src/CMakeLists.txt | 1 - src/g_heretic/a_wizard.cpp | 95 ------------------------ src/p_mobj.cpp | 27 +++++++ src/scripting/codegeneration/codegen.cpp | 14 +++- wadsrc/static/zscript/actor.txt | 24 ++++++ wadsrc/static/zscript/constants.txt | 7 ++ wadsrc/static/zscript/heretic/wizard.txt | 69 +++++++++++++++-- 7 files changed, 135 insertions(+), 102 deletions(-) delete mode 100644 src/g_heretic/a_wizard.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9f5b0346c4..b2f23afb14 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -857,7 +857,6 @@ set( NOT_COMPILED_SOURCE_FILES g_heretic/a_hereticartifacts.cpp g_heretic/a_hereticweaps.cpp g_heretic/a_ironlich.cpp - g_heretic/a_wizard.cpp g_hexen/a_bats.cpp g_hexen/a_bishop.cpp g_hexen/a_blastradius.cpp diff --git a/src/g_heretic/a_wizard.cpp b/src/g_heretic/a_wizard.cpp deleted file mode 100644 index 271fd55926..0000000000 --- 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 "vm.h" -*/ - -static FRandom pr_wizatk3 ("WizAtk3"); - -//---------------------------------------------------------------------------- -// -// PROC A_GhostOff -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_GhostOff) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->RenderStyle = STYLE_Normal; - self->flags3 &= ~MF3_GHOST; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WizAtk1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_WizAtk1) -{ - PARAM_SELF_PROLOGUE(AActor); - - A_FaceTarget (self); - CALL_ACTION(A_GhostOff, self); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WizAtk2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_WizAtk2) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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/p_mobj.cpp b/src/p_mobj.cpp index 400fe8c746..94b7391358 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6041,6 +6041,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 @@ -6283,6 +6290,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)); +} + /* ================ = @@ -6879,6 +6899,13 @@ DEFINE_ACTION_FUNCTION(AActor, GetDefaultByType) 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) { diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 5e212dfe3c..2759e41bad 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6680,7 +6680,19 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) 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) { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0baac6bf0a..d9fd23a464 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -56,6 +56,8 @@ class Actor : Thinker native 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 void SetOrigin(vector3 newpos, bool moving); @@ -64,6 +66,8 @@ class Actor : Thinker native 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); @@ -143,6 +147,26 @@ class Actor : Thinker native 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) { diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 9562e3f407..7c3038a749 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -883,3 +883,10 @@ 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/heretic/wizard.txt b/wadsrc/static/zscript/heretic/wizard.txt index d33e2dd8a6..d146ae2203 100644 --- a/wadsrc/static/zscript/heretic/wizard.txt +++ b/wadsrc/static/zscript/heretic/wizard.txt @@ -26,11 +26,6 @@ class Wizard : Actor DropItem "ArtiTomeOfPower", 4, 0; } - native void A_GhostOff (); - native void A_WizAtk1 (); - native void A_WizAtk2 (); - native void A_WizAtk3 (); - States { Spawn: @@ -70,6 +65,70 @@ class Wizard : Actor 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 -------------------------------------------------------- From 696af7d7e540a85cc11fc667ddc0f6817b470271 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 00:33:40 +0100 Subject: [PATCH 227/471] - Moved all virtual function related template code to its own file because it depends on includes that cannot be done in dobject.h. --- src/actor.h | 4 - src/dobject.cpp | 1 + src/dobject.h | 120 ----------------------------- src/dthinker.cpp | 1 + src/dthinker.h | 4 - src/g_heretic/a_hereticmisc.cpp | 1 - src/p_mobj.cpp | 1 + src/p_user.cpp | 1 + src/virtual.h | 132 ++++++++++++++++++++++++++++++++ 9 files changed, 136 insertions(+), 129 deletions(-) create mode 100644 src/virtual.h diff --git a/src/actor.h b/src/actor.h index 6f5ba46a32..833cd2c0ab 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1419,10 +1419,6 @@ public: }; -VMEXPORT_NATIVES_START(AActor, DThinker) - VMEXPORT_NATIVES_FUNC(DropInventory) -VMEXPORT_NATIVES_END(AActor) - class FActorIterator { public: diff --git a/src/dobject.cpp b/src/dobject.cpp index 6fa7d53175..ad575bebcc 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" //========================================================================== // diff --git a/src/dobject.h b/src/dobject.h index d5e11a04cb..d858e577f7 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -153,34 +153,6 @@ protected: \ #define HAS_FIELDS \ static void InitNativeFields(); -// 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) }; - #if defined(_MSC_VER) # pragma section(".creg$u",read) # define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo; @@ -615,100 +587,8 @@ protected: } }; -//Initial list -VMEXPORTED_NATIVES_START - VMEXPORTED_NATIVES_FUNC(Destroy) - VMEXPORTED_NATIVES_FUNC(Tick) - VMEXPORTED_NATIVES_FUNC(DropInventory) -VMEXPORTED_NATIVES_END - class AInventory;// -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 (ObjectFlags & OF_SuperCall) - { - 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(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); - } - } - void Tick() - { - ExportedNatives::Get()->template Tick(this); - } - AInventory *DropInventory(AInventory *item) - { - return ExportedNatives::Get()->template DropInventory(this, item); - } -}; - -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) - // 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/dthinker.cpp b/src/dthinker.cpp index 912b5642ef..06cd5dbfab 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; diff --git a/src/dthinker.h b/src/dthinker.h index e1020544cf..95985c2fb4 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -108,10 +108,6 @@ private: DThinker *NextThinker, *PrevThinker; }; -VMEXPORT_NATIVES_START(DThinker, DObject) - VMEXPORT_NATIVES_FUNC(Tick) -VMEXPORT_NATIVES_END(DThinker) - class FThinkerIterator { protected: diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index c6192b8e23..35b24eb932 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -26,7 +26,6 @@ #include "a_hereticartifacts.cpp" #include "a_hereticweaps.cpp" #include "a_ironlich.cpp" -#include "a_wizard.cpp" static FRandom pr_podpain ("PodPain"); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 94b7391358..65fd1ad348 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -72,6 +72,7 @@ #include "serializer.h" #include "r_utility.h" #include "thingdef.h" +#include "virtual.h" // MACROS ------------------------------------------------------------------ diff --git a/src/p_user.cpp b/src/p_user.cpp index f4e52ac2f8..6b0b2cfe68 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -59,6 +59,7 @@ #include "p_blockmap.h" #include "a_morph.h" #include "p_spec.h" +#include "virtual.h" static FRandom pr_skullpop ("SkullPop"); diff --git a/src/virtual.h b/src/virtual.h new file mode 100644 index 0000000000..377ec2ce8a --- /dev/null +++ b/src/virtual.h @@ -0,0 +1,132 @@ + + + +// 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(DropInventory) +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 (ObjectFlags & OF_SuperCall) + { + 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(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); + } + } + void Tick() + { + ExportedNatives::Get()->template Tick(this); + } + AInventory *DropInventory(AInventory *item) + { + return ExportedNatives::Get()->template DropInventory(this, item); + } +}; + +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_END(DThinker) + +VMEXPORT_NATIVES_START(AActor, DThinker) + VMEXPORT_NATIVES_FUNC(DropInventory) +VMEXPORT_NATIVES_END(AActor) + From 5bc89e7efcda661f5a2ebc5ffdc1b59ebb5f0eda Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 00:57:21 +0100 Subject: [PATCH 228/471] - added a VM handler for PostBeginPlay. - made a few changes to let the templates compile again on Linux. --- src/virtual.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/virtual.h b/src/virtual.h index 377ec2ce8a..188519f712 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -34,6 +34,7 @@ VMEXPORTED_NATIVES_START VMEXPORTED_NATIVES_FUNC(Destroy) VMEXPORTED_NATIVES_FUNC(Tick) + VMEXPORTED_NATIVES_FUNC(PostBeginPlay) VMEXPORTED_NATIVES_FUNC(DropInventory) VMEXPORTED_NATIVES_END @@ -71,9 +72,9 @@ private: public: void Destroy() { - if (ObjectFlags & OF_SuperCall) + if (this->ObjectFlags & OF_SuperCall) { - ObjectFlags &= OF_SuperCall; + this->ObjectFlags &= OF_SuperCall; ExportedNatives::Get()->template Destroy(this); } else @@ -90,13 +91,19 @@ public: // Without the type cast this picks the 'void *' assignment... VMValue params[1] = { (DObject*)this }; VMFrameStack stack; - stack.Call(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); + 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); + } + AInventory *DropInventory(AInventory *item) { return ExportedNatives::Get()->template DropInventory(this, item); @@ -124,7 +131,8 @@ VMEXPORT_NATIVES_END(DObject) VMEXPORT_NATIVES_START(DThinker, DObject) VMEXPORT_NATIVES_FUNC(Tick) -VMEXPORT_NATIVES_END(DThinker) + VMEXPORT_NATIVES_FUNC(PostBeginPlay) + VMEXPORT_NATIVES_END(DThinker) VMEXPORT_NATIVES_START(AActor, DThinker) VMEXPORT_NATIVES_FUNC(DropInventory) From 34fc6323a471c2f46bd47bffdab39ed27fe997c8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 09:33:43 +0100 Subject: [PATCH 229/471] - scriptified Hexen's bats. - removed AMinotaurFriend::IsOkayToAttack. The condition it checks (i.e. friendliness with player) is already covered by the base version of this function so this is quite redundant. - removed a few 'virtual' qualifiers from functions that never get overridden. --- src/actor.h | 8 +-- src/g_hexen/a_bats.cpp | 98 ---------------------------- src/g_hexen/a_hexenmisc.cpp | 1 - src/g_raven/a_minotaur.cpp | 6 -- src/g_raven/ravenshared.h | 1 - src/p_mobj.cpp | 8 +++ src/virtual.h | 10 +-- wadsrc/static/zscript/actor.txt | 7 ++ wadsrc/static/zscript/hexen/bats.txt | 82 +++++++++++++++++++++-- 9 files changed, 98 insertions(+), 123 deletions(-) delete mode 100644 src/g_hexen/a_bats.cpp diff --git a/src/actor.h b/src/actor.h index 833cd2c0ab..1228398508 100644 --- a/src/actor.h +++ b/src/actor.h @@ -614,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. @@ -733,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); @@ -958,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); @@ -970,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; diff --git a/src/g_hexen/a_bats.cpp b/src/g_hexen/a_bats.cpp deleted file mode 100644 index 02fc6111ea..0000000000 --- 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 "vm.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_SELF_PROLOGUE(AActor); - - self->special1 = 0; // Frequency count - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BatSpawn) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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(self->Speed, newangle); - - 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_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 2c91f37b24..da17d37be7 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -27,7 +27,6 @@ #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" diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index 36946ba871..dd4e4a8b81 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -117,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 ---------------------------------------- //---------------------------------------------------------------------------- diff --git a/src/g_raven/ravenshared.h b/src/g_raven/ravenshared.h index 81824a9577..3c6019ae72 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/p_mobj.cpp b/src/p_mobj.cpp index 65fd1ad348..83e4d0282e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6885,6 +6885,14 @@ DEFINE_ACTION_FUNCTION(AActor, 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); diff --git a/src/virtual.h b/src/virtual.h index 188519f712..d3a2bfa3a7 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -35,7 +35,6 @@ VMEXPORTED_NATIVES_START VMEXPORTED_NATIVES_FUNC(Destroy) VMEXPORTED_NATIVES_FUNC(Tick) VMEXPORTED_NATIVES_FUNC(PostBeginPlay) - VMEXPORTED_NATIVES_FUNC(DropInventory) VMEXPORTED_NATIVES_END template @@ -103,11 +102,6 @@ public: { ExportedNatives::Get()->template PostBeginPlay(this); } - - AInventory *DropInventory(AInventory *item) - { - return ExportedNatives::Get()->template DropInventory(this, item); - } }; template @@ -134,7 +128,7 @@ VMEXPORT_NATIVES_START(DThinker, DObject) VMEXPORT_NATIVES_FUNC(PostBeginPlay) VMEXPORT_NATIVES_END(DThinker) +/* VMEXPORT_NATIVES_START(AActor, DThinker) - VMEXPORT_NATIVES_FUNC(DropInventory) VMEXPORT_NATIVES_END(AActor) - +*/ \ No newline at end of file diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index d9fd23a464..2fd6c4e036 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -53,6 +53,12 @@ class Actor : Thinker native { 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); @@ -84,6 +90,7 @@ class Actor : Thinker native 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); diff --git a/wadsrc/static/zscript/hexen/bats.txt b/wadsrc/static/zscript/hexen/bats.txt index 1e6ee459f5..a530da1766 100644 --- a/wadsrc/static/zscript/hexen/bats.txt +++ b/wadsrc/static/zscript/hexen/bats.txt @@ -9,9 +9,6 @@ class BatSpawner : SwitchableDecoration RenderStyle "None"; } - native void A_BatSpawnInit(); - native void A_BatSpawn(); - States { Spawn: @@ -24,6 +21,48 @@ class BatSpawner : SwitchableDecoration 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 ---------------------------------------------------------------------- @@ -39,8 +78,6 @@ class Bat : Actor +NOTELEPORT +CANPASS } - native void A_BatMove(); - States { Spawn: @@ -50,4 +87,39 @@ class Bat : Actor ABAT A 2; Stop; } + + void A_BatMove() + { + if (special2 < 0) + { + SetState ("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; + } } + + + + From 30a21710801b367e904cceb5b15e636173593d05 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 10:06:26 +0100 Subject: [PATCH 230/471] - let "" be synonymous with 'none' in ZScript. --- src/scripting/codegeneration/codegen.h | 6 +++++- src/scripting/vm/vmexec.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index d5f812d528..2f82dba573 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -192,7 +192,11 @@ struct ExpVal FName GetName() const { - if (Type == TypeString) return FName(*(FString *)&pointer); + if (Type == TypeString) + { + if (((FString *)&pointer)->Len() == 0) return NAME_None; + return FName(*(FString *)&pointer); + } return Type == TypeName ? ENamedName(Int) : NAME_None; } }; diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index a6eda2a249..02e0db3dea 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1686,7 +1686,7 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c case CAST_S2N: ASSERTD(a); ASSERTS(b); - reg.d[a] = FName(reg.s[b]); + reg.d[a] = reg.s[b].Len() == 0? FName(NAME_None) : FName(reg.s[b]); break; case CAST_N2S: From e009cbec9e80b93f91244b3d81d850f549018d8b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 10:17:57 +0100 Subject: [PATCH 231/471] - fixed: PClass::StaticShutdown did not remove the class pointers for VM base classes from their class registration entries. --- src/dobjtype.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index b7e666fc1b..a7d70ca391 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2731,9 +2731,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; } } From 479b216c06bbcd176cbeed8d8476c723b71bda8c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 13:09:19 +0100 Subject: [PATCH 232/471] - fixed: ZScript did not properly fill in tentatively created classes from defaults processing. The proper setup for such classes was only done in CreateDerivedClass, but not in FindClassTentative itself. This extends CreateDerivedClass to allow it to create a class without fully initializing it. --- src/dobjtype.cpp | 28 ++++++++++++++++++--------- src/dobjtype.h | 11 +---------- src/scripting/zscript/zcc_compile.cpp | 25 +++++++++++++++--------- src/scripting/zscript/zcc_parser.cpp | 1 - 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index a7d70ca391..a6408c3077 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3120,12 +3120,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 @@ -3142,11 +3149,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->Size = size; Derive(type, name); - type->InitializeDefaults(); - type->Virtuals = Virtuals; - DeriveData(type); + type->Size = size; + if (size != TentativeClass) + { + type->InitializeDefaults(); + type->Virtuals = Virtuals; + DeriveData(type); + } if (!notnew) { type->InsertIntoHash(); @@ -3197,7 +3207,7 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) // //========================================================================== -PClass *PClass::FindClassTentative(FName name, bool fatal) +PClass *PClass::FindClassTentative(FName name) { if (name == NAME_None) { diff --git a/src/dobjtype.h b/src/dobjtype.h index 7746dce29a..be15193a4d 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -145,15 +145,6 @@ struct PSymbolTable return MapType::Iterator(Symbols); } - // add a name to help debugging. -#ifdef _DEBUG - FString name; - void SetName(const char *nm) { name = nm; } -#else - void SetName(const char *) {} -#endif - - private: PSymbolTable *ParentSymbolTable; @@ -828,7 +819,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; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f52e0e0627..c42ef299a4 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -89,10 +89,6 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) PSymbolTreeNode *childnode; ZCC_Enum *enumType = nullptr; - FString name; - name << "nodes - " << FName(cnode->NodeName); - cls->TreeNodes.SetName(name); - // Need to check if the class actually has a body. if (node != nullptr) do { @@ -418,7 +414,6 @@ void ZCCCompiler::CreateStructTypes() 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()); - s->Type()->Symbols.SetName(FName(s->NodeName())); GlobalSymbols.AddSymbol(s->strct->Symbol); for (auto e : s->Enums) @@ -486,6 +481,7 @@ void ZCCCompiler::CreateClassTypes() 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) @@ -523,12 +519,25 @@ void ZCCCompiler::CreateClassTypes() } // We will never get here if the name is a duplicate, so we can just do the assignment. - c->cls->Type = parent->FindClassTentative(c->NodeName()); + 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); - c->Type()->Symbols.SetName(c->NodeName()); Classes.Push(c); OrigClasses.Delete(i--); donesomething = true; @@ -553,7 +562,6 @@ void ZCCCompiler::CreateClassTypes() c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()); c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); GlobalSymbols.AddSymbol(c->cls->Symbol); - c->Type()->Symbols.SetName(c->NodeName()); Classes.Push(c); OrigClasses.Delete(i--); donesomething = true; @@ -569,7 +577,6 @@ void ZCCCompiler::CreateClassTypes() 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()); - c->Type()->Symbols.SetName(FName(c->NodeName()).GetChars()); GlobalSymbols.AddSymbol(c->cls->Symbol); Classes.Push(c); } diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 098a38d823..de3d2c7e15 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -375,7 +375,6 @@ static void DoParse(int lumpnum) } PSymbolTable symtable; - symtable.SetName("Global_Node"); ZCCCompiler cc(state, NULL, symtable, GlobalSymbols, lumpnum); cc.Compile(); From 5adb2fe690c67050c39e1f60fd327764b9a4800d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 13:11:32 +0100 Subject: [PATCH 233/471] - fixed copy/paste error in A_UnsetReflectiveInvulnerable. --- wadsrc/static/zscript/actor.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2fd6c4e036..a65062cfb1 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -130,7 +130,7 @@ class Actor : Thinker native void A_SetReflective() { bReflective = true; } void A_UnSetReflective() { bReflective = false; } void A_SetReflectiveInvulnerable() { bInvulnerable = true; bReflective = true; } - void A_UnSetReflectiveInvulnerable() { bInvulnerable = true; bReflective = false; } + 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; } From fe74a144315be2a97412490d86c22e3e946b9459 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 14:48:10 +0100 Subject: [PATCH 234/471] - fixed: A_GiveInventory should not try to give stuff to an owned inventory item, because it doesn't own its Inventory pointer - it is used for the linked list of the owner's inventory. --- src/CMakeLists.txt | 1 - src/p_actionfunctions.cpp | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2f23afb14..66371220b9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -857,7 +857,6 @@ set( NOT_COMPILED_SOURCE_FILES g_heretic/a_hereticartifacts.cpp g_heretic/a_hereticweaps.cpp g_heretic/a_ironlich.cpp - g_hexen/a_bats.cpp g_hexen/a_bishop.cpp g_hexen/a_blastradius.cpp g_hexen/a_boostarmor.cpp diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 1cfc44ae2f..a99ba9ab61 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -2491,6 +2491,11 @@ static bool DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS) { // 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) { From a603af805c8aebfa637aa2847e7e0e3aaa6b8bc6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 15:21:59 +0100 Subject: [PATCH 235/471] - fixed identifier resolution in FxIdentifier for action functions with a different invoker than self. - fixed creation of direct function invocations on a state line. In order to receive the implicit arguments this needs to be wrapped into a compound statement so that the local variable getter works. --- src/dobjtype.cpp | 4 ++++ src/scripting/codegeneration/codegen.cpp | 30 ++++++++++++++++-------- src/scripting/zscript/zcc_compile.cpp | 4 +++- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index a6408c3077..c2b1008df9 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2495,6 +2495,10 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra variant.SelfClass = dyn_cast(selftypeptr->PointedType); assert(variant.SelfClass != nullptr); } + else + { + variant.SelfClass = nullptr; + } return Variants.Push(variant); } diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 2759e41bad..dac88aa76b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5096,14 +5096,11 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& 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; - if ((sym = ctx.FindInClass(Identifier, symtbl)) != nullptr) + + // first check fields in self + if ((sym = ctx.FindInSelfClass(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); - } - else if (sym->IsKindOf(RUNTIME_CLASS(PField))) + if (sym->IsKindOf(RUNTIME_CLASS(PField))) { if (!ctx.Function) { @@ -5161,6 +5158,18 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) 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); } + } + + // now constants 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); + } else { if (sym->IsKindOf(RUNTIME_CLASS(PFunction))) @@ -5177,7 +5186,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } // now check the global identifiers. - else if ((sym = ctx.FindGlobal(Identifier)) != nullptr) + if (newex == nullptr && (sym = ctx.FindGlobal(Identifier)) != nullptr) { if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) { @@ -5197,12 +5206,13 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } // and line specials - else if ((num = P_FindLineSpecial(Identifier, nullptr, nullptr))) + 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); } - else + + if (newex == nullptr) { ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); delete this; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index c42ef299a4..c5ac21783b 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2577,7 +2577,9 @@ FxExpression *ZCCCompiler::ConvertAST(PClass *cls, ZCC_TreeNode *ast) // 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) { - return new FxReturnStatement(ConvertNode(ast), *ast); + auto cp = new FxCompoundStatement(*ast); + cp->Add(new FxReturnStatement(ConvertNode(ast), *ast)); + return cp; } else { From 91938cd35b69ef72f975a852d973567a347ade6e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 15:26:29 +0100 Subject: [PATCH 236/471] - fixed: The pointer defaulr for GetDistance was incorrect. --- wadsrc/static/zscript/actor.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index a65062cfb1..8a5b56e0c8 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -107,7 +107,7 @@ class Actor : Thinker native // 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_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(); From 8f8017836ffb6839fb767991ac06ea92ca1b85e4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 16:32:26 +0100 Subject: [PATCH 237/471] - scriptified Hexen's Bishop. --- src/CMakeLists.txt | 1 - src/g_hexen/a_bishop.cpp | 230 ------------------------- src/g_hexen/a_hexenmisc.cpp | 1 - src/p_mobj.cpp | 24 +++ wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/hexen/bishop.txt | 180 ++++++++++++++++++- 6 files changed, 196 insertions(+), 242 deletions(-) delete mode 100644 src/g_hexen/a_bishop.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 66371220b9..d0f73bc9ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -857,7 +857,6 @@ set( NOT_COMPILED_SOURCE_FILES g_heretic/a_hereticartifacts.cpp g_heretic/a_hereticweaps.cpp g_heretic/a_ironlich.cpp - g_hexen/a_bishop.cpp g_hexen/a_blastradius.cpp g_hexen/a_boostarmor.cpp g_hexen/a_centaur.cpp diff --git a/src/g_hexen/a_bishop.cpp b/src/g_hexen/a_bishop.cpp deleted file mode 100644 index bd9f240618..0000000000 --- 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 "vm.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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - A_Weave(self, 2, 2, 2., 1.); - return 0; -} - -//============================================================================ -// -// A_BishopDecide -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopDecide) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (pr_decide() < 220) - { - return 0; - } - else - { - self->SetState (self->FindState ("Blur")); - } - return 0; -} - -//============================================================================ -// -// A_BishopDoBlur -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BishopDoBlur) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index da17d37be7..1bb722d068 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -27,7 +27,6 @@ #include "vm.h" // Include all the Hexen stuff here to reduce compile time -#include "a_bishop.cpp" #include "a_blastradius.cpp" #include "a_boostarmor.cpp" #include "a_centaur.cpp" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 83e4d0282e..bd05941b33 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6939,6 +6939,30 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) 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); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 8a5b56e0c8..97b961eea1 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -95,6 +95,7 @@ class Actor : Thinker native 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(); @@ -292,7 +293,6 @@ class Actor : Thinker native native void A_GenericFreezeDeath(); native void A_IceGuyDie(); native void A_CentaurDefend(); - native void A_BishopMissileWeave(); native void A_CStaffMissileSlither(); native void A_PlayerScream(); native void A_SkullPop(class skulltype = "BloodySkull"); diff --git a/wadsrc/static/zscript/hexen/bishop.txt b/wadsrc/static/zscript/hexen/bishop.txt index d116ee9324..d846a64029 100644 --- a/wadsrc/static/zscript/hexen/bishop.txt +++ b/wadsrc/static/zscript/hexen/bishop.txt @@ -3,6 +3,9 @@ class Bishop : Actor { + int missilecount; + int bobstate; + Default { Health 130; @@ -23,14 +26,6 @@ class Bishop : Actor Obituary"$OB_BISHOP"; } - native void A_BishopChase(); - native void A_BishopDecide(); - native void A_BishopDoBlur(); - native void A_BishopSpawnBlur(); - native void A_BishopPainBlur(); - native void A_BishopAttack(); - native void A_BishopAttack2(); - States { Spawn: @@ -67,7 +62,7 @@ class Bishop : Actor 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 N 4 A_SpawnItemEx("BishopPuff", 0,0,40, 0,0,-0.5); BISH O 4 A_QueueCorpse; BISH P -1; Stop; @@ -76,6 +71,172 @@ class Bishop : Actor 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) + { + SetState ("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) + { + SetState ("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 -------------------------------------------------------------- @@ -164,3 +325,4 @@ class BishopBlur : Actor Stop; } } + From 213b3f1fe486b63e79ef5a7dd7c3855d2592974d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 17:21:11 +0100 Subject: [PATCH 238/471] - scriptified Hexen's Centaur. --- src/CMakeLists.txt | 1 - src/g_hexen/a_centaur.cpp | 30 ------------------------- src/g_hexen/a_hexenmisc.cpp | 1 - wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/hexen/centaur.txt | 23 +++++++++++++++++-- wadsrc/static/zscript/hexen/demons.txt | 26 ++++++++++++--------- 6 files changed, 37 insertions(+), 45 deletions(-) delete mode 100644 src/g_hexen/a_centaur.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0f73bc9ba..ffd9f339a4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -859,7 +859,6 @@ set( NOT_COMPILED_SOURCE_FILES g_heretic/a_ironlich.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 diff --git a/src/g_hexen/a_centaur.cpp b/src/g_hexen/a_centaur.cpp deleted file mode 100644 index 9bf5e60467..0000000000 --- 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 "vm.h" -*/ - -static FRandom pr_centaurdefend ("CentaurDefend"); - -//============================================================================ -// -// A_CentaurDefend -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CentaurDefend) -{ - PARAM_SELF_PROLOGUE(AActor); - - 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_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 1bb722d068..3676bf21b7 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -29,7 +29,6 @@ // Include all the Hexen stuff here to reduce compile time #include "a_blastradius.cpp" #include "a_boostarmor.cpp" -#include "a_centaur.cpp" #include "a_clericflame.cpp" #include "a_clericholy.cpp" #include "a_clericmace.cpp" diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 97b961eea1..c7a0090387 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -292,7 +292,6 @@ class Actor : Thinker native native void A_FreezeDeathChunks(); native void A_GenericFreezeDeath(); native void A_IceGuyDie(); - native void A_CentaurDefend(); native void A_CStaffMissileSlither(); native void A_PlayerScream(); native void A_SkullPop(class skulltype = "BloodySkull"); diff --git a/wadsrc/static/zscript/hexen/centaur.txt b/wadsrc/static/zscript/hexen/centaur.txt index 37a8d6b11d..f8c8e2c3d3 100644 --- a/wadsrc/static/zscript/hexen/centaur.txt +++ b/wadsrc/static/zscript/hexen/centaur.txt @@ -54,14 +54,17 @@ class Centaur : Actor XDeath: CTXD A 4; CTXD B 4 A_NoBlocking; - CTXD C 0 A_SpawnItemEx("CentaurSword", 0, 0, 45, + 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); - CTXD C 4 A_SpawnItemEx("CentaurShield", 0, 0, 45, + 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; @@ -74,6 +77,22 @@ class Centaur : Actor 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); + } } } diff --git a/wadsrc/static/zscript/hexen/demons.txt b/wadsrc/static/zscript/hexen/demons.txt index 56b4f3bdac..8aa65629de 100644 --- a/wadsrc/static/zscript/hexen/demons.txt +++ b/wadsrc/static/zscript/hexen/demons.txt @@ -56,11 +56,14 @@ class Demon1 : Actor 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); + 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; @@ -261,11 +264,14 @@ class Demon2 : Demon1 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); + 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; } } From 49ef5415138938554f4cfdedc13a06bcaf977fbf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 12 Nov 2016 19:16:47 +0100 Subject: [PATCH 239/471] - scriptified Hexen's Firedemon. --- src/CMakeLists.txt | 1 - src/g_hexen/a_firedemon.cpp | 248 ---------------------- src/g_hexen/a_hexenmisc.cpp | 1 - src/g_shared/a_action.cpp | 7 + src/p_enemy.cpp | 18 +- src/p_mobj.cpp | 14 ++ wadsrc/static/zscript/actor.txt | 6 + wadsrc/static/zscript/hexen/firedemon.txt | 227 +++++++++++++++++++- 8 files changed, 264 insertions(+), 258 deletions(-) delete mode 100644 src/g_hexen/a_firedemon.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ffd9f339a4..3c165c345b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -868,7 +868,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 diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp deleted file mode 100644 index cc9beaaeb8..0000000000 --- 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 "vm.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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - // 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_SELF_PROLOGUE(AActor); - - 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_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 3676bf21b7..1a635ff710 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -38,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_shared/a_action.cpp b/src/g_shared/a_action.cpp index 61be39a0e0..edd97a6d47 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -449,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/p_enemy.cpp b/src/p_enemy.cpp index 20a549a511..cbddb48400 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -414,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 @@ -707,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)); +} //============================================================================= @@ -1030,7 +1041,12 @@ void P_NewChaseDir(AActor * actor) } - +DEFINE_ACTION_FUNCTION(AActor, NewChaseDir) +{ + PARAM_SELF_PROLOGUE(AActor); + P_NewChaseDir(self); + return 0; +} //============================================================================= diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index bd05941b33..db6b9a287f 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3327,6 +3327,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 @@ -6877,6 +6884,13 @@ DEFINE_ACTION_FUNCTION(AActor, deltaangle) // should this be global? 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); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c7a0090387..48b5f7ded0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -66,9 +66,11 @@ class Actor : Thinker native 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 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); @@ -84,6 +86,9 @@ class Actor : Thinker native 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 void LinkToWorld(); native void UnlinkFromWorld(); @@ -104,6 +109,7 @@ class Actor : Thinker native 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); diff --git a/wadsrc/static/zscript/hexen/firedemon.txt b/wadsrc/static/zscript/hexen/firedemon.txt index 001e1629f2..b425ecb118 100644 --- a/wadsrc/static/zscript/hexen/firedemon.txt +++ b/wadsrc/static/zscript/hexen/firedemon.txt @@ -3,6 +3,9 @@ class FireDemon : Actor { + const FIREDEMON_ATTACK_RANGE = 64*8.; + int strafecount; + Default { Health 80; @@ -23,11 +26,6 @@ class FireDemon : Actor Obituary "$OB_FIREDEMON"; } - native void A_FiredRocks(); - native void A_FiredChase(); - native void A_FiredAttack(); - native void A_FiredSplotch(); - States { Spawn: @@ -71,6 +69,208 @@ class FireDemon : Actor 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 ------------------------------------------------------- @@ -124,8 +324,6 @@ class FireDemonRock1 : Actor +NOTELEPORT } - native void A_SmBounce(); - States { Spawn: @@ -137,6 +335,21 @@ class FireDemonRock1 : Actor 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 ------------------------------------------------------------ From ac0413838ccebd4e20dd1a85896aad3b3bc6fae3 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 13 Nov 2016 09:34:05 +0100 Subject: [PATCH 240/471] Fixed: A StateProvider actor could no longer use its own user variables Refactored the FxIdentifier code a bit to avoid code duplication --- src/scripting/codegeneration/codegen.cpp | 249 ++++++++++------------- src/scripting/codegeneration/codegen.h | 7 +- 2 files changed, 117 insertions(+), 139 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index dac88aa76b..f59a2753df 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5102,65 +5102,31 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) { if (sym->IsKindOf(RUNTIME_CLASS(PField))) { - if (!ctx.Function) - { - ScriptPosition.Message(MSG_ERROR, "Cannot resolve class member outside a function", sym->SymbolName.GetChars()); - delete this; - return nullptr; - } - 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", sym->SymbolName.GetChars()); - } - if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols) - { - ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", sym->SymbolName.GetChars()); - delete this; - 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."); - delete this; - return nullptr; - } - - if (ctx.Function->Variants[0].SelfClass == nullptr) - { - ScriptPosition.Message(MSG_ERROR, "Unable to access class member from static function"); - delete this; - return nullptr; - } + 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); if (ctx.Function->Variants[0].SelfClass != ctx.Class) { // Check if the restricted class can access it. PSymbol *sym2; - if ((sym2 = ctx.FindInSelfClass(Identifier, symtbl)) != nullptr) + if ((sym2 = ctx.FindInClass(Identifier, symtbl)) != nullptr) { if (sym != sym2) { + // At the moment this cannot happen as the only possibility is SelfClass being an AActor and OwningClass an AStateProvider which comes from AActor anyways. ScriptPosition.Message(MSG_ERROR, "Member variable of %s not accessible through restricted self pointer", ctx.Class->TypeName.GetChars()); + delete newex; delete this; return nullptr; } } } - 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); } } - // now constants in the owning class. + // now check in the owning class. if (newex == nullptr && (sym = ctx.FindInClass(Identifier, symtbl)) != nullptr) { if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) @@ -5170,6 +5136,23 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) delete this; return newex->Resolve(ctx); } + else if (ctx.FromDecorate && ctx.Class->IsDescendantOf(RUNTIME_CLASS(AStateProvider)) && sym->IsKindOf(RUNTIME_CLASS(PField))) + { + if (~ctx.Function->Variants[0].Flags & VARF_Action) + { + // No stateowner pointer to rely on, complete ambiguity. + // Abort here instead of risking a crash. + ScriptPosition.Message(MSG_ERROR, "Member variable access from non-action function within a StateProvider."); + delete this; + return nullptr; + } + + FxExpression *self = new FxSelf(ScriptPosition, true); + self = self->Resolve(ctx); + newex = ResolveMember(ctx, ctx.Class, self, ctx.Class); + ABORT(newex); + ScriptPosition.Message(MSG_WARNING, "Self pointer used in ambiguous context; VM execution may abort!"); + } else { if (sym->IsKindOf(RUNTIME_CLASS(PFunction))) @@ -5222,6 +5205,78 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) 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; + } +} //========================================================================== // @@ -5249,111 +5304,25 @@ FxMemberIdentifier::~FxMemberIdentifier() FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) { - PSymbol * sym; - FxExpression *newex = nullptr; - CHECKRESOLVED(); SAFE_RESOLVE(Object, ctx); if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { - PSymbolTable *symtbl; auto ptype = static_cast(Object->ValueType)->PointedType; - - if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) // PClass is a child class of PStruct so this covers both. + if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) { - PStruct *cls = static_cast(ptype); - bool isclass = cls->IsKindOf(RUNTIME_CLASS(PClass)); - if ((sym = cls->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"); - newex = 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) - { - ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); - } - if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols) - { - ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars()); - delete this; - 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."); - delete this; - return nullptr; - } - auto x = isclass? new FxClassMember(Object, vsym, ScriptPosition) : new FxStructMember(Object, vsym, ScriptPosition); - Object = nullptr; - delete this; - return x->Resolve(ctx); - } - else - { - ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); - delete this; - return nullptr; - } - } - else - { - ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); - delete this; - return nullptr; - } + auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast(ptype)); + delete this; + return ret; } } else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct))) { - if ((sym = Object->ValueType->Symbols.FindSymbol(Identifier, false)) != nullptr) - { - if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) - { - ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as struct constant\n", Identifier.GetChars()); - newex = FxConstant::MakeConstant(sym, ScriptPosition); - } - else if (sym->IsKindOf(RUNTIME_CLASS(PField))) - { - PField *vsym = static_cast(sym); - - if (vsym->Flags & VARF_Deprecated) - { - ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); - } - auto x = new FxStructMember(Object, vsym, ScriptPosition); - Object = nullptr; - delete this; - return x->Resolve(ctx); - } - else - { - ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); - delete this; - return nullptr; - } - } - else - { - ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); - delete this; - return nullptr; - } + 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()); @@ -5361,7 +5330,6 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) return nullptr; } - //========================================================================== // // @@ -5406,9 +5374,10 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) // //========================================================================== -FxSelf::FxSelf(const FScriptPosition &pos) +FxSelf::FxSelf(const FScriptPosition &pos, bool deccheck) : FxExpression(EFX_Self, pos) { + check = deccheck; } //========================================================================== @@ -5438,6 +5407,12 @@ FxExpression *FxSelf::Resolve(FCompileContext& ctx) 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); } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 2f82dba573..0f937b0cdc 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -347,12 +347,13 @@ public: FxIdentifier(FName i, const FScriptPosition &p); FxExpression *Resolve(FCompileContext&); + FxExpression *ResolveMember(FCompileContext&, PClass*, FxExpression*&, PStruct*); }; //========================================================================== // -// FxIdentifier +// FxMemberIdentifier // //========================================================================== @@ -1240,8 +1241,10 @@ public: class FxSelf : public FxExpression { + bool check; + public: - FxSelf(const FScriptPosition&); + FxSelf(const FScriptPosition&, bool deccheck = false); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; From f238f0ba5ca520cbf9a6a96b49bb00623993ab64 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Nov 2016 12:02:41 +0100 Subject: [PATCH 241/471] - try to preserve a bit more information about incorrect use of user variables to print more meaningful error messages. This is not complete yet and will need integration with the previous commit. --- src/dobjtype.cpp | 1 + src/dobjtype.h | 1 + src/p_actionfunctions.cpp | 10 ++++ src/p_pspr.cpp | 9 ++++ src/sc_man.cpp | 11 +++-- src/sc_man.h | 4 +- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/codegeneration/codegen.h | 1 + src/scripting/decorate/thingdef_parse.cpp | 1 + src/scripting/thingdef.cpp | 58 +++++++++++++++++++++++ src/scripting/vm/vm.h | 1 + 11 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index c2b1008df9..f3fda2b147 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2791,6 +2791,7 @@ PClass::PClass() Defaults = nullptr; bRuntimeClass = false; bExported = false; + bDecorateClass = false; ConstructNative = nullptr; mDescriptiveName = "Class"; diff --git a/src/dobjtype.h b/src/dobjtype.h index be15193a4d..e1bfd07968 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -775,6 +775,7 @@ public: 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 *); diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index a99ba9ab61..74d828d550 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -78,6 +78,7 @@ #include "p_spec.h" #include "templates.h" #include "vm.h" +#include "v_text.h" #include "thingdef.h" #include "math/cmath.h" @@ -132,6 +133,15 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) 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; diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index d279a180cc..56562ab219 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -29,6 +29,7 @@ #include "g_level.h" #include "d_player.h" #include "serializer.h" +#include "v_text.h" // MACROS ------------------------------------------------------------------ @@ -337,6 +338,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. diff --git a/src/sc_man.cpp b/src/sc_man.cpp index f48d6b4612..254caed625 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -1046,7 +1046,10 @@ 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 = StrictErrors || strictdecorate ? MSG_ERROR : MSG_WARNING; @@ -1073,9 +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: @@ -1085,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 5eeacd8924..fde6efbed3 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 diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f59a2753df..2ce1b42651 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -8073,7 +8073,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) delete this; return nullptr; } - ScriptPosition.Message(MSG_DEBUG, "resolving '%s' as class name", clsname.GetChars()); + ScriptPosition.Message(MSG_DEBUGLOG, "resolving '%s' as class name", clsname.GetChars()); } } FxExpression *x = new FxConstant(cls, to, ScriptPosition); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 0f937b0cdc..b9679ad31d 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -79,6 +79,7 @@ struct FCompileContext 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(PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump); diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index baa662047c..e292e18445 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -909,6 +909,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par } } 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; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 8c42e8987d..d163ffb38d 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -206,6 +206,55 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, } } +//========================================================================== +// +// 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 int 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; + int errors = 0; + + if (obj->IsDescendantOf(RUNTIME_CLASS(AWeapon))) + { + if (obj->Size == RUNTIME_CLASS(AWeapon)->Size) return 0; // This class cannot have user variables. + test = weaponstates; + } + else if (obj->IsDescendantOf(RUNTIME_CLASS(ACustomInventory))) + { + if (obj->Size == RUNTIME_CLASS(ACustomInventory)->Size) return 0; // This class cannot have user variables. + test = pickupstates; + } + else return 0; // 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); + Printf(TEXTCOLOR_RED "Unsafe state call in state %s.%d to %s, reached by %s.%s which accesses user variables.\n", + owner->TypeName.GetChars(), state - owner->OwnedStates, static_cast(state->ActionFunc)->PrintableName.GetChars(), obj->TypeName.GetChars(), FName(*test).GetChars()); + errors++; + } + state = state->NextState; + } + } + return errors; +} + //========================================================================== // // LoadActors @@ -253,6 +302,15 @@ void LoadActors () errorcount++; continue; } + + 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. + errorcount += CheckForUnsafeStates(ti); + } } if (errorcount > 0) { diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 6c7878a9a0..019d6c3a6b 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -656,6 +656,7 @@ class VMFunction : public DObject 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; From 7d49a8296350954c50fc57c8cdeea7121cbd25a2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Nov 2016 12:37:28 +0100 Subject: [PATCH 242/471] removed some unneeded checks - since we now look for fields in the base class first the restriction check is no longer needed as it was for a different mode of looking up the identifier. - In DECORATE we do not need to bother with non-action functions. Non-action functions cannot be defined from DECORATE so there's no need to check if we are in one. - make the warning for unsafe access a debug message because this can affect legitimate code. --- src/scripting/codegeneration/codegen.cpp | 29 ++---------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 2ce1b42651..8543326cff 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5106,23 +5106,6 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) self = self->Resolve(ctx); newex = ResolveMember(ctx, ctx.Function->Variants[0].SelfClass, self, ctx.Function->Variants[0].SelfClass); ABORT(newex); - - if (ctx.Function->Variants[0].SelfClass != ctx.Class) - { - // Check if the restricted class can access it. - PSymbol *sym2; - if ((sym2 = ctx.FindInClass(Identifier, symtbl)) != nullptr) - { - if (sym != sym2) - { - // At the moment this cannot happen as the only possibility is SelfClass being an AActor and OwningClass an AStateProvider which comes from AActor anyways. - ScriptPosition.Message(MSG_ERROR, "Member variable of %s not accessible through restricted self pointer", ctx.Class->TypeName.GetChars()); - delete newex; - delete this; - return nullptr; - } - } - } } } @@ -5138,20 +5121,12 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else if (ctx.FromDecorate && ctx.Class->IsDescendantOf(RUNTIME_CLASS(AStateProvider)) && sym->IsKindOf(RUNTIME_CLASS(PField))) { - if (~ctx.Function->Variants[0].Flags & VARF_Action) - { - // No stateowner pointer to rely on, complete ambiguity. - // Abort here instead of risking a crash. - ScriptPosition.Message(MSG_ERROR, "Member variable access from non-action function within a StateProvider."); - delete this; - return nullptr; - } - FxExpression *self = new FxSelf(ScriptPosition, true); self = self->Resolve(ctx); newex = ResolveMember(ctx, ctx.Class, self, ctx.Class); ABORT(newex); - ScriptPosition.Message(MSG_WARNING, "Self pointer used in ambiguous context; VM execution may abort!"); + ScriptPosition.Message(MSG_DEBUGWARN, "Self pointer used in ambiguous context; VM execution may abort!"); + ctx.Unsafe = true; } else { From a2f4cd7cdad9d850e02cdea65648d32440a562d4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Nov 2016 14:20:30 +0100 Subject: [PATCH 243/471] - fixed: All functions that are callable from weapon states and not members of Actor need to be declared 'action'. With the stricter type checks of the self pointer that were now implemented these all produced errors. --- src/g_doom/a_doomweaps.cpp | 39 --------------- src/g_heretic/a_chicken.cpp | 6 +-- src/g_heretic/a_hereticweaps.cpp | 30 ++++++------ src/g_hexen/a_clericflame.cpp | 2 +- src/g_hexen/a_clericholy.cpp | 4 +- src/g_hexen/a_clericmace.cpp | 2 +- src/g_hexen/a_clericstaff.cpp | 8 +-- src/g_hexen/a_fighteraxe.cpp | 19 +++---- src/g_hexen/a_fighterhammer.cpp | 4 +- src/g_hexen/a_fighterplayer.cpp | 2 +- src/g_hexen/a_fighterquietus.cpp | 2 +- src/g_hexen/a_magecone.cpp | 2 +- src/g_hexen/a_magelightning.cpp | 4 +- src/g_hexen/a_magestaff.cpp | 4 +- src/g_hexen/a_pig.cpp | 2 +- src/g_strife/a_strifeweapons.cpp | 44 ++++++++--------- src/p_actionfunctions.cpp | 4 +- src/p_pspr.cpp | 49 +++---------------- src/scripting/codegeneration/codegen.cpp | 20 +++++++- src/scripting/zscript/zcc_compile.cpp | 9 +++- wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/heretic/chicken.txt | 6 +-- .../static/zscript/heretic/hereticweaps.txt | 30 ++++++------ wadsrc/static/zscript/hexen/clericflame.txt | 2 +- wadsrc/static/zscript/hexen/clericholy.txt | 4 +- wadsrc/static/zscript/hexen/clericmace.txt | 2 +- wadsrc/static/zscript/hexen/clericstaff.txt | 8 +-- wadsrc/static/zscript/hexen/fighteraxe.txt | 12 ++--- wadsrc/static/zscript/hexen/fighterfist.txt | 2 +- wadsrc/static/zscript/hexen/fighterhammer.txt | 4 +- .../static/zscript/hexen/fighterquietus.txt | 2 +- wadsrc/static/zscript/hexen/magecone.txt | 2 +- wadsrc/static/zscript/hexen/magelightning.txt | 4 +- wadsrc/static/zscript/hexen/magestaff.txt | 4 +- wadsrc/static/zscript/hexen/pig.txt | 2 +- wadsrc/static/zscript/shared/inventory.txt | 41 +++++++++------- wadsrc/static/zscript/strife/sigil.txt | 20 ++++---- .../static/zscript/strife/strifeweapons.txt | 20 ++++---- 38 files changed, 185 insertions(+), 237 deletions(-) diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 37ff05c706..bc962800f4 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -336,29 +336,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) return 0; } -DEFINE_ACTION_FUNCTION(AActor, A_OpenShotgun2) -{ - PARAM_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_WEAPON, "weapons/sshoto", 1, ATTN_NORM); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_LoadShotgun2) -{ - PARAM_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CloseShotgun2) -{ - PARAM_SELF_PROLOGUE(AActor); - 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 @@ -593,12 +570,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunLeft) return 0; } -DEFINE_ACTION_FUNCTION(AActor, A_RailWait) -{ - // Okay, this was stupid. Just use a NULL function instead of this. - return 0; -} - // // A_FireBFG // @@ -717,16 +688,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray) return 0; } -// -// A_BFGsound -// -DEFINE_ACTION_FUNCTION(AActor, A_BFGsound) -{ - PARAM_SELF_PROLOGUE(AActor); - S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM); - return 0; -} - // // A_FireOldBFG // diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp index fa26f73158..8a109d46dd 100644 --- a/src/g_heretic/a_chicken.cpp +++ b/src/g_heretic/a_chicken.cpp @@ -138,7 +138,7 @@ void P_UpdateBeak (AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_BeakRaise) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -170,7 +170,7 @@ void P_PlayPeck (AActor *chicken) DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 38991b87db..a888be8848 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -61,7 +61,7 @@ extern bool P_AutoUseChaosDevice (player_t *player); DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -216,7 +216,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL1) DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL2) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); DAngle Angle; int damage; @@ -421,7 +421,7 @@ void FireMacePL1B (AActor *actor) DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL1) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); AActor *ball; player_t *player; @@ -579,7 +579,7 @@ boom: DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL2) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); AActor *mo; player_t *player; @@ -761,7 +761,7 @@ int ARipper::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -888,7 +888,7 @@ void ARainTracker::Serialize(FSerializer &arc) DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL1) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; AActor *MissileActor; @@ -1217,7 +1217,7 @@ int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL1) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -1270,7 +1270,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff) DEFINE_ACTION_FUNCTION(AActor, A_InitPhoenixPL2) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -1293,7 +1293,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InitPhoenixPL2) DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); AActor *mo; @@ -1346,7 +1346,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) DEFINE_ACTION_FUNCTION(AActor, A_ShutdownPhoenixPL2) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp index f0e9c16b24..2c66cb42d1 100644 --- a/src/g_hexen/a_clericflame.cpp +++ b/src/g_hexen/a_clericflame.cpp @@ -66,7 +66,7 @@ void ACFlameMissile::Effect () DEFINE_ACTION_FUNCTION(AActor, A_CFlameAttack) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index d09c3f6aa7..362434b023 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -211,7 +211,7 @@ void SpawnSpiritTail (AActor *spirit) DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { diff --git a/src/g_hexen/a_clericmace.cpp b/src/g_hexen/a_clericmace.cpp index 9b81489307..a15196cf8b 100644 --- a/src/g_hexen/a_clericmace.cpp +++ b/src/g_hexen/a_clericmace.cpp @@ -15,7 +15,7 @@ static FRandom pr_maceatk ("CMaceAttack"); DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack) { - PARAM_SELF_PROLOGUE(AActor); + 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 a4050a1efb..a838357d63 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -46,7 +46,7 @@ int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetyp DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); AActor *mo; player_t *player; @@ -167,7 +167,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) DEFINE_ACTION_FUNCTION(AActor, A_CStaffInitBlink) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if (self->player && self->player->ReadyWeapon) { diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index 4260f4eb41..1dc02d599e 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -19,13 +19,6 @@ DECLARE_ACTION(A_Raise) 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 @@ -68,7 +61,7 @@ FState *AFWeapAxe::GetAtkState (bool hold) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReady) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -95,7 +88,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReady) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -122,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUp) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -149,7 +142,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUp) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -176,7 +169,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; @@ -199,7 +192,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack) { - PARAM_SELF_PROLOGUE(AActor); + 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 faa15d8af0..84eca78b79 100644 --- a/src/g_hexen/a_fighterhammer.cpp +++ b/src/g_hexen/a_fighterhammer.cpp @@ -25,7 +25,7 @@ static FRandom pr_hammeratk ("FHammerAtk"); DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -95,7 +95,7 @@ hammerdone: DEFINE_ACTION_FUNCTION(AActor, A_FHammerThrow) { - PARAM_SELF_PROLOGUE(AActor); + 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 ff4348520a..7e1502a1cb 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -99,7 +99,7 @@ static bool TryPunch(APlayerPawn *pmo, DAngle angle, int damage, int power) DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack) { - PARAM_SELF_PROLOGUE(AActor); + 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 c900794ed0..8f73ef48ee 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -78,7 +78,7 @@ int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype DEFINE_ACTION_FUNCTION(AActor, A_FSwordAttack) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player; diff --git a/src/g_hexen/a_magecone.cpp b/src/g_hexen/a_magecone.cpp index f2b97fcd9e..da53a829c0 100644 --- a/src/g_hexen/a_magecone.cpp +++ b/src/g_hexen/a_magecone.cpp @@ -51,7 +51,7 @@ int AFrostMissile::DoSpecialDamage (AActor *victim, int damage, FName damagetype DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 7e11b64ed4..b06d22ce59 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -126,7 +126,7 @@ int ALightningZap::SpecialMissileHit (AActor *thing) DEFINE_ACTION_FUNCTION(AActor, A_LightningReady) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); DoReadyWeapon(self); if (pr_lightningready() < 160) @@ -257,7 +257,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningZap) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MLightningAttack) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS_DEF(floor, AActor); PARAM_CLASS_DEF(ceiling, AActor); diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index acef2e5cdc..0b78bd279d 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -122,7 +122,7 @@ void MStaffSpawn (AActor *pmo, DAngle angle, AActor *alttarget) DEFINE_ACTION_FUNCTION(AActor, A_MStaffAttack) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { diff --git a/src/g_hexen/a_pig.cpp b/src/g_hexen/a_pig.cpp index a0a0cc844b..41054da001 100644 --- a/src/g_hexen/a_pig.cpp +++ b/src/g_hexen/a_pig.cpp @@ -58,7 +58,7 @@ void APigPlayer::MorphPlayerThink () DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 3e9eb69b6c..be8452046d 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -94,7 +94,7 @@ void P_DaggerAlert (AActor *target, AActor *emitter) DEFINE_ACTION_FUNCTION(AActor, A_JabDagger) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); DAngle angle; int damage; @@ -212,7 +212,7 @@ int APoisonBolt::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, A_ClearFlash) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); bool accurate; @@ -343,7 +343,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireAssaultGun) DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; DAngle savedangle; @@ -413,7 +413,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlameDie) DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -688,7 +688,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burnination) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS(grenadetype, AActor); PARAM_ANGLE(angleofs); PARAM_STATE(flash) @@ -821,7 +821,7 @@ AInventory *ASigil::CreateCopy (AActor *other) DEFINE_ACTION_FUNCTION(AActor, A_SelectPiece) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); AActor *spot; player_t *player = self->player; @@ -1007,7 +1007,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil2) { - PARAM_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + 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_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); AActor *spot; player_t *player = self->player; @@ -1103,7 +1103,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4) DEFINE_ACTION_FUNCTION(AActor, A_FireSigil5) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 74d828d550..b6ecb5cf88 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -4643,7 +4643,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if ( self->player == NULL || self->player->ReadyWeapon == NULL ) { @@ -4696,7 +4696,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) DEFINE_ACTION_FUNCTION(AActor, A_ResetReloadCounter) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if (self->player == NULL || self->player->ReadyWeapon == NULL) return 0; diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 56562ab219..4938063ec1 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -753,7 +753,7 @@ void DoReadyWeapon(AActor *self) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT_DEF(flags); DoReadyWeaponToSwitch(self, !(flags & WRF_NoSwitch)); @@ -885,7 +885,7 @@ static void P_CheckWeaponButtons (player_t *player) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_ReFire) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE_DEF(state); A_ReFire(self, state); return 0; @@ -923,7 +923,7 @@ void A_ReFire(AActor *self, FState *state) DEFINE_ACTION_FUNCTION(AInventory, A_ClearReFire) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; if (NULL != player) @@ -945,7 +945,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_ClearReFire) DEFINE_ACTION_FUNCTION(AInventory, A_CheckReload) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if (self->player != NULL) { @@ -1133,7 +1133,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayID) DEFINE_ACTION_FUNCTION(AInventory, A_Lower) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; DPSprite *psp; @@ -1181,7 +1181,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Lower) DEFINE_ACTION_FUNCTION(AInventory, A_Raise) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); if (self == nullptr) { @@ -1293,7 +1293,7 @@ enum GF_Flags DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE_DEF(flash); PARAM_INT_DEF(flags); @@ -1381,42 +1381,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_SELF_PROLOGUE(AActor); - - if (self->player != NULL) - { - self->player->extralight = 0; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AInventory, A_Light1) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->player != NULL) - { - self->player->extralight = 1; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AInventory, A_Light2) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->player != NULL) - { - self->player->extralight = 2; - } - return 0; -} - DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_Light) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(light); if (self->player != NULL) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8543326cff..cbe9183e27 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6007,6 +6007,24 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) 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; @@ -6306,7 +6324,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) isresolved: bool error = false; - PFunction *afd = FindClassMemberFunction(cls, cls, MethodName, ScriptPosition, &error); + PFunction *afd = FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error); if (error) { delete this; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index c5ac21783b..7e0af9ee47 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2317,7 +2317,14 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) { FArgumentList argumentlist; // We can use this function directly without wrapping it in a caller. - return new FxVMFunctionCall(new FxSelf(*af), afd, argumentlist, *af, false); + 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 diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 48b5f7ded0..7634ccaeaa 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -317,7 +317,6 @@ class Actor : Thinker native native void A_Countdown(); native void A_AlertMonsters(float maxdist = 0, int flags = 0); native void A_ClearSoundTarget(); - native void A_FireAssaultGun(); native void A_CheckTerrain(); deprecated native void A_MissileAttack(); diff --git a/wadsrc/static/zscript/heretic/chicken.txt b/wadsrc/static/zscript/heretic/chicken.txt index 77e2b0a92e..2e5ada81c8 100644 --- a/wadsrc/static/zscript/heretic/chicken.txt +++ b/wadsrc/static/zscript/heretic/chicken.txt @@ -26,8 +26,8 @@ class Beak : Weapon Weapon.SisterWeapon "BeakPowered"; } - native void A_BeakRaise (); - native void A_BeakAttackPL1(); + action native void A_BeakRaise (); + action native void A_BeakAttackPL1(); States { @@ -55,7 +55,7 @@ class BeakPowered : Beak Weapon.SisterWeapon "Beak"; } - native void A_BeakAttackPL2(); + action native void A_BeakAttackPL2(); States { diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index ae5e971797..4c254500b9 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -23,7 +23,7 @@ class Staff : HereticWeapon Tag "$TAG_STAFF"; } - native void A_StaffAttack (int damage, class puff); + action native void A_StaffAttack (int damage, class puff); States { @@ -142,7 +142,7 @@ class GoldWand : HereticWeapon Tag "$TAG_GOLDWAND"; } - native void A_FireGoldWandPL1 (); + action native void A_FireGoldWandPL1 (); States { @@ -178,7 +178,7 @@ class GoldWandPowered : GoldWand Tag "$TAG_GOLDWANDP"; } - native void A_FireGoldWandPL2 (); + action native void A_FireGoldWandPL2 (); States { @@ -294,7 +294,7 @@ class Crossbow : HereticWeapon Tag "$TAG_CROSSBOW"; } - native void A_FireCrossbowPL1 (); + action native void A_FireCrossbowPL1 (); States { @@ -330,7 +330,7 @@ class CrossbowPowered : Crossbow Tag "$TAG_CROSSBOWP"; } - native void A_FireCrossbowPL2(); + action native void A_FireCrossbowPL2(); States { @@ -462,7 +462,7 @@ class Gauntlets : Weapon Obituary "$OB_MPGAUNTLETS"; } - native void A_GauntletAttack (int power); + action native void A_GauntletAttack (int power); States { @@ -574,7 +574,7 @@ class Mace : HereticWeapon Tag "$TAG_MACE"; } - native void A_FireMacePL1(); + action native void A_FireMacePL1(); States { @@ -611,7 +611,7 @@ class MacePowered : Mace Tag "$TAG_MACEP"; } - native void A_FireMacePL2(); + action native void A_FireMacePL2(); States { @@ -778,7 +778,7 @@ class Blaster : HereticWeapon Obituary "$OB_MPBLASTER"; } - native void A_FireBlasterPL1(); + action native void A_FireBlasterPL1(); States { @@ -950,7 +950,7 @@ class SkullRod : HereticWeapon Tag "$TAG_SKULLROD"; } - native void A_FireSkullRodPL1(); + action native void A_FireSkullRodPL1(); States { @@ -984,7 +984,7 @@ class SkullRodPowered : SkullRod Tag "$TAG_SKULLRODP"; } - native void A_FireSkullRodPL2(); + action native void A_FireSkullRodPL2(); States { @@ -1140,7 +1140,7 @@ class PhoenixRod : Weapon native Tag "$TAG_PHOENIXROD"; } - native void A_FirePhoenixPL1(); + action native void A_FirePhoenixPL1(); States { @@ -1176,9 +1176,9 @@ class PhoenixRodPowered : PhoenixRod native Tag "$TAG_PHOENIXRODP"; } - native void A_InitPhoenixPL2(); - native void A_FirePhoenixPL2(); - native void A_ShutdownPhoenixPL2(); + action native void A_InitPhoenixPL2(); + action native void A_FirePhoenixPL2(); + action native void A_ShutdownPhoenixPL2(); States { diff --git a/wadsrc/static/zscript/hexen/clericflame.txt b/wadsrc/static/zscript/hexen/clericflame.txt index e724965300..13fca8ad10 100644 --- a/wadsrc/static/zscript/hexen/clericflame.txt +++ b/wadsrc/static/zscript/hexen/clericflame.txt @@ -16,7 +16,7 @@ class CWeapFlame : ClericWeapon Tag "$TAG_CWEAPFLAME"; } - native void A_CFlameAttack(); + action native void A_CFlameAttack(); States { diff --git a/wadsrc/static/zscript/hexen/clericholy.txt b/wadsrc/static/zscript/hexen/clericholy.txt index 6fc9cf43d4..1a4372f4db 100644 --- a/wadsrc/static/zscript/hexen/clericholy.txt +++ b/wadsrc/static/zscript/hexen/clericholy.txt @@ -96,8 +96,8 @@ class CWeapWraithverge : ClericWeapon native Inventory.PickupSound "WeaponBuild"; } - native void A_CHolyAttack(); - native void A_CHolyPalette(); + action native void A_CHolyAttack(); + action native void A_CHolyPalette(); States { diff --git a/wadsrc/static/zscript/hexen/clericmace.txt b/wadsrc/static/zscript/hexen/clericmace.txt index b47974d4b8..5e00b9c3b7 100644 --- a/wadsrc/static/zscript/hexen/clericmace.txt +++ b/wadsrc/static/zscript/hexen/clericmace.txt @@ -13,7 +13,7 @@ class CWeapMace : ClericWeapon Tag "$TAG_CWEAPMACE"; } - native void A_CMaceAttack(); + action native void A_CMaceAttack(); States { diff --git a/wadsrc/static/zscript/hexen/clericstaff.txt b/wadsrc/static/zscript/hexen/clericstaff.txt index c33f14a803..7ae0e9da37 100644 --- a/wadsrc/static/zscript/hexen/clericstaff.txt +++ b/wadsrc/static/zscript/hexen/clericstaff.txt @@ -16,10 +16,10 @@ class CWeapStaff : ClericWeapon Tag "$TAG_CWEAPSTAFF"; } - native void A_CStaffInitBlink(); - native void A_CStaffCheckBlink(); - native void A_CStaffCheck(); - native void A_CStaffAttack(); + action native void A_CStaffInitBlink(); + action native void A_CStaffCheckBlink(); + action native void A_CStaffCheck(); + action native void A_CStaffAttack(); States { diff --git a/wadsrc/static/zscript/hexen/fighteraxe.txt b/wadsrc/static/zscript/hexen/fighteraxe.txt index 436172bef4..30b235192d 100644 --- a/wadsrc/static/zscript/hexen/fighteraxe.txt +++ b/wadsrc/static/zscript/hexen/fighteraxe.txt @@ -17,12 +17,12 @@ class FWeapAxe : FighterWeapon native Tag "$TAG_FWEAPAXE"; } - native void A_FAxeCheckUp(); - native void A_FAxeCheckReady(); - native void A_FAxeCheckAtk(); - native void A_FAxeAttack(); - native void A_FAxeCheckUpG(); - native void A_FAxeCheckReadyG(); + 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 { diff --git a/wadsrc/static/zscript/hexen/fighterfist.txt b/wadsrc/static/zscript/hexen/fighterfist.txt index e556ebd870..8428ebe7da 100644 --- a/wadsrc/static/zscript/hexen/fighterfist.txt +++ b/wadsrc/static/zscript/hexen/fighterfist.txt @@ -13,7 +13,7 @@ class FWeapFist : FighterWeapon Tag "$TAG_FWEAPFIST"; } - native void A_FPunchAttack(); + action native void A_FPunchAttack(); States { diff --git a/wadsrc/static/zscript/hexen/fighterhammer.txt b/wadsrc/static/zscript/hexen/fighterhammer.txt index 0104c76704..f415cbb722 100644 --- a/wadsrc/static/zscript/hexen/fighterhammer.txt +++ b/wadsrc/static/zscript/hexen/fighterhammer.txt @@ -18,8 +18,8 @@ class FWeapHammer : FighterWeapon Tag "$TAG_FWEAPHAMMER"; } - native void A_FHammerAttack(); - native void A_FHammerThrow(); + action native void A_FHammerAttack(); + action native void A_FHammerThrow(); States { diff --git a/wadsrc/static/zscript/hexen/fighterquietus.txt b/wadsrc/static/zscript/hexen/fighterquietus.txt index 2430cd70c4..7c94f7901f 100644 --- a/wadsrc/static/zscript/hexen/fighterquietus.txt +++ b/wadsrc/static/zscript/hexen/fighterquietus.txt @@ -97,7 +97,7 @@ class FWeapQuietus : FighterWeapon Tag "$TAG_FWEAPQUIETUS"; } - native void A_FSwordAttack(); + action native void A_FSwordAttack(); States { diff --git a/wadsrc/static/zscript/hexen/magecone.txt b/wadsrc/static/zscript/hexen/magecone.txt index 471b5b0b70..a9f2d29dcb 100644 --- a/wadsrc/static/zscript/hexen/magecone.txt +++ b/wadsrc/static/zscript/hexen/magecone.txt @@ -17,7 +17,7 @@ class MWeapFrost : MageWeapon Tag "$TAG_MWEAPFROST"; } - native void A_FireConePL1(); + action native void A_FireConePL1(); States { diff --git a/wadsrc/static/zscript/hexen/magelightning.txt b/wadsrc/static/zscript/hexen/magelightning.txt index 46687e813c..154776d155 100644 --- a/wadsrc/static/zscript/hexen/magelightning.txt +++ b/wadsrc/static/zscript/hexen/magelightning.txt @@ -16,8 +16,8 @@ class MWeapLightning : MageWeapon Tag "$TAG_MWEAPLIGHTNING"; } - native void A_LightningReady(); - native void A_MLightningAttack(class floor = "LightningFloor", class ceiling = "LightningCeiling"); + action native void A_LightningReady(); + action native void A_MLightningAttack(class floor = "LightningFloor", class ceiling = "LightningCeiling"); States { diff --git a/wadsrc/static/zscript/hexen/magestaff.txt b/wadsrc/static/zscript/hexen/magestaff.txt index 9338febe63..c115428348 100644 --- a/wadsrc/static/zscript/hexen/magestaff.txt +++ b/wadsrc/static/zscript/hexen/magestaff.txt @@ -97,8 +97,8 @@ class MWeapBloodscourge : MageWeapon native Tag "$TAG_MWEAPBLOODSCOURGE"; } - native void A_MStaffAttack(); - native void A_MStaffPalette(); + action native void A_MStaffAttack(); + action native void A_MStaffPalette(); States { diff --git a/wadsrc/static/zscript/hexen/pig.txt b/wadsrc/static/zscript/hexen/pig.txt index 6362ff36e8..8fa4468827 100644 --- a/wadsrc/static/zscript/hexen/pig.txt +++ b/wadsrc/static/zscript/hexen/pig.txt @@ -34,7 +34,7 @@ class Snout : Weapon Weapon.YAdjust 10; } - native void A_SnoutAttack (); + action native void A_SnoutAttack (); States { diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 4a9cde7407..fc037d13fd 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -46,20 +46,22 @@ class StateProvider : Inventory native 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 void A_Light(int extralight); - native void A_Light0(); - native void A_Light1(); - native void A_Light2(); - native void A_LightInverse(); - native void A_WeaponReady(int flags = 0); - native void A_Lower(); - native void A_Raise(); + 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(); - native void A_OpenShotgun2(); - native void A_LoadShotgun2(); - native void A_CloseShotgun2(); + + 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(); @@ -67,17 +69,18 @@ class StateProvider : Inventory native action native void A_FireRailgun(); action native void A_FireRailgunLeft(); action native void A_FireRailgunRight(); - native void A_RailWait(); - native void A_BFGsound(); + action void A_RailWait() {} + action void A_BFGsound() { A_PlaySound("weapons/bfgf", CHAN_WEAPON); } action native void A_FireBFG(); action native void A_FireOldBFG(); - native void A_ReFire(state flash = null); - native void A_ClearReFire(); - native void A_CheckReload(); - native void A_GunFlash(state flash = null, int flags = 0); + action native void A_ReFire(state flash = null); + action native void A_ClearReFire(); + action native void A_CheckReload(); + action native void A_GunFlash(state 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"); - native state A_CheckForReload(int counter, state label, bool dontincrement = false); - native void A_ResetReloadCounter(); + action native state A_CheckForReload(int counter, state label, bool dontincrement = false); + action native void A_ResetReloadCounter(); } class ScoreItem : Inventory native diff --git a/wadsrc/static/zscript/strife/sigil.txt b/wadsrc/static/zscript/strife/sigil.txt index dab1db2f57..d8b1f80f8a 100644 --- a/wadsrc/static/zscript/strife/sigil.txt +++ b/wadsrc/static/zscript/strife/sigil.txt @@ -16,16 +16,16 @@ class Sigil : Weapon native Inventory.PickupMessage "$TXT_SIGIL"; } - native void A_SelectPiece (); - native void A_SelectSigilView (); - native void A_SelectSigilDown (); - native void A_SelectSigilAttack (); - native void A_SigilCharge (); - native void A_FireSigil1 (); - native void A_FireSigil2 (); - native void A_FireSigil3 (); - native void A_FireSigil4 (); - native void A_FireSigil5 (); + 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 { diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index bf94706c9d..178b2b27a1 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -62,7 +62,7 @@ class PunchDagger : StrifeWeapon Tag "$TAG_PUNCHDAGGER"; } - native void A_JabDagger (); + action native void A_JabDagger (); States { @@ -184,9 +184,9 @@ class StrifeCrossbow : StrifeWeapon Inventory.Icon "CBOWA0"; } - native void A_ClearFlash (); - native void A_ShowElectricFlash (); - native void A_FireArrow (class proj); + action native void A_ClearFlash (); + action native void A_ShowElectricFlash (); + action native void A_FireArrow (class proj); States { @@ -331,7 +331,7 @@ class MiniMissileLauncher : StrifeWeapon Inventory.PickupMessage "$TXT_MMLAUNCHER"; } - native void A_FireMiniMissile (); + action native void A_FireMiniMissile (); States { @@ -446,7 +446,7 @@ class FlameThrower : StrifeWeapon Inventory.PickupMessage "$TXT_FLAMER"; } - native void A_FireFlamer (); + action native void A_FireFlamer (); States { @@ -528,7 +528,7 @@ class Mauler : StrifeWeapon Obituary "$OB_MPMAULER1"; } - native void A_FireMauler1 (); + action native void A_FireMauler1 (); States { @@ -571,8 +571,8 @@ class Mauler2 : Mauler Tag "$TAG_MAULER2"; } - native void A_FireMauler2Pre (); - native void A_FireMauler2 (); + action native void A_FireMauler2Pre (); + action native void A_FireMauler2 (); States { @@ -816,7 +816,7 @@ class StrifeGrenadeLauncher : StrifeWeapon Inventory.PickupMessage "$TXT_GLAUNCHER"; } - native void A_FireGrenade (class grenadetype, float angleofs, state flash); + action native void A_FireGrenade (class grenadetype, float angleofs, state flash); States { From 1e6a632774f5db7e604362ab0963c30fe68304e9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Nov 2016 14:48:27 +0100 Subject: [PATCH 244/471] - copy the Unsafe flag to the actual function. This must have gotten lost during the merge between my own code and Leonard2's fix. Now even in DECORATE it is possible to report most cases in which user variables are accessed from non-item states as an error. This will report all states which can be traced by a direct link from a special state label. It will not find states that only get used via A_Jump etc. --- src/scripting/vm/vmbuilder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index acb67e2f54..19d89fc6f6 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -762,6 +762,7 @@ void FFunctionBuildList::Build() codesize += sfunc->CodeSize; } sfunc->PrintableName = item.PrintableName; + sfunc->Unsafe = ctx.Unsafe; } delete item.Code; if (dump != nullptr) From ac86a535e7c3c7899c70519a9b22714141ca5b46 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 14:12:27 +0100 Subject: [PATCH 245/471] - fixed: State labels were resolved in the calling function's context instead of the called function one's. This could cause problems with functions that take states as parameters but use them to set them internally instead of passing them through the A_Jump interface back to the caller, like A_Chase or A_LookEx. This required some quite significant refactoring because the entire state resolution logic had been baked into the compiler which turned out to be a major maintenance problem. Fixed this by adding a new builtin type 'statelabel'. This is an opaque identifier representing a state, with the actual data either directly encoded into the number for single label state or an index into a state information table. The state resolution is now the task of the called function as it should always have remained. Note, that this required giving back the 'action' qualifier to most state jumping functions. - refactored most A_Jump checkers to a two stage setup with a pure checker that returns a boolean and a scripted A_Jump wrapper, for some simpler checks the checker function was entirely omitted and calculated inline in the A_Jump function. It is strongly recommended to use the boolean checkers unless using an inline function invocation in a state as they lead to vastly clearer code and offer more flexibility. - let Min() and Max() use the OP_MIN and OP_MAX opcodes. Although these were present, these function were implemented using some grossly inefficient branching tests. - the DECORATE 'state' cast kludge will now actually call ResolveState because a state label is not a state and needs conversion. --- src/d_dehacked.cpp | 2 +- src/dobjtype.cpp | 29 +- src/dobjtype.h | 14 +- src/info.h | 38 ++ src/namedef.h | 4 +- src/p_actionfunctions.cpp | 429 +++--------------- src/p_mobj.cpp | 4 +- src/p_pspr.cpp | 19 +- src/p_pspr.h | 1 + src/p_states.cpp | 90 ++++ src/scripting/codegeneration/codegen.cpp | 273 +++-------- src/scripting/codegeneration/codegen.h | 8 +- src/scripting/decorate/thingdef_parse.cpp | 5 +- src/scripting/decorate/thingdef_states.cpp | 7 +- src/scripting/vm/vm.h | 12 +- src/scripting/zscript/zcc_compile.cpp | 10 +- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 47 +- wadsrc/static/zscript/actor_checks.txt | 274 +++++++++++ wadsrc/static/zscript/doom/bossbrain.txt | 2 +- wadsrc/static/zscript/heretic/hereticimp.txt | 2 +- wadsrc/static/zscript/hexen/bats.txt | 2 +- wadsrc/static/zscript/hexen/bishop.txt | 4 +- wadsrc/static/zscript/shared/inventory.txt | 8 +- .../static/zscript/strife/strifeweapons.txt | 2 +- 25 files changed, 641 insertions(+), 646 deletions(-) create mode 100644 wadsrc/static/zscript/actor_checks.txt diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index eef9b137a3..880cd7dfe8 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1494,7 +1494,7 @@ static int PatchFrame (int frameNum) DEFINE_ACTION_FUNCTION(AActor, isDEHState) { PARAM_PROLOGUE; - PARAM_STATE(state); + PARAM_POINTER(state, FState); ACTION_RETURN_BOOL(state != nullptr && (state->DefineFlags & SDF_DEHACKED)); } diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index f3fda2b147..2c88da92a1 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -82,6 +82,7 @@ PName *TypeName; PSound *TypeSound; PColor *TypeColor; PStatePointer *TypeState; +PStateLabel *TypeStateLabel; PStruct *TypeVector2; PStruct *TypeVector3; PPointer *TypeNullPtr; @@ -546,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); @@ -564,6 +566,7 @@ 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); @@ -701,7 +704,7 @@ IMPLEMENT_CLASS(PInt, false, false, false, false) //========================================================================== 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)); @@ -715,8 +718,8 @@ 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); @@ -1308,7 +1311,7 @@ IMPLEMENT_CLASS(PName, false, false, false, false) //========================================================================== PName::PName() -: PInt(sizeof(FName), true) +: PInt(sizeof(FName), true, false) { mDescriptiveName = "Name"; assert(sizeof(FName) == __alignof(FName)); @@ -1414,6 +1417,22 @@ PColor::PColor() assert(sizeof(PalEntry) == __alignof(PalEntry)); } +/* PStateLabel *****************************************************************/ + +IMPLEMENT_CLASS(PStateLabel, false, false, false, false) + +//========================================================================== +// +// PStateLabel Default Constructor +// +//========================================================================== + +PStateLabel::PStateLabel() + : PInt(sizeof(int), false, false) +{ + mDescriptiveName = "StateLabel"; +} + /* PStatePointer **********************************************************/ IMPLEMENT_CLASS(PStatePointer, false, false, false, false) diff --git a/src/dobjtype.h b/src/dobjtype.h index e1bfd07968..1ca5df8325 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -227,6 +227,7 @@ public: 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 &)); @@ -417,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; @@ -426,8 +427,10 @@ public: virtual void SetValue(void *addr, double val); virtual int GetValueInt(void *addr) const; virtual double GetValueFloat(void *addr) const; + virtual bool isNumeric() override { return IntCompatible; } bool Unsigned; + bool IntCompatible; protected: PInt(); void SetOps(); @@ -453,6 +456,7 @@ public: virtual void SetValue(void *addr, double val); virtual int GetValueInt(void *addr) const; virtual double GetValueFloat(void *addr) const; + virtual bool isNumeric() override { return true; } protected: PFloat(); void SetOps(); @@ -516,6 +520,13 @@ public: PColor(); }; +class PStateLabel : public PInt +{ + DECLARE_CLASS(PStateLabel, PInt); +public: + PStateLabel(); +}; + // Pointers ----------------------------------------------------------------- class PStatePointer : public PBasicType @@ -903,6 +914,7 @@ 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/info.h b/src/info.h index 6aee02bedb..e198bb26cd 100644 --- a/src/info.h +++ b/src/info.h @@ -313,6 +313,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, diff --git a/src/namedef.h b/src/namedef.h index 8f1a54337b..ee7d08f407 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -730,10 +730,10 @@ 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(A_Jump) \ No newline at end of file +xx(StateLabel) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index b6ecb5cf88..9440dc0d67 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -715,7 +715,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountProximity) //=========================================================================== // -// __decorate_internal_state__ // __decorate_internal_int__ // __decorate_internal_bool__ // __decorate_internal_float__ @@ -725,13 +724,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); @@ -1158,7 +1150,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack) //========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(maxchance); paramnum++; // Increment paramnum to point at the first jump target @@ -1166,7 +1158,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) if (count > 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); @@ -1177,137 +1169,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) // State jump function // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHealthLower) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (health); - PARAM_STATE (jump); - PARAM_INT_DEF (ptr_selector); - 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_DEF(noz); - - 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, VM_ARGS) +DEFINE_ACTION_FUNCTION(AActor, CheckInventory) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (itemtype, AInventory); PARAM_INT (itemamount); - PARAM_STATE (label); - PARAM_INT_DEF (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); @@ -1318,48 +1195,32 @@ int DoJumpIfInventory(AActor *owner, VM_ARGS) { 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, VM_ARGS_NAMES); -} - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetInventory) -{ - PARAM_SELF_PROLOGUE(AActor); - return DoJumpIfInventory(self->target, VM_ARGS_NAMES); -} //========================================================================== // // 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_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); } //========================================================================== @@ -1910,7 +1771,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfNoAmmo) { PARAM_ACTION_PROLOGUE(AActor); - PARAM_STATE(jump); + PARAM_STATE_ACTION(jump); if (!ACTION_CALL_FROM_PSPRITE() || self->player->ReadyWeapon == nullptr) { @@ -3637,10 +3498,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++) { @@ -3649,17 +3509,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); } //=========================================================================== @@ -3706,11 +3566,10 @@ 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_DEF(twodi); range *= range; @@ -3721,25 +3580,24 @@ 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_DEF(twodi); range *= range; @@ -3750,17 +3608,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(false); } @@ -3813,20 +3671,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 @@ -3917,43 +3761,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 @@ -4077,17 +3884,12 @@ 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); } // [KS] *** Start of my modifications *** @@ -4220,7 +4022,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 @@ -4233,7 +4035,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) DVector3 vel; PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE (jump); PARAM_INT_DEF (flags) PARAM_FLOAT_DEF (range) PARAM_FLOAT_DEF (minrange) @@ -4290,7 +4091,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) double distance = self->Distance3D(target); if (distance > range) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } } @@ -4339,7 +4140,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) } else { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } double cp = pitch.Cos(); @@ -4377,7 +4178,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)) { @@ -4385,9 +4186,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); } //========================================================================== @@ -4422,10 +4223,9 @@ 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_DEF (fov) PARAM_INT_DEF (flags) PARAM_FLOAT_DEF (dist_max) @@ -4456,11 +4256,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); @@ -4472,7 +4272,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) if (!t.linetarget) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } target = t.linetarget; @@ -4498,24 +4298,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.; @@ -4529,7 +4329,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) @@ -4546,10 +4346,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); } @@ -4560,10 +4360,9 @@ 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_DEF (fov) PARAM_INT_DEF (flags) PARAM_FLOAT_DEF (dist_max) @@ -4589,19 +4388,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); @@ -4610,7 +4409,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.; @@ -4625,14 +4424,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); } //=========================================================================== @@ -4650,7 +4449,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) ACTION_RETURN_STATE(NULL); } PARAM_INT (count); - PARAM_STATE (jump); + PARAM_STATE_ACTION (jump); PARAM_BOOL_DEF (dontincrement); if (numret > 0) @@ -4727,24 +4526,14 @@ 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_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)); } @@ -5175,7 +4964,7 @@ enum T_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE_DEF (teleport_state) PARAM_CLASS_DEF (target_type, ASpecialSpot) PARAM_CLASS_DEF (fog_type, AActor) @@ -5605,7 +5394,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(destination_selector); PARAM_FLOAT_DEF(xofs) PARAM_FLOAT_DEF(yofs) @@ -5902,27 +5691,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_DEF(species); - PARAM_INT_DEF(ptr); - - AActor *mobj = COPY_AAPTR(self, ptr); - - if (mobj != NULL && jump && mobj->GetSpecies() == species) - { - ACTION_RETURN_STATE(jump); - } - ACTION_RETURN_STATE(NULL); -} - //========================================================================== // // A_SetTics @@ -6666,44 +6434,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_DEF(offsethigh); - PARAM_FLOAT_DEF(offsetlow); - PARAM_BOOL_DEF(includeHeight); - PARAM_INT_DEF(ptr); - - 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) // @@ -6760,29 +6490,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_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)); } /*=========================================================================== @@ -6806,10 +6523,9 @@ 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_DEF(flags) PARAM_INT_DEF(ptr) PARAM_FLOAT_DEF(xofs) @@ -6822,7 +6538,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) //Needs at least one state jump to work. if (!mobj) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if (!(flags & CBF_ABSOLUTEANGLE)) @@ -6872,7 +6588,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) if (checker) { - ACTION_RETURN_STATE(NULL); + ACTION_RETURN_BOOL(false); } if (mobj->BlockingMobj) @@ -6886,23 +6602,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)); } //=========================================================================== diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index db6b9a287f..05cfb7cc48 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -159,6 +159,7 @@ 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)); @@ -168,6 +169,7 @@ void AActor::InitNativeFields() 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! @@ -694,7 +696,7 @@ bool AActor::SetState (FState *newstate, bool nofunction) DEFINE_ACTION_FUNCTION(AActor, SetState) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(state); + PARAM_POINTER(state, FState); PARAM_BOOL_DEF(nofunction); ACTION_RETURN_BOOL(self->SetState(state, nofunction)); }; diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 4938063ec1..f371c68889 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -886,7 +886,7 @@ static void P_CheckWeaponButtons (player_t *player) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_ReFire) { PARAM_ACTION_PROLOGUE(AActor); - PARAM_STATE_DEF(state); + PARAM_STATE_ACTION_DEF(state); A_ReFire(self, state); return 0; } @@ -1224,7 +1224,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Overlay) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT (layer); - PARAM_STATE_DEF(state); + PARAM_STATE_ACTION_DEF(state); PARAM_BOOL_DEF(dontoverride); player_t *player = self->player; @@ -1294,7 +1294,7 @@ enum GF_Flags DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { PARAM_ACTION_PROLOGUE(AActor); - PARAM_STATE_DEF(flash); + PARAM_STATE_ACTION_DEF(flash); PARAM_INT_DEF(flags); player_t *player = self->player; @@ -1361,6 +1361,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 diff --git a/src/p_pspr.h b/src/p_pspr.h index 2809216a7a..3f819714c7 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -110,6 +110,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); diff --git a/src/p_states.cpp b/src/p_states.cpp index 00b011e3d8..2c1b88eafb 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -42,6 +42,9 @@ #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 // actor. States are archived by recording the actor they belong @@ -258,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); +} //========================================================================== // diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index cbe9183e27..103e38efff 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -812,7 +812,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) if (basex->ValueType->GetRegType() == REGT_INT) { - if (basex->ValueType != TypeName || Explicit) // names can be converted to int, but only with an explicit type cast. + if (basex->ValueType->isNumeric() || Explicit) // names can be converted to int, but only with an explicit type cast. { FxExpression *x = basex; x->ValueType = ValueType; @@ -822,7 +822,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) } 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. :( + // 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"); @@ -919,7 +919,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) } else if (basex->ValueType->GetRegType() == REGT_INT) { - if (basex->ValueType != TypeName) + if (basex->ValueType->isNumeric()) { if (basex->isConstant()) { @@ -1428,8 +1428,15 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } - else if (ValueType == TypeState) + 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)) { @@ -4022,6 +4029,10 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) 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) @@ -4519,23 +4530,21 @@ static void EmitLoad(VMFunctionBuilder *build, const ExpEmit resultreg, const Ex ExpEmit FxMinMax::Emit(VMFunctionBuilder *build) { unsigned i; - int opcode, opA; + int opcode; 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); + 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_LEF_RR : OP_LE_RR; - opA = 1; + opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_MINF_RR : OP_MIN_RR; } else { - opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_LTF_RR : OP_LT_RR; - opA = 0; + opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_MAXF_RR : OP_MAX_RR; } ExpEmit bestreg; @@ -4556,17 +4565,8 @@ ExpEmit FxMinMax::Emit(VMFunctionBuilder *build) { 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); - } + build->Emit(opcode + checkreg.Konst, bestreg.RegNum, bestreg.RegNum, checkreg.RegNum); + checkreg.Free(build); } return bestreg; } @@ -6121,7 +6121,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Name: case NAME_Color: case NAME_Sound: - case NAME_State: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { PType *type = @@ -6131,8 +6130,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) MethodName == NAME_Float ? TypeFloat64 : MethodName == NAME_Double ? TypeFloat64 : MethodName == NAME_Name ? TypeName : - MethodName == NAME_Color ? TypeColor : - MethodName == NAME_State? TypeState :(PType*)TypeSound; + MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; func = new FxTypeCast(ArgList[0], type, true, true); ArgList[0] = nullptr; @@ -6819,7 +6817,6 @@ bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, Ex 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]; @@ -7926,6 +7923,13 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx) } 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(); } @@ -8135,7 +8139,9 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) //========================================================================== // -// +// Symbolic state labels. +// Conversion will not happen inside the compiler anymore because it causes +// just too many problems. // //========================================================================== @@ -8155,7 +8161,9 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) delete this; return nullptr; } - FxExpression *x = new FxConstant(aclass->OwnedStates + index, ScriptPosition); + int symlabel = StateLabels.AddPointer(aclass->OwnedStates + index); + FxExpression *x = new FxConstant(symlabel, ScriptPosition); + x->ValueType = TypeStateLabel; delete this; return x; } @@ -8169,8 +8177,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) FxRuntimeStateIndex::FxRuntimeStateIndex(FxExpression *index) : FxExpression(EFX_RuntimeStateIndex, index->ScriptPosition), Index(index) { - EmitTail = false; - ValueType = TypeState; + ValueType = TypeStateLabel; } FxRuntimeStateIndex::~FxRuntimeStateIndex() @@ -8178,12 +8185,6 @@ FxRuntimeStateIndex::~FxRuntimeStateIndex() SAFE_DELETE(Index); } -PPrototype *FxRuntimeStateIndex::ReturnProto() -{ - EmitTail = true; - return FxExpression::ReturnProto(); -} - FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); @@ -8206,13 +8207,15 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) } else if (index == 0) { - auto x = new FxConstant((FState*)nullptr, ScriptPosition); + int symlabel = StateLabels.AddPointer(nullptr); + auto x = new FxConstant(symlabel, ScriptPosition); delete this; - return x->Resolve(ctx); + x->ValueType = TypeStateLabel; + return x; } else { - auto x = new FxStateByIndex(index, ScriptPosition); + auto x = new FxStateByIndex(ctx.StateIndex + index, ScriptPosition); delete this; return x->Resolve(ctx); } @@ -8222,84 +8225,21 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) 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; } -static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int index) -{ - PClassActor *cls = stateowner->GetClass(); - - if (stateinfo->mCallingState != nullptr) - { - 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 BuiltinHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, 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) { - // This can only be called from inline state functions which must be VARF_Action. - assert(build->NumImplicits >= NAP && build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits && - "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 = FindBuiltinFunction(NAME_BuiltinHandleRuntimeState, BuiltinHandleRuntimeState); - 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); - } - + 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; } @@ -8340,6 +8280,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); ABORT(ctx.Class); + int symlabel; if (names[0] == NAME_None) { @@ -8379,107 +8320,17 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) 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 == nullptr) - { - 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 BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, 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 BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, TArray &defaultparam, 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->NumImplicits == NAP) - { - build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // pass stateowner + symlabel = StateLabels.AddPointer(destination); } else { - build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self + names.Delete(0); + symlabel = StateLabels.AddNames(names); } - for (unsigned i = 0; i < names.Size(); ++i) - { - build->EmitParamInt(names[i]); - } - - // For one name, use the BuiltinFindSingleNameState function. For more than - // one name, use the BuiltinFindMultiNameState function. - VMFunction *callfunc; - PSymbol *sym; - - if (names.Size() == 1) - { - sym = FindBuiltinFunction(NAME_BuiltinFindSingleNameState, BuiltinFindSingleNameState); - } - else - { - sym = FindBuiltinFunction(NAME_BuiltinFindMultiNameState, BuiltinFindMultiNameState); - } - - 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), names.Size() + 1, 1); - build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); - names.Clear(); - names.ShrinkToFit(); - return dest; + FxExpression *x = new FxConstant(symlabel, ScriptPosition); + x->ValueType = TypeStateLabel; + delete this; + return x; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index b9679ad31d..f1778512f4 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -310,9 +310,9 @@ public: virtual PPrototype *ReturnProto(); virtual VMFunction *GetDirectFunction(); virtual bool CheckReturn() { return false; } - bool IsNumeric() const { return ValueType != TypeName && ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } + bool IsNumeric() const { return ValueType->isNumeric(); } bool IsFloat() const { return ValueType->GetRegType() == REGT_FLOAT && ValueType->GetRegCount() == 1; } - bool IsInteger() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT); } + 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); } @@ -1684,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); }; @@ -1709,7 +1708,6 @@ public: FxMultiNameState(const char *statestring, const FScriptPosition &pos); FxExpression *Resolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build); }; //========================================================================== diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index e292e18445..151d885219 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -174,14 +174,15 @@ 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*)nullptr, sc); + x = new FxConstant(0, sc); + x->ValueType = TypeStateLabel; } else if (sc.Compare("*")) { diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index e3cb74c328..c9be2c7476 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -626,7 +626,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) @@ -646,7 +646,8 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArrayValueType = TypeStateLabel; } } else @@ -703,7 +704,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/vm/vm.h b/src/scripting/vm/vm.h index 019d6c3a6b..2f98c8d818 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -940,15 +940,12 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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_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].atag == ATAG_GENERIC || 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_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) @@ -965,7 +962,8 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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)) { ASSERTSTATE(param[p]); x = (FState*)param[p].a; } else { ASSERTSTATE(defaultparam[p]); x = (FState*)defaultparam[p].a; } +#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; } @@ -982,6 +980,7 @@ 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) @@ -995,6 +994,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 7e0af9ee47..b8c0a2a387 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1429,7 +1429,15 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n break; case ZCC_UserType: - retval = ResolveUserType(btype, &outertype->Symbols); + // 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; diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 8ea4bb114c..42f32a4476 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,6 +1,7 @@ zscript/base.txt zscript/constants.txt zscript/actor.txt +zscript/actor_checks.txt zscript/shared/inventory.txt zscript/shared/player.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 7634ccaeaa..f3cd9aa3cf 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -71,6 +71,7 @@ class Actor : Thinker native 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); @@ -90,6 +91,9 @@ class Actor : Thinker native 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); @@ -282,7 +286,7 @@ class Actor : Thinker native void A_Fall() { A_NoBlocking(); } native void A_XScream(); native void A_Look(); - native void A_Chase(state melee = null, state missile = null, int flags = 0); + 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(); @@ -332,18 +336,10 @@ class Actor : Thinker native 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 state A_Jump(int chance, state label, ...); + 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 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); 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); @@ -361,33 +357,29 @@ class Actor : Thinker native 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 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 = 0); deprecated native void A_ChangeFlag(string flagname, bool value); - deprecated native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); - native state A_JumpIf(bool expression, state label); native void A_RaiseMaster(bool copy = 0); native void A_RaiseChildren(bool copy = 0); native void A_RaiseSiblings(bool copy = 0); - native state A_CheckFloor(state label); - native state A_CheckCeiling(state label); - native state A_PlayerSkinCheck(state label); deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); - native state, bool A_Teleport(state teleportstate = null, class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 128, int ptr = AAPTR_DEFAULT); - native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = null, float heightoffset = 0, float radiusoffset = 0, float pitch = 0); action native bool A_ThrowGrenade(class itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); native void A_Weave(int xspeed, int yspeed, float xdist, float ydist); + + 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); + 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 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 = null, name species = "None", float mindist = 0, int limit = 0); - native state A_CheckSpecies(state jump, name species = 'none', int ptr = AAPTR_DEFAULT); - native void A_CountdownArg(int argnum, state targstate = null); native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); native void A_CustomComboAttack(class missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); native void A_Burst(class chunktype); @@ -399,11 +391,7 @@ class Actor : Thinker native native void A_Respawn(int flags = 1); native void A_QueueCorpse(); native void A_DeQueueCorpse(); - native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = null); native void A_ClearLastHeard(); - 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 fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); - native state A_JumpIfInTargetLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); native bool A_SelectWeapon(class whichweapon, int flags = 0); action native void A_Punch(); native void A_Feathers(); @@ -416,7 +404,6 @@ class Actor : Thinker native native void A_RemoveForcefield(); native void A_DropWeaponPieces(class p1, class p2, class p3); native void A_PigPain (); - native state A_MonsterRefire(int chance, state label); 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); @@ -455,13 +442,8 @@ class Actor : Thinker native native void A_SwapTeleFog(); native void A_SetHealth(int health, int ptr = AAPTR_DEFAULT); native void 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_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); 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); @@ -472,7 +454,7 @@ class Actor : Thinker native native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0); native void A_CopyFriendliness(int ptr_source = AAPTR_MASTER); - action native bool A_Overlay(int layer, state start = null, bool nooverride = false); + 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); @@ -525,7 +507,6 @@ class Actor : Thinker native } // Internal functions - deprecated private native state __decorate_internal_state__(state s); 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 0000000000..8065397530 --- /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/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index b1aa901a33..f097e2c3b3 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -162,7 +162,7 @@ extend class Actor boom.DeathSound = "misc/brainexplode"; boom.Vel.z = random[BrainScream](0, 255)/128.; - boom.SetState ("BossBrain::Brainexplode"); + boom.SetStateLabel ("BossBrain::Brainexplode"); boom.bRocketTrail = false; boom.SetDamage(0); // disables collision detection which is not wanted here boom.tics -= random[BrainScream](0, 7); diff --git a/wadsrc/static/zscript/heretic/hereticimp.txt b/wadsrc/static/zscript/heretic/hereticimp.txt index 34738ed566..c1443de032 100644 --- a/wadsrc/static/zscript/heretic/hereticimp.txt +++ b/wadsrc/static/zscript/heretic/hereticimp.txt @@ -113,7 +113,7 @@ class HereticImp : Actor if (extremecrash) { - SetState ("XCrash"); + SetStateLabel ("XCrash"); } } diff --git a/wadsrc/static/zscript/hexen/bats.txt b/wadsrc/static/zscript/hexen/bats.txt index a530da1766..aaefaaeb70 100644 --- a/wadsrc/static/zscript/hexen/bats.txt +++ b/wadsrc/static/zscript/hexen/bats.txt @@ -92,7 +92,7 @@ class Bat : Actor { if (special2 < 0) { - SetState ("Death"); + SetStateLabel ("Death"); } special2 -= 2; // Called every 2 tics diff --git a/wadsrc/static/zscript/hexen/bishop.txt b/wadsrc/static/zscript/hexen/bishop.txt index d846a64029..32f0f3e633 100644 --- a/wadsrc/static/zscript/hexen/bishop.txt +++ b/wadsrc/static/zscript/hexen/bishop.txt @@ -131,7 +131,7 @@ class Bishop : Actor { if (random[BishopDecide]() >= 220) { - SetState ("Blur"); + SetStateLabel ("Blur"); } } @@ -210,7 +210,7 @@ class Bishop : Actor { if (random[BishopPainBlur]() < 64) { - SetState ("Blur"); + SetStateLabel ("Blur"); return; } double xo = random2[BishopPainBlur]() / 16.; diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index fc037d13fd..e38ddbdb1e 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -41,7 +41,7 @@ class Inventory : Actor native class StateProvider : Inventory native { - action native state A_JumpIfNoAmmo(state label); + 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); @@ -73,13 +73,13 @@ class StateProvider : Inventory native 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(state flash = null); + action native void A_ReFire(statelabel flash = null); action native void A_ClearReFire(); action native void A_CheckReload(); - action native void A_GunFlash(state flash = null, int flags = 0); + 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, state label, bool dontincrement = false); + action native state A_CheckForReload(int counter, statelabel label, bool dontincrement = false); action native void A_ResetReloadCounter(); } diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index 178b2b27a1..9e44638937 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -816,7 +816,7 @@ class StrifeGrenadeLauncher : StrifeWeapon Inventory.PickupMessage "$TXT_GLAUNCHER"; } - action native void A_FireGrenade (class grenadetype, float angleofs, state flash); + action native void A_FireGrenade (class grenadetype, float angleofs, statelabel flash); States { From 56a3dcfe800b7a5b6578e62c86e8f0d47aadba1d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 15:02:44 +0100 Subject: [PATCH 246/471] - moved the 'brainexplode' state to the rocket, which is the actor which actually uses it. This appears to be the only case where an actor was set to a state owned by a completely unrelated actor which would present some problems with state owner checking in AActor::SetState, so let's better get rid of it ASAP. I believe the only reason this wasn't changed when all actors were exported 8 years ago was that old binary DEHSUPP lump. --- src/namedef.h | 1 - src/scripting/decorate/thingdef_exp.cpp | 4 ++++ wadsrc/static/dehsupp.txt | 2 +- wadsrc/static/zscript/doom/bossbrain.txt | 6 +----- wadsrc/static/zscript/doom/doomweapons.txt | 4 ++++ 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index ee7d08f407..f8475f7169 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) diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 7e4c3b3987..229c8f1f48 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -476,6 +476,10 @@ 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; } diff --git a/wadsrc/static/dehsupp.txt b/wadsrc/static/dehsupp.txt index 78948677f4..436e894b48 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/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index f097e2c3b3..6a72de2bfb 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -20,10 +20,6 @@ class BossBrain : Actor } States { - BrainExplode: - MISL BC 10 Bright; - MISL D 10 A_BrainExplode; - Stop; Spawn: BBRN A -1; Stop; @@ -162,7 +158,7 @@ extend class Actor boom.DeathSound = "misc/brainexplode"; boom.Vel.z = random[BrainScream](0, 255)/128.; - boom.SetStateLabel ("BossBrain::Brainexplode"); + boom.SetStateLabel ("Brainexplode"); boom.bRocketTrail = false; boom.SetDamage(0); // disables collision detection which is not wanted here boom.tics -= random[BrainScream](0, 7); diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index 41f2c434fa..a6eecd1891 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -357,6 +357,10 @@ class Rocket : Actor MISL C 6 Bright; MISL D 4 Bright; Stop; + BrainExplode: + MISL BC 10 Bright; + MISL D 10 A_BrainExplode; + Stop; } } From ba62a86c80c58c7a78935e925be59606195e6302 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 15:48:34 +0100 Subject: [PATCH 247/471] - fixed: A_SetInventory still had default initializers. --- src/p_actionfunctions.cpp | 4 ++-- src/scripting/codegeneration/codegen.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index ff7aa2af69..d61dc100c7 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -2464,8 +2464,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetInventory) PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(itemtype, AInventory); PARAM_INT(amount); - PARAM_INT_DEF(ptr) { ptr = AAPTR_DEFAULT; } - PARAM_BOOL_DEF(beyondMax) { beyondMax = false; } + PARAM_INT_DEF(ptr); + PARAM_BOOL_DEF(beyondMax); bool res = false; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 103e38efff..89b3a81a33 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -8299,7 +8299,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) delete this; return nullptr; } - else if (!scope->IsAncestorOf(ctx.Class) && ctx.Class != RUNTIME_CLASS(AActor)) // AActor needs access to subclasses in a few places. TBD: Relax this for non-action functions? + 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; From 199e2e2f9c1904343d8c01ffbcdf81c785ed420c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 17:50:09 +0100 Subject: [PATCH 248/471] - fixed CheckRange return value. - removed the error message for multiple state blocks in DECORATE. - added some constants for state types. --- src/info.h | 15 ++++++++++++++- src/p_actionfunctions.cpp | 2 +- src/scripting/decorate/thingdef_parse.cpp | 5 ----- src/scripting/thingdef.h | 5 +++++ wadsrc/static/zscript/constants.txt | 8 ++++++++ 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/info.h b/src/info.h index e198bb26cd..86d653fe42 100644 --- a/src/info.h +++ b/src/info.h @@ -67,6 +67,14 @@ enum EStateDefineFlags 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, @@ -97,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; @@ -153,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); diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index d61dc100c7..d56c7ee644 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -3622,7 +3622,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckRange) } } } - ACTION_RETURN_BOOL(false); + ACTION_RETURN_BOOL(true); } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 151d885219..490d9cf799 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -1062,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; diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 2c13d8eb7d..3ff347ac62 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -63,6 +63,7 @@ class FStateDefinitions FState *laststatebeforelabel; intptr_t lastlabel; TArray StateArray; + uint8_t UseType; static FStateDefine *FindStateLabelInList(TArray &list, FName name, bool create); static FStateLabels *CreateStateLabelList(TArray &statelist); @@ -74,6 +75,10 @@ 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); + void SetUseType(int type) + { + UseType = uint8_t(type); + } public: diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 7c3038a749..5e47bbc7ed 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,6 +1,14 @@ // 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 enum EPainAttackFlags { From a8e2f4d539b6ec525259a3b70eddf8f46d8f74de Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 18:11:44 +0100 Subject: [PATCH 249/471] - added missing 'action' qualifiers to A_Warp and A_Teleport --- wadsrc/static/zscript/actor.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index f3cd9aa3cf..441db62f31 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -370,8 +370,8 @@ class Actor : Thinker native native void A_Weave(int xspeed, int yspeed, float xdist, float ydist); - 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); - 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); + 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); From 384f4fe7cea52be6a09b97455071e2a11858e3c7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 18:31:12 +0100 Subject: [PATCH 250/471] - added a 'DefaultStateUsage' property so that this setting can be properly set up for the classes that can inject states into other actors. --- src/info.cpp | 1 + src/info.h | 1 + src/scripting/codegeneration/codegen.cpp | 2 + src/scripting/thingdef_properties.cpp | 9 ++++ wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/shared/inventory.txt | 63 ++++++++++++---------- 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 83b455fb4b..e771108c3a 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -285,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; diff --git a/src/info.h b/src/info.h index 86d653fe42..0b7d4dfc3d 100644 --- a/src/info.h +++ b/src/info.h @@ -271,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; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 89b3a81a33..24da143213 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6121,6 +6121,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Name: case NAME_Color: case NAME_Sound: + case NAME_State: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { PType *type = @@ -6130,6 +6131,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) 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); diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 45d78557c0..7faab937bc 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -533,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; + +} //========================================================================== // //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 441db62f31..c55c7cd3a0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -45,6 +45,7 @@ class Actor : Thinker native StencilColor "00 00 00"; VisibleAngles 0, 0; VisiblePitch 0, 0; + DefaultStateUsage SUF_ACTOR|SUF_OVERLAY; } // Functions diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index e38ddbdb1e..9bc99cefbc 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -88,9 +88,9 @@ class ScoreItem : Inventory native Default { Height 10; - +COUNTITEM; + +COUNTITEM Inventory.Amount 1; - +Inventory.ALWAYSPICKUP; + +Inventory.ALWAYSPICKUP } } @@ -98,7 +98,7 @@ class Ammo : Inventory native { Default { - +INVENTORY.KEEPDEPLETED; + +INVENTORY.KEEPDEPLETED Inventory.PickupSound "misc/ammo_pkup"; } } @@ -119,7 +119,7 @@ class BasicArmor : Armor native { Default { - +Inventory.KEEPDEPLETED; + +Inventory.KEEPDEPLETED } } @@ -127,8 +127,8 @@ class BasicArmorBonus : Armor native { Default { - +Inventory.AUTOACTIVATE; - +Inventory.ALWAYSPICKUP; + +Inventory.AUTOACTIVATE + +Inventory.ALWAYSPICKUP Inventory.MaxAmount 0; Armor.SavePercent 33.335; } @@ -147,8 +147,8 @@ class HexenArmor : Armor native { Default { - +Inventory.KEEPDEPLETED; - +Inventory.UNDROPPABLE; + +Inventory.KEEPDEPLETED + +Inventory.UNDROPPABLE } } @@ -156,7 +156,13 @@ class DehackedPickup : Inventory native {} class FakeInventory : Inventory native {} -class CustomInventory : StateProvider native {} +class CustomInventory : StateProvider native +{ + Default + { + DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_ITEM; + } +} class Health : Inventory native { @@ -173,7 +179,7 @@ class HealthPickup : Inventory native Default { Inventory.DefMaxAmount; - +INVENTORY.INVBAR; + +INVENTORY.INVBAR } } @@ -192,8 +198,8 @@ class PowerupGiver : Inventory native Default { Inventory.DefMaxAmount; - +INVENTORY.INVBAR; - +INVENTORY.FANCYPICKUPSOUND; + +INVENTORY.INVBAR + +INVENTORY.FANCYPICKUPSOUND Inventory.PickupSound "misc/p_pkup"; } } @@ -215,7 +221,7 @@ class PowerStrength : Powerup native { Powerup.Duration 1; Powerup.Color "ff 00 00", 0.5; - +INVENTORY.HUBPOWER; + +INVENTORY.HUBPOWER } } @@ -245,7 +251,7 @@ class PowerShadow : PowerInvisibility { Default { - +INVENTORY.HUBPOWER; + +INVENTORY.HUBPOWER Powerup.Duration -55; Powerup.Strength 75; Powerup.Mode "Cumulative"; @@ -267,7 +273,7 @@ class PowerMask : PowerIronFeet native { Powerup.Duration -80; Powerup.Color "00 00 00", 0; - +INVENTORY.HUBPOWER; + +INVENTORY.HUBPOWER Inventory.Icon "I_MASK"; } } @@ -287,7 +293,7 @@ class PowerFlight : Powerup native Default { Powerup.Duration -60; - +INVENTORY.HUBPOWER; + +INVENTORY.HUBPOWER } } @@ -297,7 +303,7 @@ class PowerWeaponLevel2 : Powerup native { Powerup.Duration -40; Inventory.Icon "SPINBK0"; - +INVENTORY.NOTELEPORTFREEZE; + +INVENTORY.NOTELEPORTFREEZE } } @@ -308,7 +314,7 @@ class PowerSpeed : Powerup native Powerup.Duration -45; Speed 1.5; Inventory.Icon "SPBOOT0"; - +INVENTORY.NOTELEPORTFREEZE; + +INVENTORY.NOTELEPORTFREEZE } } @@ -318,8 +324,8 @@ class PlayerSpeedTrail native { Default { - +NOBLOCKMAP; - +NOGRAVITY; + +NOBLOCKMAP + +NOGRAVITY Alpha 0.6; RenderStyle "Translucent"; } @@ -339,7 +345,7 @@ class PowerTargeter : Powerup native Default { Powerup.Duration -160; - +INVENTORY.HUBPOWER; + +INVENTORY.HUBPOWER } States { @@ -374,7 +380,7 @@ class PowerScanner : Powerup native Default { Powerup.Duration -80; - +INVENTORY.HUBPOWER; + +INVENTORY.HUBPOWER } } @@ -445,8 +451,8 @@ class PuzzleItem : Inventory native { Default { - +NOGRAVITY; - +INVENTORY.INVBAR; + +NOGRAVITY + +INVENTORY.INVBAR Inventory.DefMaxAmount; Inventory.UseSound "PuzzleSuccess"; Inventory.PickupSound "misc/i_pkup"; @@ -462,7 +468,8 @@ class Weapon : StateProvider native Weapon.BobSpeed 1.0; Weapon.BobRangeX 1.0; Weapon.BobRangeY 1.0; - +WEAPONSPAWN; + +WEAPONSPAWN + DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_ITEM; } States { @@ -491,9 +498,9 @@ class WeaponHolder : Inventory native { Default { - +NOBLOCKMAP; - +NOSECTOR; - +INVENTORY.UNDROPPABLE; + +NOBLOCKMAP + +NOSECTOR + +INVENTORY.UNDROPPABLE } } From 7bcd83f0c1c8646cecb5421b13b58d104fad1f97 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 19:35:29 +0100 Subject: [PATCH 251/471] - parser for states flags. --- src/resourcefiles/file_zip.cpp | 82 ++++++++++++---------- src/scripting/decorate/thingdef_states.cpp | 17 +++++ src/scripting/thingdef.h | 6 -- src/scripting/zscript/ast.cpp | 1 + src/scripting/zscript/zcc-parse.lemon | 23 ++++++ src/scripting/zscript/zcc_parser.h | 1 + 6 files changed, 87 insertions(+), 43 deletions(-) diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 8713fe554a..3f45480403 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/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index c9be2c7476..db424ed44f 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -144,6 +144,22 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage & char lastsprite[5] = ""; FxExpression *ScriptCode; FArgumentList *args = nullptr; + int flagdef = actor->DefaultStateUsage; + + 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 @@ -151,6 +167,7 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage & { ScriptCode = nullptr; memset(&state,0,sizeof(state)); + state.UseFlags = (uint8_t)flagdef; statestring = ParseStateString(sc); if (!statestring.CompareNoCase("GOTO")) { diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 3ff347ac62..eeea42f87b 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -63,7 +63,6 @@ class FStateDefinitions FState *laststatebeforelabel; intptr_t lastlabel; TArray StateArray; - uint8_t UseType; static FStateDefine *FindStateLabelInList(TArray &list, FName name, bool create); static FStateLabels *CreateStateLabelList(TArray &statelist); @@ -75,11 +74,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); - void SetUseType(int type) - { - UseType = uint8_t(type); - } - public: FStateDefinitions() diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index cb0240dea8..c248678374 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -358,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(); } diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 6caef777e1..1882aa41ca 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -418,14 +418,37 @@ 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 diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index ec8bd956a6..1a187af829 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -228,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 From c797319314ec1f3e28de335e4b6a07e9229df37c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 20:00:01 +0100 Subject: [PATCH 252/471] - fixed parser for state block options. - fixed incorrect flags for weapons. --- src/scripting/zscript/zcc-parse.lemon | 1 - wadsrc/static/zscript/shared/inventory.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 1882aa41ca..a29d3d9433 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -421,7 +421,6 @@ enumerator(X) ::= IDENTIFIER(A) EQ expr(B). /* Expression must be constant. */ %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); diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 9bc99cefbc..c6fb203a8f 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -469,7 +469,7 @@ class Weapon : StateProvider native Weapon.BobRangeX 1.0; Weapon.BobRangeY 1.0; +WEAPONSPAWN - DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_ITEM; + DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_WEAPON; } States { From 4f998fa87951c1c2f5324a3688b0e721fccd49c4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Nov 2016 23:24:10 +0100 Subject: [PATCH 253/471] - finished the state usage parser. - added state usage specifiers to Actor and Inventory. The states in these classes must be set to full access so that any existing mod can link to them. --- src/namedef.h | 1 + src/scripting/zscript/zcc_compile.cpp | 33 ++++++++++++++++++++++ wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/shared/inventory.txt | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index f8475f7169..e9324d44b3 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -736,3 +736,4 @@ xx(DamageFunction) xx(Length) xx(Unit) xx(StateLabel) +xx(Overlay) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index b8c0a2a387..2603fea7d5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2387,6 +2387,39 @@ void ZCCCompiler::CompileStates() 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 { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c55c7cd3a0..09b5683c83 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -489,7 +489,7 @@ class Actor : Thinker native return ACS_ExecuteAlways(-int(script), mapnum, arg1, arg2, arg3); } - States + States(Actor, Overlay, Weapon, Item) { Spawn: TNT1 A -1; diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index c6fb203a8f..a6d7af8353 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -16,7 +16,7 @@ class Inventory : Actor native private native void A_RestoreSpecialThing1(); private native void A_RestoreSpecialThing2(); - States + States(Actor, Overlay, Weapon, Item) { HideDoomish: TNT1 A 1050; From 647e1399f13606f65207320d1254d3fc318b71a7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 00:18:57 +0100 Subject: [PATCH 254/471] - added runtime checks for the state usage flags. --- src/p_actionfunctions.cpp | 7 +++++++ src/p_mobj.cpp | 8 ++++++++ src/p_pspr.cpp | 10 ++++++++++ src/scripting/zscript/zcc_compile.cpp | 1 + 4 files changed, 26 insertions(+) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index d56c7ee644..1c0f846b90 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -128,6 +128,13 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) while (state != NULL) { + if (!(state->UseFlags & SUF_ITEM)) + { + auto so = FState::StaticFindStateOwner(state); + Printf("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 diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 05cfb7cc48..c7f1818380 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -626,6 +626,14 @@ bool AActor::SetState (FState *newstate, bool nofunction) { prevsprite = -1; } + if (!(newstate->UseFlags & SUF_ACTOR)) + { + auto so = FState::StaticFindStateOwner(newstate); + Printf("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()); diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index f371c68889..1d39d907ea 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -296,6 +296,16 @@ 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("State %s.%d not flagged for use in overlays or weapons\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates)); + State = nullptr; + Destroy(); + return; + } + State = newstate; if (newstate->sprite != SPR_FIXED) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 2603fea7d5..48be582cf8 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2437,6 +2437,7 @@ void ZCCCompiler::CompileStates() 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()); From 96d093d01f0675d65873c30f80edc026affe896b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 11:21:08 +0100 Subject: [PATCH 255/471] - added compile time checks for bad state links and state label references. - preserve a state's source line information for the postprocessing phase so that the checker can output more useful information. - added missing check for weapon psprites to DPSprite::SetState. --- src/p_actionfunctions.cpp | 2 +- src/p_mobj.cpp | 2 +- src/p_pspr.cpp | 13 +- src/p_states.cpp | 5 +- src/scripting/codegeneration/codegen.cpp | 5 +- src/scripting/decorate/olddecorations.cpp | 25 ++-- src/scripting/decorate/thingdef_states.cpp | 6 +- src/scripting/thingdef.cpp | 149 +++++++++++++++++---- src/scripting/thingdef.h | 9 +- src/scripting/zscript/zcc_compile.cpp | 8 +- 10 files changed, 179 insertions(+), 45 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 1c0f846b90..d59b45256a 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -131,7 +131,7 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) if (!(state->UseFlags & SUF_ITEM)) { auto so = FState::StaticFindStateOwner(state); - Printf("State %s.%d not flagged for use in CustomInventory state chains.\n", so->TypeName.GetChars(), int(state - so->OwnedStates)); + Printf(TEXTCOLOR_RED "State %s.%d not flagged for use in CustomInventory state chains.\n", so->TypeName.GetChars(), int(state - so->OwnedStates)); return false; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index c7f1818380..ce74684ccf 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -629,7 +629,7 @@ bool AActor::SetState (FState *newstate, bool nofunction) if (!(newstate->UseFlags & SUF_ACTOR)) { auto so = FState::StaticFindStateOwner(newstate); - Printf("State %s.%d in %s not flagged for use as an actor sprite\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates), GetClass()->TypeName.GetChars()); + 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; diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 1d39d907ea..9ae7b530de 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -300,11 +300,22 @@ void DPSprite::SetState(FState *newstate, bool pending) 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("State %s.%d not flagged for use in overlays or weapons\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates)); + 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; diff --git a/src/p_states.cpp b/src/p_states.cpp index 2c1b88eafb..f7f237c777 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -913,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; @@ -939,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 @@ -968,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! @@ -1012,6 +1014,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) } + //========================================================================== // // Prints all state label info to the logfile diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 24da143213..626dcde242 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5119,13 +5119,14 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) delete this; return newex->Resolve(ctx); } - else if (ctx.FromDecorate && ctx.Class->IsDescendantOf(RUNTIME_CLASS(AStateProvider)) && sym->IsKindOf(RUNTIME_CLASS(PField))) + // 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_DEBUGWARN, "Self pointer used in ambiguous context; VM execution may abort!"); + ScriptPosition.Message(MSG_OPTERROR, "Self pointer used in ambiguous context; VM execution may abort!"); ctx.Unsafe = true; } else diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index d1b79328f9..a4cf20de40 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -103,8 +103,8 @@ IMPLEMENT_CLASS(AFakeInventory, false, false, false, false) // 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 ------------------------------------------------ @@ -147,6 +147,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) { Baggage bag; TArray StateArray; + TArray SourceLines; FExtraInfo extra; PClassActor *type; PClassActor *parent; @@ -168,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) @@ -192,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) { @@ -353,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"; @@ -403,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) && @@ -411,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")) @@ -650,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) { @@ -705,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'; @@ -714,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/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index db424ed44f..cad542d1b8 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -145,6 +145,7 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage & FxExpression *ScriptCode; FArgumentList *args = nullptr; int flagdef = actor->DefaultStateUsage; + FScriptPosition scp; if (sc.CheckString("(")) { @@ -238,6 +239,7 @@ 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(); @@ -341,10 +343,10 @@ do_stop: endofstate: if (ScriptCode != nullptr) { - auto funcsym = CreateAnonymousFunction(actor, nullptr, VARF_Method | VARF_Action); + 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); + int count = bag.statedef.AddStates(&state, statestring, scp); if (count < 0) { sc.ScriptError("Invalid frame character string '%s'", statestring.GetChars()); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index d163ffb38d..bf6b08ea71 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -72,6 +72,30 @@ 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 @@ -80,7 +104,7 @@ PClassActor *QuestItemClasses[31]; // //========================================================================== -void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags) +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); @@ -98,8 +122,8 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArrayIsDescendantOf(RUNTIME_CLASS(AStateProvider))) + // 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. } @@ -139,11 +163,14 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i 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, flags); + 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, flags); + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, fflags); return sym; } @@ -201,7 +228,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, else { auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition); - auto funcsym = CreateAnonymousFunction(info, TypeSInt32, VARF_Method); + auto funcsym = CreateAnonymousFunction(info, TypeSInt32, 0); defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate); } } @@ -215,25 +242,24 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, // For such cases a runtime check in the relevant places is also present. // //========================================================================== -static int CheckForUnsafeStates(PClassActor *obj) +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; - int errors = 0; if (obj->IsDescendantOf(RUNTIME_CLASS(AWeapon))) { - if (obj->Size == RUNTIME_CLASS(AWeapon)->Size) return 0; // This class cannot have user variables. + 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 0; // This class cannot have user variables. + if (obj->Size == RUNTIME_CLASS(ACustomInventory)->Size) return; // This class cannot have user variables. test = pickupstates; } - else return 0; // something else derived from AStateProvider. We do not know what this may be. + else return; // something else derived from AStateProvider. We do not know what this may be. for (; *test != NAME_None; test++) { @@ -245,14 +271,87 @@ static int CheckForUnsafeStates(PClassActor *obj) { // 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, reached by %s.%s which accesses user variables.\n", - owner->TypeName.GetChars(), state - owner->OwnedStates, static_cast(state->ActionFunc)->PrintableName.GetChars(), obj->TypeName.GetChars(), FName(*test).GetChars()); - errors++; + 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; } } - return errors; +} + +//========================================================================== +// +// 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)); + } + } } //========================================================================== @@ -285,41 +384,44 @@ void LoadActors () { I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter); } + FScriptPosition::ResetErrorCounter(); - int errorcount = 0; for (auto ti : PClassActor::AllActorClasses) { if (ti->Size == TentativeClass) { Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); - errorcount++; + FScriptPosition::ErrorCounter++; continue; } if (GetDefaultByType(ti) == nullptr) { Printf(TEXTCOLOR_RED "No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars()); - errorcount++; + 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. - errorcount += CheckForUnsafeStates(ti); + CheckForUnsafeStates(ti); } + } - if (errorcount > 0) + if (FScriptPosition::ErrorCounter > 0) { - I_Error("%d errors during actor postprocessing", errorcount); + I_Error("%d errors during actor postprocessing", FScriptPosition::ErrorCounter); } timer.Unclock(); - if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); - // Base time: ~52 ms + 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++) @@ -328,4 +430,5 @@ void LoadActors () mysnprintf(fmt, countof(fmt), "QuestItem%d", i + 1); QuestItemClasses[i] = PClass::FindActor(fmt); } + StateSourceLines.Clear(); } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index eeea42f87b..7218a84e6c 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -63,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); @@ -97,10 +98,14 @@ 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(); } }; + +void SaveStateSourceLines(FState *firststate, TArray &positions); +FScriptPosition & GetStateSource(FState *state); + //========================================================================== // // Extra info maintained while defining an actor. @@ -152,7 +157,7 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags); +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); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 48be582cf8..57475c50e4 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2096,7 +2096,9 @@ void ZCCCompiler::InitFunctions() (*afd->VMPointer)->ImplicitArgs = BYTE(implicitargs); } } - SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags); + // 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; @@ -2518,12 +2520,12 @@ void ZCCCompiler::CompileStates() auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); if (code != nullptr) { - auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action); + 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()); + int count = statedef.AddStates(&state, sl->Frames->GetChars(), *sl); if (count < 0) { Error(sl, "Invalid frame character string '%s'", sl->Frames->GetChars()); From a8ac6e4774d2b7c910b1db65e3d7431a1eb2a46e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 11:43:35 +0100 Subject: [PATCH 256/471] - converted dynamic light definitions. --- wadsrc/static/actors/shared/dynlights.txt | 102 ---------------------- wadsrc/static/zscript.txt | 1 + 2 files changed, 1 insertion(+), 102 deletions(-) delete mode 100644 wadsrc/static/actors/shared/dynlights.txt diff --git a/wadsrc/static/actors/shared/dynlights.txt b/wadsrc/static/actors/shared/dynlights.txt deleted file mode 100644 index 4a2940be10..0000000000 --- a/wadsrc/static/actors/shared/dynlights.txt +++ /dev/null @@ -1,102 +0,0 @@ -ACTOR DynamicLight native -{ - Height 0 - Radius 0.1 - FloatBobPhase 0 - +NOBLOCKMAP - +NOGRAVITY - +FIXMAPTHINGPOS - +INVISIBLE -} - - -ACTOR PointLight : DynamicLight -{ - DynamicLight.Type "Point" -} - -ACTOR PointLightPulse : PointLight -{ - DynamicLight.Type "Pulse" -} - -ACTOR PointLightFlicker : PointLight -{ - DynamicLight.Type "Flicker" -} - -ACTOR SectorPointLight : PointLight -{ - DynamicLight.Type "Sector" -} - -ACTOR PointLightFlickerRandom : PointLight -{ - DynamicLight.Type "RandomFlicker" -} - -// MISSILEMORE and MISSILEEVENMORE are used by the lights for additive and subtractive lights - -ACTOR PointLightAdditive : PointLight -{ - +MISSILEMORE -} - -ACTOR PointLightPulseAdditive : PointLightPulse -{ - +MISSILEMORE -} - -ACTOR PointLightFlickerAdditive : PointLightFlicker -{ - +MISSILEMORE -} - -ACTOR SectorPointLightAdditive : SectorPointLight -{ - +MISSILEMORE -} - -ACTOR PointLightFlickerRandomAdditive :PointLightFlickerRandom -{ - +MISSILEMORE -} - -ACTOR PointLightSubtractive : PointLight -{ - +MISSILEEVENMORE -} - -ACTOR PointLightPulseSubtractive : PointLightPulse -{ - +MISSILEEVENMORE -} - -ACTOR PointLightFlickerSubtractive : PointLightFlicker -{ - +MISSILEEVENMORE -} - -ACTOR SectorPointLightSubtractive : SectorPointLight -{ - +MISSILEEVENMORE -} - -ACTOR PointLightFlickerRandomSubtractive : PointLightFlickerRandom -{ - +MISSILEEVENMORE -} - - -ACTOR VavoomLight : DynamicLight native -{ -} - -ACTOR VavoomLightWhite : VavoomLight native -{ -} - -ACTOR VavoomLightColor : VavoomLight native -{ -} - diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 42f32a4476..047bb1c80a 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -31,6 +31,7 @@ zscript/shared/setcolor.txt zscript/shared/sectoraction.txt zscript/shared/ice.txt zscript/shared/dog.txt +zscript/shared/dynlights.txt zscript/doom/doomplayer.txt zscript/doom/possessed.txt From 3a2d0e348630058b5ed46146aa2781171ab3ccf5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 11:49:27 +0100 Subject: [PATCH 257/471] - copied all necessary adjustments from the test branch in the QZDoom repo. --- src/gl/dynlights/a_dynlight.cpp | 10 +++++----- src/gl/system/gl_framebuffer.cpp | 2 +- src/posix/sdl/sdlglvideo.cpp | 2 +- src/win32/win32gliface.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp index 0e52eedd8a..5c85fce85c 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -62,7 +62,7 @@ #include "p_local.h" #include "c_dispatch.h" #include "g_level.h" -#include "thingdef/thingdef.h" +#include "scripting/thingdef.h" #include "i_system.h" #include "templates.h" #include "doomdata.h" @@ -106,10 +106,10 @@ DEFINE_CLASS_PROPERTY(type, S, DynamicLight) // which is controlled by flags // //========================================================================== -IMPLEMENT_CLASS (ADynamicLight) -IMPLEMENT_CLASS (AVavoomLight) -IMPLEMENT_CLASS (AVavoomLightWhite) -IMPLEMENT_CLASS (AVavoomLightColor) +IMPLEMENT_CLASS (ADynamicLight, false, false, false, false) +IMPLEMENT_CLASS (AVavoomLight, false, false, false, false) +IMPLEMENT_CLASS (AVavoomLightWhite, false, false, false, false) +IMPLEMENT_CLASS (AVavoomLightColor, false, false, false, false) void AVavoomLight::BeginPlay () { diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 4904cc1f6f..259cef5e0e 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -53,7 +53,7 @@ #include "gl/renderer/gl_2ddrawer.h" #include "gl_debug.h" -IMPLEMENT_CLASS(OpenGLFrameBuffer) +IMPLEMENT_CLASS(OpenGLFrameBuffer, false, false, false, false) EXTERN_CVAR (Float, vid_brightness) EXTERN_CVAR (Float, vid_contrast) EXTERN_CVAR (Bool, vid_vsync) diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index d8c00f2363..cebd928ee7 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -29,7 +29,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS(SDLGLFB) +IMPLEMENT_ABSTRACT_CLASS(SDLGLFB, false, false, false, false) struct MiniModeInfo { diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index 5d68d84278..6b9e413af5 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -854,7 +854,7 @@ bool Win32GLVideo::SetFullscreen(const char *devicename, int w, int h, int bits, // //========================================================================== -IMPLEMENT_ABSTRACT_CLASS(Win32GLFrameBuffer) +IMPLEMENT_CLASS(Win32GLFrameBuffer, true, false, false, false) //========================================================================== // From d3332b03dba5a35ccb6c314d06723915143d8adc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 13:37:56 +0100 Subject: [PATCH 258/471] - dynlights.txt. --- wadsrc/static/zscript/shared/dynlights.txt | 159 +++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 wadsrc/static/zscript/shared/dynlights.txt diff --git a/wadsrc/static/zscript/shared/dynlights.txt b/wadsrc/static/zscript/shared/dynlights.txt new file mode 100644 index 0000000000..55698f079c --- /dev/null +++ b/wadsrc/static/zscript/shared/dynlights.txt @@ -0,0 +1,159 @@ +class DynamicLight : Actor native +{ + Default + { + Height 0; + Radius 0.1; + FloatBobPhase 0; + +NOBLOCKMAP + +NOGRAVITY + +FIXMAPTHINGPOS + +INVISIBLE + } +} + + +class PointLight : DynamicLight +{ + Default + { + DynamicLight.Type "Point"; + } +} + +class PointLightPulse : PointLight +{ + Default + { + DynamicLight.Type "Pulse"; + } +} + +class PointLightFlicker : PointLight +{ + Default + { + DynamicLight.Type "Flicker"; + } +} + +class SectorPointLight : PointLight +{ + Default + { + DynamicLight.Type "Sector"; + } +} + +class PointLightFlickerRandom : PointLight +{ + Default + { + DynamicLight.Type "RandomFlicker"; + } +} + +// MISSILEMORE and MISSILEEVENMORE are used by the lights for additive and subtractive lights + +class PointLightAdditive : PointLight +{ + Default + { + +MISSILEMORE + } +} + +class PointLightPulseAdditive : PointLightPulse +{ + Default + { + +MISSILEMORE + } +} + +class PointLightFlickerAdditive : PointLightFlicker +{ + Default + { + +MISSILEMORE + } +} + +class SectorPointLightAdditive : SectorPointLight +{ + Default + { + +MISSILEMORE + } +} + +class PointLightFlickerRandomAdditive :PointLightFlickerRandom +{ + Default + { + +MISSILEMORE + } +} + +class PointLightSubtractive : PointLight +{ + Default + { + +MISSILEEVENMORE + } +} + +class PointLightPulseSubtractive : PointLightPulse +{ + Default + { + +MISSILEEVENMORE + } +} + +class PointLightFlickerSubtractive : PointLightFlicker +{ + Default + { + +MISSILEEVENMORE + } +} + +class SectorPointLightSubtractive : SectorPointLight +{ + Default + { + +MISSILEEVENMORE + } +} + +class PointLightFlickerRandomSubtractive : PointLightFlickerRandom +{ + Default + { + +MISSILEEVENMORE + } +} + + +class VavoomLight : DynamicLight native +{ + Default + { + } +} + +class VavoomLightWhite : VavoomLight native +{ + Default + { + } +} + +class VavoomLightColor : VavoomLight native +{ + Default + { + } +} + From a63c749f0417712d9a6d5c314a14c20d01e0a71c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 13:39:41 +0100 Subject: [PATCH 259/471] - moved A_Light to Actor after finding some mods which used it badly. Besides, it should be fine to use this from PlayerPawns as well. --- src/g_strife/a_strifeweapons.cpp | 17 ----------------- src/p_pspr.cpp | 4 ++-- wadsrc/static/zscript/actor.txt | 6 ++++++ wadsrc/static/zscript/shared/inventory.txt | 5 ----- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index be8452046d..4dad52de4d 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -937,23 +937,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_SigilCharge) return 0; } -//============================================================================ -// -// A_LightInverse -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LightInverse) -{ - PARAM_ACTION_PROLOGUE(AActor); - - if (self->player != NULL) - { - self->player->extralight = INT_MIN; - } - return 0; -} - //============================================================================ // // A_FireSigil1 diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 9ae7b530de..1bb0db9093 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1415,9 +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_PARAMS(AInventory, A_Light) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Light) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_SELF_PROLOGUE(AActor); PARAM_INT(light); if (self->player != NULL) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 09b5683c83..8e8b2fdd88 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -77,6 +77,12 @@ class Actor : Thinker native 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 void A_Light(int extralight); + void A_Light0() { A_Light(0); } + void A_Light1() { A_Light(1); } + void A_Light2() { A_Light(2); } + void A_LightInverse() { A_Light(0x80000000); } 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); diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index a6d7af8353..377463adc1 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -46,11 +46,6 @@ class StateProvider : Inventory native 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(); From d4d6b739e00c2ebf043e9cd05287b90774ddc206 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 13:52:38 +0100 Subject: [PATCH 260/471] - fixed: FxUnaryNotBoolean is not necessarily TypeBoolean, it can be altered by a type cast so the asserts had to be adjusted to cover that case. --- src/scripting/codegeneration/codegen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 626dcde242..dad7402e8c 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1847,8 +1847,8 @@ FxExpression *FxUnaryNotBoolean::Resolve(FCompileContext& ctx) ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) { - assert(Operand->ValueType == ValueType); - assert(ValueType == TypeBool); + assert(Operand->ValueType == TypeBool); + assert(ValueType == TypeBool || IsInteger()); // this may have been changed by an int cast. ExpEmit from = Operand->Emit(build); assert(!from.Konst); // boolean not is the same as XOR-ing the lowest bit From 97e643c7e1731e574f2bc5ffc78d1918b6f7e3ec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 14:53:01 +0100 Subject: [PATCH 261/471] - fixed: DECORATE tried to resolved null states again, causing a type conflict. --- src/scripting/decorate/thingdef_exp.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 229c8f1f48..2d69be3405 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -477,9 +477,12 @@ 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); + if (!exp->isConstant()) + { + FArgumentList args; + args.Push(exp); + exp = new FxFunctionCall(NAME_ResolveState, NAME_None, args, sc); + } sc.MustGetToken(')'); return exp; } From 77a99890cf4a54c905c88602637f96675cc4f440 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 15:34:00 +0100 Subject: [PATCH 262/471] - relaxed the message for incompatible class types in DECORATE to a warning. Like finding no class at all here, this initially fell under a situation that was not discoverable and there's mods that break by making it a fatal error. --- src/scripting/codegeneration/codegen.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index dad7402e8c..f45bea5e34 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -8069,11 +8069,10 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { 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_OPTERROR, "class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); + cls = nullptr; } - ScriptPosition.Message(MSG_DEBUGLOG, "resolving '%s' as class name", clsname.GetChars()); + else ScriptPosition.Message(MSG_DEBUGLOG, "resolving '%s' as class name", clsname.GetChars()); } } FxExpression *x = new FxConstant(cls, to, ScriptPosition); From e559109419e0d33c70eb968d99db237066b64142 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 16:00:35 +0100 Subject: [PATCH 263/471] - made the floating point truncation warning a debug message because I can see this becoming more a hassle than an asset. --- src/scripting/codegeneration/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f45bea5e34..8909dd31b0 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -848,7 +848,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) } else if (!NoWarn) { - ScriptPosition.Message(MSG_WARNING, "Truncation of floating point value"); + ScriptPosition.Message(MSG_DEBUGWARN, "Truncation of floating point value"); } return this; From 4cc7d95ba5f33c8fa357adda863d39aca8d93d4b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 16:05:42 +0100 Subject: [PATCH 264/471] - fixed: A_ZoomFactor and A_SetCrosshair need to be declared 'action'. --- src/g_shared/a_weapons.cpp | 4 ++-- wadsrc/static/zscript/shared/inventory.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 9063c6c2c7..9fc2334c4f 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -1925,7 +1925,7 @@ PClassWeapon *Net_ReadWeapon(BYTE **stream) DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_ZoomFactor) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_FLOAT_DEF(zoom); PARAM_INT_DEF(flags); @@ -1953,7 +1953,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_ZoomFactor) DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_SetCrosshair) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(xhair); if (self->player != NULL && self->player->ReadyWeapon != NULL) diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 377463adc1..12f30c4848 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -473,11 +473,11 @@ class Weapon : StateProvider native Stop; } - native void A_ZoomFactor(float scale = 1, int flags = 0); + native action void A_ZoomFactor(float scale = 1, int flags = 0); + native action void A_SetCrosshair(int xhair); const ZOOM_INSTANT = 1; const ZOOM_NOSCALETURNING = 2; - native void A_SetCrosshair(int xhair); } class WeaponGiver : Weapon native From 1d006b37c3a96f7ba05ceb6268f6430c6734201a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 17:41:49 +0100 Subject: [PATCH 265/471] - fixed: The distance check in CheckIfCloser used the wrong variable. --- wadsrc/static/zscript/actor_checks.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actor_checks.txt b/wadsrc/static/zscript/actor_checks.txt index 8065397530..3ad4255d72 100644 --- a/wadsrc/static/zscript/actor_checks.txt +++ b/wadsrc/static/zscript/actor_checks.txt @@ -35,7 +35,7 @@ extend class Actor { if (!targ) return false; return - (Distance2D(target) < dist && (noz || + (Distance2D(targ) < 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) ) From a2e17c0ab57409f4c068ba57e9d144dd30710dd8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Nov 2016 21:38:12 +0100 Subject: [PATCH 266/471] - implemented usage restrictions for action functions. --- src/dobjtype.cpp | 3 +- src/dobjtype.h | 5 +- src/scripting/codegeneration/codegen.cpp | 89 +++++++++++++++++------- src/scripting/thingdef.cpp | 2 +- src/scripting/zscript/ast.cpp | 12 ++++ src/scripting/zscript/zcc-parse.lemon | 78 +++++++++++++++------ src/scripting/zscript/zcc_compile.cpp | 50 +++++++++++-- src/scripting/zscript/zcc_parser.h | 8 +++ 8 files changed, 189 insertions(+), 58 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 2c88da92a1..5e56bab564 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2489,7 +2489,7 @@ size_t PFunction::PropagateMark() // //========================================================================== -unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags) +unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags, int useflags) { Variant variant; @@ -2497,6 +2497,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra assert(Variants.Size() == 0); variant.Flags = flags; + variant.UseFlags = useflags; variant.Proto = proto; variant.ArgFlags = std::move(argflags); variant.ArgNames = std::move(argnames); diff --git a/src/dobjtype.h b/src/dobjtype.h index 1ca5df8325..186cb8117f 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -724,13 +724,14 @@ public: 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; + uint32_t Flags; + int UseFlags; PClass *SelfClass; }; TArray Variants; PClass *OwningClass = nullptr; - unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags); + unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags, int useflags); int GetImplicitArgs() { if (Variants[0].Flags & VARF_Action) return 3; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8909dd31b0..b64e0c4391 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5931,6 +5931,42 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) return dest; } +//========================================================================== +// +// Checks if a function may be called from the current context. +// +//========================================================================== + +static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction *caller, PFunction *callee) +{ + if (callee->Variants[0].Flags & VARF_Method) + { + // The called function must support all usage modes of the current function. It may support more, but must not support less. + if ((callee->Variants[0].UseFlags & caller->Variants[0].UseFlags) != caller->Variants[0].UseFlags) + { + ScriptPosition.Message(MSG_ERROR, "Function %s incompatible with current context\n", callee->SymbolName.GetChars()); + return false; + } + + if (!(caller->Variants[0].Flags & VARF_Method)) + { + ScriptPosition.Message(MSG_ERROR, "Call to non-static function %s from a static context", callee->SymbolName.GetChars()); + return false; + } + else + { + auto callingself = caller->Variants[0].SelfClass; + auto calledself = callee->Variants[0].SelfClass; + if (!callingself->IsDescendantOf(calledself)) + { + ScriptPosition.Message(MSG_ERROR, "Call to member function %s with incompatible self pointer.", callee->SymbolName.GetChars()); + return false; + } + } + } + return true; +} + //========================================================================== // // @@ -6008,39 +6044,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) 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)) + if (!CheckFunctionCompatiblity(ScriptPosition, ctx.Function, afd)) { - 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 self = (afd->Variants[0].Flags & VARF_Method)? new FxSelf(ScriptPosition) : nullptr; auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, false); delete this; return x->Resolve(ctx); @@ -6338,6 +6350,7 @@ isresolved: delete this; return nullptr; } + if (staticonly && (afd->Variants[0].Flags & VARF_Method)) { if (!ctx.Class->IsDescendantOf(cls)) @@ -6355,6 +6368,28 @@ isresolved: } } + if (afd->Variants[0].Flags & VARF_Method) + { + if (Self->ExprType == EFX_Self) + { + if (!CheckFunctionCompatiblity(ScriptPosition, ctx.Function, afd)) + { + delete this; + return nullptr; + } + } + else + { + // Functions with no Actor usage may not be called through a pointer because they will lose their context. + if (!(afd->Variants[0].UseFlags & SUF_ACTOR)) + { + ScriptPosition.Message(MSG_ERROR, "Function %s cannot be used with a non-self object\n", afd->SymbolName.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); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index bf6b08ea71..3abce216db 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -170,7 +170,7 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i 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); + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, fflags, flags); return sym; } diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index c248678374..89cc9487e3 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -820,6 +820,7 @@ static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node) out.Break(); out.Open("func-declarator"); out.AddHex(dnode->Flags); + PrintNodes(out, dnode->UseFlags); PrintNodes(out, dnode->Type); out.AddName(dnode->Name); PrintNodes(out, dnode->Params); @@ -827,6 +828,16 @@ static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node) out.Close(); } +static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node) +{ + auto dnode = (ZCC_DeclFlags *)node; + out.Break(); + out.Open("decl-flags"); + out.AddHex(dnode->Flags); + PrintNodes(out, dnode->Id); + out.Close(); +} + static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node) { auto dnode = (ZCC_FlagStmt *)node; @@ -901,6 +912,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintFlagStmt, PrintPropertyStmt, PrintVectorInitializer, + PrintDeclFlags, }; FString ZCC_PrintAST(ZCC_TreeNode *root) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index a29d3d9433..f152cfdd58 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -814,20 +814,21 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C). } else if (C.FuncName != NAME_None) { // A function - NEW_AST_NODE(FuncDeclarator, decl, A.SourceLoc); + NEW_AST_NODE(FuncDeclarator, decl, A == nullptr? C.SourceLoc : A->SourceLoc); decl->Type = B; decl->Params = C.FuncParams; decl->Name = C.FuncName; - decl->Flags = A.Int | C.FuncFlags; + decl->UseFlags = A == nullptr? nullptr : A->Id; + decl->Flags = (A == nullptr? 0 : A->Flags) | C.FuncFlags; decl->Body = C.FuncBody; X = decl; } else if (B != NULL && B->SiblingNext == B) { // A variable - NEW_AST_NODE(VarDeclarator, decl, A.SourceLoc); + NEW_AST_NODE(VarDeclarator, decl, A == nullptr? B->SourceLoc : A->SourceLoc); decl->Type = B; decl->Names = C.VarNames; - decl->Flags = A.Int; + decl->Flags = (A == nullptr? 0 : A->Flags); X = decl; } else @@ -845,10 +846,10 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C). } declarator_no_fun(X) ::= decl_flags(A) type(B) variable_list(C) SEMICOLON. { - NEW_AST_NODE(VarDeclarator, decl, A.SourceLoc ? A.SourceLoc : B->SourceLoc); + NEW_AST_NODE(VarDeclarator, decl, A != nullptr? A->SourceLoc : B->SourceLoc); decl->Type = B; decl->Names = C; - decl->Flags = A.Int; + decl->Flags = A == nullptr? 0 : A->Flags; X = decl; } @@ -916,19 +917,52 @@ variable_list(X) ::= variable_list(A) COMMA variable_name(B). X = A; /*X-overwrites-A*/ } -decl_flags(X) ::= . { X.Int = 0; X.SourceLoc = 0; } -decl_flags(X) ::= decl_flags(A) NATIVE(T). { X.Int = A.Int | ZCC_Native; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -decl_flags(X) ::= decl_flags(A) STATIC(T). { X.Int = A.Int | ZCC_Static; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -decl_flags(X) ::= decl_flags(A) PRIVATE(T). { X.Int = A.Int | ZCC_Private; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -decl_flags(X) ::= decl_flags(A) PROTECTED(T). { X.Int = A.Int | ZCC_Protected; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -decl_flags(X) ::= decl_flags(A) LATENT(T). { X.Int = A.Int | ZCC_Latent; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -decl_flags(X) ::= decl_flags(A) FINAL(T). { X.Int = A.Int | ZCC_Final; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -decl_flags(X) ::= decl_flags(A) META(T). { X.Int = A.Int | ZCC_Meta; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -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; } +%type decl_flags { ZCC_DeclFlags * } +decl_flags(X) ::= . { X = NULL; } +decl_flags(X) ::= decl_flags(F) decl_flag(A). +{ + if (F == nullptr) + { + NEW_AST_NODE(DeclFlags,nil_f,A); + X = nil_f; + X->Id = nullptr; + X->Flags = A.Int; + } + else + { + X = F; + X->Flags |= A.Int; + } +} + + +decl_flags(X) ::= decl_flags(F) ACTION(B) states_opts(A). +{ + if (F == nullptr) + { + NEW_AST_NODE(DeclFlags,nil_f,B.SourceLoc); + X = nil_f; + X->Flags = ZCC_Action; + } + else + { + X = F; + X->Flags |= ZCC_Action; + } + X->Id = A; +} + +decl_flag(X) ::= NATIVE(T). { X.Int = ZCC_Native; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= STATIC(T). { X.Int = ZCC_Static; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= PRIVATE(T). { X.Int = ZCC_Private; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= PROTECTED(T). { X.Int = ZCC_Protected; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= LATENT(T). { X.Int = ZCC_Latent; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= FINAL(T). { X.Int = ZCC_Final; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= META(T). { X.Int = ZCC_Meta; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= READONLY(T). { X.Int = ZCC_ReadOnly; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= DEPRECATED(T). { X.Int = ZCC_Deprecated; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= VIRTUAL(T). { X.Int = ZCC_Virtual; X.SourceLoc = T.SourceLoc; } +decl_flag(X) ::= OVERRIDE(T). { X.Int = ZCC_Override; X.SourceLoc = T.SourceLoc; } func_const(X) ::= . { X.Int = 0; X.SourceLoc = stat->sc->GetMessageLine(); } func_const(X) ::= CONST(T). { X.Int = ZCC_FuncConst; X.SourceLoc = T.SourceLoc; } @@ -979,9 +1013,9 @@ func_param(X) ::= func_param_flags(A) type(B) IDENTIFIER(C) EQ expr(D). } func_param_flags(X) ::= . { X.Int = 0; X.SourceLoc = 0; } -func_param_flags(X) ::= func_param_flags(A) IN(T). { X.Int = A.Int | ZCC_In; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -func_param_flags(X) ::= func_param_flags(A) OUT(T). { X.Int = A.Int | ZCC_Out; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } -func_param_flags(X) ::= func_param_flags(A) OPTIONAL(T). { X.Int = A.Int | ZCC_Optional; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; } +func_param_flags(X) ::= func_param_flags(A) IN(T). { X.Int = A.Int | ZCC_In; X.SourceLoc = T.SourceLoc; } +func_param_flags(X) ::= func_param_flags(A) OUT(T). { X.Int = A.Int | ZCC_Out; X.SourceLoc = T.SourceLoc; } +func_param_flags(X) ::= func_param_flags(A) OPTIONAL(T). { X.Int = A.Int | ZCC_Optional; X.SourceLoc = T.SourceLoc; } /************ Expressions ************/ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 57475c50e4..6cf719d3d3 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2051,6 +2051,35 @@ void ZCCCompiler::InitFunctions() uint32_t varflags = VARF_Method; int implicitargs = 1; AFuncDesc *afd = nullptr; + int useflags = SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM; + if (f->UseFlags != nullptr) + { + useflags = 0; + auto p = f->UseFlags; + do + { + switch (p->Id) + { + case NAME_Actor: + useflags |= SUF_ACTOR; + break; + case NAME_Overlay: + useflags |= SUF_OVERLAY; + break; + case NAME_Weapon: + useflags |= SUF_WEAPON; + break; + case NAME_Item: + useflags |= SUF_ITEM; + break; + default: + Error(p, "Unknown Action qualifier %s", FName(p->Id).GetChars()); + break; + } + + p = static_cast(p->SiblingNext); + } while (p != f->UseFlags); + } // map to implementation flags. if (f->Flags & ZCC_Private) varflags |= VARF_Private; @@ -2058,9 +2087,22 @@ void ZCCCompiler::InitFunctions() 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_Action) + { + varflags |= VARF_Final; // Action implies Final. + if (useflags & (SUF_OVERLAY | SUF_WEAPON | SUF_ITEM)) + { + varflags |= VARF_Action; + implicitargs = 3; + } + else + { + implicitargs = 1; + } + } 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 }; @@ -2096,9 +2138,7 @@ void ZCCCompiler::InitFunctions() (*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); + SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags, useflags); argdefaults.Resize(argnames.Size()); auto p = f->Params; bool hasoptionals = false; @@ -2225,7 +2265,7 @@ void ZCCCompiler::InitFunctions() } PFunction *sym = new PFunction(c->Type(), f->Name); - sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr? nullptr : *(afd->VMPointer), varflags); + sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr? nullptr : *(afd->VMPointer), varflags, useflags); c->Type()->Symbols.ReplaceSymbol(sym); if (!(f->Flags & ZCC_Native)) diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 1a187af829..ffff78cb83 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -101,6 +101,7 @@ enum EZCCTreeNodeType AST_FlagStmt, AST_PropertyStmt, AST_VectorValue, + AST_DeclFlags, NUM_AST_NODE_TYPES }; @@ -473,6 +474,12 @@ struct ZCC_FuncParamDecl : ZCC_TreeNode int Flags; }; +struct ZCC_DeclFlags : ZCC_TreeNode +{ + ZCC_Identifier *Id; + int Flags; +}; + struct ZCC_ConstantDef : ZCC_NamedNode { ZCC_Expression *Value; @@ -498,6 +505,7 @@ struct ZCC_FuncDeclarator : ZCC_Declarator ZCC_FuncParamDecl *Params; ENamedName Name; ZCC_Statement *Body; + ZCC_Identifier *UseFlags; }; struct ZCC_Default : ZCC_CompoundStmt From 633da6e5d874825ee95508e48f70afac8772305b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Nov 2016 01:36:21 +0100 Subject: [PATCH 267/471] - scriptified two of the Acolyte's functions. - added a DActorIterator class. - fixed: It was not possible to have functions of the same name in two different classes because the name they were searched for was not qualified by the class. Changed so that the class name is included now, but to avoid renaming several hundreds of functions all at once, if the search fails, it will repeat with 'Actor' as class name. This commit contains preparations for scriptifying Hexen's Dragon, but that doesn't work yet so it's not included. --- src/CMakeLists.txt | 1 - src/actor.h | 4 + src/d_dehacked.cpp | 22 +- src/g_doom/a_bossbrain.cpp | 2 +- src/g_doom/a_doomweaps.cpp | 6 +- src/g_doom/a_scriptedmarine.cpp | 10 +- src/g_heretic/a_hereticmisc.cpp | 4 +- src/g_heretic/a_hereticweaps.cpp | 4 +- src/g_hexen/a_blastradius.cpp | 2 +- src/g_hexen/a_fighterquietus.cpp | 2 +- src/g_hexen/a_magelightning.cpp | 2 +- src/g_shared/a_bridge.cpp | 2 +- src/g_shared/a_specialspot.cpp | 2 +- src/g_shared/a_weapons.cpp | 4 +- src/g_strife/a_acolyte.cpp | 44 ---- src/g_strife/a_strifeweapons.cpp | 6 +- src/g_strife/a_thingstoblowup.cpp | 2 +- src/p_actionfunctions.cpp | 258 +++++++++++------------ src/p_enemy.cpp | 10 +- src/p_mobj.cpp | 51 +++++ src/p_pspr.cpp | 20 +- src/p_states.cpp | 2 +- src/p_user.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/thingdef.h | 2 +- src/scripting/thingdef_data.cpp | 41 ++-- src/scripting/vm/vm.h | 17 +- src/scripting/zscript/zcc_compile.cpp | 2 +- wadsrc/static/zscript/actor.txt | 2 + wadsrc/static/zscript/base.txt | 7 + wadsrc/static/zscript/constants.txt | 19 ++ wadsrc/static/zscript/strife/acolyte.txt | 40 +++- 32 files changed, 334 insertions(+), 260 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ecc28a57df..8e5c022cbf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -881,7 +881,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_clericholy.cpp g_hexen/a_clericmace.cpp g_hexen/a_clericstaff.cpp - g_hexen/a_dragon.cpp g_hexen/a_fighteraxe.cpp g_hexen/a_fighterhammer.cpp g_hexen/a_fighterplayer.cpp diff --git a/src/actor.h b/src/actor.h index 1228398508..d8bb1a8979 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1442,6 +1442,10 @@ public: return base; } + void Reinit() + { + base = nullptr; + } private: AActor *base; int id; diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 880cd7dfe8..d0addb0951 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -185,17 +185,17 @@ DECLARE_ACTION(A_FireRailgun) // Default ammo use of the various weapon attacks static AmmoPerAttack AmmoPerAttacks[] = { - { &A_Punch_VMPtr, 0}, - { &A_FirePistol_VMPtr, 1}, - { &A_FireShotgun_VMPtr, 1}, - { &A_FireShotgun2_VMPtr, 2}, - { &A_FireCGun_VMPtr, 1}, - { &A_FireMissile_VMPtr, 1}, - { &A_Saw_VMPtr, 0}, - { &A_FirePlasma_VMPtr, 1}, - { &A_FireBFG_VMPtr, -1}, // uses deh.BFGCells - { &A_FireOldBFG_VMPtr, 1}, - { &A_FireRailgun_VMPtr, 1}, + { &AActor_A_Punch_VMPtr, 0}, + { &AActor_A_FirePistol_VMPtr, 1}, + { &AActor_A_FireShotgun_VMPtr, 1}, + { &AActor_A_FireShotgun2_VMPtr, 2}, + { &AActor_A_FireCGun_VMPtr, 1}, + { &AActor_A_FireMissile_VMPtr, 1}, + { &AActor_A_Saw_VMPtr, 0}, + { &AActor_A_FirePlasma_VMPtr, 1}, + { &AActor_A_FireBFG_VMPtr, -1}, // uses deh.BFGCells + { &AActor_A_FireOldBFG_VMPtr, 1}, + { &AActor_A_FireRailgun_VMPtr, 1}, { NULL, 0} }; diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 5807ce1759..8adb5c1dfc 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -14,7 +14,7 @@ static FRandom pr_spawnfly ("SpawnFly"); -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit) +DEFINE_ACTION_FUNCTION(AActor, A_BrainSpit) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_DEF(spawntype, AActor); diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index bc962800f4..108a730c47 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -113,7 +113,7 @@ enum SAW_Flags SF_STEALARMOR = 128, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) +DEFINE_ACTION_FUNCTION(AActor, A_Saw) { PARAM_ACTION_PROLOGUE(AActor); PARAM_SOUND_DEF (fullsound) @@ -454,7 +454,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) // // A_FireSTGrenade: not exactly backported from ST, but should work the same // -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade) +DEFINE_ACTION_FUNCTION(AActor, A_FireSTGrenade) { PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS_DEF(grenade, AActor); @@ -607,7 +607,7 @@ enum BFG_Flags BFGF_MISSILEORIGIN = 2, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray) +DEFINE_ACTION_FUNCTION(AActor, A_BFGSpray) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_DEF (spraytype, AActor) diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index da2c7f7910..e270af6b51 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -148,7 +148,7 @@ void AScriptedMarine::Tick () // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Refire) +DEFINE_ACTION_FUNCTION(AActor, A_M_Refire) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_DEF(ignoremissile); @@ -247,7 +247,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MarineLook) // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw) +DEFINE_ACTION_FUNCTION(AActor, A_M_Saw) { PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND_DEF (fullsound) @@ -345,7 +345,7 @@ static void MarinePunch(AActor *self, int damagemul) } } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Punch) +DEFINE_ACTION_FUNCTION(AActor, A_M_Punch) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(mult); @@ -382,7 +382,7 @@ void P_GunShot2 (AActor *mo, bool accurate, DAngle pitch, PClassActor *pufftype) // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FirePistol) +DEFINE_ACTION_FUNCTION(AActor, A_M_FirePistol) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(accurate); @@ -481,7 +481,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun2) // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FireCGun) +DEFINE_ACTION_FUNCTION(AActor, A_M_FireCGun) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(accurate); diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 35b24eb932..6af969842c 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -42,7 +42,7 @@ static FRandom pr_volcimpact ("VolcBallImpact"); // //---------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain) +DEFINE_ACTION_FUNCTION(AActor, A_PodPain) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_DEF (gootype, AActor) @@ -97,7 +97,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RemovePod) #define MAX_GEN_PODS 16 -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MakePod) +DEFINE_ACTION_FUNCTION(AActor, A_MakePod) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_DEF(podtype, AActor) diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index a888be8848..4d3a0b0e82 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -59,7 +59,7 @@ extern bool P_AutoUseChaosDevice (player_t *player); // //---------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack) +DEFINE_ACTION_FUNCTION(AActor, A_StaffAttack) { PARAM_ACTION_PROLOGUE(AActor); @@ -245,7 +245,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL2) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) +DEFINE_ACTION_FUNCTION(AActor, A_GauntletAttack) { PARAM_ACTION_PROLOGUE(AActor); diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp index f8bc60a7f6..0776e107f5 100644 --- a/src/g_hexen/a_blastradius.cpp +++ b/src/g_hexen/a_blastradius.cpp @@ -93,7 +93,7 @@ enum // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast) +DEFINE_ACTION_FUNCTION (AActor, A_Blast) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT_DEF (blastflags) diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index 8f73ef48ee..adba8d2354 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -24,7 +24,7 @@ static FRandom pr_fswordflame ("FSwordFlame"); // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropWeaponPieces) +DEFINE_ACTION_FUNCTION(AActor, A_DropWeaponPieces) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(p1, AActor); diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index b06d22ce59..2a744db75d 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -255,7 +255,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningZap) // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MLightningAttack) +DEFINE_ACTION_FUNCTION(AActor, A_MLightningAttack) { PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS_DEF(floor, AActor); diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index ab0df27e14..8ce23b68e6 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -119,7 +119,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BridgeInit) +DEFINE_ACTION_FUNCTION(AActor, A_BridgeInit) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_DEF(balltype, AActor); diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 86d0b5e8a3..92306ce6b7 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -377,7 +377,7 @@ void ASpecialSpot::Destroy() // will build a list of all mace spots in the level and spawn a // mace. The rest of the spots will do nothing. -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnSingleItem) +DEFINE_ACTION_FUNCTION(AActor, A_SpawnSingleItem) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (cls, AActor); diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 9fc2334c4f..2d159eb7d7 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -1923,7 +1923,7 @@ PClassWeapon *Net_ReadWeapon(BYTE **stream) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_ZoomFactor) +DEFINE_ACTION_FUNCTION(AWeapon, A_ZoomFactor) { PARAM_ACTION_PROLOGUE(AActor); PARAM_FLOAT_DEF(zoom); @@ -1951,7 +1951,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_ZoomFactor) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AWeapon, A_SetCrosshair) +DEFINE_ACTION_FUNCTION(AWeapon, A_SetCrosshair) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(xhair); diff --git a/src/g_strife/a_acolyte.cpp b/src/g_strife/a_acolyte.cpp index a21c06619e..f0ed0c414c 100644 --- a/src/g_strife/a_acolyte.cpp +++ b/src/g_strife/a_acolyte.cpp @@ -84,47 +84,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_AcolyteDie) return 0; } -//============================================================================ -// -// A_BeShadowyFoe -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BeShadowyFoe) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->RenderStyle = STYLE_Translucent; - self->Alpha = HR_SHADOW; - self->flags &= ~MF_FRIENDLY; - return 0; -} - -//============================================================================ -// -// A_AcolyteBits -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_AcolyteBits) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->SpawnFlags & MTF_SHADOW) - { - CALL_ACTION(A_BeShadowyFoe, self); - } - if (self->SpawnFlags & MTF_ALTSHADOW) - { - //self->flags |= MF_STRIFEx8000000; - if (self->flags & MF_SHADOW) - { - // I dunno. - } - else - { - self->RenderStyle.BlendOp = STYLEOP_None; - } - } - return 0; -} diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 4dad52de4d..56eb06597c 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -144,7 +144,7 @@ enum AMF_EMITFROMTARGET = 4, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_AlertMonsters) +DEFINE_ACTION_FUNCTION(AActor, A_AlertMonsters) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_DEF(maxdist); @@ -246,7 +246,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShowElectricFlash) // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireArrow) +DEFINE_ACTION_FUNCTION(AActor, A_FireArrow) { PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS(ti, AActor); @@ -686,7 +686,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burnination) // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade) +DEFINE_ACTION_FUNCTION(AActor, A_FireGrenade) { PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS(grenadetype, AActor); diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp index 5e1bc42d2c..08670d484e 100644 --- a/src/g_strife/a_thingstoblowup.cpp +++ b/src/g_strife/a_thingstoblowup.cpp @@ -26,7 +26,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Bang4Cloud) // ------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveQuestItem) +DEFINE_ACTION_FUNCTION(AActor, A_GiveQuestItem) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(questitem); diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index d59b45256a..2d219fc387 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -306,7 +306,7 @@ DEFINE_ACTION_FUNCTION(AActor, GetMissileDamage) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountInv) +DEFINE_ACTION_FUNCTION(AActor, CountInv) { if (numret > 0) { @@ -337,7 +337,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountInv) // NON-ACTION function to get the distance in double. // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetDistance) +DEFINE_ACTION_FUNCTION(AActor, GetDistance) { if (numret > 0) { @@ -380,7 +380,7 @@ enum GAFlags GAF_SWITCH = 1 << 1, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetAngle) +DEFINE_ACTION_FUNCTION(AActor, GetAngle) { if (numret > 0) { @@ -413,7 +413,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetAngle) // GetSpawnHealth // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpawnHealth) +DEFINE_ACTION_FUNCTION(AActor, GetSpawnHealth) { if (numret > 0) { @@ -429,7 +429,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpawnHealth) // GetGibHealth // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetGibHealth) +DEFINE_ACTION_FUNCTION(AActor, GetGibHealth) { if (numret > 0) { @@ -446,7 +446,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetGibHealth) // // NON-ACTION function returns the sprite angle of a pointer. //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpriteAngle) +DEFINE_ACTION_FUNCTION(AActor, GetSpriteAngle) { if (numret > 0) { @@ -475,7 +475,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpriteAngle) // // NON-ACTION function returns the sprite rotation of a pointer. //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpriteRotation) +DEFINE_ACTION_FUNCTION(AActor, GetSpriteRotation) { if (numret > 0) { @@ -515,7 +515,7 @@ enum GZFlags GZF_NO3DFLOOR = 1 << 5, // Pass all 3D floors. }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetZAt) +DEFINE_ACTION_FUNCTION(AActor, GetZAt) { if (numret > 0) { @@ -603,7 +603,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetZAt) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) +DEFINE_ACTION_FUNCTION(AActor, GetCrouchFactor) { if (numret > 0) { @@ -633,7 +633,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCVar) +DEFINE_ACTION_FUNCTION(AActor, GetCVar) { if (numret > 0) { @@ -663,7 +663,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCVar) // Takes a pointer as anyone may or may not be a player. //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetPlayerInput) +DEFINE_ACTION_FUNCTION(AActor, GetPlayerInput) { if (numret > 0) { @@ -696,7 +696,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetPlayerInput) // Takes a pointer as anyone may or may not be a player. //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountProximity) +DEFINE_ACTION_FUNCTION(AActor, CountProximity) { if (numret > 0) { @@ -731,21 +731,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountProximity) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_int__) +DEFINE_ACTION_FUNCTION(AActor, __decorate_internal_int__) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(returnme); ACTION_RETURN_INT(returnme); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_bool__) +DEFINE_ACTION_FUNCTION(AActor, __decorate_internal_bool__) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(returnme); ACTION_RETURN_BOOL(returnme); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_float__) +DEFINE_ACTION_FUNCTION(AActor, __decorate_internal_float__) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(returnme); @@ -768,7 +768,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_float__) //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RearrangePointers) +DEFINE_ACTION_FUNCTION(AActor, A_RearrangePointers) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (ptr_target); @@ -848,7 +848,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RearrangePointers) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TransferPointer) +DEFINE_ACTION_FUNCTION(AActor, A_TransferPointer) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (ptr_source); @@ -891,7 +891,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TransferPointer) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopyFriendliness) +DEFINE_ACTION_FUNCTION(AActor, A_CopyFriendliness) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF (ptr_source); @@ -974,7 +974,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack) return 0; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BasicAttack) +DEFINE_ACTION_FUNCTION(AActor, A_BasicAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (melee_damage); @@ -995,7 +995,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BasicAttack) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) +DEFINE_ACTION_FUNCTION(AActor, A_PlaySound) { PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND_DEF (soundid); @@ -1019,7 +1019,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound) return 0; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSound) +DEFINE_ACTION_FUNCTION(AActor, A_StopSound) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(slot); @@ -1037,7 +1037,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSound) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySoundEx) +DEFINE_ACTION_FUNCTION(AActor, A_PlaySoundEx) { PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND (soundid); @@ -1074,7 +1074,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySoundEx) return 0; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSoundEx) +DEFINE_ACTION_FUNCTION(AActor, A_StopSoundEx) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME(channel); @@ -1098,7 +1098,7 @@ enum SMF_PRECISE = 2, SMF_CURSPEED = 4, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SeekerMissile) +DEFINE_ACTION_FUNCTION(AActor, A_SeekerMissile) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(ang1); @@ -1155,7 +1155,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack) // State jump function // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) +DEFINE_ACTION_FUNCTION(AActor, A_Jump) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(maxchance); @@ -1219,7 +1219,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckInventory) // State jump function // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckArmorType) +DEFINE_ACTION_FUNCTION(AActor, CheckArmorType) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME (type); @@ -1244,7 +1244,7 @@ enum XF_NOSPLASH = 16, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) +DEFINE_ACTION_FUNCTION(AActor, A_Explode) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF (damage); @@ -1313,7 +1313,7 @@ enum RTF_NOTMISSILE = 4, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust) +DEFINE_ACTION_FUNCTION(AActor, A_RadiusThrust) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF (force); @@ -1353,7 +1353,7 @@ enum RDSF_BFGDAMAGE = 1, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusDamageSelf) +DEFINE_ACTION_FUNCTION(AActor, A_RadiusDamageSelf) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(damage); @@ -1414,7 +1414,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusDamageSelf) // Execute a line special / script // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CallSpecial) +DEFINE_ACTION_FUNCTION(AActor, A_CallSpecial) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (special); @@ -1447,7 +1447,7 @@ enum CM_Flags CMF_ABSOLUTEANGLE = 128 }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile) +DEFINE_ACTION_FUNCTION(AActor, A_CustomMissile) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (ti, AActor); @@ -1596,7 +1596,7 @@ enum CBA_Flags static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, bool cba); -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) +DEFINE_ACTION_FUNCTION(AActor, A_CustomBulletAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE (spread_xy); @@ -1688,7 +1688,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) // A fully customizable melee attack // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMeleeAttack) +DEFINE_ACTION_FUNCTION(AActor, A_CustomMeleeAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF (damage); @@ -1725,7 +1725,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMeleeAttack) // A fully customizable combo attack // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack) +DEFINE_ACTION_FUNCTION(AActor, A_CustomComboAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (ti, AActor); @@ -1775,7 +1775,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack) // State jump function // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfNoAmmo) +DEFINE_ACTION_FUNCTION(AActor, A_JumpIfNoAmmo) { PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE_ACTION(jump); @@ -1846,7 +1846,7 @@ static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, b } } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) +DEFINE_ACTION_FUNCTION(AActor, A_FireBullets) { PARAM_ACTION_PROLOGUE(AActor); PARAM_ANGLE (spread_xy); @@ -1976,7 +1976,7 @@ enum FP_Flags FPF_TRANSFERTRANSLATION = 2, FPF_NOAUTOAIM = 4, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile) +DEFINE_ACTION_FUNCTION(AActor, A_FireCustomMissile) { PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS (ti, AActor); @@ -2053,7 +2053,7 @@ enum CPF_STEALARMOR = 32, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) +DEFINE_ACTION_FUNCTION(AActor, A_CustomPunch) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT (damage); @@ -2157,7 +2157,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) // customizable railgun attack function // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack) +DEFINE_ACTION_FUNCTION(AActor, A_RailAttack) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT (damage); @@ -2236,7 +2236,7 @@ enum CRF_EXPLICITANGLE = 4, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) +DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (damage); @@ -2409,19 +2409,19 @@ static bool DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS) return false; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveInventory) +DEFINE_ACTION_FUNCTION(AActor, A_GiveInventory) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(DoGiveInventory(self, false, VM_ARGS_NAMES)); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToTarget) +DEFINE_ACTION_FUNCTION(AActor, A_GiveToTarget) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(DoGiveInventory(self->target, false, VM_ARGS_NAMES)); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToChildren) +DEFINE_ACTION_FUNCTION(AActor, A_GiveToChildren) { PARAM_SELF_PROLOGUE(AActor); @@ -2439,7 +2439,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToChildren) ACTION_RETURN_INT(count); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) +DEFINE_ACTION_FUNCTION(AActor, A_GiveToSiblings) { PARAM_SELF_PROLOGUE(AActor); @@ -2466,7 +2466,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetInventory) +DEFINE_ACTION_FUNCTION(AActor, A_SetInventory) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(itemtype, AInventory); @@ -2585,19 +2585,19 @@ bool DoTakeInventory(AActor *receiver, bool orresult, VM_ARGS) return receiver->TakeInventory(itemtype, amount, true, (flags & TIF_NOTAKEINFINITE) != 0); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeInventory) +DEFINE_ACTION_FUNCTION(AActor, A_TakeInventory) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(DoTakeInventory(self, false, VM_ARGS_NAMES)); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromTarget) +DEFINE_ACTION_FUNCTION(AActor, A_TakeFromTarget) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(DoTakeInventory(self->target, false, VM_ARGS_NAMES)); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromChildren) +DEFINE_ACTION_FUNCTION(AActor, A_TakeFromChildren) { PARAM_SELF_PROLOGUE(AActor); TThinkerIterator it; @@ -2614,7 +2614,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromChildren) ACTION_RETURN_INT(count); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromSiblings) +DEFINE_ACTION_FUNCTION(AActor, A_TakeFromSiblings) { PARAM_SELF_PROLOGUE(AActor); TThinkerIterator it; @@ -2850,7 +2850,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) +DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem) { PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS_DEF (missile, AActor) @@ -2898,7 +2898,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) // Enhanced spawning function // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx) +DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (missile, AActor); @@ -2982,7 +2982,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx) // Throws a grenade (like Hexen's fighter flechette) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) +DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade) { PARAM_ACTION_PROLOGUE(AActor); PARAM_CLASS (missile, AActor); @@ -3060,7 +3060,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) // A_Recoil // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Recoil) +DEFINE_ACTION_FUNCTION(AActor, A_Recoil) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(xyvel); @@ -3079,7 +3079,7 @@ enum SW_Flags { SWF_SELECTPRIORITY = 1, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SelectWeapon) +DEFINE_ACTION_FUNCTION(AActor, A_SelectWeapon) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(cls, AWeapon); @@ -3124,7 +3124,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SelectWeapon) //=========================================================================== EXTERN_CVAR(Float, con_midtime) -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Print) +DEFINE_ACTION_FUNCTION(AActor, A_Print) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING (text); @@ -3159,7 +3159,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Print) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PrintBold) +DEFINE_ACTION_FUNCTION(AActor, A_PrintBold) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING (text); @@ -3190,7 +3190,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PrintBold) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log) +DEFINE_ACTION_FUNCTION(AActor, A_Log) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING(text); @@ -3207,7 +3207,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogInt) +DEFINE_ACTION_FUNCTION(AActor, A_LogInt) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(num); @@ -3221,7 +3221,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogInt) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogFloat) +DEFINE_ACTION_FUNCTION(AActor, A_LogFloat) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(num); @@ -3236,7 +3236,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogFloat) // A_SetTranslucent // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslucent) +DEFINE_ACTION_FUNCTION(AActor, A_SetTranslucent) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT (alpha); @@ -3255,7 +3255,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslucent) // A_SetRenderStyle // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRenderStyle) +DEFINE_ACTION_FUNCTION(AActor, A_SetRenderStyle) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(alpha); @@ -3280,7 +3280,7 @@ enum FadeFlags FTF_CLAMP = 1 << 1, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) +DEFINE_ACTION_FUNCTION(AActor, A_FadeIn) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_DEF(reduce); @@ -3315,7 +3315,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn) // fades the actor out and destroys it when done // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeOut) +DEFINE_ACTION_FUNCTION(AActor, A_FadeOut) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_DEF(reduce); @@ -3349,7 +3349,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeOut) // destroys it if so desired // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeTo) +DEFINE_ACTION_FUNCTION(AActor, A_FadeTo) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT (target); @@ -3392,7 +3392,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeTo) // A_SpawnDebris // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnDebris) +DEFINE_ACTION_FUNCTION(AActor, A_SpawnDebris) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (debris, AActor); @@ -3448,7 +3448,7 @@ enum SPFflag SPF_NOTIMEFREEZE = 1 << 5, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) +DEFINE_ACTION_FUNCTION(AActor, A_SpawnParticle) { PARAM_SELF_PROLOGUE(AActor); PARAM_COLOR (color); @@ -3509,7 +3509,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) // jumps if no player can see this actor // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckIfSeen) +DEFINE_ACTION_FUNCTION(AActor, CheckIfSeen) { PARAM_SELF_PROLOGUE(AActor); @@ -3577,7 +3577,7 @@ static bool DoCheckSightOrRange(AActor *self, AActor *camera, double range, bool return false; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckSightOrRange) +DEFINE_ACTION_FUNCTION(AActor, CheckSightOrRange) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(range); @@ -3605,7 +3605,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckSightOrRange) } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckRange) +DEFINE_ACTION_FUNCTION(AActor, CheckRange) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(range); @@ -3638,7 +3638,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckRange) // Inventory drop // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropInventory) +DEFINE_ACTION_FUNCTION(AActor, A_DropInventory) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(drop, AInventory); @@ -3660,7 +3660,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropInventory) // A_SetBlend // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetBlend) +DEFINE_ACTION_FUNCTION(AActor, A_SetBlend) { PARAM_SELF_PROLOGUE(AActor); PARAM_COLOR (color); @@ -3688,7 +3688,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetBlend) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CountdownArg) +DEFINE_ACTION_FUNCTION(AActor, A_CountdownArg) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(cnt); @@ -3720,7 +3720,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CountdownArg) // //============================================================================ -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst) +DEFINE_ACTION_FUNCTION(AActor, A_Burst) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(chunk, AActor); @@ -3816,7 +3816,7 @@ enum RS_Flags RSF_TELEFRAG=4, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) +DEFINE_ACTION_FUNCTION(AActor, A_Respawn) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(flags); @@ -4033,7 +4033,7 @@ ETraceStatus CheckLOFTraceFunc(FTraceResults &trace, void *userdata) return TRACE_Abort; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckLOF) +DEFINE_ACTION_FUNCTION(AActor, CheckLOF) { // Check line of fire @@ -4234,7 +4234,7 @@ enum JLOS_flags JLOSF_CHECKTRACER = 1 << 12, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckIfTargetInLOS) +DEFINE_ACTION_FUNCTION(AActor, CheckIfTargetInLOS) { PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_DEF (fov) @@ -4371,7 +4371,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckIfTargetInLOS) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckIfInTargetLOS) +DEFINE_ACTION_FUNCTION(AActor, CheckIfInTargetLOS) { PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_DEF (fov) @@ -4451,7 +4451,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckIfInTargetLOS) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) +DEFINE_ACTION_FUNCTION(AActor, A_CheckForReload) { PARAM_ACTION_PROLOGUE(AActor); @@ -4521,7 +4521,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ResetReloadCounter) // A_ChangeFlag // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) +DEFINE_ACTION_FUNCTION(AActor, A_ChangeFlag) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING (flagname); @@ -4537,7 +4537,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckFlag) +DEFINE_ACTION_FUNCTION(AActor, CheckFlag) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING (flagname); @@ -4548,7 +4548,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckFlag) } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeCountFlags) +DEFINE_ACTION_FUNCTION(AActor, A_ChangeCountFlags) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(kill); @@ -4655,7 +4655,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings) // Keep firing unless target got out of sight // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MonsterRefire) +DEFINE_ACTION_FUNCTION(AActor, A_MonsterRefire) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (prob); @@ -4691,7 +4691,7 @@ enum }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) +DEFINE_ACTION_FUNCTION(AActor, A_SetAngle) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_DEF(angle); @@ -4714,7 +4714,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) +DEFINE_ACTION_FUNCTION(AActor, A_SetPitch) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(pitch); @@ -4738,7 +4738,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRoll) +DEFINE_ACTION_FUNCTION(AActor, A_SetRoll) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT (roll); @@ -4761,7 +4761,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRoll) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ScaleVelocity) +DEFINE_ACTION_FUNCTION(AActor, A_ScaleVelocity) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(scale); @@ -4793,7 +4793,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ScaleVelocity) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity) +DEFINE_ACTION_FUNCTION(AActor, A_ChangeVelocity) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT_DEF (x) @@ -4855,7 +4855,7 @@ static PField *GetVar(DObject *self, FName varname) return var; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserVar) +DEFINE_ACTION_FUNCTION(AActor, A_SetUserVar) { PARAM_SELF_PROLOGUE(DObject); PARAM_NAME (varname); @@ -4870,7 +4870,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserVar) return 0; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserVarFloat) +DEFINE_ACTION_FUNCTION(AActor, A_SetUserVarFloat) { PARAM_SELF_PROLOGUE(DObject); PARAM_NAME (varname); @@ -4912,7 +4912,7 @@ static PField *GetArrayVar(DObject *self, FName varname, int pos) return var; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray) +DEFINE_ACTION_FUNCTION(AActor, A_SetUserArray) { PARAM_SELF_PROLOGUE(DObject); PARAM_NAME (varname); @@ -4929,7 +4929,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray) return 0; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArrayFloat) +DEFINE_ACTION_FUNCTION(AActor, A_SetUserArrayFloat) { PARAM_SELF_PROLOGUE(DObject); PARAM_NAME (varname); @@ -4973,7 +4973,7 @@ enum T_Flags TF_SENSITIVEZ = 0x00000800, // Fail if the actor wouldn't fit in the position (for Z). }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) +DEFINE_ACTION_FUNCTION(AActor, A_Teleport) { PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE_DEF (teleport_state) @@ -5149,7 +5149,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Quake) +DEFINE_ACTION_FUNCTION(AActor, A_Quake) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (intensity); @@ -5170,7 +5170,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Quake) // take flags. //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_QuakeEx) +DEFINE_ACTION_FUNCTION(AActor, A_QuakeEx) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(intensityX); @@ -5241,7 +5241,7 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, double xydist, double zdist) } } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Weave) +DEFINE_ACTION_FUNCTION(AActor, A_Weave) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (xspeed); @@ -5263,7 +5263,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Weave) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LineEffect) +DEFINE_ACTION_FUNCTION(AActor, A_LineEffect) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(special); @@ -5298,7 +5298,7 @@ enum WolfAttackFlags WAF_USEPUFF = 2, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack) +DEFINE_ACTION_FUNCTION(AActor, A_WolfAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF (flags) @@ -5403,7 +5403,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) +DEFINE_ACTION_FUNCTION(AActor, A_Warp) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(destination_selector); @@ -5655,7 +5655,7 @@ static bool DoRadiusGive(AActor *self, AActor *thing, PClassActor *item, int amo return false; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) +DEFINE_ACTION_FUNCTION(AActor, A_RadiusGive) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (item, AInventory); @@ -5708,7 +5708,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics) +DEFINE_ACTION_FUNCTION(AActor, A_SetTics) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT(tics_to_set); @@ -5737,7 +5737,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem) +DEFINE_ACTION_FUNCTION(AActor, A_DropItem) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS (spawntype, AActor); @@ -5818,7 +5818,7 @@ static void DoDamage(AActor *dmgtarget, AActor *inflictor, AActor *source, int a // // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf) +DEFINE_ACTION_FUNCTION(AActor, A_DamageSelf) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); @@ -5841,7 +5841,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf) // // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget) +DEFINE_ACTION_FUNCTION(AActor, A_DamageTarget) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); @@ -5865,7 +5865,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget) // // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer) +DEFINE_ACTION_FUNCTION(AActor, A_DamageTracer) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); @@ -5889,7 +5889,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer) // // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster) +DEFINE_ACTION_FUNCTION(AActor, A_DamageMaster) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); @@ -5913,7 +5913,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster) // // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) +DEFINE_ACTION_FUNCTION(AActor, A_DamageChildren) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); @@ -5943,7 +5943,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) // // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings) +DEFINE_ACTION_FUNCTION(AActor, A_DamageSiblings) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (amount); @@ -6026,7 +6026,7 @@ static void DoKill(AActor *killtarget, AActor *inflictor, AActor *source, FName // A_KillTarget(damagetype, int flags) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) +DEFINE_ACTION_FUNCTION(AActor, A_KillTarget) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_DEF (damagetype) @@ -6049,7 +6049,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) // A_KillTracer(damagetype, int flags) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) +DEFINE_ACTION_FUNCTION(AActor, A_KillTracer) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_DEF (damagetype) @@ -6072,7 +6072,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) // A_KillMaster(damagetype, int flags) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) +DEFINE_ACTION_FUNCTION(AActor, A_KillMaster) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_DEF (damagetype) @@ -6095,7 +6095,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) // A_KillChildren(damagetype, int flags) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) +DEFINE_ACTION_FUNCTION(AActor, A_KillChildren) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_DEF (damagetype) @@ -6126,7 +6126,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) // A_KillSiblings(damagetype, int flags) // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) +DEFINE_ACTION_FUNCTION(AActor, A_KillSiblings) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME_DEF (damagetype) @@ -6202,7 +6202,7 @@ static void DoRemove(AActor *removetarget, int flags, PClassActor *filter, FName // A_RemoveTarget // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) +DEFINE_ACTION_FUNCTION(AActor, A_RemoveTarget) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(flags); @@ -6221,7 +6221,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget) // A_RemoveTracer // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) +DEFINE_ACTION_FUNCTION(AActor, A_RemoveTracer) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(flags); @@ -6240,7 +6240,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer) // A_RemoveMaster // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) +DEFINE_ACTION_FUNCTION(AActor, A_RemoveMaster) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(flags); @@ -6259,7 +6259,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster) // A_RemoveChildren // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) +DEFINE_ACTION_FUNCTION(AActor, A_RemoveChildren) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_DEF(removeall); @@ -6285,7 +6285,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren) // A_RemoveSiblings // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings) +DEFINE_ACTION_FUNCTION(AActor, A_RemoveSiblings) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL_DEF(removeall); @@ -6314,7 +6314,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings) // A_Remove // //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Remove) +DEFINE_ACTION_FUNCTION(AActor, A_Remove) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(removee); @@ -6338,7 +6338,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Remove) // Takes a name of the classes for the source and destination. //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTeleFog) +DEFINE_ACTION_FUNCTION(AActor, A_SetTeleFog) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(oldpos, AActor); @@ -6383,7 +6383,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SwapTeleFog) // Takes a pointer as well. //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetHealth) +DEFINE_ACTION_FUNCTION(AActor, A_SetHealth) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT (health); @@ -6421,7 +6421,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetHealth) // Takes a pointer. //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) +DEFINE_ACTION_FUNCTION(AActor, A_ResetHealth) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(ptr); @@ -6450,7 +6450,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) // // Sets the species of the calling actor('s pointer). //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecies) +DEFINE_ACTION_FUNCTION(AActor, A_SetSpecies) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME(species); @@ -6474,7 +6474,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecies) // changes the default threshold which the actor resets to once it switches // targets and doesn't have the +QUICKTORETALIATE flag. //=========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetChaseThreshold) +DEFINE_ACTION_FUNCTION(AActor, A_SetChaseThreshold) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(threshold); @@ -6501,7 +6501,7 @@ 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, CheckProximity) +DEFINE_ACTION_FUNCTION(AActor, CheckProximity) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(classname, AActor); @@ -6534,7 +6534,7 @@ enum CBF CBF_ABSOLUTEANGLE = 1 << 8, //Absolute angle for offsets. }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, CheckBlock) +DEFINE_ACTION_FUNCTION(AActor, CheckBlock) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(flags) @@ -6633,7 +6633,7 @@ enum FMDFlags FMDF_INTERPOLATE = 1 << 1, FMDF_NOANGLE = 1 << 2, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection) +DEFINE_ACTION_FUNCTION(AActor, A_FaceMovementDirection) { PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_DEF(offset) @@ -6727,7 +6727,7 @@ enum CPSFFlags CPSF_NOFRAME = 1 << 1, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame) +DEFINE_ACTION_FUNCTION(AActor, A_CopySpriteFrame) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(from); @@ -6762,7 +6762,7 @@ enum VRFFlags VRF_NOPITCHEND = 1 << 3, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetVisibleRotation) +DEFINE_ACTION_FUNCTION(AActor, A_SetVisibleRotation) { PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE_DEF(anglestart) @@ -6805,7 +6805,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetVisibleRotation) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslation) +DEFINE_ACTION_FUNCTION(AActor, A_SetTranslation) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING(trname); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index cbddb48400..d36a8de9d8 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1942,7 +1942,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) +DEFINE_ACTION_FUNCTION(AActor, A_LookEx) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF (flags) @@ -2159,7 +2159,7 @@ enum ChaseFlags CHF_STOPIFBLOCKED = 256, }; -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Wander) +DEFINE_ACTION_FUNCTION(AActor, A_Wander) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(flags); @@ -2801,7 +2801,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) // //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase) +DEFINE_ACTION_FUNCTION(AActor, A_Chase) { PARAM_SELF_PROLOGUE(AActor); PARAM_STATE_DEF (melee) @@ -2840,7 +2840,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VileChase) return 0; } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ExtChase) +DEFINE_ACTION_FUNCTION(AActor, A_ExtChase) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL (domelee); @@ -2980,7 +2980,7 @@ void A_FaceTarget(AActor *self) A_Face(self, self->target); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Face) +DEFINE_ACTION_FUNCTION(AActor, A_Face) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(faceto, AActor) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index ce74684ccf..408cdbf917 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3098,6 +3098,13 @@ void AActor::RemoveFromHash () tid = 0; } +DEFINE_ACTION_FUNCTION(AActor, RemoveFromHash) +{ + PARAM_SELF_PROLOGUE(AActor); + self->RemoveFromHash(); + return 0; +} + //========================================================================== // // P_IsTIDUsed @@ -6886,6 +6893,42 @@ void AActor::SetTranslation(const char *trname) // silently ignore if the name does not exist, this would create some insane message spam otherwise. } + +class DActorIterator : public DObject, public NActorIterator +{ + DECLARE_CLASS(DActorIterator, DObject) + +public: + DActorIterator(PClassActor *cls= nullptr, int tid = 0) + : NActorIterator(cls, tid) + { + } +}; + +IMPLEMENT_CLASS(DActorIterator, false, false, false, false); +DEFINE_ACTION_FUNCTION(DActorIterator, Create) +{ + PARAM_PROLOGUE; + PARAM_INT_DEF(tid); + PARAM_CLASS_DEF(type, AActor); + ACTION_RETURN_OBJECT(new DActorIterator(type, tid)); +} + +DEFINE_ACTION_FUNCTION(DActorIterator, Next) +{ + PARAM_SELF_PROLOGUE(DActorIterator); + ACTION_RETURN_OBJECT(self->Next()); +} + +DEFINE_ACTION_FUNCTION(DActorIterator, Reinit) +{ + PARAM_SELF_PROLOGUE(DActorIterator); + self->Reinit(); + return 0; +} + + + DEFINE_ACTION_FUNCTION(AActor, deltaangle) // should this be global? { PARAM_PROLOGUE; @@ -6894,6 +6937,14 @@ DEFINE_ACTION_FUNCTION(AActor, deltaangle) // should this be global? ACTION_RETURN_FLOAT(deltaangle(DAngle(a1), DAngle(a2)).Degrees); } +DEFINE_ACTION_FUNCTION(AActor, absangle) // should this be global? +{ + PARAM_PROLOGUE; + PARAM_FLOAT(a1); + PARAM_FLOAT(a2); + ACTION_RETURN_FLOAT(absangle(DAngle(a1), DAngle(a2)).Degrees); +} + DEFINE_ACTION_FUNCTION(AActor, Distance2D) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 1bb0db9093..5a76f0b550 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -772,7 +772,7 @@ void DoReadyWeapon(AActor *self) DoReadyWeaponToGeneric(self, ~0); } -DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady) +DEFINE_ACTION_FUNCTION(AStateProvider, A_WeaponReady) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT_DEF(flags); @@ -904,7 +904,7 @@ static void P_CheckWeaponButtons (player_t *player) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_ReFire) +DEFINE_ACTION_FUNCTION(AStateProvider, A_ReFire) { PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE_ACTION_DEF(state); @@ -942,7 +942,7 @@ void A_ReFire(AActor *self, FState *state) } } -DEFINE_ACTION_FUNCTION(AInventory, A_ClearReFire) +DEFINE_ACTION_FUNCTION(AStateProvider, A_ClearReFire) { PARAM_ACTION_PROLOGUE(AActor); player_t *player = self->player; @@ -964,7 +964,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_ClearReFire) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AInventory, A_CheckReload) +DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckReload) { PARAM_ACTION_PROLOGUE(AActor); @@ -1152,7 +1152,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayID) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AInventory, A_Lower) +DEFINE_ACTION_FUNCTION(AStateProvider, A_Lower) { PARAM_ACTION_PROLOGUE(AActor); @@ -1200,7 +1200,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Lower) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AInventory, A_Raise) +DEFINE_ACTION_FUNCTION(AActor, A_Raise) { PARAM_ACTION_PROLOGUE(AActor); @@ -1241,7 +1241,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Raise) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Overlay) +DEFINE_ACTION_FUNCTION(AActor, A_Overlay) { PARAM_ACTION_PROLOGUE(AActor); PARAM_INT (layer); @@ -1261,7 +1261,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Overlay) ACTION_RETURN_BOOL(true); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ClearOverlays) +DEFINE_ACTION_FUNCTION(AActor, A_ClearOverlays) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT_DEF(start); @@ -1312,7 +1312,7 @@ enum GF_Flags GFF_NOEXTCHANGE = 1, }; -DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) +DEFINE_ACTION_FUNCTION(AStateProvider, A_GunFlash) { PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE_ACTION_DEF(flash); @@ -1415,7 +1415,7 @@ void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch) P_LineAttack (mo, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, pufftype); } -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Light) +DEFINE_ACTION_FUNCTION(AActor, A_Light) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(light); diff --git a/src/p_states.cpp b/src/p_states.cpp index f7f237c777..ac7121f49a 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -343,7 +343,7 @@ DEFINE_ACTION_FUNCTION(AActor, FindState) } // same as above but context aware. -DEFINE_ACTION_FUNCTION_PARAMS(AActor, ResolveState) +DEFINE_ACTION_FUNCTION(AActor, ResolveState) { PARAM_ACTION_PROLOGUE(AActor); PARAM_STATE_ACTION(newstate); diff --git a/src/p_user.cpp b/src/p_user.cpp index 6b0b2cfe68..8c8858b635 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1626,7 +1626,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream) // //---------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop) +DEFINE_ACTION_FUNCTION(AActor, A_SkullPop) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_DEF(spawntype, APlayerChunk); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index b64e0c4391..e339865504 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7962,7 +7962,7 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx) 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) + if (ctx.ReturnProto != nullptr && ctx.ReturnProto->ReturnTypes.Size() > 0 && ctx.Function->SymbolName != NAME_None) { Value = new FxTypeCast(Value, ctx.ReturnProto->ReturnTypes[0], false, false); Value = Value->Resolve(ctx); diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 7218a84e6c..5992dba04a 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -147,7 +147,7 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) // //========================================================================== -AFuncDesc *FindFunction(const char * string); +AFuncDesc *FindFunction(PClass *cls, const char * string); FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, bool mustresolve = false); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 4ccc72748e..8de1aaff86 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -571,28 +571,33 @@ FPropertyInfo *FindProperty(const char * string) // //========================================================================== -AFuncDesc *FindFunction(const char * string) +AFuncDesc *FindFunction(PClass *cls, const char * string) { - int min = 0, max = AFTable.Size()-1; - - while (min <= max) + for (int i = 0; i < 2; i++) { - int mid = (min + max) / 2; - int lexval = stricmp (string, AFTable[mid].Name); - if (lexval == 0) + if (i == 1 && !cls->IsDescendantOf(RUNTIME_CLASS(AActor))) break; + FStringf fullname("%s_%s", i == 0 ? cls->TypeName.GetChars() : "Actor", string); + int min = 0, max = AFTable.Size() - 1; + + while (min <= max) { - return &AFTable[mid]; - } - else if (lexval > 0) - { - min = mid + 1; - } - else - { - max = mid - 1; + int mid = (min + max) / 2; + int lexval = stricmp(fullname, AFTable[mid].Name + 1); + if (lexval == 0) + { + return &AFTable[mid]; + } + else if (lexval > 0) + { + min = mid + 1; + } + else + { + max = mid - 1; + } } } - return NULL; + return nullptr; } @@ -627,7 +632,7 @@ static int propcmp(const void * a, const void * b) static int funccmp(const void * a, const void * b) { - return stricmp( ((AFuncDesc*)a)->Name, ((AFuncDesc*)b)->Name); + return stricmp(((AFuncDesc*)a)->Name + 1, ((AFuncDesc*)b)->Name + 1); // +1 to get past the prefix letter of the native class name, which gets omitted by the FName for the class. } //========================================================================== diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 2f98c8d818..ae867a975d 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1020,26 +1020,21 @@ struct AFuncDesc // 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; +#define DECLARE_ACTION(name) extern VMNativeFunction *AActor_##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 }; \ + static int AF_##cls##_##name(VM_ARGS); \ + VMNativeFunction *cls##_##name##_VMPtr; \ + static const AFuncDesc cls##_##name##_Hook = { #cls "_" #name, AF_##cls##_##name, &cls##_##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 + static int AF_##cls##_##name(VM_ARGS) class AActor; void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); -#define CALL_ACTION(name, self) CallAction(stack, name##_VMPtr, self); +#define CALL_ACTION(name, self) CallAction(stack, AActor_##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) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6cf719d3d3..aec8f5853e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2128,7 +2128,7 @@ void ZCCCompiler::InitFunctions() if (f->Flags & ZCC_Native) { varflags |= VARF_Native; - afd = FindFunction(FName(f->Name).GetChars()); + afd = FindFunction(c->Type(), FName(f->Name).GetChars()); if (afd == nullptr) { Error(f, "The function '%s' has not been exported from the executable.", FName(f->Name).GetChars()); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 8e8b2fdd88..f28045764e 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -63,7 +63,9 @@ class Actor : Thinker native native static readonly GetDefaultByType(class cls); native static float deltaangle(float ang1, float ang2); + native static float absangle(float ang1, float ang2); native static float GetDefaultSpeed(class type); + native void RemoveFromHash(); native float GetBobOffset(float frac = 0); native void SetDamage(int dmg); native static bool isDehState(state st); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 33c1c61352..6cf2835e81 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -20,6 +20,13 @@ class ThinkerIterator : Object native native void Reinit(); } +class ActorIterator : Object native +{ + native static ActorIterator Create(int tid, class type = "Actor"); + native Actor Next(); + native void Reinit(); +} + class DropItem : Object native { /* native fields listed for reference only for now diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 5e47bbc7ed..3f7a26461d 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -898,3 +898,22 @@ 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.); + +enum EMapThingFlags +{ + MTF_AMBUSH = 0x0008, // Thing is deaf + MTF_DORMANT = 0x0010, // Thing is dormant (use Thing_Activate) + + MTF_SINGLE = 0x0100, // Thing appears in single-player games + MTF_COOPERATIVE = 0x0200, // Thing appears in cooperative games + MTF_DEATHMATCH = 0x0400, // Thing appears in deathmatch games + + MTF_SHADOW = 0x0800, + MTF_ALTSHADOW = 0x1000, + MTF_FRIENDLY = 0x2000, + MTF_STANDSTILL = 0x4000, + MTF_STRIFESOMETHING = 0x8000, + + MTF_SECRET = 0x080000, // Secret pickup + MTF_NOINFIGHTING = 0x100000, +}; diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt index 0c1305b57d..9a6b0105ad 100644 --- a/wadsrc/static/zscript/strife/acolyte.txt +++ b/wadsrc/static/zscript/strife/acolyte.txt @@ -26,8 +26,6 @@ class Acolyte : StrifeHumanoid Obituary "$OB_ACOLYTE"; } - native void A_BeShadowyFoe (); - native void A_AcolyteBits (); native void A_AcolyteDie (); States @@ -76,6 +74,44 @@ class Acolyte : StrifeHumanoid GIBS L 1400; Stop; } + + //============================================================================ + // + // A_BeShadowyFoe + // + //============================================================================ + + void A_BeShadowyFoe() + { + A_SetRenderStyle(HR_SHADOW, STYLE_Translucent); + bFriendly = false; + } + + //============================================================================ + // + // A_AcolyteBits + // + //============================================================================ + + void A_AcolyteBits() + { + if (SpawnFlags & MTF_SHADOW) + { + A_BeShadowyFoe(); + } + if (SpawnFlags & MTF_ALTSHADOW) + { + if (bShadow) + { + // I dunno. + } + else + { + A_SetRenderStyle(0, STYLE_None); + } + } + } + } From 76a74e0364fe12171ad7ae307f54161f777faa69 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Nov 2016 19:18:21 +0100 Subject: [PATCH 268/471] - scriptified Hexen's Dragon. - fixed several places in the code generator that did not consider locked registers for local variables: array indices, abs and floating point builtin functions. - added some debug aids to the bounds opcode. Just triggering an exception here which loses all relevant info is perfectly useless in a debug situation. --- src/g_hexen/a_dragon.cpp | 311 ----------------------- src/g_hexen/a_hexenmisc.cpp | 1 - src/scripting/codegeneration/codegen.cpp | 78 ++++-- src/scripting/vm/vmexec.h | 2 + wadsrc/static/zscript/hexen/dragon.txt | 282 +++++++++++++++++++- 5 files changed, 327 insertions(+), 347 deletions(-) delete mode 100644 src/g_hexen/a_dragon.cpp diff --git a/src/g_hexen/a_dragon.cpp b/src/g_hexen/a_dragon.cpp deleted file mode 100644 index b79d92b368..0000000000 --- a/src/g_hexen/a_dragon.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_enemy.h" -#include "p_local.h" -#include "a_action.h" -#include "m_random.h" -#include "s_sound.h" -#include "vm.h" -*/ - -static FRandom pr_dragonseek ("DragonSeek"); -static FRandom pr_dragonflight ("DragonFlight"); -static FRandom pr_dragonflap ("DragonFlap"); -static FRandom pr_dragonfx2 ("DragonFX2"); - -DECLARE_ACTION(A_DragonFlight) - -//============================================================================ -// -// DragonSeek -// -//============================================================================ - -static void DragonSeek (AActor *actor, DAngle thresh, DAngle turnMax) -{ - int dir; - double dist; - DAngle delta; - AActor *target; - int i; - DAngle bestAngle; - DAngle angleToSpot, angleToTarget; - AActor *mo; - - target = actor->tracer; - if(target == NULL) - { - return; - } - dir = P_FaceMobj (actor, target, &delta); - if (delta > thresh) - { - delta /= 2; - if (delta > turnMax) - { - delta = turnMax; - } - } - if (dir) - { // Turn clockwise - actor->Angles.Yaw += delta; - } - else - { // Turn counter clockwise - actor->Angles.Yaw -= delta; - } - actor->VelFromAngle(); - - dist = actor->DistanceBySpeed(target, actor->Speed); - if (actor->Top() < target->Z() || - target->Top() < actor->Z()) - { - actor->Vel.Z = (target->Z() - actor->Z()) / dist; - } - if (target->flags&MF_SHOOTABLE && pr_dragonseek() < 64) - { // attack the destination mobj if it's attackable - AActor *oldTarget; - - if (absangle(actor->Angles.Yaw, actor->AngleTo(target)) < 22.5) - { - oldTarget = actor->target; - actor->target = target; - if (actor->CheckMeleeRange ()) - { - int damage = pr_dragonseek.HitDice (10); - int newdam = P_DamageMobj (actor->target, actor, actor, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, actor->target, actor); - S_Sound (actor, CHAN_WEAPON, actor->AttackSound, 1, ATTN_NORM); - } - else if (pr_dragonseek() < 128 && P_CheckMissileRange(actor)) - { - P_SpawnMissile(actor, target, PClass::FindActor("DragonFireball")); - S_Sound (actor, CHAN_WEAPON, actor->AttackSound, 1, ATTN_NORM); - } - actor->target = oldTarget; - } - } - if (dist < 4) - { // Hit the target thing - if (actor->target && pr_dragonseek() < 200) - { - AActor *bestActor = NULL; - bestAngle = 360.; - angleToTarget = actor->AngleTo(actor->target); - for (i = 0; i < 5; i++) - { - if (!target->args[i]) - { - continue; - } - FActorIterator iterator (target->args[i]); - mo = iterator.Next (); - if (mo == NULL) - { - continue; - } - angleToSpot = actor->AngleTo(mo); - DAngle diff = absangle(angleToSpot, angleToTarget); - if (diff < bestAngle) - { - bestAngle = diff; - bestActor = mo; - } - } - if (bestActor != NULL) - { - actor->tracer = bestActor; - } - } - else - { - // [RH] Don't lock up if the dragon doesn't have any - // targets defined - for (i = 0; i < 5; ++i) - { - if (target->args[i] != 0) - { - break; - } - } - if (i < 5) - { - do - { - i = (pr_dragonseek()>>2)%5; - } while(!target->args[i]); - FActorIterator iterator (target->args[i]); - actor->tracer = iterator.Next (); - } - } - } -} - -//============================================================================ -// -// A_DragonInitFlight -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DragonInitFlight) -{ - PARAM_SELF_PROLOGUE(AActor); - - FActorIterator iterator (self->tid); - - do - { // find the first tid identical to the dragon's tid - self->tracer = iterator.Next (); - if (self->tracer == NULL) - { - self->SetState (self->SpawnState); - return 0; - } - } while (self->tracer == self); - self->RemoveFromHash (); - return 0; -} - -//============================================================================ -// -// A_DragonFlight -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DragonFlight) -{ - PARAM_SELF_PROLOGUE(AActor); - - DAngle angle; - - DragonSeek (self, 4., 8.); - if (self->target) - { - if(!(self->target->flags&MF_SHOOTABLE)) - { // target died - self->target = NULL; - return 0; - } - angle = absangle(self->Angles.Yaw, self->AngleTo(self->target)); - if (angle <22.5 && self->CheckMeleeRange()) - { - int damage = pr_dragonflight.HitDice (8); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - } - else if (angle <= 20) - { - self->SetState (self->MissileState); - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - } - } - else - { - P_LookForPlayers (self, true, NULL); - } - return 0; -} - -//============================================================================ -// -// A_DragonFlap -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DragonFlap) -{ - PARAM_SELF_PROLOGUE(AActor); - - CALL_ACTION(A_DragonFlight, self); - if (pr_dragonflap() < 240) - { - S_Sound (self, CHAN_BODY, "DragonWingflap", 1, ATTN_NORM); - } - else - { - self->PlayActiveSound (); - } - return 0; -} - -//============================================================================ -// -// A_DragonAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DragonAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - P_SpawnMissile (self, self->target, PClass::FindActor("DragonFireball")); - return 0; -} - -//============================================================================ -// -// A_DragonFX2 -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DragonFX2) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - int i; - int delay; - - delay = 16+(pr_dragonfx2()>>3); - for (i = 1+(pr_dragonfx2()&3); i; i--) - { - double xo = (pr_dragonfx2() - 128) / 4.; - double yo = (pr_dragonfx2() - 128) / 4.; - double zo = (pr_dragonfx2() - 128) / 16.; - - mo = Spawn ("DragonExplosion", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - if (mo) - { - mo->tics = delay+(pr_dragonfx2()&3)*i*2; - mo->target = self->target; - } - } - return 0; -} - -//============================================================================ -// -// A_DragonPain -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DragonPain) -{ - PARAM_SELF_PROLOGUE(AActor); - - CALL_ACTION(A_Pain, self); - if (!self->tracer) - { // no destination spot yet - self->SetState (self->SeeState); - } - return 0; -} - -//============================================================================ -// -// A_DragonCheckCrash -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DragonCheckCrash) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->Z() <= self->floorz) - { - self->SetState (self->FindState ("Crash")); - } - return 0; -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 1a635ff710..f1f4a86fe8 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -33,7 +33,6 @@ #include "a_clericholy.cpp" #include "a_clericmace.cpp" #include "a_clericstaff.cpp" -#include "a_dragon.cpp" #include "a_fighteraxe.cpp" #include "a_fighterhammer.cpp" #include "a_fighterplayer.cpp" diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index e339865504..44d7cda889 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1670,19 +1670,23 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) { assert(ValueType == Operand->ValueType); ExpEmit from = Operand->Emit(build); + ExpEmit to; 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; + to = ExpEmit(build, from.RegType, from.RegCount); + from.Free(build); + } + else + { + to = from; } if (ValueType->GetRegType() == REGT_INT) { - build->Emit(OP_NEG, from.RegNum, from.RegNum, 0); + build->Emit(OP_NEG, to.RegNum, from.RegNum, 0); } else { @@ -1690,20 +1694,20 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) switch (from.RegCount) { case 1: - build->Emit(OP_FLOP, from.RegNum, from.RegNum, FLOP_NEG); + build->Emit(OP_FLOP, to.RegNum, from.RegNum, FLOP_NEG); break; case 2: - build->Emit(OP_NEGV2, from.RegNum, from.RegNum); + build->Emit(OP_NEGV2, to.RegNum, from.RegNum); break; case 3: - build->Emit(OP_NEGV3, from.RegNum, from.RegNum); + build->Emit(OP_NEGV3, to.RegNum, from.RegNum); break; } } - return from; + return to; } //========================================================================== @@ -4255,19 +4259,31 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx) ExpEmit FxAbs::Emit(VMFunctionBuilder *build) { - ExpEmit absofsteal = val->Emit(build); - assert(!absofsteal.Konst); - ExpEmit out(build, absofsteal.RegType); - if (absofsteal.RegType == REGT_INT) + assert(ValueType == val->ValueType); + ExpEmit from = val->Emit(build); + ExpEmit to; + assert(from.Konst == 0); + assert(ValueType->GetRegCount() == 1); + // Do it in-place, unless a local variable + if (from.Fixed) { - build->Emit(OP_ABS, out.RegNum, absofsteal.RegNum, 0); + to = ExpEmit(build, from.RegType); + from.Free(build); } else { - assert(absofsteal.RegType == REGT_FLOAT); - build->Emit(OP_FLOP, out.RegNum, absofsteal.RegNum, FLOP_ABS); + to = from; } - return out; + + if (ValueType->GetRegType() == REGT_INT) + { + build->Emit(OP_ABS, to.RegNum, from.RegNum, 0); + } + else + { + build->Emit(OP_FLOP, to.RegNum, from.RegNum, FLOP_ABS); + } + return to; } //========================================================================== @@ -5898,6 +5914,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) else { ExpEmit indexv(index->Emit(build)); + ExpEmit indexwork = indexv.Fixed ? ExpEmit(build, indexv.RegType) : indexv; int shiftbits = 0; while (1u << shiftbits < arraytype->ElementSize) { @@ -5907,19 +5924,19 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); if (shiftbits > 0) { - build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, shiftbits); + build->Emit(OP_SLL_RI, indexwork.RegNum, indexv.RegNum, shiftbits); } if (AddressRequested) { - build->Emit(OP_ADDA_RR, start.RegNum, start.RegNum, indexv.RegNum); + build->Emit(OP_ADDA_RR, start.RegNum, start.RegNum, indexwork.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 + dest.RegNum, start.RegNum, indexwork.RegNum); // takes the offset from a register } - indexv.Free(build); + indexwork.Free(build); } if (AddressRequested) { @@ -6955,13 +6972,26 @@ FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx) ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) { - ExpEmit v = ArgList[0]->Emit(build); - assert(!v.Konst && v.RegType == REGT_FLOAT); + assert(ValueType == ArgList[0]->ValueType); + ExpEmit from = ArgList[0]->Emit(build); + ExpEmit to; + assert(from.Konst == 0); + assert(ValueType->GetRegCount() == 1); + // Do it in-place, unless a local variable + if (from.Fixed) + { + to = ExpEmit(build, from.RegType); + from.Free(build); + } + else + { + to = from; + } - build->Emit(OP_FLOP, v.RegNum, v.RegNum, FxFlops[Index].Flop); + build->Emit(OP_FLOP, to.RegNum, from.RegNum, FxFlops[Index].Flop); ArgList.Clear(); ArgList.ShrinkToFit(); - return v; + return to; } diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 02e0db3dea..fcdb2eb8b8 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -696,6 +696,8 @@ begin: OP(BOUND): if (reg.d[a] >= BC) { + assert(false); + Printf("Array access out of bounds: Max. index = %u, current index = %u\n", BC, reg.d[a]); THROW(X_ARRAY_OUT_OF_BOUNDS); } NEXTOP; diff --git a/wadsrc/static/zscript/hexen/dragon.txt b/wadsrc/static/zscript/hexen/dragon.txt index 6df3da9437..ed6e86d4ac 100644 --- a/wadsrc/static/zscript/hexen/dragon.txt +++ b/wadsrc/static/zscript/hexen/dragon.txt @@ -1,6 +1,4 @@ - // Dragon ------------------------------------------------------------------- - class Dragon : Actor { Default @@ -23,13 +21,6 @@ class Dragon : Actor 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: @@ -58,6 +49,253 @@ class Dragon : Actor DRAG M -1; Stop; } + + //============================================================================ + // + // DragonSeek + // + //============================================================================ + + private void DragonSeek (double thresh, double turnMax) + { + double dist; + double delta; + Actor targ; + int i; + double bestAngle; + double angleToSpot, angleToTarget; + Actor mo; + + targ = tracer; + if(targ == null) + { + return; + } + + double diff = deltaangle(angle, AngleTo(targ)); + delta = abs(diff); + + if (delta > thresh) + { + delta /= 2; + if (delta > turnMax) + { + delta = turnMax; + } + } + if (diff > 0) + { // Turn clockwise + angle = angle + delta; + } + else + { // Turn counter clockwise + angle = angle - delta; + } + VelFromAngle(); + + dist = DistanceBySpeed(targ, Speed); + if (pos.z + height < targ.pos.z || targ.pos.z + targ.height < pos.z) + { + Vel.Z = (targ.pos.z - pos.z) / dist; + } + if (targ.bShootable && random[DragonSeek]() < 64) + { // attack the destination mobj if it's attackable + Actor oldTarget; + + if (absangle(angle, AngleTo(targ)) < 22.5) + { + oldTarget = target; + target = targ; + if (CheckMeleeRange ()) + { + int damage = random[DragonSeek](1, 8) * 10; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + A_PlaySound (AttackSound, CHAN_WEAPON); + } + else if (random[DragonSeek]() < 128 && CheckMissileRange()) + { + SpawnMissile(targ, "DragonFireball"); + A_PlaySound (AttackSound, CHAN_WEAPON); + } + target = oldTarget; + } + } + if (dist < 4) + { // Hit the target thing + if (target && random[DragonSeek]() < 200) + { + Actor bestActor = null; + bestAngle = 360.; + angleToTarget = AngleTo(target); + for (i = 0; i < 5; i++) + { + if (!targ.args[i]) + { + continue; + } + ActorIterator iter = ActorIterator.Create(targ.args[i]); + mo = iter.Next (); + if (mo == null) + { + continue; + } + angleToSpot = AngleTo(mo); + double diff = absangle(angleToSpot, angleToTarget); + if (diff < bestAngle) + { + bestAngle = diff; + bestActor = mo; + } + } + if (bestActor != null) + { + tracer = bestActor; + } + } + else + { + // [RH] Don't lock up if the dragon doesn't have any + // targs defined + for (i = 0; i < 5; ++i) + { + if (targ.args[i] != 0) + { + break; + } + } + if (i < 5) + { + do + { + i = (random[DragonSeek]() >> 2) % 5; + } while(!targ.args[i]); + ActorIterator iter = ActorIterator.Create(targ.args[i]); + tracer = iter.Next (); + } + } + } + } + + //============================================================================ + // + // A_DragonInitFlight + // + //============================================================================ + + void A_DragonInitFlight() + { + ActorIterator iter = ActorIterator.Create(tid); + + do + { // find the first tid identical to the dragon's tid + tracer = iter.Next (); + if (tracer == null) + { + SetState (SpawnState); + return; + } + } while (tracer == self); + RemoveFromHash (); + } + + //============================================================================ + // + // A_DragonFlight + // + //============================================================================ + + void A_DragonFlight() + { + double ang; + + DragonSeek (4., 8.); + if (target) + { + if(!target.bShootable) + { // target died + target = null; + return; + } + ang = absangle(angle, AngleTo(target)); + if (ang <22.5 && CheckMeleeRange()) + { + int damage = random[DragonFlight](1, 8) * 8; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + A_PlaySound (AttackSound, CHAN_WEAPON); + } + else if (ang <= 20) + { + SetState (MissileState); + A_PlaySound (AttackSound, CHAN_WEAPON); + } + } + else + { + LookForPlayers (true); + } + } + + //============================================================================ + // + // A_DragonFlap + // + //============================================================================ + + void A_DragonFlap() + { + A_DragonFlight(); + if (random[DragonFlight]() < 240) + { + A_PlaySound ("DragonWingflap", CHAN_BODY); + } + else + { + PlayActiveSound (); + } + } + + //============================================================================ + // + // A_DragonAttack + // + //============================================================================ + + void A_DragonAttack() + { + SpawnMissile (target, "DragonFireball"); + } + + + //============================================================================ + // + // A_DragonPain + // + //============================================================================ + + void A_DragonPain() + { + A_Pain(); + if (!tracer) + { // no destination spot yet + SetState (SeeState); + } + } + + //============================================================================ + // + // A_DragonCheckCrash + // + //============================================================================ + + void A_DragonCheckCrash() + { + if (pos.z < floorz) + { + SetStateLabel ("Crash"); + } + } } // Dragon Fireball ---------------------------------------------------------- @@ -77,8 +315,6 @@ class DragonFireball : Actor DeathSound "DragonFireballExplode"; } - native void A_DragonFX2(); - States { Spawn: @@ -90,6 +326,30 @@ class DragonFireball : Actor DRFX KL 3 Bright; Stop; } + + //============================================================================ + // + // A_DragonFX2 + // + //============================================================================ + + void A_DragonFX2() + { + int delay = 16+(random[DragonFX2]()>>3); + for (int i = random[DragonFX2](1, 4); i; i--) + { + double xo = (random[DragonFX2]() - 128) / 4.; + double yo = (random[DragonFX2]() - 128) / 4.; + double zo = (random[DragonFX2]() - 128) / 16.; + + Actor mo = Spawn ("DragonExplosion", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + if (mo) + { + mo.tics = delay + (random[DragonFX2](0, 3)) * i*2; + mo.target = target; + } + } + } } // Dragon Fireball Secondary Explosion -------------------------------------- From 60d93008ba53edb1e26562893f31bff5869935ae Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Wed, 16 Nov 2016 11:47:45 -0600 Subject: [PATCH 269/471] Exported TryMove. --- src/p_map.cpp | 8 ++++++++ wadsrc/static/zscript/actor.txt | 1 + 2 files changed, 9 insertions(+) diff --git a/src/p_map.cpp b/src/p_map.cpp index d7bffa5895..b904dc1d45 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2498,6 +2498,14 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, return P_TryMove(thing, pos, dropoff, onfloor, tm); } +DEFINE_ACTION_FUNCTION(AActor, TryMove) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT_DEF(x); + PARAM_FLOAT_DEF(y); + PARAM_INT(dropoff); + ACTION_RETURN_BOOL(P_TryMove(self, DVector2(x, y), dropoff)); +} //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index f28045764e..9980d28f5e 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -97,6 +97,7 @@ class Actor : Thinker native native bool CheckSight(Actor target, int flags = 0); native bool HitFriend(); native bool MonsterMove(); + native bool TryMove(vector2 newpos, int dropoff); native void NewChaseDir(); native bool CheckMissileRange(); native bool SetState(state st, bool nofunction = false); From af3bda3f2a1dbfc7bdb7ea30ce66f76a12a9f401 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Wed, 16 Nov 2016 12:29:06 -0600 Subject: [PATCH 270/471] Removed _DEF. --- src/p_map.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index b904dc1d45..3f0edc8d74 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2501,8 +2501,8 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, DEFINE_ACTION_FUNCTION(AActor, TryMove) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_DEF(x); - PARAM_FLOAT_DEF(y); + PARAM_FLOAT(x); + PARAM_FLOAT(y); PARAM_INT(dropoff); ACTION_RETURN_BOOL(P_TryMove(self, DVector2(x, y), dropoff)); } From 063e94971dba8093855d41422d1e866bc0ad2a28 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Nov 2016 19:46:36 +0100 Subject: [PATCH 271/471] - removed incorrect _DEF. --- src/p_mobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 408cdbf917..52541a6691 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6909,7 +6909,7 @@ IMPLEMENT_CLASS(DActorIterator, false, false, false, false); DEFINE_ACTION_FUNCTION(DActorIterator, Create) { PARAM_PROLOGUE; - PARAM_INT_DEF(tid); + PARAM_INT(tid); PARAM_CLASS_DEF(type, AActor); ACTION_RETURN_OBJECT(new DActorIterator(type, tid)); } From 7a29e6cfdcf70bd36916de8d5a766910c49d4792 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Nov 2016 20:00:25 +0100 Subject: [PATCH 272/471] - scriptified Hexen's fog. --- src/CMakeLists.txt | 1 - src/g_hexen/a_fog.cpp | 99 ----------------------------- src/g_hexen/a_hexenmisc.cpp | 1 - wadsrc/static/zscript/hexen/fog.txt | 85 ++++++++++++++++++++++++- 4 files changed, 83 insertions(+), 103 deletions(-) delete mode 100644 src/g_hexen/a_fog.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8e5c022cbf..f1fc1bab54 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -887,7 +887,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_fighterquietus.cpp g_hexen/a_flechette.cpp g_hexen/a_flies.cpp - g_hexen/a_fog.cpp g_hexen/a_healingradius.cpp g_hexen/a_heresiarch.cpp g_hexen/a_hexenspecialdecs.cpp diff --git a/src/g_hexen/a_fog.cpp b/src/g_hexen/a_fog.cpp deleted file mode 100644 index 6b2bc97069..0000000000 --- a/src/g_hexen/a_fog.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* -#include "m_random.h" -#include "p_local.h" -#include "vm.h" -*/ - -static FRandom pr_fogspawn ("FogSpawn"); - -//========================================================================== -// Fog Variables: -// -// args[0] Speed (0..10) of fog -// args[1] Angle of spread (0..128) -// args[2] Frequency of spawn (1..10) -// args[3] Lifetime countdown -// args[4] Boolean: fog moving? -// special1 Internal: Counter for spawn frequency -// WeaveIndexZ Internal: Index into floatbob table -// -//========================================================================== - -//========================================================================== -// -// A_FogSpawn -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_FogSpawn) -{ - PARAM_SELF_PROLOGUE(AActor); - - static const char *fogs[3] = - { - "FogPatchSmall", - "FogPatchMedium", - "FogPatchLarge" - }; - - AActor *mo = NULL; - int delta; - - if (self->special1-- > 0) - { - return 0; - } - self->special1 = self->args[2]; // Reset frequency count - - mo = Spawn (fogs[pr_fogspawn()%3], self->Pos(), ALLOW_REPLACE); - - if (mo) - { - delta = self->args[1]; - if (delta==0) delta=1; - mo->Angles.Yaw = self->Angles.Yaw + (((pr_fogspawn() % delta) - (delta >> 1)) * (360 / 256.)); - mo->target = self; - if (self->args[0] < 1) self->args[0] = 1; - mo->args[0] = (pr_fogspawn() % (self->args[0]))+1; // Random speed - mo->args[3] = self->args[3]; // Set lifetime - mo->args[4] = 1; // Set to moving - mo->WeaveIndexZ = pr_fogspawn()&63; - } - return 0; -} - -//========================================================================== -// -// A_FogMove -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_FogMove) -{ - PARAM_SELF_PROLOGUE(AActor); - - double speed = self->args[0]; - int weaveindex; - - if (!self->args[4]) - { - return 0; - } - - if (self->args[3]-- <= 0) - { - self->SetState (self->FindState(NAME_Death), true); - return 0; - } - - if ((self->args[3] % 4) == 0) - { - weaveindex = self->WeaveIndexZ; - self->AddZ(BobSin(weaveindex) / 2); - self->WeaveIndexZ = (weaveindex + 1) & 63; - } - - self->VelFromAngle(speed); - return 0; -} - diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index f1f4a86fe8..9003405e49 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -39,7 +39,6 @@ #include "a_fighterquietus.cpp" #include "a_flechette.cpp" #include "a_flies.cpp" -#include "a_fog.cpp" #include "a_healingradius.cpp" #include "a_heresiarch.cpp" #include "a_hexenspecialdecs.cpp" diff --git a/wadsrc/static/zscript/hexen/fog.txt b/wadsrc/static/zscript/hexen/fog.txt index 93b5e9593e..276cf2d73c 100644 --- a/wadsrc/static/zscript/hexen/fog.txt +++ b/wadsrc/static/zscript/hexen/fog.txt @@ -1,3 +1,15 @@ +//========================================================================== +// Fog Variables: +// +// args[0] Speed (0..10) of fog +// args[1] Angle of spread (0..128) +// args[2] Frequency of spawn (1..10) +// args[3] Lifetime countdown +// args[4] Boolean: fog moving? +// special1 Internal: Counter for spawn frequency +// WeaveIndexZ Internal: Index into floatbob table +// +//========================================================================== // Fog Spawner -------------------------------------------------------------- @@ -11,7 +23,6 @@ class FogSpawner : Actor +INVISIBLE } - native void A_FogSpawn(); States { @@ -19,6 +30,45 @@ class FogSpawner : Actor TNT1 A 20 A_FogSpawn; Loop; } + + //========================================================================== + // + // A_FogSpawn + // + //========================================================================== + + void A_FogSpawn() + { + if (special1-- > 0) + { + return; + } + special1 = args[2]; // Reset frequency count + + class fog; + switch (random[FogSpawn](0,2)) + { + default: + case 0: fog = "FogPatchSmall"; break; + case 1: fog = "FogPatchMedium"; break; + case 2: fog = "FogPatchLarge"; break; + } + Actor mo = Spawn (fog, Pos, ALLOW_REPLACE); + + if (mo) + { + int delta = args[1]; + if (delta == 0) delta = 1; + mo.angle = angle + (((random[FogSpawn]() % delta) - (delta >> 1)) * (360 / 256.)); + mo.target = self; + if (args[0] < 1) args[0] = 1; + mo.args[0] = (random[FogSpawn]() % (args[0]))+1; // Random speed + mo.args[3] = args[3]; // Set lifetime + mo.args[4] = 1; // Set to moving + mo.WeaveIndexZ = random[FogSpawn](0, 63); + } + } + } // Small Fog Patch ---------------------------------------------------------- @@ -34,7 +84,6 @@ class FogPatchSmall : Actor Alpha 0.6; } - native void A_FogMove(); States { @@ -45,6 +94,37 @@ class FogPatchSmall : Actor FOGS E 5; Stop; } + + //========================================================================== + // + // A_FogMove + // + //========================================================================== + + void A_FogMove() + { + double speed = args[0]; + int weaveindex; + + if (!args[4]) + { + return; + } + + if (args[3]-- <= 0) + { + SetStateLabel ('Death', true); + return; + } + + if ((args[3] % 4) == 0) + { + weaveindex = WeaveIndexZ; + AddZ(BobSin(weaveindex) / 2); + WeaveIndexZ = (weaveindex + 1) & 63; + } + VelFromAngle(speed); + } } // Medium Fog Patch --------------------------------------------------------- @@ -76,3 +156,4 @@ class FogPatchLarge : FogPatchMedium Goto Super::Death; } } + From df43ee96cea8085fa1d8da0be05f39095b58bda7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Nov 2016 21:12:16 +0100 Subject: [PATCH 273/471] - fixed a lost '='. - scriptified A_TimeBomb. --- src/g_heretic/a_hereticartifacts.cpp | 12 ------------ src/p_mobj.cpp | 3 ++- wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/heretic/hereticartifacts.txt | 9 +++++++-- wadsrc/static/zscript/hexen/dragon.txt | 2 +- wadsrc/static/zscript/hexen/flechette.txt | 9 +++++++-- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index 169d0e7714..f2ad18b2fa 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -44,18 +44,6 @@ bool AArtiTomeOfPower::Use (bool pickup) // Time bomb ---------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AActor, A_TimeBomb) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->AddZ(32, false); - self->RenderStyle = STYLE_Add; - self->Alpha = 1.; - P_RadiusAttack (self, self->target, 128, 128, self->DamageType, RADF_HURTSOURCE); - P_CheckSplash(self, 128); - return 0; -} - class AArtiTimeBomb : public AInventory { DECLARE_CLASS (AArtiTimeBomb, AInventory) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 52541a6691..abbd057d73 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6956,7 +6956,8 @@ DEFINE_ACTION_FUNCTION(AActor, AddZ) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(addz); - self->AddZ(addz); + PARAM_BOOL_DEF(moving); + self->AddZ(addz, moving); return 0; } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 9980d28f5e..7b6b63672d 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -108,7 +108,7 @@ class Actor : Thinker native native void UnlinkFromWorld(); native bool CanSeek(Actor target); native double AngleTo(Actor target, bool absolute = false); - native void AddZ(float zadd); + native void AddZ(float zadd, bool moving = true); 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); diff --git a/wadsrc/static/zscript/heretic/hereticartifacts.txt b/wadsrc/static/zscript/heretic/hereticartifacts.txt index e239748ff8..50a25008a3 100644 --- a/wadsrc/static/zscript/heretic/hereticartifacts.txt +++ b/wadsrc/static/zscript/heretic/hereticartifacts.txt @@ -80,8 +80,6 @@ Class ActivatedTimeBomb : Actor DeathSound "misc/timebomb"; } - native void A_Timebomb(); - States { Spawn: @@ -91,6 +89,13 @@ Class ActivatedTimeBomb : Actor XPL1 BCDEF 4 BRIGHT; Stop; } + + void A_TimeBomb() + { + AddZ(32, false); + A_SetRenderStyle(1., STYLE_Add); + A_Explode(); + } } diff --git a/wadsrc/static/zscript/hexen/dragon.txt b/wadsrc/static/zscript/hexen/dragon.txt index ed6e86d4ac..6082d1c61c 100644 --- a/wadsrc/static/zscript/hexen/dragon.txt +++ b/wadsrc/static/zscript/hexen/dragon.txt @@ -291,7 +291,7 @@ class Dragon : Actor void A_DragonCheckCrash() { - if (pos.z < floorz) + if (pos.z <= floorz) { SetStateLabel ("Crash"); } diff --git a/wadsrc/static/zscript/hexen/flechette.txt b/wadsrc/static/zscript/hexen/flechette.txt index 6f7b3a818c..c024770640 100644 --- a/wadsrc/static/zscript/hexen/flechette.txt +++ b/wadsrc/static/zscript/hexen/flechette.txt @@ -37,8 +37,6 @@ class FireBomb : Actor DeathSound "FlechetteExplode"; } - native void A_TimeBomb(); - States { Spawn: @@ -50,6 +48,13 @@ class FireBomb : Actor XPL1 BCDEF 4 Bright; Stop; } + + void A_TimeBomb() + { + AddZ(32, false); + A_SetRenderStyle(1., STYLE_Add); + A_Explode(); + } } // Throwing Bomb (Flechette used by Fighter) -------------------------------- From 21a1d5ffc80517c45e3f76dc541b8bb98bde402e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 00:44:43 +0100 Subject: [PATCH 274/471] - scriptified Hexen's Wraith and parts of the Spike. --- src/CMakeLists.txt | 1 - src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_spike.cpp | 101 +--------- src/g_hexen/a_wraith.cpp | 258 ------------------------- src/g_shared/a_debris.cpp | 24 --- src/g_shared/a_sharedglobal.h | 1 - src/p_enemy.cpp | 41 ---- src/p_enemy.h | 3 - src/p_mobj.cpp | 6 +- wadsrc/static/zscript/actor.txt | 62 ++++++ wadsrc/static/zscript/hexen/spike.txt | 77 +++++++- wadsrc/static/zscript/hexen/wraith.txt | 223 ++++++++++++++++++++- 12 files changed, 354 insertions(+), 444 deletions(-) delete mode 100644 src/g_hexen/a_wraith.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1fc1bab54..c5f307d56f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -900,7 +900,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_spike.cpp g_hexen/a_summon.cpp g_hexen/a_teleportother.cpp - g_hexen/a_wraith.cpp g_strife/a_acolyte.cpp g_strife/a_alienspectres.cpp g_strife/a_coin.cpp diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 9003405e49..21227e8486 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -52,4 +52,3 @@ #include "a_spike.cpp" #include "a_summon.cpp" #include "a_teleportother.cpp" -#include "a_wraith.cpp" diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp index 9b2cb5d6e2..be28e38dfd 100644 --- a/src/g_hexen/a_spike.cpp +++ b/src/g_hexen/a_spike.cpp @@ -20,28 +20,13 @@ static FRandom pr_thrustraise ("ThrustRaise"); class AThrustFloor : public AActor { DECLARE_CLASS (AThrustFloor, AActor) - HAS_OBJECT_POINTERS public: - void Serialize(FSerializer &arc); - void Activate (AActor *activator); void Deactivate (AActor *activator); - - TObjPtr DirtClump; }; -IMPLEMENT_CLASS(AThrustFloor, false, true, false, false) - -IMPLEMENT_POINTERS_START(AThrustFloor) - IMPLEMENT_POINTER(DirtClump) -IMPLEMENT_POINTERS_END - -void AThrustFloor::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - arc("dirtclump", DirtClump); -} +IMPLEMENT_CLASS(AThrustFloor, false, false, false, false) void AThrustFloor::Activate (AActor *activator) { @@ -68,90 +53,6 @@ void AThrustFloor::Deactivate (AActor *activator) } } -//=========================================================================== -// -// Thrust floor stuff -// -// Thrust Spike Variables -// DirtClump pointer to dirt clump actor -// special2 speed of raise -// args[0] 0 = lowered, 1 = raised -// args[1] 0 = normal, 1 = bloody -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_ThrustInitUp) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->special2 = 5; // Raise speed - self->args[0] = 1; // Mark as up - self->Floorclip = 0; - self->flags = MF_SOLID; - self->flags2 = MF2_NOTELEPORT|MF2_FLOORCLIP; - self->special1 = 0L; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_ThrustInitDn) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->special2 = 5; // Raise speed - self->args[0] = 0; // Mark as down - self->Floorclip = self->GetDefault()->Height; - self->flags = 0; - self->flags2 = MF2_NOTELEPORT|MF2_FLOORCLIP; - self->renderflags = RF_INVISIBLE; - static_cast(self)->DirtClump = - Spawn("DirtClump", self->Pos(), ALLOW_REPLACE); - return 0; -} - - -DEFINE_ACTION_FUNCTION(AActor, A_ThrustRaise) -{ - PARAM_SELF_PROLOGUE(AActor); - - AThrustFloor *actor = static_cast(self); - - if (A_RaiseMobj (actor, self->special2)) - { // Reached it's target height - actor->args[0] = 1; - if (actor->args[1]) - actor->SetState (actor->FindState ("BloodThrustInit2"), true); - else - actor->SetState (actor->FindState ("ThrustInit2"), true); - } - - // Lose the dirt clump - if ((actor->Floorclip < actor->Height) && actor->DirtClump) - { - actor->DirtClump->Destroy (); - actor->DirtClump = NULL; - } - - // Spawn some dirt - if (pr_thrustraise()<40) - P_SpawnDirt (actor, actor->radius); - actor->special2++; // Increase raise speed - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_ThrustLower) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (A_SinkMobj (self, 6)) - { - self->args[0] = 0; - if (self->args[1]) - self->SetState (self->FindState ("BloodThrustInit1"), true); - else - self->SetState (self->FindState ("ThrustInit1"), true); - } - return 0; -} - DEFINE_ACTION_FUNCTION(AActor, A_ThrustImpale) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/g_hexen/a_wraith.cpp b/src/g_hexen/a_wraith.cpp deleted file mode 100644 index fcd0d75f34..0000000000 --- a/src/g_hexen/a_wraith.cpp +++ /dev/null @@ -1,258 +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 "a_sharedglobal.h" -#include "vm.h" -*/ - -static FRandom pr_stealhealth ("StealHealth"); -static FRandom pr_wraithfx2 ("WraithFX2"); -static FRandom pr_wraithfx3 ("WraithFX3"); -static FRandom pr_wraithfx4 ("WraithFX4"); - -//============================================================================ -// -// A_WraithInit -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_WraithInit) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->AddZ(48); - - // [RH] Make sure the wraith didn't go into the ceiling - if (self->Top() > self->ceilingz) - { - self->SetZ(self->ceilingz - self->Height); - } - - self->WeaveIndexZ = 0; // index into floatbob - return 0; -} - -//============================================================================ -// -// A_WraithRaiseInit -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_WraithRaiseInit) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->renderflags &= ~RF_INVISIBLE; - self->flags2 &= ~MF2_NONSHOOTABLE; - self->flags3 &= ~MF3_DONTBLAST; - self->flags |= MF_SHOOTABLE|MF_SOLID; - self->Floorclip = self->Height; - return 0; -} - -//============================================================================ -// -// A_WraithRaise -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_WraithRaise) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (A_RaiseMobj (self, 2)) - { - // Reached it's target height - // [RH] Once a buried wraith is fully raised, it should be - // morphable, right? - self->flags3 &= ~(MF3_DONTMORPH|MF3_SPECIALFLOORCLIP); - self->SetState (self->FindState("Chase")); - // [RH] Reset PainChance to a normal wraith's. - self->PainChance = GetDefaultByName ("Wraith")->PainChance; - } - - P_SpawnDirt (self, self->radius); - return 0; -} - -//============================================================================ -// -// A_WraithMelee -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_WraithMelee) -{ - PARAM_SELF_PROLOGUE(AActor); - - int amount; - - // Steal health from target and give to self - if (self->CheckMeleeRange() && (pr_stealhealth()<220)) - { - amount = pr_stealhealth.HitDice (2); - P_DamageMobj (self->target, self, self, amount, NAME_Melee); - self->health += amount; - } - return 0; -} - -//============================================================================ -// -// A_WraithFX2 - spawns sparkle tail of missile -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_WraithFX2) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - DAngle angle; - int i; - - for (i = 2; i; --i) - { - mo = Spawn ("WraithFX2", self->Pos(), ALLOW_REPLACE); - if(mo) - { - angle = pr_wraithfx2() * (360 / 1024.f); - if (pr_wraithfx2() >= 128) - { - angle = -angle; - } - angle += self->Angles.Yaw; - mo->Vel.X = ((pr_wraithfx2() / 512.) + 1) * angle.Cos(); - mo->Vel.Y = ((pr_wraithfx2() / 512.) + 1) * angle.Sin(); - mo->Vel.Z = 0; - mo->target = self; - mo->Floorclip = 10; - } - } - return 0; -} - -//============================================================================ -// -// A_WraithFX3 -// -// Spawn an FX3 around the self during attacks -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_WraithFX3) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - int numdropped = pr_wraithfx3() % 15; - - while (numdropped-- > 0) - { - double xo = (pr_wraithfx3() - 128) / 32.; - double yo = (pr_wraithfx3() - 128) / 32.; - double zo = pr_wraithfx3() / 64.; - - mo = Spawn("WraithFX3", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - if (mo) - { - mo->floorz = self->floorz; - mo->ceilingz = self->ceilingz; - mo->target = self; - } - } - return 0; -} - -//============================================================================ -// -// A_WraithFX4 -// -// Spawn an FX4 during movement -// -//============================================================================ - -void A_WraithFX4 (AActor *self) -{ - AActor *mo; - int chance = pr_wraithfx4(); - bool spawn4, spawn5; - - if (chance < 10) - { - spawn4 = true; - spawn5 = false; - } - else if (chance < 20) - { - spawn4 = false; - spawn5 = true; - } - else if (chance < 25) - { - spawn4 = true; - spawn5 = true; - } - else - { - spawn4 = false; - spawn5 = false; - } - - if (spawn4) - { - double xo = (pr_wraithfx4() - 128) / 16.; - double yo = (pr_wraithfx4() - 128) / 16.; - double zo = (pr_wraithfx4() / 64.); - - mo = Spawn ("WraithFX4", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - if (mo) - { - mo->floorz = self->floorz; - mo->ceilingz = self->ceilingz; - mo->target = self; - } - } - if (spawn5) - { - double xo = (pr_wraithfx4() - 128) / 32.; - double yo = (pr_wraithfx4() - 128) / 32.; - double zo = (pr_wraithfx4() / 64.); - - mo = Spawn ("WraithFX5", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - if (mo) - { - mo->floorz = self->floorz; - mo->ceilingz = self->ceilingz; - mo->target = self; - } - } -} - -//============================================================================ -// -// A_WraithChase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_WraithChase) -{ - PARAM_SELF_PROLOGUE(AActor); - - int weaveindex = self->WeaveIndexZ; - self->AddZ(BobSin(weaveindex)); - self->WeaveIndexZ = (weaveindex + 2) & 63; -// if (self->Floorclip > 0) -// { -// P_SetMobjState(self, S_WRAITH_RAISE2); -// return; -// } - A_Chase (stack, self); - A_WraithFX4 (self); - return 0; -} diff --git a/src/g_shared/a_debris.cpp b/src/g_shared/a_debris.cpp index 3be3c22409..d3d69d7f6b 100644 --- a/src/g_shared/a_debris.cpp +++ b/src/g_shared/a_debris.cpp @@ -3,8 +3,6 @@ #include "m_random.h" #include "m_fixed.h" -static FRandom pr_dirt ("SpawnDirt"); - // Stained glass ------------------------------------------------------------ class AGlassShard : public AActor @@ -27,25 +25,3 @@ public: IMPLEMENT_CLASS(AGlassShard, false, false, false, false) -// Dirt stuff - -void P_SpawnDirt (AActor *actor, double radius) -{ - PClassActor *dtype = NULL; - AActor *mo; - - double zo = pr_dirt() / 128. + 1; - DVector3 pos = actor->Vec3Angle(radius, pr_dirt() * (360./256), zo); - - char fmt[8]; - mysnprintf(fmt, countof(fmt), "Dirt%d", 1 + pr_dirt()%6); - dtype = PClass::FindActor(fmt); - if (dtype) - { - mo = Spawn (dtype, pos, ALLOW_REPLACE); - if (mo) - { - mo->Vel.Z = pr_dirt() / 64.; - } - } -} diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index c00cd8cf0c..65f9d90b63 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -10,7 +10,6 @@ struct side_t; struct F3DFloor; class DBaseDecal; -void P_SpawnDirt (AActor *actor, double radius); class DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, double x, double y, double z, DAngle angle, double tracedist, bool permanent); class DBaseDecal : public DThinker diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index d36a8de9d8..6bb96ef30c 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3468,47 +3468,6 @@ int P_Massacre () return killcount; } -// -// A_SinkMobj -// Sink a mobj incrementally into the floor -// - -bool A_SinkMobj (AActor *actor, double speed) -{ - if (actor->Floorclip < actor->Height) - { - actor->Floorclip += speed; - return false; - } - return true; -} - -// -// A_RaiseMobj -// Raise a mobj incrementally from the floor to -// - -bool A_RaiseMobj (AActor *actor, double speed) -{ - bool done = true; - - // Raise a mobj from the ground - if (actor->Floorclip > 0) - { - actor->Floorclip -= speed; - if (actor->Floorclip <= 0) - { - actor->Floorclip = 0; - done = true; - } - else - { - done = false; - } - } - return done; // Reached target height -} - DEFINE_ACTION_FUNCTION(AActor, A_ClassBossHealth) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/p_enemy.h b/src/p_enemy.h index 7f4424fd6f..c4a966344b 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -75,9 +75,6 @@ void A_Chase(VMFrameStack *stack, AActor *self); void A_FaceTarget(AActor *actor); void A_Face(AActor *self, AActor *other, DAngle max_turn = 0., DAngle max_pitch = 270., DAngle ang_offset = 0., DAngle pitch_offset = 0., int flags = 0, double z_add = 0); -bool A_RaiseMobj (AActor *, double speed); -bool A_SinkMobj (AActor *, double speed); - bool CheckBossDeath (AActor *); int P_Massacre (); bool P_CheckMissileRange (AActor *actor); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index abbd057d73..9c36e861cb 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -204,8 +204,8 @@ void AActor::InitNativeFields() 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(NAME_CeilingZ, TypeFloat64, myoffsetof(AActor, ceilingz)); + meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz)); 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? @@ -225,7 +225,7 @@ void AActor::InitNativeFields() 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(NAME_Health, TypeSInt32, myoffsetof(AActor, health)); meta->AddNativeField("movedir", TypeUInt8, myoffsetof(AActor, movedir)); meta->AddNativeField("visdir", TypeSInt8, myoffsetof(AActor, visdir)); meta->AddNativeField("movecount", TypeSInt16, myoffsetof(AActor, movecount)); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 7b6b63672d..f20a0b19ec 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -268,6 +268,68 @@ class Actor : Thinker native DamageMobj(null, null, health, damagetype, DMG_FORCED); } + void SpawnDirt (double radius) + { + class dtype; + switch (random[Dirt](0, 5)) + { + case 0: dtype = "Dirt1"; break; + case 1: dtype = "Dirt2"; break; + case 2: dtype = "Dirt3"; break; + case 3: dtype = "Dirt4"; break; + case 4: dtype = "Dirt5"; break; + default: dtype = "Dirt6"; break; + } + + double zo = random[Dirt]() / 128. + 1; + Vector3 pos = Vec3Angle(radius, random[Dirt]() * (360./256), zo); + + Actor mo = Spawn (dtype, pos, ALLOW_REPLACE); + if (mo) + { + mo.Vel.Z = random[Dirt]() / 64.; + } + } + + // + // A_SinkMobj + // Sink a mobj incrementally into the floor + // + + bool SinkMobj (double speed) + { + if (Floorclip < Height) + { + Floorclip += speed; + return false; + } + return true; + } + + // + // A_RaiseMobj + // Raise a mobj incrementally from the floor to + // + + bool RaiseMobj (double speed) + { + // Raise a mobj from the ground + if (Floorclip > 0) + { + Floorclip -= speed; + if (Floorclip <= 0) + { + Floorclip = 0; + return true; + } + else + { + return false; + } + } + return true; + } + 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); diff --git a/wadsrc/static/zscript/hexen/spike.txt b/wadsrc/static/zscript/hexen/spike.txt index 58f763ccc7..8d418d55a5 100644 --- a/wadsrc/static/zscript/hexen/spike.txt +++ b/wadsrc/static/zscript/hexen/spike.txt @@ -26,11 +26,7 @@ class ThrustFloor : Actor native Height 128; } - native void A_ThrustRaise(); native void A_ThrustImpale(); - native void A_ThrustLower(); - native void A_ThrustInitDn(); - native void A_ThrustInitUp(); States { @@ -81,6 +77,79 @@ class ThrustFloor : Actor native TSPK B 2 A_ThrustImpale; Loop; } + + //=========================================================================== + // + // Thrust floor stuff + // + // Thrust Spike Variables + // master pointer to dirt clump actor + // special2 speed of raise + // args[0] 0 = lowered, 1 = raised + // args[1] 0 = normal, 1 = bloody + //=========================================================================== + + void A_ThrustInitUp() + { + special2 = 5; // Raise speed + args[0] = 1; // Mark as up + Floorclip = 0; + bSolid = true; + bNoTeleport = true; + bFloorClip = true; + special1 = 0; + } + + void A_ThrustInitDn() + { + special2 = 5; // Raise speed + args[0] = 0; // Mark as down + Floorclip = Default.Height; + bSolid = false; + bNoTeleport = true; + bFloorClip = true; + bInvisible = true; + master = Spawn("DirtClump", Pos, ALLOW_REPLACE); + } + + + void A_ThrustRaise() + { + if (RaiseMobj (special2)) + { // Reached it's target height + args[0] = 1; + if (args[1]) + SetStateLabel ("BloodThrustInit2", true); + else + SetStateLabel ("ThrustInit2", true); + } + + // Lose the dirt clump + if ((Floorclip < Height) && master) + { + master.Destroy (); + master = null; + } + + // Spawn some dirt + if (random[Thrustraise]()<40) + SpawnDirt (radius); + special2++; // Increase raise speed + } + + void A_ThrustLower() + { + if (SinkMobj (6)) + { + args[0] = 0; + if (args[1]) + SetStateLabel ("BloodThrustInit1", true); + else + SetStateLabel ("ThrustInit1", true); + } + } + + } // Spike up ----------------------------------------------------------------- diff --git a/wadsrc/static/zscript/hexen/wraith.txt b/wadsrc/static/zscript/hexen/wraith.txt index 86df72d94e..42a81ae6c5 100644 --- a/wadsrc/static/zscript/hexen/wraith.txt +++ b/wadsrc/static/zscript/hexen/wraith.txt @@ -23,11 +23,6 @@ class Wraith : Actor Obituary "$OB_WRAITH"; } - native void A_WraithInit(); - native void A_WraithChase(); - native void A_WraithFX3(); - native void A_WraithMelee(); - States { Spawn: @@ -78,6 +73,150 @@ class Wraith : Actor WRT2 I 1 A_FreezeDeathChunks; Wait; } + + //============================================================================ + // + // A_WraithInit + // + //============================================================================ + + void A_WraithInit() + { + AddZ(48); + + // [RH] Make sure the wraith didn't go into the ceiling + if (pos.z + height > ceilingz) + { + SetZ(ceilingz - Height); + } + + WeaveIndexZ = 0; // index into floatbob + } + + + //============================================================================ + // + // A_WraithChase + // + //============================================================================ + + void A_WraithChase() + { + int weaveindex = WeaveIndexZ; + AddZ(BobSin(weaveindex)); + WeaveIndexZ = (weaveindex + 2) & 63; + A_Chase (); + A_WraithFX4 (); + } + + //============================================================================ + // + // A_WraithFX3 + // + // Spawn an FX3 around the wraith during attacks + // + //============================================================================ + + void A_WraithFX3() + { + int numdropped = random[WraithFX3](0,14); + + while (numdropped-- > 0) + { + double xo = (random[WraithFX3]() - 128) / 32.; + double yo = (random[WraithFX3]() - 128) / 32.; + double zo = random[WraithFX3]() / 64.; + + Actor mo = Spawn("WraithFX3", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + if (mo) + { + mo.floorz = floorz; + mo.ceilingz = ceilingz; + mo.target = self; + } + } + } + + //============================================================================ + // + // A_WraithFX4 + // + // Spawn an FX4 during movement + // + //============================================================================ + + void A_WraithFX4 () + { + int chance = random[WraithFX4](); + bool spawn4, spawn5; + + if (chance < 10) + { + spawn4 = true; + spawn5 = false; + } + else if (chance < 20) + { + spawn4 = false; + spawn5 = true; + } + else if (chance < 25) + { + spawn4 = true; + spawn5 = true; + } + else + { + spawn4 = false; + spawn5 = false; + } + + if (spawn4) + { + double xo = (random[WraithFX4]() - 128) / 16.; + double yo = (random[WraithFX4]() - 128) / 16.; + double zo = (random[WraithFX4]() / 64.); + + Actor mo = Spawn ("WraithFX4", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + if (mo) + { + mo.floorz = floorz; + mo.ceilingz = ceilingz; + mo.target = self; + } + } + if (spawn5) + { + double xo = (random[WraithFX4]() - 128) / 32.; + double yo = (random[WraithFX4]() - 128) / 32.; + double zo = (random[WraithFX4]() / 64.); + + Actor mo = Spawn ("WraithFX5", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + if (mo) + { + mo.floorz = floorz; + mo.ceilingz = ceilingz; + mo.target = self; + } + } + } + + //============================================================================ + // + // A_WraithMelee + // + //============================================================================ + + void A_WraithMelee() + { + // Steal health from target and give to self + if (CheckMeleeRange() && (random[StealHealth]()<220)) + { + int amount = random[StealHealth](1, 8) * 2; + target.DamageMobj (self, self, amount, 'Melee'); + health += amount; + } + } } // Buried wraith ------------------------------------------------------------ @@ -97,8 +236,6 @@ class WraithBuried : Wraith PainChance 0; } - native void A_WraithRaiseInit(); - native void A_WraithRaise(); States { @@ -113,6 +250,47 @@ class WraithBuried : Wraith Chase: Goto Super::See; } + + //============================================================================ + // + // A_WraithRaiseInit + // + //============================================================================ + + void A_WraithRaiseInit() + { + bInvisible = false; + bNonShootable = false; + bDontBlast = false; + bShootable = true; + bSolid = true; + Floorclip = Height; + } + + //============================================================================ + // + // A_WraithRaise + // + //============================================================================ + + void A_WraithRaise() + { + if (RaiseMobj (2)) + { + // Reached it's target height + // [RH] Once a buried wraith is fully raised, it should be + // morphable, right? + bDontMorph = false; + bSpecialFloorClip = false; + SetStateLabel ("Chase"); + // [RH] Reset PainChance to a normal wraith's. + PainChance = GetDefaultByType("Wraith").PainChance; + } + + SpawnDirt (radius); + } + + } // Wraith FX 1 -------------------------------------------------------------- @@ -133,7 +311,6 @@ class WraithFX1 : Actor DeathSound "WraithMissileExplode"; } - native void A_WraithFX2(); States { @@ -150,6 +327,36 @@ class WraithFX1 : Actor WRBL I 3 Bright; Stop; } + + //============================================================================ + // + // A_WraithFX2 - spawns sparkle tail of missile + // + //============================================================================ + + void A_WraithFX2() + { + for (int i = 2; i; --i) + { + Actor mo = Spawn ("WraithFX2", Pos, ALLOW_REPLACE); + if(mo) + { + double newangle = random[WraithFX2]() * (360 / 1024.f); + if (random[WraithFX2]() >= 128) + { + newangle = -newangle; + } + newangle += angle; + mo.Vel.X = ((random[WraithFX2]() / 512.) + 1) * cos(newangle); + mo.Vel.Y = ((random[WraithFX2]() / 512.) + 1) * sin(newangle); + mo.Vel.Z = 0; + mo.target = self; + mo.Floorclip = 10; + } + } + } + + } // Wraith FX 2 -------------------------------------------------------------- From 30e6e8e25f10bfba6c151163356a60443982a3ec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 11:16:00 +0100 Subject: [PATCH 275/471] - added bookkeeping info to types for allowing data on the stack that requires construction and destruction. - removed unused PVector type. --- src/dobjtype.cpp | 198 +++++++++++++++++++++++++++++++++++------------ src/dobjtype.h | 36 +++++---- 2 files changed, 170 insertions(+), 64 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 5e56bab564..b9d518abf3 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -541,7 +541,6 @@ void PType::StaticInit() RUNTIME_CLASS(PEnum)->TypeTableType = RUNTIME_CLASS(PEnum); RUNTIME_CLASS(PArray)->TypeTableType = RUNTIME_CLASS(PArray); RUNTIME_CLASS(PDynArray)->TypeTableType = RUNTIME_CLASS(PDynArray); - RUNTIME_CLASS(PVector)->TypeTableType = RUNTIME_CLASS(PVector); RUNTIME_CLASS(PMap)->TypeTableType = RUNTIME_CLASS(PMap); RUNTIME_CLASS(PStruct)->TypeTableType = RUNTIME_CLASS(PStruct); RUNTIME_CLASS(PPrototype)->TypeTableType = RUNTIME_CLASS(PPrototype); @@ -1870,6 +1869,39 @@ void PArray::SetDefaultValue(void *base, unsigned offset, TArray } } +//========================================================================== +// +// PArray :: InitializeValue +// This is needed for local array variables +// +//========================================================================== + +void PArray::InitializeValue(void *addr, const void *def) const +{ + char *caddr = (char*)addr; + char *cdef = (char*)def; + for (unsigned i = 0; i < ElementCount; ++i) + { + ElementType->InitializeValue(caddr + i * ElementSize, cdef + i * ElementSize); + } +} + +//========================================================================== +// +// PArray :: DestroyValue +// This is needed for local array variables +// +//========================================================================== + +void PArray::DestroyValue(void *addr) const +{ + char *caddr = (char*)addr; + for (unsigned i = 0; i < ElementCount; ++i) + { + ElementType->DestroyValue(caddr + i * ElementSize); + } +} + //========================================================================== // // NewArray @@ -1891,56 +1923,6 @@ PArray *NewArray(PType *type, unsigned int count) return (PArray *)atype; } -/* PVector ****************************************************************/ - -IMPLEMENT_CLASS(PVector, false, false, false, false) - -//========================================================================== -// -// PVector - Default Constructor -// -//========================================================================== - -PVector::PVector() -: PArray(TypeFloat32, 3) -{ - mDescriptiveName = "Vector"; -} - -//========================================================================== -// -// PVector - Parameterized Constructor -// -//========================================================================== - -PVector::PVector(unsigned int size) -: PArray(TypeFloat32, size) -{ - mDescriptiveName.Format("Vector<%d>", size); - assert(size >= 2 && size <= 4); -} - -//========================================================================== -// -// NewVector -// -// Returns a PVector with the given dimension, making sure not to create -// duplicates. -// -//========================================================================== - -PVector *NewVector(unsigned int size) -{ - size_t bucket; - PType *type = TypeTable.FindType(RUNTIME_CLASS(PVector), (intptr_t)TypeFloat32, size, &bucket); - if (type == NULL) - { - type = new PVector(size); - TypeTable.AddType(type, RUNTIME_CLASS(PVector), (intptr_t)TypeFloat32, size, bucket); - } - return (PVector *)type; -} - /* PDynArray **************************************************************/ IMPLEMENT_CLASS(PDynArray, false, true, false, false) @@ -2003,6 +1985,28 @@ void PDynArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = 0; } +//========================================================================== +// +// PDynArray :: InitializeValue +// +//========================================================================== + +void PDynArray::InitializeValue(void *addr, const void *def) const +{ + // DynArrays are not implemented yet. +} + +//========================================================================== +// +// PDynArray :: DestroyValue +// +//========================================================================== + +void PDynArray::DestroyValue(void *addr) const +{ + // DynArrays are not implemented yet. +} + //========================================================================== // // NewDynArray @@ -2087,6 +2091,28 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = (intptr_t)ValueType; } +//========================================================================== +// +// PMap :: InitializeValue +// +//========================================================================== + +void PMap::InitializeValue(void *addr, const void *def) const +{ + // Maps are not implemented yet. +} + +//========================================================================== +// +// PMap :: DestroyValue +// +//========================================================================== + +void PMap::DestroyValue(void *addr) const +{ + // Maps are not implemented yet. +} + //========================================================================== // // NewMap @@ -2309,6 +2335,76 @@ size_t PStruct::PropagateMark() return Fields.Size() * sizeof(void*) + Super::PropagateMark(); } +//========================================================================== +// +// PStruct :: InitializeValue +// This is needed for local array variables +// +//========================================================================== + +void PStruct::InitializeValue(void *addr, const void *def) const +{ + char *caddr = (char*)addr; + char *cdef = (char*)def; + + for (auto tao : SpecialInits) + { + tao.first->InitializeValue(caddr + tao.second, cdef + tao.second); + } +} + +//========================================================================== +// +// PStruct :: DestroyValue +// This is needed for local array variables +// +//========================================================================== + +void PStruct::DestroyValue(void *addr) const +{ + char *caddr = (char*)addr; + for (auto tao : SpecialInits) + { + tao.first->DestroyValue(caddr + tao.second); + } +} + + +//========================================================================== +// +// PStruct :: InitializeSpecialInits +// +// Initialize special field list. +// +//========================================================================== + +void PStruct::InitializeSpecialInits() +{ + // 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(nullptr, unsigned(field->Offset), &SpecialInits); + } + } +} + +//========================================================================== +// +// PStruct :: RequireConstruction +// +//========================================================================== + +bool PStruct::RequireConstruction() const +{ + return SpecialInits.Size() > 0; +} + //========================================================================== // // NewStruct diff --git a/src/dobjtype.h b/src/dobjtype.h index 186cb8117f..dcf316fec9 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -256,6 +256,9 @@ public: // Initialize the value, if needed (e.g. strings) virtual void InitializeValue(void *addr, const void *def) const; + // This is for stack variables that may need construction/destruction at runtime + virtual bool RequireConstruction() const { return false; } + // Destroy the value, if needed (e.g. strings) virtual void DestroyValue(void *addr) const; @@ -489,6 +492,7 @@ public: void SetDefaultValue(void *base, unsigned offset, TArray *special=NULL) const override; void InitializeValue(void *addr, const void *def) const override; void DestroyValue(void *addr) const override; + virtual bool RequireConstruction() const override { return true; } }; // Variations of integer types ---------------------------------------------- @@ -626,22 +630,14 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *special) const override; + void InitializeValue(void *addr, const void *def) const override; + void DestroyValue(void *addr) const override; + bool RequireConstruction() const override { return ElementType->RequireConstruction(); } protected: PArray(); }; -// A vector is an array with extra operations. -class PVector : public PArray -{ - DECLARE_CLASS(PVector, PArray); - HAS_OBJECT_POINTERS; -public: - PVector(unsigned int size); -protected: - PVector(); -}; - class PDynArray : public PCompoundType { DECLARE_CLASS(PDynArray, PCompoundType); @@ -653,6 +649,9 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + void InitializeValue(void *addr, const void *def) const override; + void DestroyValue(void *addr) const override; + bool RequireConstruction() const override { return true; } protected: PDynArray(); }; @@ -669,6 +668,9 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + void InitializeValue(void *addr, const void *def) const override; + void DestroyValue(void *addr) const override; + bool RequireConstruction() const override { return true; } protected: PMap(); }; @@ -676,6 +678,10 @@ protected: class PStruct : public PNamedType { DECLARE_CLASS(PStruct, PNamedType); + +protected: + TArray SpecialInits; + public: PStruct(FName name, PTypeBase *outer); @@ -693,6 +699,12 @@ public: static void WriteFields(FSerializer &ar, const void *addr, const TArray &fields); bool ReadFields(FSerializer &ar, void *addr) const; + + void InitializeValue(void *addr, const void *def) const override; + void DestroyValue(void *addr) const override; + bool RequireConstruction() const override; + void InitializeSpecialInits(); + protected: PStruct(); }; @@ -759,7 +771,6 @@ class PClass : public PStruct protected: // We unravel _WITH_META here just as we did for PType. enum { MetaClassNum = CLASSREG_PClassClass }; - TArray SpecialInits; void Derive(PClass *newclass, FName name); void InitializeSpecials(void *addr) const; void SetSuper(); @@ -889,7 +900,6 @@ struct FTypeTable extern FTypeTable TypeTable; // Returns a type from the TypeTable. Will create one if it isn't present. -PVector *NewVector(unsigned int size); PMap *NewMap(PType *keytype, PType *valuetype); PArray *NewArray(PType *type, unsigned int count); PDynArray *NewDynArray(PType *type); From d86f03e2e00bce5f95b87ce77b393891ef3993fc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 13:10:19 +0100 Subject: [PATCH 276/471] - reverted most of the last commit after realizing that trying to manage constructing/destructing per variable is not going to work because it'd require some extensive exception management in the compiled VM code. - instead add a list of SpecialInits to VMScriptFunction so this can be done transparently when setting up and popping the stack frame. The only drawback is that this requires permanent allocation of stack objects for the entire lifetime of a function but this is a relatively small tradeoff for significantly reduced maintenance work throughout. - removed most #include "vm.h", because nearly all files already pull this in through dobject.h. --- src/d_dehacked.cpp | 1 - src/d_main.cpp | 1 - src/dobjgc.cpp | 1 - src/dobjtype.cpp | 147 ------------------------------- src/dobjtype.h | 28 +----- src/g_doom/a_doommisc.cpp | 2 - src/g_heretic/a_hereticmisc.cpp | 2 - src/g_hexen/a_hexenmisc.cpp | 2 - src/g_shared/a_action.cpp | 1 - src/g_shared/a_bridge.cpp | 1 - src/g_shared/a_pickups.cpp | 1 - src/g_shared/a_randomspawner.cpp | 1 - src/g_shared/a_specialspot.cpp | 1 - src/g_shared/a_weapons.cpp | 1 - src/info.cpp | 2 - src/info.h | 1 - src/p_actionfunctions.cpp | 2 - src/p_enemy.cpp | 2 - src/p_enemy.h | 2 +- src/p_mobj.cpp | 1 - src/p_pspr.cpp | 1 - src/p_pspr.h | 1 - src/p_states.cpp | 1 - src/p_user.cpp | 1 - src/scripting/thingdef.h | 1 - src/scripting/vm/vm.h | 8 +- src/scripting/vm/vmbuilder.h | 2 +- src/scripting/vm/vmdisasm.cpp | 2 +- src/scripting/vm/vmexec.cpp | 2 +- src/scripting/vm/vmframe.cpp | 71 +++++++++------ 30 files changed, 55 insertions(+), 235 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index d0addb0951..8d3a135803 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -70,7 +70,6 @@ #include "doomerrors.h" #include "p_effect.h" #include "serializer.h" -#include "vm.h" #include "thingdef.h" #include "info.h" #include "v_text.h" diff --git a/src/d_main.cpp b/src/d_main.cpp index d7757ddf47..dad2b86d95 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -109,7 +109,6 @@ #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/dobjgc.cpp b/src/dobjgc.cpp index fa8723e902..40ef7b7845 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -77,7 +77,6 @@ #include "r_utility.h" #include "menu/menu.h" #include "intermission/intermission.h" -#include "vm.h" // MACROS ------------------------------------------------------------------ diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index b9d518abf3..1597494d95 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1869,39 +1869,6 @@ void PArray::SetDefaultValue(void *base, unsigned offset, TArray } } -//========================================================================== -// -// PArray :: InitializeValue -// This is needed for local array variables -// -//========================================================================== - -void PArray::InitializeValue(void *addr, const void *def) const -{ - char *caddr = (char*)addr; - char *cdef = (char*)def; - for (unsigned i = 0; i < ElementCount; ++i) - { - ElementType->InitializeValue(caddr + i * ElementSize, cdef + i * ElementSize); - } -} - -//========================================================================== -// -// PArray :: DestroyValue -// This is needed for local array variables -// -//========================================================================== - -void PArray::DestroyValue(void *addr) const -{ - char *caddr = (char*)addr; - for (unsigned i = 0; i < ElementCount; ++i) - { - ElementType->DestroyValue(caddr + i * ElementSize); - } -} - //========================================================================== // // NewArray @@ -1985,28 +1952,6 @@ void PDynArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = 0; } -//========================================================================== -// -// PDynArray :: InitializeValue -// -//========================================================================== - -void PDynArray::InitializeValue(void *addr, const void *def) const -{ - // DynArrays are not implemented yet. -} - -//========================================================================== -// -// PDynArray :: DestroyValue -// -//========================================================================== - -void PDynArray::DestroyValue(void *addr) const -{ - // DynArrays are not implemented yet. -} - //========================================================================== // // NewDynArray @@ -2091,28 +2036,6 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = (intptr_t)ValueType; } -//========================================================================== -// -// PMap :: InitializeValue -// -//========================================================================== - -void PMap::InitializeValue(void *addr, const void *def) const -{ - // Maps are not implemented yet. -} - -//========================================================================== -// -// PMap :: DestroyValue -// -//========================================================================== - -void PMap::DestroyValue(void *addr) const -{ - // Maps are not implemented yet. -} - //========================================================================== // // NewMap @@ -2335,76 +2258,6 @@ size_t PStruct::PropagateMark() return Fields.Size() * sizeof(void*) + Super::PropagateMark(); } -//========================================================================== -// -// PStruct :: InitializeValue -// This is needed for local array variables -// -//========================================================================== - -void PStruct::InitializeValue(void *addr, const void *def) const -{ - char *caddr = (char*)addr; - char *cdef = (char*)def; - - for (auto tao : SpecialInits) - { - tao.first->InitializeValue(caddr + tao.second, cdef + tao.second); - } -} - -//========================================================================== -// -// PStruct :: DestroyValue -// This is needed for local array variables -// -//========================================================================== - -void PStruct::DestroyValue(void *addr) const -{ - char *caddr = (char*)addr; - for (auto tao : SpecialInits) - { - tao.first->DestroyValue(caddr + tao.second); - } -} - - -//========================================================================== -// -// PStruct :: InitializeSpecialInits -// -// Initialize special field list. -// -//========================================================================== - -void PStruct::InitializeSpecialInits() -{ - // 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(nullptr, unsigned(field->Offset), &SpecialInits); - } - } -} - -//========================================================================== -// -// PStruct :: RequireConstruction -// -//========================================================================== - -bool PStruct::RequireConstruction() const -{ - return SpecialInits.Size() > 0; -} - //========================================================================== // // NewStruct diff --git a/src/dobjtype.h b/src/dobjtype.h index dcf316fec9..0062c56ab7 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -5,10 +5,10 @@ #error You must #include "dobject.h" to get dobjtype.h #endif -#include "vm.h" - typedef std::pair FTypeAndOffset; +#include "vm.h" + // Variable/parameter/field flags ------------------------------------------- // Making all these different storage types use a common set of flags seems @@ -256,9 +256,6 @@ public: // Initialize the value, if needed (e.g. strings) virtual void InitializeValue(void *addr, const void *def) const; - // This is for stack variables that may need construction/destruction at runtime - virtual bool RequireConstruction() const { return false; } - // Destroy the value, if needed (e.g. strings) virtual void DestroyValue(void *addr) const; @@ -492,7 +489,6 @@ public: void SetDefaultValue(void *base, unsigned offset, TArray *special=NULL) const override; void InitializeValue(void *addr, const void *def) const override; void DestroyValue(void *addr) const override; - virtual bool RequireConstruction() const override { return true; } }; // Variations of integer types ---------------------------------------------- @@ -630,9 +626,6 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *special) const override; - void InitializeValue(void *addr, const void *def) const override; - void DestroyValue(void *addr) const override; - bool RequireConstruction() const override { return ElementType->RequireConstruction(); } protected: PArray(); @@ -649,9 +642,6 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; - void InitializeValue(void *addr, const void *def) const override; - void DestroyValue(void *addr) const override; - bool RequireConstruction() const override { return true; } protected: PDynArray(); }; @@ -668,9 +658,6 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; - void InitializeValue(void *addr, const void *def) const override; - void DestroyValue(void *addr) const override; - bool RequireConstruction() const override { return true; } protected: PMap(); }; @@ -678,10 +665,6 @@ protected: class PStruct : public PNamedType { DECLARE_CLASS(PStruct, PNamedType); - -protected: - TArray SpecialInits; - public: PStruct(FName name, PTypeBase *outer); @@ -699,12 +682,6 @@ public: static void WriteFields(FSerializer &ar, const void *addr, const TArray &fields); bool ReadFields(FSerializer &ar, void *addr) const; - - void InitializeValue(void *addr, const void *def) const override; - void DestroyValue(void *addr) const override; - bool RequireConstruction() const override; - void InitializeSpecialInits(); - protected: PStruct(); }; @@ -771,6 +748,7 @@ class PClass : public PStruct protected: // We unravel _WITH_META here just as we did for PType. enum { MetaClassNum = CLASSREG_PClassClass }; + TArray SpecialInits; void Derive(PClass *newclass, FName name); void InitializeSpecials(void *addr) const; void SetSuper(); diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index eabf887f07..30fd6c671e 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -7,7 +7,6 @@ #include "gi.h" #include "doomstat.h" #include "gstrings.h" -#include "vm.h" #include "g_level.h" #include "p_enemy.h" #include "a_doomglobal.h" @@ -19,7 +18,6 @@ #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_bossbrain.cpp" diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 6af969842c..17cd4df097 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -6,7 +6,6 @@ #include "p_local.h" #include "s_sound.h" #include "gstrings.h" -#include "vm.h" #include "p_enemy.h" #include "a_specialspot.h" #include "g_level.h" @@ -18,7 +17,6 @@ #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" diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 21227e8486..c87c9e46d3 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -7,7 +7,6 @@ #include "a_sharedglobal.h" #include "a_hexenglobal.h" #include "i_system.h" -#include "vm.h" #include "gi.h" #include "g_level.h" #include "p_enemy.h" @@ -24,7 +23,6 @@ #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_blastradius.cpp" diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index edd97a6d47..a371e4ad51 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -1,5 +1,4 @@ #include "actor.h" -#include "vm.h" #include "p_conversation.h" #include "p_lnspec.h" #include "a_action.h" diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 8ce23b68e6..c4b452f770 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -2,7 +2,6 @@ #include "info.h" #include "gi.h" #include "m_random.h" -#include "vm.h" static FRandom pr_orbit ("Orbit"); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 223a2f75f8..fbc5ea509d 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -14,7 +14,6 @@ #include "a_strifeglobal.h" #include "a_morph.h" #include "a_specialspot.h" -#include "vm.h" #include "g_level.h" #include "g_game.h" #include "doomstat.h" diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index 2b2c82956c..40fdd0745f 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -14,7 +14,6 @@ #include "statnums.h" #include "gstrings.h" #include "a_action.h" -#include "vm.h" #include "v_text.h" #include "doomstat.h" #include "doomdata.h" diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 92306ce6b7..c094ee8ba3 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -37,7 +37,6 @@ #include "p_local.h" #include "statnums.h" #include "i_system.h" -#include "vm.h" #include "doomstat.h" #include "serializer.h" #include "a_pickups.h" diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 2d159eb7d7..4a947cbee9 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -13,7 +13,6 @@ #include "cmdlib.h" #include "templates.h" #include "sbar.h" -#include "vm.h" #include "doomstat.h" #include "g_level.h" #include "d_net.h" diff --git a/src/info.cpp b/src/info.cpp index e771108c3a..8ef594d1bf 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -43,7 +43,6 @@ #include "v_text.h" #include "gi.h" -#include "vm.h" #include "actor.h" #include "r_state.h" #include "i_system.h" @@ -52,7 +51,6 @@ #include "cmdlib.h" #include "g_level.h" #include "stats.h" -#include "vm.h" #include "thingdef.h" #include "d_player.h" #include "doomerrors.h" diff --git a/src/info.h b/src/info.h index 0b7d4dfc3d..5af51f34b8 100644 --- a/src/info.h +++ b/src/info.h @@ -43,7 +43,6 @@ #include "dobject.h" #include "doomdef.h" -#include "vm.h" #include "s_sound.h" #include "m_fixed.h" diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 2d219fc387..37a2d533ed 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -61,7 +61,6 @@ #include "c_console.h" #include "doomerrors.h" #include "a_sharedglobal.h" -#include "vm.h" #include "v_video.h" #include "v_font.h" #include "doomstat.h" @@ -77,7 +76,6 @@ #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" diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 6bb96ef30c..db237e8bb2 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -43,7 +43,6 @@ #include "p_enemy.h" #include "a_sharedglobal.h" #include "a_action.h" -#include "vm.h" #include "d_dehacked.h" #include "g_level.h" #include "r_utility.h" @@ -53,7 +52,6 @@ #include "p_spec.h" #include "p_checkposition.h" #include "math/cmath.h" -#include "vm.h" #include "gi.h" diff --git a/src/p_enemy.h b/src/p_enemy.h index c4a966344b..a9aa40dc22 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -1,7 +1,7 @@ #ifndef __P_ENEMY_H__ #define __P_ENEMY_H__ -#include "vm.h" +#include "dobject.h" #include "vectors.h" struct sector_t; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 9c36e861cb..02c2a35788 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -53,7 +53,6 @@ #include "a_action.h" #include "a_keys.h" #include "p_conversation.h" -#include "vm.h" #include "g_game.h" #include "teaminfo.h" #include "r_data/r_translate.h" diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 5a76f0b550..1ba452b2b9 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -25,7 +25,6 @@ #include "gi.h" #include "p_pspr.h" #include "templates.h" -#include "vm.h" #include "g_level.h" #include "d_player.h" #include "serializer.h" diff --git a/src/p_pspr.h b/src/p_pspr.h index 3f819714c7..d75f08b067 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -25,7 +25,6 @@ // Basic data types. // Needs fixed point, and BAM angles. -//#include "vm.h" #define WEAPONBOTTOM 128. diff --git a/src/p_states.cpp b/src/p_states.cpp index ac7121f49a..a49d30af25 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -39,7 +39,6 @@ #include "i_system.h" #include "c_dispatch.h" #include "v_text.h" -#include "vm.h" #include "thingdef.h" // stores indices for symbolic state labels for some old-style DECORATE functions. diff --git a/src/p_user.cpp b/src/p_user.cpp index 8c8858b635..11fe487b9b 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -48,7 +48,6 @@ #include "doomdef.h" #include "c_dispatch.h" #include "tarray.h" -#include "vm.h" #include "g_level.h" #include "d_net.h" #include "gstrings.h" diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 5992dba04a..a2c2245580 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -6,7 +6,6 @@ #include "s_sound.h" #include "sc_man.h" #include "cmdlib.h" -#include "vm.h" class FScanner; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index ae867a975d..d82411d518 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -2,7 +2,6 @@ #define VM_H #include "zstring.h" -#include "dobject.h" #include "autosegs.h" #include "vectors.h" @@ -815,6 +814,12 @@ public: 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. + TArray SpecialInits; // list of all contents on the extra stack which require construction and destruction + + void InitExtra(void *addr); + void DestroyExtra(void *addr); + void SetExtraSpecial(PType *type, unsigned offset); + int AllocExtraStack(PType *type); }; class VMFrameStack @@ -822,7 +827,6 @@ class VMFrameStack public: VMFrameStack(); ~VMFrameStack(); - VMFrame *AllocFrame(int numregd, int numregf, int numregs, int numrega); VMFrame *AllocFrame(VMScriptFunction *func); VMFrame *PopFrame(); VMFrame *TopFrame() diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 5394dec32c..a5013dc57a 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -1,7 +1,7 @@ #ifndef VMUTIL_H #define VMUTIL_H -#include "vm.h" +#include "dobject.h" class VMFunctionBuilder { diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 49c929f053..48b6d168b2 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -31,7 +31,7 @@ ** */ -#include "vm.h" +#include "dobject.h" #include "c_console.h" #include "templates.h" diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 57ce48a95a..8f8559d93e 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -34,7 +34,7 @@ #include #include #include -#include "vm.h" +#include "dobject.h" #include "xs_Float.h" #include "math/cmath.h" diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 3a593861c1..e5a302606b 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -32,7 +32,7 @@ */ #include -#include "vm.h" +#include "dobject.h" IMPLEMENT_CLASS(VMException, false, false, false, false) IMPLEMENT_CLASS(VMFunction, true, true, false, false) @@ -162,6 +162,38 @@ size_t VMScriptFunction::PropagateMark() return NumKonstA * sizeof(void *) + Super::PropagateMark(); } +void VMScriptFunction::InitExtra(void *addr) +{ + char *caddr = (char*)addr; + + for (auto tao : SpecialInits) + { + tao.first->InitializeValue(caddr + tao.second, nullptr); + } +} + +void VMScriptFunction::DestroyExtra(void *addr) +{ + char *caddr = (char*)addr; + + for (auto tao : SpecialInits) + { + tao.first->DestroyValue(caddr + tao.second); + } +} + +void VMScriptFunction::SetExtraSpecial(PType *type, unsigned offset) +{ + type->SetDefaultValue(nullptr, offset, &SpecialInits); +} + +int VMScriptFunction::AllocExtraStack(PType *type) +{ + int address = ((ExtraSpace + type->Align - 1) / type->Align) * type->Align; + ExtraSpace = address + type->Size; + return address; +} + //=========================================================================== // // VMFrame :: InitRegS @@ -223,34 +255,6 @@ VMFrameStack::~VMFrameStack() UnusedBlocks = NULL; } -//=========================================================================== -// -// VMFrameStack :: AllocFrame -// -// Allocates a frame from the stack with the desired number of registers. -// -//=========================================================================== - -VMFrame *VMFrameStack::AllocFrame(int numregd, int numregf, int numregs, int numrega) -{ - assert((unsigned)numregd < 255); - assert((unsigned)numregf < 255); - assert((unsigned)numregs < 255); - assert((unsigned)numrega < 255); - // To keep the arguments to this function simpler, it assumes that every - // register might be used as a parameter for a single call. - int numparam = numregd + numregf + numregs + numrega; - int size = VMFrame::FrameSize(numregd, numregf, numregs, numrega, numparam, 0); - VMFrame *frame = Alloc(size); - frame->NumRegD = numregd; - frame->NumRegF = numregf; - frame->NumRegS = numregs; - frame->NumRegA = numrega; - frame->MaxParam = numparam; - frame->InitRegS(); - return frame; -} - //=========================================================================== // // VMFrameStack :: AllocFrame @@ -273,6 +277,10 @@ VMFrame *VMFrameStack::AllocFrame(VMScriptFunction *func) frame->MaxParam = func->MaxParam; frame->Func = func; frame->InitRegS(); + if (func->SpecialInits.Size()) + { + func->InitExtra(frame->GetExtra()); + } return frame; } @@ -358,6 +366,11 @@ VMFrame *VMFrameStack::PopFrame() { return NULL; } + auto Func = static_cast(frame->Func); + if (Func->SpecialInits.Size()) + { + Func->DestroyExtra(frame->GetExtra()); + } // Free any string registers this frame had. FString *regs = frame->GetRegS(); for (int i = frame->NumRegS; i != 0; --i) From 2cc48ec378e438eaba6f79a78be90b2cc1585482 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 16:44:41 +0100 Subject: [PATCH 277/471] - implemented code generation for stack variables. - fixed code generation for using local variables as array index. This must use a different register for the array element offset because the original register may not be overwritten. --- src/p_mobj.cpp | 7 + src/scripting/codegeneration/codegen.cpp | 292 ++++++++++++++++++----- src/scripting/codegeneration/codegen.h | 35 ++- src/scripting/vm/vm.h | 2 +- src/scripting/vm/vmbuilder.cpp | 7 + src/scripting/vm/vmbuilder.h | 16 ++ src/scripting/vm/vmframe.cpp | 6 +- src/scripting/zscript/zcc_compile.cpp | 40 ++-- wadsrc/static/zscript/actor.txt | 1 + 9 files changed, 310 insertions(+), 96 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 02c2a35788..8029e24c03 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6829,6 +6829,13 @@ const char *AActor::GetTag(const char *def) const } } +DEFINE_ACTION_FUNCTION(AActor, GetTag) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(def); + ACTION_RETURN_STRING(self->GetTag(def.Len() == 0? nullptr : def.GetChars())); +} + void AActor::SetTag(const char *def) { if (def == NULL || *def == 0) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 44d7cda889..c522b2145d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5084,9 +5084,18 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) FxLocalVariableDeclaration *local = ctx.FindLocalVariable(Identifier); if (local != nullptr) { - auto x = new FxLocalVariable(local, ScriptPosition); - delete this; - return x->Resolve(ctx); + if (local->ValueType->GetRegType() != REGT_NIL) + { + auto x = new FxLocalVariable(local, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + else + { + auto x = new FxStackVariable(local->ValueType, local->StackOffset, ScriptPosition); + delete this; + return x->Resolve(ctx); + } } if (Identifier == NAME_Default) @@ -5584,6 +5593,106 @@ ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos) + : FxExpression(EFX_StackVariable, pos) +{ + membervar = new PField(NAME_None, type, 0, offset); + AddressRequested = false; + AddressWritable = true; // must be true unless classx tells us otherwise if requested. +} + +//========================================================================== +// +// force delete the PField because we know we won't need it anymore +// and it won't get GC'd until the compiler finishes. +// +//========================================================================== + +FxStackVariable::~FxStackVariable() +{ + // Q: Is this good or bad? Needs testing if this is fine or better left to the GC anyway. DObject's destructor is anything but cheap. + membervar->ObjectFlags |= OF_YesReallyDelete; + delete membervar; +} + +//========================================================================== +// +// +//========================================================================== + +void FxStackVariable::ReplaceField(PField *newfield) +{ + membervar->ObjectFlags |= OF_YesReallyDelete; + delete membervar; + membervar = newfield; +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FxStackVariable::RequestAddress(FCompileContext &ctx, bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = AddressWritable && !ctx.CheckReadOnly(membervar->Flags); + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxStackVariable::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + ValueType = membervar->Type; + return this; +} + +ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) +{ + int offsetreg = -1; + + if (membervar->Offset != 0) offsetreg = build->GetConstantInt((int)membervar->Offset); + + if (AddressRequested) + { + ExpEmit obj(build, REGT_POINTER); + if (offsetreg >= 0) + { + build->Emit(OP_ADDA_RK, obj.RegNum, build->FramePointer.RegNum, offsetreg); + return obj; + } + else return build->FramePointer; + } + ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); + + if (membervar->BitValue == -1) + { + if (offsetreg == -1) offsetreg = build->GetConstantInt(0); + build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, build->FramePointer.RegNum, offsetreg); + } + else + { + ExpEmit obj(build, REGT_POINTER); + if (offsetreg >= 0) build->Emit(OP_ADDA_RK, obj.RegNum, build->FramePointer.RegNum, offsetreg); + obj.Free(build); + build->Emit(OP_LBIT, loc.RegNum, obj.RegNum, 1 << membervar->BitValue); + } + return loc; +} + + //========================================================================== // // @@ -5684,6 +5793,16 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) classx = nullptr; return x; } + else if (classx->ExprType == EFX_StackVariable) + { + 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)->ReplaceField(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. @@ -5831,7 +5950,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) return nullptr; } } - if (index->ValueType->GetRegType() != REGT_INT && index->ValueType != TypeName) + if (!index->IsInteger()) { ScriptPosition.Message(MSG_ERROR, "Array index must be integer"); delete this; @@ -5854,16 +5973,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) delete this; return nullptr; } + // Todo: optimize out the array. } 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."); @@ -5902,7 +6015,18 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) { if (indexval != 0) { - build->Emit(OP_ADDA_RK, start.RegNum, start.RegNum, build->GetConstantInt(indexval)); + if (!start.Fixed) + { + build->Emit(OP_ADDA_RK, start.RegNum, start.RegNum, build->GetConstantInt(indexval)); + } + else + { + // do not clobber local variables. + ExpEmit temp(build, start.RegType); + build->Emit(OP_ADDA_RK, temp.RegNum, start.RegNum, build->GetConstantInt(indexval)); + start.Free(build); + start = temp; + } } } else @@ -5915,21 +6039,40 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) { ExpEmit indexv(index->Emit(build)); ExpEmit indexwork = indexv.Fixed ? ExpEmit(build, indexv.RegType) : indexv; + build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); + 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) + if (1u << shiftbits == arraytype->ElementSize) { - build->Emit(OP_SLL_RI, indexwork.RegNum, indexv.RegNum, shiftbits); + if (shiftbits > 0) + { + build->Emit(OP_SLL_RI, indexwork.RegNum, indexv.RegNum, shiftbits); + } + } + else + { + // A shift won't do, so use a multiplication + build->Emit(OP_MUL_RK, indexwork.RegNum, indexv.RegNum, build->GetConstantInt(arraytype->ElementSize)); } if (AddressRequested) { - build->Emit(OP_ADDA_RR, start.RegNum, start.RegNum, indexwork.RegNum); + if (!start.Fixed) + { + build->Emit(OP_ADDA_RR, start.RegNum, start.RegNum, indexwork.RegNum); + } + else + { + // do not clobber local variables. + ExpEmit temp(build, start.RegType); + build->Emit(OP_ADDA_RR, temp.RegNum, start.RegNum, indexwork.RegNum); + start.Free(build); + start = temp; + } } else { @@ -8413,7 +8556,7 @@ FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, VarFlags = varflags; Name = name; RegCount = type == TypeVector2 ? 2 : type == TypeVector3 ? 3 : 1; - Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false); + Init = initval; } FxLocalVariableDeclaration::~FxLocalVariableDeclaration() @@ -8424,75 +8567,96 @@ FxLocalVariableDeclaration::~FxLocalVariableDeclaration() 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; } + if (ValueType->RegType == REGT_NIL) + { + auto sfunc = static_cast(ctx.Function->Variants[0].Implementation); + StackOffset = sfunc->AllocExtraStack(ValueType); + // Todo: Process the compound initializer once implemented. + } + else + { + if (Init) Init = new FxTypeCast(Init, ValueType, false); + SAFE_RESOLVE_OPT(Init, ctx); + } ctx.Block->LocalVars.Push(this); return this; } ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) { - if (Init == nullptr) + if (ValueType->RegType != REGT_NIL) { - RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); - } - else - { - ExpEmit emitval = Init->Emit(build); - - int regtype = emitval.RegType; - if (regtype < REGT_INT || regtype > REGT_TYPE) + if (Init == nullptr) { - 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; + RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); } else { - ExpEmit out(build, emitval.RegType, emitval.RegCount); - build->Emit(ValueType->GetMoveOp(), out.RegNum, emitval.RegNum); - RegNum = out.RegNum; + 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; + } } } + else + { + // Init arrays and structs. + } 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); + if(RegNum != -1) + { + build->Registers[ValueType->GetRegType()].Return(RegNum, RegCount); + } + // Stack space will not be released because that would make controlled destruction impossible. + // For that all local stack variables need to live for the entire execution of a function. } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index f1778512f4..84ddfcdd81 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -44,6 +44,7 @@ #include "sc_man.h" #include "s_sound.h" #include "actor.h" +#include "vmbuilder.h" #define CHECKRESOLVED() if (isresolved) return this; isresolved=true; @@ -202,17 +203,6 @@ struct ExpVal } }; -struct ExpEmit -{ - 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, RegCount, Konst:1, Fixed:1, Final:1, Target:1; -}; - enum EFxType { EFX_Expression, @@ -282,6 +272,7 @@ enum EFxType EFX_DynamicCast, EFX_GlobalVariable, EFX_Super, + EFX_StackVariable, EFX_COUNT }; @@ -1234,6 +1225,27 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxLocalVariable +// +//========================================================================== + +class FxStackVariable : public FxExpression +{ +public: + PField *membervar; + bool AddressRequested; + bool AddressWritable; + + FxStackVariable(PType *type, int offset, const FScriptPosition&); + ~FxStackVariable(); + void ReplaceField(PField *newfield); + FxExpression *Resolve(FCompileContext&); + bool RequestAddress(FCompileContext &ctx, bool *writable); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxSelf @@ -1746,6 +1758,7 @@ class FxLocalVariableDeclaration : public FxExpression int VarFlags; int RegCount; public: + int StackOffset = -1; int RegNum = -1; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index d82411d518..c9f75f2144 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -818,7 +818,6 @@ public: void InitExtra(void *addr); void DestroyExtra(void *addr); - void SetExtraSpecial(PType *type, unsigned offset); int AllocExtraStack(PType *type); }; @@ -1047,6 +1046,7 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); #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) +#define ACTION_RETURN_STRING(v) do { FString u = v; if (numret > 0) { assert(ret != NULL); ret->SetString(u); return 1; } return 0; } while(0) // Checks to see what called the current action function #define ACTION_CALL_FROM_ACTOR() (stateinfo == nullptr || stateinfo->mStateType == STATE_Actor) diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 19d89fc6f6..721ff5fab7 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -718,6 +718,13 @@ void FFunctionBuildList::Build() FScriptPosition::StrictErrors = !item.FromDecorate; item.Code = item.Code->Resolve(ctx); + // If we need extra space, load the frame pointer into a register so that we do not have to call the wasteful LFP instruction more than once. + if (item.Function->ExtraSpace > 0) + { + buildit.FramePointer = ExpEmit(&buildit, REGT_POINTER); + buildit.FramePointer.Fixed = true; + buildit.Emit(OP_LFP, buildit.FramePointer.RegNum); + } // Make sure resolving it didn't obliterate it. if (item.Code != nullptr) diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index a5013dc57a..d69c97707f 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -3,6 +3,19 @@ #include "dobject.h" +class VMFunctionBuilder; + +struct ExpEmit +{ + 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, RegCount, Konst:1, Fixed : 1, Final : 1, Target : 1; +}; + class VMFunctionBuilder { public: @@ -63,6 +76,9 @@ public: // amount of implicit parameters so that proper code can be emitted for method calls int NumImplicits; + // keep the frame pointer, if needed, in a register because the LFP opcode is hideously inefficient, requiring more than 20 instructions on x64. + ExpEmit FramePointer; + private: struct AddrKonst { diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index e5a302606b..b20c8ac898 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -182,15 +182,11 @@ void VMScriptFunction::DestroyExtra(void *addr) } } -void VMScriptFunction::SetExtraSpecial(PType *type, unsigned offset) -{ - type->SetDefaultValue(nullptr, offset, &SpecialInits); -} - int VMScriptFunction::AllocExtraStack(PType *type) { int address = ((ExtraSpace + type->Align - 1) / type->Align) * type->Align; ExtraSpace = address + type->Size; + type->SetDefaultValue(nullptr, address, &SpecialInits); return address; } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index aec8f5853e..596b7d8c4d 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2970,29 +2970,39 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) auto loc = static_cast(ast); auto node = loc->Vars; FxSequence *list = new FxSequence(*ast); + + PType *ztype = DetermineType(ConvertClass, node, node->Name, loc->Type, true, false); + + if (loc->Type->ArraySize != nullptr) + { + ztype = ResolveArraySize(ztype, loc->Type->ArraySize, &ConvertClass->Symbols); + } + 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))) + PType *type; + + if (node->ArraySize != nullptr) { - Error(loc, "Local array variables not implemented yet."); + type = ResolveArraySize(ztype, node->ArraySize, &ConvertClass->Symbols); } 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. + type = ztype; } + FxExpression *val; + if (node->InitIsArray) + { + Error(node, "Compound initializer not implemented yet"); + 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; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index f20a0b19ec..043ab3ed49 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -66,6 +66,7 @@ class Actor : Thinker native native static float absangle(float ang1, float ang2); native static float GetDefaultSpeed(class type); native void RemoveFromHash(); + native string GetTag(string defstr = ""); native float GetBobOffset(float frac = 0); native void SetDamage(int dmg); native static bool isDehState(state st); From 8205e6cf08a05be474eafdde302570873567c622 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 18:06:56 +0100 Subject: [PATCH 278/471] - optimize access to array members with constant index. Like with struct members this can be combined with the outer index/address. - fixed register allocation with array indices and stack variables. --- src/scripting/codegeneration/codegen.cpp | 69 +++++++++++++++++------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c522b2145d..f7eadbe909 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5667,13 +5667,16 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) if (AddressRequested) { - ExpEmit obj(build, REGT_POINTER); if (offsetreg >= 0) { + ExpEmit obj(build, REGT_POINTER); build->Emit(OP_ADDA_RK, obj.RegNum, build->FramePointer.RegNum, offsetreg); return obj; } - else return build->FramePointer; + else + { + return build->FramePointer; + } } ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); @@ -5973,7 +5976,39 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) delete this; return nullptr; } - // Todo: optimize out the array. + + // if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. + if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember) + { + auto parentfield = static_cast(Array)->membervar; + // PFields are garbage collected so this will be automatically taken care of later. + auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); + static_cast(Array)->membervar = newfield; + Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. + auto x = Array->Resolve(ctx); + Array = nullptr; + return x; + } + else if (Array->ExprType == EFX_GlobalVariable) + { + auto parentfield = static_cast(Array)->membervar; + auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); + static_cast(Array)->membervar = newfield; + Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. + auto x = Array->Resolve(ctx); + Array = nullptr; + return x; + } + else if (Array->ExprType == EFX_StackVariable) + { + auto parentfield = static_cast(Array)->membervar; + auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); + static_cast(Array)->ReplaceField(newfield); + Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. + auto x = Array->Resolve(ctx); + Array = nullptr; + return x; + } } ValueType = arraytype->ElementType; @@ -5996,7 +6031,6 @@ 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) { @@ -6028,11 +6062,14 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) start = temp; } } + return start; } else { - build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum, - start.RegNum, build->GetConstantInt(indexval)); + start.Free(build); + ExpEmit dest(build, ValueType->GetRegType()); + build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum, start.RegNum, build->GetConstantInt(indexval)); + return dest; } } else @@ -6059,6 +6096,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) build->Emit(OP_MUL_RK, indexwork.RegNum, indexv.RegNum, build->GetConstantInt(arraytype->ElementSize)); } + indexwork.Free(build); if (AddressRequested) { if (!start.Fixed) @@ -6067,28 +6105,23 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) } else { + start.Free(build); // do not clobber local variables. ExpEmit temp(build, start.RegType); build->Emit(OP_ADDA_RR, temp.RegNum, start.RegNum, indexwork.RegNum); - start.Free(build); start = temp; } + return start; } else { - build->Emit(arraytype->ElementType->GetLoadOp() + 1, // added 1 to use the *_R version that - dest.RegNum, start.RegNum, indexwork.RegNum); // takes the offset from a register + start.Free(build); + ExpEmit dest(build, ValueType->GetRegType()); + // added 1 to use the *_R version that takes the offset from a register + build->Emit(arraytype->ElementType->GetLoadOp() + 1, dest.RegNum, start.RegNum, indexwork.RegNum); + return dest; } - indexwork.Free(build); } - if (AddressRequested) - { - dest.Free(build); - return start; - } - - start.Free(build); - return dest; } //========================================================================== From 022228d8a94e295a16a39051a4ed1b342c6c18ef Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 19:30:30 +0100 Subject: [PATCH 279/471] - fixed code generation of class type cast for local variables. --- src/scripting/codegeneration/codegen.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f7eadbe909..0c559e8501 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3884,7 +3884,6 @@ int BuiltinTypeCheck(VMFrameStack *stack, VMValue *param, TArray &defau ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build) { - ExpEmit out(build, REGT_INT); EmitParameter(build, left, ScriptPosition); EmitParameter(build, right, ScriptPosition); @@ -3905,6 +3904,7 @@ ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build) return call; } + ExpEmit out(build, REGT_INT); build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); return out; } @@ -3963,11 +3963,13 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx) ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build) { - ExpEmit out = expr->Emit(build); + ExpEmit in = expr->Emit(build); + ExpEmit out = in.Fixed ? ExpEmit(build, in.RegType) : in; ExpEmit check(build, REGT_INT); assert(out.RegType == REGT_POINTER); - build->Emit(OP_PARAM, 0, REGT_POINTER, out.RegNum); + if (in.Fixed) build->Emit(OP_MOVEA, out.RegNum, in.RegNum); + build->Emit(OP_PARAM, 0, REGT_POINTER, in.RegNum); build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(CastType, ATAG_OBJECT)); PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck); From 3bcd85eb8a08d407ff28be24578b34fec763fd26 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 20:31:53 +0100 Subject: [PATCH 280/471] added class pointer casts. Due to grammar problems the type has to be put into parentheses to get the class token out of the global parsing namespace: class myclass = (class)(GetClass()); --- src/namedef.h | 1 + src/scripting/codegeneration/codegen.cpp | 101 +++++++++++++++++++++++ src/scripting/codegeneration/codegen.h | 20 +++++ src/scripting/zscript/ast.cpp | 11 +++ src/scripting/zscript/zcc-parse.lemon | 8 ++ src/scripting/zscript/zcc_compile.cpp | 18 ++++ src/scripting/zscript/zcc_exprlist.h | 1 + src/scripting/zscript/zcc_parser.h | 7 ++ 8 files changed, 167 insertions(+) diff --git a/src/namedef.h b/src/namedef.h index e9324d44b3..01859d01a8 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -683,6 +683,7 @@ xx(BuiltinFindMultiNameState) xx(BuiltinFindSingleNameState) xx(BuiltinHandleRuntimeState) xx(BuiltinGetDefault) +xx(BuiltinClassCast) xx(Damage) // basic type names diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 0c559e8501..d63db0f8d1 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -8382,6 +8382,107 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) return dest; } +//========================================================================== +// +//========================================================================== + +FxClassPtrCast::FxClassPtrCast(PClass *dtype, FxExpression *x) + : FxExpression(EFX_ClassPtrCast, x->ScriptPosition) +{ + ValueType = NewClassPointer(dtype); + desttype = dtype; + basex = x; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxClassPtrCast::~FxClassPtrCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxClassPtrCast::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); + // Downcast is always ok. + if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction)) + { + basex->ValueType = to; + auto x = basex; + basex = nullptr; + delete this; + return x; + } + // Upcast needs a runtime check. + else if (to->ClassRestriction->IsDescendantOf(from->ClassRestriction)) + { + return this; + } + } + // Everything else is an error. + ScriptPosition.Message(MSG_ERROR, "Cannot cast %s to %s. The types are incompatible.", basex->ValueType->DescriptiveName(), to->DescriptiveName()); + delete this; + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +int BuiltinClassCast(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +{ + PARAM_PROLOGUE; + PARAM_CLASS(from, DObject); + PARAM_CLASS(to, DObject); + ACTION_RETURN_OBJECT(from->IsDescendantOf(to) ? from : nullptr); +} + +ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build) +{ + ExpEmit clsname = basex->Emit(build); + + build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype, ATAG_OBJECT)); + + VMFunction *callfunc; + PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast); + + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); + assert(((PSymbolVMFunction *)sym)->Function != nullptr); + callfunc = ((PSymbolVMFunction *)sym)->Function; + clsname.Free(build); + ExpEmit dest(build, REGT_POINTER); + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); + build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); + return dest; +} + //========================================================================== // // Symbolic state labels. diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 84ddfcdd81..0ec3491bbb 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -258,6 +258,7 @@ enum EFxType EFX_JumpStatement, EFX_ReturnStatement, EFX_ClassTypeCast, + EFX_ClassPtrCast, EFX_StateByIndex, EFX_RuntimeStateIndex, EFX_MultiNameState, @@ -1668,6 +1669,25 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxClassPtrCast : public FxExpression +{ + PClass *desttype; + FxExpression *basex; + +public: + + FxClassPtrCast(PClass *dtype, FxExpression *x); + ~FxClassPtrCast(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // Only used to resolve the old jump by index feature of DECORATE diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index 89cc9487e3..d8945ca3b0 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -585,6 +585,16 @@ static void PrintExprFuncCall(FLispString &out, ZCC_TreeNode *node) out.Close(); } +static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node) +{ + ZCC_ClassCast *enode = (ZCC_ClassCast *)node; + assert(enode->Operation == PEX_ClassCast); + out.Open("expr-class-cast"); + out.AddName(enode->ClassName); + PrintNodes(out, enode->Parameters, false); + out.Close(); +} + static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node) { ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node; @@ -913,6 +923,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintPropertyStmt, PrintVectorInitializer, PrintDeclFlags, + PrintExprClassCast, }; FString ZCC_PrintAST(ZCC_TreeNode *root) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index f152cfdd58..c88cab481c 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -1080,6 +1080,14 @@ primary(X) ::= primary(A) LPAREN func_expr_list(B) RPAREN. [DOT] // Function ca expr->Parameters = B; X = expr; } +primary(X) ::= LPAREN CLASS LT IDENTIFIER(A) GT RPAREN LPAREN func_expr_list(B) RPAREN. [DOT] // class type cast +{ + NEW_AST_NODE(ClassCast, expr, A); + expr->Operation = PEX_ClassCast; + expr->ClassName = ENamedName(A.Int); + expr->Parameters = B; + X = expr; +} primary(X) ::= primary(A) LBRACKET expr(B) RBRACKET. [DOT] // Array access { NEW_AST_NODE(ExprBinary, expr, B); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 596b7d8c4d..baf76027ba 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2766,6 +2766,24 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) break; } + case AST_ClassCast: + { + auto cc = static_cast(ast); + if (cc->Parameters == nullptr || cc->Parameters->SiblingNext != cc->Parameters) + { + Error(cc, "Class type cast requires exactly one parameter"); + return new FxNop(*ast); // return something so that the compiler can continue. + } + auto cls = PClass::FindClass(cc->ClassName); + if (cls == nullptr) + { + Error(cc, "Unknown class %s", FName(cc->ClassName).GetChars()); + return new FxNop(*ast); // return something so that the compiler can continue. + } + return new FxClassPtrCast(cls, ConvertNode(cc->Parameters)); + } + + case AST_ExprMemberAccess: { auto memaccess = static_cast(ast); diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index b565c00fb2..faf6af6a43 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -8,6 +8,7 @@ xx(ConstValue, TK_Const) xx(FuncCall, '(') xx(ArrayAccess, TK_Array) xx(MemberAccess, '.') +xx(ClassCast, TK_Class) xx(TypeRef, TK_Class) xx(Vector, TK_Vector2) diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index ffff78cb83..070bef449d 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -102,6 +102,7 @@ enum EZCCTreeNodeType AST_PropertyStmt, AST_VectorValue, AST_DeclFlags, + AST_ClassCast, NUM_AST_NODE_TYPES }; @@ -366,6 +367,12 @@ struct ZCC_ExprFuncCall : ZCC_Expression ZCC_FuncParm *Parameters; }; +struct ZCC_ClassCast : ZCC_Expression +{ + ENamedName ClassName; + ZCC_FuncParm *Parameters; +}; + struct ZCC_ExprMemberAccess : ZCC_Expression { ZCC_Expression *Left; From e4dfb13d25cdbcaa4ba1de3b9e7952aa4261bd5d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 20:41:59 +0100 Subject: [PATCH 281/471] - fixed: OP_LO was missing a read barrier. --- src/scripting/vm/vmexec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index fcdb2eb8b8..6cc0d40cd1 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -175,7 +175,7 @@ begin: OP(LO): ASSERTA(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); - reg.a[a] = *(DObject **)ptr; + reg.a[a] = GC::ReadBarrier(*(DObject **)ptr); reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(LO_R): From 6461f5995b684c0232520538fcb40880a9566ef5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 22:21:08 +0100 Subject: [PATCH 282/471] - fixed: Script defined pointers were not added to the FlatPointers array. --- src/dobjtype.cpp | 105 ++++++++++++++++++++++++++++++++++++++++------- src/dobjtype.h | 7 ++++ 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 1597494d95..609fed8c1f 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -419,6 +419,16 @@ void PType::SetDefaultValue(void *base, unsigned offset, TArray { } +//========================================================================== +// +// PType :: SetDefaultValue +// +//========================================================================== + +void PType::SetPointer(void *base, unsigned offset, TArray *stroffs) const +{ +} + //========================================================================== // // PType :: InitializeValue @@ -1550,6 +1560,21 @@ void PPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = 0; } +//========================================================================== +// +// PPointer :: SetDefaultValue +// +//========================================================================== + +void PPointer::SetPointer(void *base, unsigned offset, TArray *special) const +{ + if (PointedType != nullptr && PointedType->IsKindOf(RUNTIME_CLASS(PClass))) + { + // Add to the list of pointers for this class. + special->Push(offset); + } +} + //========================================================================== // // PPointer :: WriteValue @@ -1869,6 +1894,20 @@ void PArray::SetDefaultValue(void *base, unsigned offset, TArray } } +//========================================================================== +// +// PArray :: SetDefaultValue +// +//========================================================================== + +void PArray::SetPointer(void *base, unsigned offset, TArray *special) const +{ + for (unsigned i = 0; i < ElementCount; ++i) + { + ElementType->SetPointer(base, offset + i*ElementSize, special); + } +} + //========================================================================== // // NewArray @@ -2104,6 +2143,23 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArray *special) const +{ + for (const PField *field : Fields) + { + if (!(field->Flags & VARF_Native)) + { + field->Type->SetPointer(base, unsigned(offset + field->Offset), special); + } + } +} + //========================================================================== // // PStruct :: WriteValue @@ -3045,14 +3101,9 @@ void PClass::InitializeDefaults() assert(ParentClass != NULL); ParentClass->InitializeSpecials(Defaults); - // and initialize our own special values. - auto it = Symbols.GetIterator(); - PSymbolTable::MapType::Pair *pair; - - while (it.NextPair(pair)) + for (const PField *field : Fields) { - auto field = dyn_cast(pair->Value); - if (field != nullptr && !(field->Flags & VARF_Native)) + if (!(field->Flags & VARF_Native)) { field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } @@ -3270,7 +3321,7 @@ void PClass::BuildFlatPointers () return; } else if (ParentClass == NULL) - { // No parent: FlatPointers is the same as Pointers. + { // No parent (i.e. DObject: FlatPointers is the same as Pointers. if (Pointers == NULL) { // No pointers: Make FlatPointers a harmless non-NULL. FlatPointers = &TheEnd; @@ -3283,7 +3334,19 @@ void PClass::BuildFlatPointers () else { ParentClass->BuildFlatPointers (); - if (Pointers == NULL) + + TArray ScriptPointers; + + // Collect all pointers in scripted fields. These are not part of the Pointers list. + for (auto field : Fields) + { + if (!(field->Flags & VARF_Native)) + { + field->Type->SetPointer(Defaults, unsigned(field->Offset), &ScriptPointers); + } + } + + if (Pointers == nullptr && ScriptPointers.Size() == 0) { // No new pointers: Just use the same FlatPointers as the parent. FlatPointers = ParentClass->FlatPointers; } @@ -3291,20 +3354,34 @@ void PClass::BuildFlatPointers () { // New pointers: Create a new FlatPointers array and add them. int numPointers, numSuperPointers; - // Count pointers defined by this class. - for (numPointers = 0; Pointers[numPointers] != ~(size_t)0; numPointers++) - { } + if (Pointers != nullptr) + { + // Count pointers defined by this class. + for (numPointers = 0; Pointers[numPointers] != ~(size_t)0; numPointers++) + { + } + } + else numPointers = 0; + // Count pointers defined by superclasses. for (numSuperPointers = 0; ParentClass->FlatPointers[numSuperPointers] != ~(size_t)0; numSuperPointers++) { } // Concatenate them into a new array - size_t *flat = new size_t[numPointers + numSuperPointers + 1]; + size_t *flat = new size_t[numPointers + numSuperPointers + ScriptPointers.Size() + 1]; if (numSuperPointers > 0) { memcpy (flat, ParentClass->FlatPointers, sizeof(size_t)*numSuperPointers); } - memcpy (flat + numSuperPointers, Pointers, sizeof(size_t)*(numPointers+1)); + if (numPointers > 0) + { + memcpy(flat + numSuperPointers, Pointers, sizeof(size_t)*numPointers); + } + if (ScriptPointers.Size() > 0) + { + memcpy(flat + numSuperPointers + numPointers, &ScriptPointers[0], sizeof(size_t) * ScriptPointers.Size()); + } + flat[numSuperPointers + numPointers + ScriptPointers.Size()] = ~(size_t)0; FlatPointers = flat; } } diff --git a/src/dobjtype.h b/src/dobjtype.h index 0062c56ab7..bf4608c7b5 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -252,6 +252,7 @@ public: // initialization when the object is created and destruction when the // object is destroyed. virtual void SetDefaultValue(void *base, unsigned offset, TArray *special=NULL) const; + virtual void SetPointer(void *base, unsigned offset, TArray *ptrofs = NULL) const; // Initialize the value, if needed (e.g. strings) virtual void InitializeValue(void *addr, const void *def) const; @@ -552,6 +553,7 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + void SetPointer(void *base, unsigned offset, TArray *special = NULL) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; @@ -569,6 +571,9 @@ public: class PClass *ClassRestriction; + // this is only here to block PPointer's implementation + void SetPointer(void *base, unsigned offset, TArray *special = NULL) const override {} + virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; protected: @@ -626,6 +631,7 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *special) const override; + void SetPointer(void *base, unsigned offset, TArray *special) const override; protected: PArray(); @@ -679,6 +685,7 @@ public: 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 *specials) const override; + void SetPointer(void *base, unsigned offset, TArray *specials) const override; static void WriteFields(FSerializer &ar, const void *addr, const TArray &fields); bool ReadFields(FSerializer &ar, void *addr) const; From 8650d6806ee348b4382b67cbacf8d696223ac642 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 00:42:04 +0100 Subject: [PATCH 283/471] - script export of player_t. - replaced __alignof with the standard alignof equivalent. --- src/dobjtype.cpp | 22 +++---- src/p_mobj.cpp | 5 +- src/p_user.cpp | 113 ++++++++++++++++++++++++++++++++ src/scripting/thingdef_data.cpp | 2 + 4 files changed, 128 insertions(+), 14 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 609fed8c1f..32fd30c679 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1223,7 +1223,7 @@ IMPLEMENT_CLASS(PString, false, false, false, false) //========================================================================== PString::PString() -: PBasicType(sizeof(FString), __alignof(FString)) +: PBasicType(sizeof(FString), alignof(FString)) { mDescriptiveName = "String"; storeOp = OP_SS; @@ -1323,7 +1323,7 @@ PName::PName() : PInt(sizeof(FName), true, false) { mDescriptiveName = "Name"; - assert(sizeof(FName) == __alignof(FName)); + assert(sizeof(FName) == alignof(FName)); } //========================================================================== @@ -1373,7 +1373,7 @@ PSound::PSound() : PInt(sizeof(FSoundID), true) { mDescriptiveName = "Sound"; - assert(sizeof(FSoundID) == __alignof(FSoundID)); + assert(sizeof(FSoundID) == alignof(FSoundID)); } //========================================================================== @@ -1423,7 +1423,7 @@ PColor::PColor() : PInt(sizeof(PalEntry), true) { mDescriptiveName = "Color"; - assert(sizeof(PalEntry) == __alignof(PalEntry)); + assert(sizeof(PalEntry) == alignof(PalEntry)); } /* PStateLabel *****************************************************************/ @@ -1453,7 +1453,7 @@ IMPLEMENT_CLASS(PStatePointer, false, false, false, false) //========================================================================== PStatePointer::PStatePointer() -: PBasicType(sizeof(FState *), __alignof(FState *)) +: PBasicType(sizeof(FState *), alignof(FState *)) { mDescriptiveName = "State"; storeOp = OP_SP; @@ -1501,7 +1501,7 @@ IMPLEMENT_POINTERS_END //========================================================================== PPointer::PPointer() -: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL), IsConst(false) +: PBasicType(sizeof(void *), alignof(void *)), PointedType(NULL), IsConst(false) { mDescriptiveName = "NullPointer"; SetOps(); @@ -1514,7 +1514,7 @@ PPointer::PPointer() //========================================================================== PPointer::PPointer(PType *pointsat, bool isconst) -: PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat), IsConst(isconst) +: PBasicType(sizeof(void *), alignof(void *)), PointedType(pointsat), IsConst(isconst) { mDescriptiveName.Format("Pointer<%s%s>", pointsat->DescriptiveName(), isconst? "readonly " : ""); SetOps(); @@ -1948,7 +1948,7 @@ PDynArray::PDynArray() { mDescriptiveName = "DynArray"; Size = sizeof(FArray); - Align = __alignof(FArray); + Align = alignof(FArray); } //========================================================================== @@ -1962,7 +1962,7 @@ PDynArray::PDynArray(PType *etype) { mDescriptiveName.Format("DynArray<%s>", etype->DescriptiveName()); Size = sizeof(FArray); - Align = __alignof(FArray); + Align = alignof(FArray); } //========================================================================== @@ -2032,7 +2032,7 @@ PMap::PMap() { mDescriptiveName = "Map"; Size = sizeof(FMap); - Align = __alignof(FMap); + Align = alignof(FMap); } //========================================================================== @@ -2046,7 +2046,7 @@ PMap::PMap(PType *keytype, PType *valtype) { mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName()); Size = sizeof(FMap); - Align = __alignof(FMap); + Align = alignof(FMap); } //========================================================================== diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 8029e24c03..59b4c43e96 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -158,12 +158,11 @@ 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 *TypePlayer = NewPointer(NewStruct("Player", nullptr)); + auto TypeSector = NewPointer(NewStruct("Sector", nullptr)); PType *array5 = NewArray(TypeSInt32, 5); auto meta = RUNTIME_CLASS(AActor); diff --git a/src/p_user.cpp b/src/p_user.cpp index 11fe487b9b..00e58e5ef1 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3119,3 +3119,116 @@ bool P_IsPlayerTotallyFrozen(const player_t *player) player->cheats & CF_TOTALLYFROZEN || ((level.flags2 & LEVEL2_FROZEN) && player->timefreezer == 0); } + + +//========================================================================== +// +// sets up the script-side version of players +// Since this is a global variable and the script compiler does +// not allow defining them, it will be fully set up here. +// +//========================================================================== + +void P_InitPlayerForScript() +{ + PStruct *pstruct = NewStruct("Player", nullptr); + pstruct->Size = sizeof(player_t); + pstruct->Align = alignof(player_t); + PArray *parray = NewArray(pstruct, MAXPLAYERS); + pstruct->Size = 0; // make sure it cannot be instantiated in the script. + PField *playerf = new PField("players", pstruct, VARF_Native | VARF_Static, (intptr_t)&players); + GlobalSymbols.AddSymbol(playerf); + + PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); + PType *TypePlayerPawn = NewPointer(RUNTIME_CLASS(APlayerPawn)); + PType *TypeWeapon = NewPointer(RUNTIME_CLASS(AWeapon)); + PType *TypeClassActor = NewClassPointer(RUNTIME_CLASS(AActor)); + PType *TypeClassPlayerPawn = NewClassPointer(RUNTIME_CLASS(APlayerPawn)); + PType *TypeClassWeapon = NewClassPointer(RUNTIME_CLASS(AWeapon)); + + //ticcmd_t cmd; + //usercmd_t original_cmd; + //userinfo_t userinfo; // [RH] who is this? + //FWeaponSlots weapons; + pstruct->AddNativeField("mo", TypePlayerPawn, myoffsetof(player_t, mo), VARF_ReadOnly); + pstruct->AddNativeField("playerstate", TypeUInt8, myoffsetof(player_t, playerstate)); + pstruct->AddNativeField("original_oldbuttons", TypeUInt32, myoffsetof(player_t, original_oldbuttons)); + pstruct->AddNativeField("cls", TypeClassPlayerPawn, myoffsetof(player_t, cls), VARF_ReadOnly); + pstruct->AddNativeField("DesiredFOV", TypeFloat32, myoffsetof(player_t, DesiredFOV)); + pstruct->AddNativeField("FOV", TypeFloat32, myoffsetof(player_t, FOV), VARF_ReadOnly); + pstruct->AddNativeField("viewz", TypeFloat64, myoffsetof(player_t, viewz)); + pstruct->AddNativeField("viewheight", TypeFloat64, myoffsetof(player_t, viewheight)); + pstruct->AddNativeField("deltaviewheight", TypeFloat64, myoffsetof(player_t, deltaviewheight)); + pstruct->AddNativeField("bob", TypeFloat64, myoffsetof(player_t, bob)); + pstruct->AddNativeField("vel", TypeVector2, myoffsetof(player_t, Vel)); + pstruct->AddNativeField("centering", TypeBool, myoffsetof(player_t, centering)); + pstruct->AddNativeField("turnticks", TypeUInt8, myoffsetof(player_t, turnticks)); + pstruct->AddNativeField("attackdown", TypeBool, myoffsetof(player_t, attackdown)); + pstruct->AddNativeField("usedown", TypeBool, myoffsetof(player_t, usedown)); + pstruct->AddNativeField("oldbuttons", TypeUInt32, myoffsetof(player_t, oldbuttons)); + pstruct->AddNativeField("health", TypeSInt32, myoffsetof(player_t, health)); + pstruct->AddNativeField("inventorytics", TypeSInt32, myoffsetof(player_t, inventorytics)); + pstruct->AddNativeField("CurrentPlayerClass", TypeUInt8, myoffsetof(player_t, CurrentPlayerClass)); + pstruct->AddNativeField("frags", NewArray(TypeSInt32, MAXPLAYERS), myoffsetof(player_t, frags)); + pstruct->AddNativeField("fragcount", TypeSInt32, myoffsetof(player_t, fragcount)); + pstruct->AddNativeField("lastkilltime", TypeSInt32, myoffsetof(player_t, lastkilltime)); + pstruct->AddNativeField("multicount", TypeUInt8, myoffsetof(player_t, multicount)); + pstruct->AddNativeField("spreecount", TypeUInt8, myoffsetof(player_t, spreecount)); + pstruct->AddNativeField("WeaponState", TypeUInt16, myoffsetof(player_t, WeaponState)); + pstruct->AddNativeField("ReadyWeapon", TypeWeapon, myoffsetof(player_t, ReadyWeapon)); + pstruct->AddNativeField("PendingWeapon", TypeWeapon, myoffsetof(player_t, PendingWeapon)); + pstruct->AddNativeField("psprites", NewPointer(RUNTIME_CLASS(DPSprite)), myoffsetof(player_t, psprites)); + pstruct->AddNativeField("cheats", TypeSInt32, myoffsetof(player_t, cheats)); + pstruct->AddNativeField("timefreezer", TypeSInt32, myoffsetof(player_t, timefreezer)); + pstruct->AddNativeField("refire", TypeSInt16, myoffsetof(player_t, refire)); + pstruct->AddNativeField("inconsistent", TypeSInt16, myoffsetof(player_t, inconsistant)); + pstruct->AddNativeField("waiting", TypeSInt32, myoffsetof(player_t, waiting)); + pstruct->AddNativeField("killcount", TypeSInt32, myoffsetof(player_t, killcount)); + pstruct->AddNativeField("itemcount", TypeSInt32, myoffsetof(player_t, itemcount)); + pstruct->AddNativeField("secretcount", TypeSInt32, myoffsetof(player_t, secretcount)); + pstruct->AddNativeField("damagecount", TypeSInt32, myoffsetof(player_t, damagecount)); + pstruct->AddNativeField("bonuscount", TypeSInt32, myoffsetof(player_t, bonuscount)); + pstruct->AddNativeField("hazardcount", TypeSInt32, myoffsetof(player_t, hazardcount)); + pstruct->AddNativeField("hazardinterval", TypeSInt32, myoffsetof(player_t, hazardinterval)); + pstruct->AddNativeField("hazardtype", TypeName, myoffsetof(player_t, hazardtype)); + pstruct->AddNativeField("poisoncount", TypeSInt32, myoffsetof(player_t, poisoncount)); + pstruct->AddNativeField("poisontype", TypeName, myoffsetof(player_t, poisontype)); + pstruct->AddNativeField("poisonpaintype", TypeName, myoffsetof(player_t, poisonpaintype)); + pstruct->AddNativeField("poisoner", TypeActor, myoffsetof(player_t, poisoner)); + pstruct->AddNativeField("attacker", TypeActor, myoffsetof(player_t, attacker)); + pstruct->AddNativeField("extralight", TypeSInt32, myoffsetof(player_t, extralight)); + pstruct->AddNativeField("fixedcolormap", TypeSInt16, myoffsetof(player_t, fixedcolormap)); + pstruct->AddNativeField("fixedlightlevel", TypeSInt16, myoffsetof(player_t, fixedlightlevel)); + pstruct->AddNativeField("morphtics", TypeSInt32, myoffsetof(player_t, morphTics)); + pstruct->AddNativeField("MorphedPlayerClass", TypeClassPlayerPawn, myoffsetof(player_t, MorphedPlayerClass)); + pstruct->AddNativeField("MorphStyle", TypeSInt32, myoffsetof(player_t, MorphStyle)); + pstruct->AddNativeField("MorphExitFlash", TypeClassActor, myoffsetof(player_t, MorphExitFlash)); + pstruct->AddNativeField("PremorphWeapon", TypeClassWeapon, myoffsetof(player_t, PremorphWeapon)); + pstruct->AddNativeField("chickenPeck", TypeSInt32, myoffsetof(player_t, chickenPeck)); + pstruct->AddNativeField("jumpTics", TypeSInt32, myoffsetof(player_t, jumpTics)); + pstruct->AddNativeField("onground", TypeBool, myoffsetof(player_t, onground)); + pstruct->AddNativeField("respawn_time", TypeSInt32, myoffsetof(player_t, respawn_time)); + pstruct->AddNativeField("camera", TypeActor, myoffsetof(player_t, camera)); + pstruct->AddNativeField("air_finished", TypeSInt32, myoffsetof(player_t, air_finished)); + pstruct->AddNativeField("LastDamageType", TypeName, myoffsetof(player_t, LastDamageType)); + pstruct->AddNativeField("MUSINFOactor", TypeActor, myoffsetof(player_t, MUSINFOactor)); + pstruct->AddNativeField("MUSINFOtics", TypeSInt8, myoffsetof(player_t, MUSINFOtics)); + pstruct->AddNativeField("settings_controller", TypeBool, myoffsetof(player_t, settings_controller)); + pstruct->AddNativeField("crouching", TypeSInt8, myoffsetof(player_t, crouching)); + pstruct->AddNativeField("crouchdir", TypeSInt8, myoffsetof(player_t, crouchdir)); + pstruct->AddNativeField("bot", NewPointer(RUNTIME_CLASS(DBot)), myoffsetof(player_t, Bot)); + pstruct->AddNativeField("BlendR", TypeFloat32, myoffsetof(player_t, BlendR)); + pstruct->AddNativeField("BlendG", TypeFloat32, myoffsetof(player_t, BlendG)); + pstruct->AddNativeField("BlendB", TypeFloat32, myoffsetof(player_t, BlendB)); + pstruct->AddNativeField("BlendA", TypeFloat32, myoffsetof(player_t, BlendA)); + pstruct->AddNativeField("LogText", TypeString, myoffsetof(player_t, LogText)); + pstruct->AddNativeField("MinPitch", TypeFloat64, myoffsetof(player_t, MinPitch)); + pstruct->AddNativeField("MaxPitch", TypeFloat64, myoffsetof(player_t, MaxPitch)); + pstruct->AddNativeField("crouchfactor", TypeFloat64, myoffsetof(player_t, crouchfactor)); + pstruct->AddNativeField("crouchoffset", TypeFloat64, myoffsetof(player_t, crouchoffset)); + pstruct->AddNativeField("crouchviewdelta", TypeFloat64, myoffsetof(player_t, crouchviewdelta)); + pstruct->AddNativeField("ConversationNPC", TypeActor, myoffsetof(player_t, ConversationNPC)); + pstruct->AddNativeField("ConversationPC", TypeActor, myoffsetof(player_t, ConversationPC)); + pstruct->AddNativeField("ConversationNPCAngle", TypeFloat64, myoffsetof(player_t, ConversationNPCAngle)); + pstruct->AddNativeField("ConversationFaceTalker", TypeBool, myoffsetof(player_t, ConversationFaceTalker)); +} \ No newline at end of file diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 8de1aaff86..95dc0bdce9 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -641,6 +641,7 @@ static int funccmp(const void * a, const void * b) // //========================================================================== void G_InitLevelLocalsForScript(); +void P_InitPlayerForScript(); void InitThingdef() { @@ -687,6 +688,7 @@ void InitThingdef() sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); G_InitLevelLocalsForScript(); + P_InitPlayerForScript(); FAutoSegIterator probe(CRegHead, CRegTail); From a00181c89946d150fdabf08c2f7e3eba0aae86a7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 11:28:15 +0100 Subject: [PATCH 284/471] - started refactoring binary operators by starting to movw the relevant parts or ResolveLR into the respective Resolve methods. FxAddSub complete. This one-size-fits all function has become too unwieldy with all its special cases and makes improvements harder than necessary. --- src/scripting/codegeneration/codegen.cpp | 72 +++++++++++++++--------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d63db0f8d1..515569ae6a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2377,10 +2377,6 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) { switch (Operator) { - case '+': - // later - break; - case '<': case '>': case TK_Geq: @@ -2421,22 +2417,6 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) { 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()) { @@ -2592,16 +2572,55 @@ FxAddSub::FxAddSub(int o, FxExpression *l, FxExpression *r) FxExpression *FxAddSub::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) - return nullptr; - if (!IsNumeric() && !IsVector()) + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return nullptr; + return false; } - else if (left->isConstant() && right->isConstant()) + + if (left->IsVector() && right->IsVector()) + { + // 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; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for %s", Operator == '+' ? "addition" : "subtraction"); + delete this; + return nullptr; + } + } + else if (left->IsNumeric() && right->IsNumeric()) + { + // Addition and subtraction of unsigned ints results in an unsigned int. (16 and 8 bit values never get here, they get promoted to regular ints elsewhere already.) + if (left->ValueType == TypeUInt32 && right->ValueType == TypeUInt32) + { + ValueType = TypeUInt32; + } + else if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) + { + ValueType = TypeSInt32; // Addition and subtraction forces all integer-derived types to signed int. + } + else + { + ValueType = TypeFloat64; + Promote(ctx); + } + } + 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 operands for %s", Operator == '+' ? "addition" : "subtraction"); + delete this; + return false; + } + + if (left->isConstant() && right->isConstant()) { if (IsFloat()) { @@ -2631,7 +2650,6 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) } } - Promote(ctx); return this; } From b6801d526b10236700f59565c54c2a6dc6ca2e96 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 11:53:18 +0100 Subject: [PATCH 285/471] - same as last commit for FxMulDiv and FxPow. - some streamlining of FxAddSub. --- src/scripting/codegeneration/codegen.cpp | 189 ++++++++++++++--------- 1 file changed, 117 insertions(+), 72 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 515569ae6a..418fc4a5f2 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2417,39 +2417,6 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) { switch (Operator) { - 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) @@ -2540,15 +2507,34 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) return true; } +//========================================================================== +// +// +// +//========================================================================== + void FxBinary::Promote(FCompileContext &ctx) { - if (left->ValueType->GetRegType() == REGT_FLOAT && right->ValueType->GetRegType() == REGT_INT) + // math operations of unsigned ints results in an unsigned int. (16 and 8 bit values never get here, they get promoted to regular ints elsewhere already.) + if (left->ValueType == TypeUInt32 && right->ValueType == TypeUInt32) { - right = (new FxFloatCast(right))->Resolve(ctx); + ValueType = TypeUInt32; } - else if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_FLOAT) + else if (left->IsInteger() && right->IsInteger()) { - left = (new FxFloatCast(left))->Resolve(ctx); + ValueType = TypeSInt32; // Addition and subtraction forces all integer-derived types to signed int. + } + else + { + ValueType = TypeFloat64; + if (left->IsFloat() && right->IsInteger()) + { + right = (new FxFloatCast(right))->Resolve(ctx); + } + else if (left->IsInteger() && right->IsFloat()) + { + left = (new FxFloatCast(left))->Resolve(ctx); + } } } @@ -2590,34 +2576,17 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) } else { - ScriptPosition.Message(MSG_ERROR, "Incompatible operands for %s", Operator == '+' ? "addition" : "subtraction"); - delete this; - return nullptr; + goto error; } } else if (left->IsNumeric() && right->IsNumeric()) { - // Addition and subtraction of unsigned ints results in an unsigned int. (16 and 8 bit values never get here, they get promoted to regular ints elsewhere already.) - if (left->ValueType == TypeUInt32 && right->ValueType == TypeUInt32) - { - ValueType = TypeUInt32; - } - else if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) - { - ValueType = TypeSInt32; // Addition and subtraction forces all integer-derived types to signed int. - } - else - { - ValueType = TypeFloat64; - Promote(ctx); - } + Promote(ctx); } 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 operands for %s", Operator == '+' ? "addition" : "subtraction"); - delete this; - return false; + goto error; } if (left->isConstant() && right->isConstant()) @@ -2651,6 +2620,11 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) } } return this; + +error: + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for %s", Operator == '+' ? "addition" : "subtraction"); + delete this; + return nullptr; } //========================================================================== @@ -2750,16 +2724,70 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) - return nullptr; - - if (!IsNumeric() && !IsVector()) + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; - return nullptr; + return false; } - else if (left->isConstant() && right->isConstant()) + + if (left->IsVector() || right->IsVector()) + { + switch (Operator) + { + case '/': + // For division, the vector must be the first operand. + if (right->IsVector()) goto error; + + case '*': + if (left->IsVector() && right->IsNumeric()) + { + if (right->IsInteger()) + { + right = new FxFloatCast(right); + right = right->Resolve(ctx); + if (right == nullptr) + { + delete this; + return false; + } + } + ValueType = left->ValueType; + } + else if (right->IsVector() && left->IsNumeric()) + { + if (left->IsInteger()) + { + left = new FxFloatCast(left); + left = left->Resolve(ctx); + if (left == nullptr) + { + delete this; + return false; + } + } + ValueType = right->ValueType; + } + break; + + default: + // Vector modulus is not permitted + goto error; + + } + } + else if (left->IsNumeric() && right->IsNumeric()) + { + Promote(ctx); + } + else + { + // To check: It may be that this could pass in DECORATE, although setting TypeVoid here would pretty much prevent that. + goto error; + } + + if (left->isConstant() && right->isConstant()) { if (IsFloat()) { @@ -2805,8 +2833,13 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) } } - Promote(ctx); return this; + +error: + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for %s", Operator == '*' ? "multiplication" : Operator == '%' ? "modulus" : "division"); + delete this; + return nullptr; + } @@ -2818,7 +2851,6 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) 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); @@ -2919,15 +2951,29 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) - return nullptr; - - if (!IsNumeric()) + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return false; + } + if (!left->IsNumeric() || !right->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected for '**'"); delete this; return nullptr; } + if (!left->IsFloat()) + { + left = (new FxFloatCast(left))->Resolve(ctx); + ABORT(left); + } + if (!right->IsFloat()) + { + right = (new FxFloatCast(right))->Resolve(ctx); + ABORT(right); + } if (left->isConstant() && right->isConstant()) { double v1 = static_cast(left)->GetValue().GetFloat(); @@ -2937,7 +2983,6 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx) return this; } - //========================================================================== // // From d9953eb3bddc2881a40564ad0cd5aeb70b97af0f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 12:23:58 +0100 Subject: [PATCH 286/471] - cleaned up FxCompareRel::Resolve. Also added unsigned integer support to it and FxMulDiv (these, aside from the float cast, are the only two operations where this is important.) --- src/scripting/codegeneration/codegen.cpp | 90 +++++++++++++++++++----- src/scripting/codegeneration/codegen.h | 9 ++- 2 files changed, 80 insertions(+), 19 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 418fc4a5f2..c18548bdc9 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2922,9 +2922,18 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) { 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); + if (ValueType == TypeUInt32) + { + build->Emit(Operator == '/' ? (op1.Konst ? OP_DIVU_KR : op2.Konst ? OP_DIVU_RK : OP_DIVU_RR) + : (op1.Konst ? OP_MODU_KR : op2.Konst ? OP_MODU_RK : OP_MODU_RR), + to.RegNum, op1.RegNum, op2.RegNum); + } + else + { + 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; } } @@ -3024,16 +3033,51 @@ FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r) FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) - return nullptr; - if (!IsNumeric()) + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; return nullptr; } - else if (left->isConstant() && right->isConstant()) + + if (left->ValueType == TypeString || right->ValueType == TypeString) + { + if (left->ValueType != TypeString) + { + left = new FxStringCast(left); + left = left->Resolve(ctx); + if (left == nullptr) + { + delete this; + return nullptr; + } + } + if (right->ValueType != TypeString) + { + right = new FxStringCast(right); + right = right->Resolve(ctx); + if (right == nullptr) + { + delete this; + return nullptr; + } + } + ValueType == TypeString; + } + else if (left->IsNumeric() && right->IsNumeric()) + { + Promote(ctx); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for relative comparison"); + delete this; + return nullptr; + } + + if (left->isConstant() && right->isConstant()) { int v; @@ -3056,20 +3100,29 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) Operator == TK_Geq? v1 >= v2 : Operator == TK_Leq? v1 <= v2 : 0; } - else + else if (ValueType == TypeUInt32) { - int v1 = static_cast(left)->GetValue().GetInt(); - int v2 = static_cast(right)->GetValue().GetInt(); + int v1 = static_cast(left)->GetValue().GetUInt(); + int v2 = static_cast(right)->GetValue().GetUInt(); 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); + CompareType = ValueType; // needs to be preserved for detection of unsigned compare. ValueType = TypeBool; return this; } @@ -3124,10 +3177,10 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build) 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 } // <= + { OP_LT_RR, OP_LTF_RR, OP_LTU_RR, 0 }, // < + { OP_LE_RR, OP_LEF_RR, OP_LEU_RR, 1 }, // > + { OP_LT_RR, OP_LTF_RR, OP_LTU_RR, 1 }, // >= + { OP_LE_RR, OP_LEF_RR, OP_LEU_RR, 0 } // <= }; int instr, check; ExpEmit to(build, REGT_INT); @@ -3135,8 +3188,9 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build) Operator == '>' ? 1 : Operator == TK_Geq ? 2 : 3; - instr = InstrMap[index][op1.RegType == REGT_INT ? 0 : 1]; - check = InstrMap[index][2]; + int mode = op1.RegType == REGT_FLOAT ? 1 : CompareType == TypeUInt32 ? 2 : 0; + instr = InstrMap[index][mode]; + check = InstrMap[index][3]; if (op2.Konst) { instr += 1; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 0ec3491bbb..5f7791e3eb 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -169,10 +169,16 @@ struct ExpVal return regtype == REGT_INT ? Int : regtype == REGT_FLOAT ? int(Float) : 0; } + unsigned GetUInt() const + { + int regtype = Type->GetRegType(); + return regtype == REGT_INT ? unsigned(Int) : regtype == REGT_FLOAT ? unsigned(Float) : 0; + } + double GetFloat() const { int regtype = Type->GetRegType(); - return regtype == REGT_INT ? double(Int) : regtype == REGT_FLOAT ? Float : 0; + return regtype == REGT_INT ? (Type == TypeUInt32? double(unsigned(Int)) : double(Int)) : regtype == REGT_FLOAT ? Float : 0; } void *GetPointer() const @@ -864,6 +870,7 @@ public: class FxCompareRel : public FxBinary { + PType *CompareType; public: FxCompareRel(int, FxExpression*, FxExpression*); From f71aad4cdde28b4cb487481e103615623b3fb7ca Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 14:19:55 +0100 Subject: [PATCH 287/471] - cleanup of the remaining FxBinary operators. - changed FxCompareEq with strings and other types that can be cast to from a string always convert the string to the other type before comparing. --- src/scripting/codegeneration/codegen.cpp | 473 +++++++++++------------ src/scripting/codegeneration/codegen.h | 22 +- src/scripting/decorate/thingdef_exp.cpp | 20 +- src/scripting/zscript/zcc_compile.cpp | 8 +- 4 files changed, 260 insertions(+), 263 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c18548bdc9..e57303c0a7 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -838,7 +838,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) { ExpVal constval = static_cast(basex)->GetValue(); FxExpression *x = new FxConstant(constval.GetInt(), ScriptPosition); - if (!NoWarn && constval.GetInt() != constval.GetFloat()) + if (constval.GetInt() != constval.GetFloat()) { ScriptPosition.Message(MSG_WARNING, "Truncation of floating point constant %f", constval.GetFloat()); } @@ -2363,157 +2363,7 @@ FxBinary::~FxBinary() // //========================================================================== -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 '<': - 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 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) +bool FxBinary::Promote(FCompileContext &ctx, bool forceint) { // math operations of unsigned ints results in an unsigned int. (16 and 8 bit values never get here, they get promoted to regular ints elsewhere already.) if (left->ValueType == TypeUInt32 && right->ValueType == TypeUInt32) @@ -2524,7 +2374,7 @@ void FxBinary::Promote(FCompileContext &ctx) { ValueType = TypeSInt32; // Addition and subtraction forces all integer-derived types to signed int. } - else + else if (!forceint) { ValueType = TypeFloat64; if (left->IsFloat() && right->IsInteger()) @@ -2536,6 +2386,34 @@ void FxBinary::Promote(FCompileContext &ctx) left = (new FxFloatCast(left))->Resolve(ctx); } } + else if (ctx.FromDecorate) + { + // For DECORATE which allows floats here. ZScript does not. + if (left->IsFloat()) + { + left = new FxIntCast(left, ctx.FromDecorate); + left = left->Resolve(ctx); + } + if (right->IsFloat()) + { + right = new FxIntCast(right, ctx.FromDecorate); + right = right->Resolve(ctx); + } + if (left == nullptr || right == nullptr) + { + delete this; + return false; + } + ValueType = TypeSInt32; + + } + else + { + ScriptPosition.Message(MSG_ERROR, "Integer operand expected"); + delete this; + return false; + } + return true; } //========================================================================== @@ -3064,7 +2942,7 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) return nullptr; } } - ValueType == TypeString; + ValueType = TypeString; } else if (left->IsNumeric() && right->IsNumeric()) { @@ -3238,24 +3116,66 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) - return nullptr; - + RESOLVE(left, ctx); + RESOLVE(right, ctx); if (!left || !right) { delete this; return nullptr; } - if (!IsNumeric() && !IsPointer() && !IsVector() && ValueType != TypeName) + if (left->ValueType != right->ValueType) // identical types are always comparable, if they can be placed in a register, so we can save most checks if this is the case. { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return nullptr; + // Special cases: Compare strings and names with names, sounds, colors, state labels and class types. + // These are all types a string can be implicitly cast into, so for convenience, so they should when doing a comparison. + if ((left->ValueType == TypeString || left->ValueType == TypeName) && + (right->ValueType == TypeName || right->ValueType == TypeSound || right->ValueType == TypeColor || right->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || right->ValueType == TypeStateLabel)) + { + left = new FxTypeCast(left, right->ValueType, false, true); + left = left->Resolve(ctx); + ABORT(left); + ValueType = right->ValueType; + } + else if ((right->ValueType == TypeString || right->ValueType == TypeName) && + (left->ValueType == TypeName || left->ValueType == TypeSound || left->ValueType == TypeColor || left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || left->ValueType == TypeStateLabel)) + { + right = new FxTypeCast(right, left->ValueType, false, true); + right = right->Resolve(ctx); + ABORT(right); + ValueType = left->ValueType; + } + else if (left->IsNumeric() && right->IsNumeric()) + { + Promote(ctx); + } + else if (left->ValueType->GetRegType() == REGT_POINTER && right->ValueType->GetRegType() == REGT_POINTER) + { + if (left->ValueType != right->ValueType && right->ValueType != TypeNullPtr && left->ValueType != TypeNullPtr && + !AreCompatiblePointerTypes(left->ValueType, right->ValueType)) + { + goto error; + } + } + else + { + goto error; + } + } + else if (left->ValueType->GetRegType() == REGT_NIL) + { + goto error; + } + else + { + ValueType = left->ValueType; + } + + if (Operator == TK_ApproxEq && ValueType->GetRegType() != REGT_FLOAT && ValueType->GetRegType() != REGT_STRING) + { + // Only floats, vectors and strings have handling for '~==', for all other types this is an error. + goto error; } - if (Operator == TK_ApproxEq && left->ValueType->GetRegType() != REGT_FLOAT && left->ValueType->GetRegType() != REGT_STRING) - Operator = TK_Eq; if (left->isConstant() && right->isConstant()) { int v; @@ -3357,9 +3277,13 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) } } } - Promote(ctx); ValueType = TypeBool; return this; + +error: + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for %s comparison", Operator == TK_Eq ? "==" : Operator == TK_Neq ? "!=" : "~=="); + delete this; + return nullptr; } //========================================================================== @@ -3435,7 +3359,7 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) // //========================================================================== -FxBinaryInt::FxBinaryInt(int o, FxExpression *l, FxExpression *r) +FxBitOp::FxBitOp(int o, FxExpression *l, FxExpression *r) : FxBinary(o, l, r) { ValueType = TypeSInt32; @@ -3447,48 +3371,39 @@ FxBinaryInt::FxBinaryInt(int o, FxExpression *l, FxExpression *r) // //========================================================================== -FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) +FxExpression *FxBitOp::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, false)) - return nullptr; - if (IsFloat() && ctx.FromDecorate) + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) { - // 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; + delete this; + return false; } - if (ValueType->GetRegType() != REGT_INT) + if (left->ValueType == TypeBool && right->ValueType == TypeBool) { - ScriptPosition.Message(MSG_ERROR, "Integer type expected"); + ValueType = TypeBool; + } + else if (left->IsNumeric() && right->IsNumeric()) + { + if (!Promote(ctx, true)) return nullptr; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for bit operation"); delete this; return nullptr; } - else if (left->isConstant() && right->isConstant()) + + 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); @@ -3505,7 +3420,98 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx) // //========================================================================== -ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build) +ExpEmit FxBitOp::Emit(VMFunctionBuilder *build) +{ + assert(left->ValueType->GetRegType() == REGT_INT); + assert(right->ValueType->GetRegType() == REGT_INT); + int instr, rop; + ExpEmit op1, op2; + + op1 = left->Emit(build); + op2 = right->Emit(build); + if (op1.Konst) + { + swapvalues(op1, op2); + } + assert(!op1.Konst); + rop = op2.RegNum; + op2.Free(build); + op1.Free(build); + + instr = Operator == '&' ? OP_AND_RR : + Operator == '|' ? OP_OR_RR : + Operator == '^' ? OP_XOR_RR : -1; + + assert(instr > 0); + ExpEmit to(build, REGT_INT); + build->Emit(instr + op2.Konst, to.RegNum, op1.RegNum, rop); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxShift::FxShift(int o, FxExpression *l, FxExpression *r) + : FxBinary(o, l, r) +{ + ValueType = TypeSInt32; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxShift::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) + { + delete this; + return false; + } + + if (left->IsNumeric() && right->IsNumeric()) + { + if (!Promote(ctx, true)) return nullptr; + if (ValueType == TypeUInt32 && Operator == TK_RShift) Operator = TK_URShift; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Incompatible operands for shift operation"); + delete this; + return nullptr; + } + + 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) : 0, ScriptPosition); + + delete this; + return e; + } + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxShift::Emit(VMFunctionBuilder *build) { assert(left->ValueType->GetRegType() == REGT_INT); assert(right->ValueType->GetRegType() == REGT_INT); @@ -3514,65 +3520,41 @@ ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build) { 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; + Operator == TK_URShift ? 2 : -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; - } + + // Shift instructions use right-hand immediates instead of constant registers. + if (right->isConstant()) + { + rop = static_cast(right)->GetValue().GetInt(); + op2.Konst = true; } 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; + assert(!op2.Konst); op2.Free(build); + rop = op2.RegNum; } + if (!op1.Konst) { op1.Free(build); - if (!op2.Konst) - { - instr = InstrMap[index][0]; - } - else - { - instr = InstrMap[index][2]; - } + instr = InstrMap[index][op2.Konst? 0:2]; } else { assert(!op2.Konst); instr = InstrMap[index][1]; } - assert(instr != 0); + assert(instr > 0); ExpEmit to(build, REGT_INT); build->Emit(instr, to.RegNum, op1.RegNum, rop); return to; @@ -3599,30 +3581,27 @@ FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r) FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ResolveLR(ctx, true)) - return nullptr; - if (!left->IsNumeric() || !right->IsNumeric()) + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) + { + delete this; + return false; + } + + if (left->IsNumeric() && right->IsNumeric()) + { + Promote(ctx); + } + else { 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()) + 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(); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 5f7791e3eb..df0634b43d 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -813,8 +813,7 @@ public: FxBinary(int, FxExpression*, FxExpression*); ~FxBinary(); - bool ResolveLR(FCompileContext& ctx, bool castnumeric); - void Promote(FCompileContext &ctx); + bool Promote(FCompileContext &ctx, bool forceint = false); }; //========================================================================== @@ -899,11 +898,26 @@ public: // //========================================================================== -class FxBinaryInt : public FxBinary +class FxBitOp : public FxBinary { public: - FxBinaryInt(int, FxExpression*, FxExpression*); + FxBitOp(int, FxExpression*, FxExpression*); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + +//========================================================================== +// +// FxBinary +// +//========================================================================== + +class FxShift : public FxBinary +{ +public: + + FxShift(int, FxExpression*, FxExpression*); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); }; diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 2d69be3405..e7d217609a 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -139,27 +139,27 @@ static FxExpression *ParseExpressionM (FScanner &sc, PClassActor *cls) break; case TK_LShiftEq: - exp = new FxBinaryInt(TK_LShift, left, nullptr); + exp = new FxShift(TK_LShift, left, nullptr); break; case TK_RShiftEq: - exp = new FxBinaryInt(TK_RShift, left, nullptr); + exp = new FxShift(TK_RShift, left, nullptr); break; case TK_URShiftEq: - exp = new FxBinaryInt(TK_URShift, left, nullptr); + exp = new FxShift(TK_URShift, left, nullptr); break; case TK_AndEq: - exp = new FxBinaryInt('&', left, nullptr); + exp = new FxBitOp('&', left, nullptr); break; case TK_XorEq: - exp = new FxBinaryInt('^', left, nullptr); + exp = new FxBitOp('^', left, nullptr); break; case TK_OrEq: - exp = new FxBinaryInt('|', left, nullptr); + exp = new FxBitOp('|', left, nullptr); break; default: @@ -207,7 +207,7 @@ static FxExpression *ParseExpressionJ (FScanner &sc, PClassActor *cls) while (sc.CheckToken('|')) { FxExpression *right = ParseExpressionI (sc, cls); - tmp = new FxBinaryInt('|', tmp, right); + tmp = new FxBitOp('|', tmp, right); } return tmp; } @@ -219,7 +219,7 @@ static FxExpression *ParseExpressionI (FScanner &sc, PClassActor *cls) while (sc.CheckToken('^')) { FxExpression *right = ParseExpressionH (sc, cls); - tmp = new FxBinaryInt('^', tmp, right); + tmp = new FxBitOp('^', tmp, right); } return tmp; } @@ -231,7 +231,7 @@ static FxExpression *ParseExpressionH (FScanner &sc, PClassActor *cls) while (sc.CheckToken('&')) { FxExpression *right = ParseExpressionG (sc, cls); - tmp = new FxBinaryInt('&', tmp, right); + tmp = new FxBitOp('&', tmp, right); } return tmp; } @@ -272,7 +272,7 @@ static FxExpression *ParseExpressionE (FScanner &sc, PClassActor *cls) { int token = sc.TokenType; FxExpression *right = ParseExpressionD (sc, cls); - tmp = new FxBinaryInt(token, tmp, right); + tmp = new FxShift(token, tmp, right); } if (!sc.End) sc.UnGet(); return tmp; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index baf76027ba..206e2dd887 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2902,10 +2902,12 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_LeftShift: case PEX_RightShift: case PEX_URightShift: + return new FxShift(tok, left, right); + case PEX_BitAnd: case PEX_BitOr: case PEX_BitXor: - return new FxBinaryInt(tok, left, right); + return new FxBitOp(tok, left, right); case PEX_BoolOr: case PEX_BoolAnd: @@ -2937,10 +2939,12 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_LshAssign: case PEX_RshAssign: case PEX_URshAssign: + return ModifyAssign(new FxShift(tok, new FxAssignSelf(*ast), right), left); + case PEX_AndAssign: case PEX_OrAssign: case PEX_XorAssign: - return ModifyAssign(new FxBinaryInt(tok, new FxAssignSelf(*ast), right), left); + return ModifyAssign(new FxBitOp(tok, new FxAssignSelf(*ast), right), left); case PEX_LTGTEQ: return new FxLtGtEq(left, right); From 24481781b4a20b40189a9f810ab5487bc8723d0b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 14:50:21 +0100 Subject: [PATCH 288/471] - added missing unsigned casts to the VM. - make the pointer to string cast a bit more useful by using the actual object's type rather than 'Object' which can be a great asset when debugging. - fixed a few bad asserts. --- src/scripting/codegeneration/codegen.cpp | 6 +++--- src/scripting/vm/vm.h | 3 +++ src/scripting/vm/vmdisasm.cpp | 3 +++ src/scripting/vm/vmexec.h | 14 +++++++++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index e57303c0a7..c8cf6b7402 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -871,7 +871,7 @@ ExpEmit FxIntCast::Emit(VMFunctionBuilder *build) assert(basex->ValueType->GetRegType() == REGT_FLOAT); from.Free(build); ExpEmit to(build, REGT_INT); - build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_F2I); + build->Emit(OP_CAST, to.RegNum, from.RegNum, ValueType == TypeUInt32? CAST_F2U : CAST_F2I); return to; } @@ -962,7 +962,7 @@ ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build) assert(basex->ValueType->GetRegType() == REGT_INT); from.Free(build); ExpEmit to(build, REGT_FLOAT); - build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_I2F); + build->Emit(OP_CAST, to.RegNum, from.RegNum, basex->ValueType == TypeUInt32? CAST_U2F : CAST_I2F); return to; } @@ -3554,7 +3554,7 @@ ExpEmit FxShift::Emit(VMFunctionBuilder *build) assert(!op2.Konst); instr = InstrMap[index][1]; } - assert(instr > 0); + assert(instr != 0); ExpEmit to(build, REGT_INT); build->Emit(instr, to.RegNum, op1.RegNum, rop); return to; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index c9f75f2144..4e833cf0ba 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -111,7 +111,10 @@ enum { CAST_I2F, CAST_I2S, + CAST_U2F, + CAST_U2S, CAST_F2I, + CAST_F2U, CAST_F2S, CAST_P2S, CAST_S2I, diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 48b6d168b2..d39723dea9 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -381,15 +381,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction switch (code[i].c) { case CAST_I2F: + case CAST_U2F: mode = MODE_AF | MODE_BI | MODE_CUNUSED; break; case CAST_Co2S: case CAST_So2S: case CAST_N2S: case CAST_I2S: + case CAST_U2S: mode = MODE_AS | MODE_BI | MODE_CUNUSED; break; case CAST_F2I: + case CAST_F2U: mode = MODE_AI | MODE_BF | MODE_CUNUSED; break; case CAST_F2S: diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 6cc0d40cd1..673582bda9 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1658,15 +1658,27 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c ASSERTF(a); ASSERTD(b); reg.f[a] = reg.d[b]; break; + case CAST_U2F: + ASSERTF(a); ASSERTD(b); + reg.f[a] = unsigned(reg.d[b]); + break; case CAST_I2S: ASSERTS(a); ASSERTD(b); reg.s[a].Format("%d", reg.d[b]); break; + case CAST_U2S: + ASSERTS(a); ASSERTD(b); + reg.s[a].Format("%u", reg.d[b]); + break; case CAST_F2I: ASSERTD(a); ASSERTF(b); reg.d[a] = (int)reg.f[b]; break; + case CAST_F2U: + ASSERTD(a); ASSERTF(b); + reg.d[a] = (int)(unsigned)reg.f[b]; + break; case CAST_F2S: ASSERTS(a); ASSERTD(b); reg.s[a].Format("%.14g", reg.f[b]); @@ -1674,7 +1686,7 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c case CAST_P2S: ASSERTS(a); ASSERTA(b); - reg.s[a].Format("%s<%p>", reg.atag[b] == ATAG_OBJECT ? "Object" : "Pointer", reg.a[b]); + reg.s[a].Format("%s<%p>", reg.atag[b] == ATAG_OBJECT ? (reg.a[b] == nullptr? "Object" : ((DObject*)reg.a[b])->GetClass()->TypeName.GetChars() ) : "Pointer", reg.a[b]); break; case CAST_S2I: From 34c949f84b32615f19f14816eb145677de8a9918 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 17:44:25 +0100 Subject: [PATCH 289/471] - implemented the string concatenation operator '..'. This is capable of stringifying all of the common types for output. - gave OP_CONCAT some sane semantics. The way this was defined, by specifying the source operands as a range of registers instead of a pair like everything else made it completely useless for the task at hand. - changed formatting for floats to %.5f which for normal output in a game makes more sense. For special cases there should be a special formatting function for ints and floats that can do more specialized conversions. --- src/scripting/codegeneration/codegen.cpp | 153 +++++++++++++++++++++-- src/scripting/codegeneration/codegen.h | 15 +++ src/scripting/vm/vm.h | 2 + src/scripting/vm/vmdisasm.cpp | 2 + src/scripting/vm/vmexec.h | 23 ++-- src/scripting/vm/vmops.h | 2 +- src/scripting/zscript/zcc_compile.cpp | 2 +- 7 files changed, 175 insertions(+), 24 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c8cf6b7402..a5f6a3bc7f 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2442,7 +2442,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) if (!left || !right) { delete this; - return false; + return nullptr; } if (left->IsVector() && right->IsVector()) @@ -2607,7 +2607,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) if (!left || !right) { delete this; - return false; + return nullptr; } if (left->IsVector() || right->IsVector()) @@ -2628,7 +2628,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) if (right == nullptr) { delete this; - return false; + return nullptr; } } ValueType = left->ValueType; @@ -2642,7 +2642,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) if (left == nullptr) { delete this; - return false; + return nullptr; } } ValueType = right->ValueType; @@ -2843,7 +2843,7 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx) if (!left || !right) { delete this; - return false; + return nullptr; } if (!left->IsNumeric() || !right->IsNumeric()) { @@ -3380,7 +3380,7 @@ FxExpression *FxBitOp::Resolve(FCompileContext& ctx) if (!left || !right) { delete this; - return false; + return nullptr; } if (left->ValueType == TypeBool && right->ValueType == TypeBool) @@ -3474,7 +3474,7 @@ FxExpression *FxShift::Resolve(FCompileContext& ctx) if (!left || !right) { delete this; - return false; + return nullptr; } if (left->IsNumeric() && right->IsNumeric()) @@ -3587,7 +3587,7 @@ FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx) if (!left || !right) { delete this; - return false; + return nullptr; } if (left->IsNumeric() && right->IsNumeric()) @@ -3656,6 +3656,137 @@ ExpEmit FxLtGtEq::Emit(VMFunctionBuilder *build) // //========================================================================== +FxConcat::FxConcat(FxExpression *l, FxExpression *r) + : FxBinary(TK_DotDot, l, r) +{ + ValueType = TypeString; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxConcat::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + + RESOLVE(left, ctx); + RESOLVE(right, ctx); + if (!left || !right) + { + delete this; + return nullptr; + } + + // To concatenate two operands the only requirement is that they are integral types, i.e. can occupy a register + if (left->ValueType->GetRegType() == REGT_NIL || right->ValueType->GetRegType() == REGT_NIL) + { + ScriptPosition.Message(MSG_ERROR, "Invalid operand for string concatenation"); + delete this; + return nullptr; + } + + if (left->isConstant() && right->isConstant() && (left->ValueType == TypeString || left->ValueType == TypeName) && (right->ValueType == TypeString || right->ValueType == TypeName)) + { + // for now this is only types which have a constant string representation. + auto v1 = static_cast(left)->GetValue().GetString(); + auto v2 = static_cast(right)->GetValue().GetString(); + auto e = new FxConstant(v1 + v2, ScriptPosition); + delete this; + return e; + } + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxConcat::Emit(VMFunctionBuilder *build) +{ + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + ExpEmit strng, strng2; + + if (op1.RegType == REGT_STRING && op1.Konst) + { + strng = ExpEmit(build, REGT_STRING); + build->Emit(OP_LKS, strng.RegNum, op1.RegNum); + } + else if (op1.RegType == REGT_STRING) + { + strng = op1; + } + else + { + int cast; + strng = ExpEmit(build, REGT_STRING); + if (op1.Konst) + { + ExpEmit nonconst(build, op1.RegType); + build->Emit(op1.RegType == REGT_INT ? OP_LK : op1.RegType == REGT_FLOAT ? OP_LKF : OP_LKP, nonconst.RegNum, op1.RegNum); + op1 = nonconst; + } + if (op1.RegType == REGT_FLOAT) cast = op1.RegCount == 1 ? CAST_F2S : op1.RegCount == 2 ? CAST_V22S : CAST_V32S; + else if (left->ValueType == TypeUInt32) cast = CAST_U2S; + else if (left->ValueType == TypeName) cast = CAST_N2S; + else if (left->ValueType == TypeSound) cast = CAST_So2S; + else if (left->ValueType == TypeColor) cast = CAST_Co2S; + else if (op1.RegType == REGT_POINTER) cast = CAST_P2S; + else if (op1.RegType == REGT_INT) cast = CAST_I2S; + else assert(false && "Bad type for string concatenation"); + build->Emit(OP_CAST, strng.RegNum, op1.RegNum, cast); + op1.Free(build); + } + + if (op2.RegType == REGT_STRING && op2.Konst) + { + strng2 = ExpEmit(build, REGT_STRING); + build->Emit(OP_LKS, strng2.RegNum, op2.RegNum); + } + else if (op2.RegType == REGT_STRING) + { + strng2 = op2; + } + else + { + int cast; + strng2 = ExpEmit(build, REGT_STRING); + if (op2.Konst) + { + ExpEmit nonconst(build, op2.RegType); + build->Emit(op2.RegType == REGT_INT ? OP_LK : op2.RegType == REGT_FLOAT ? OP_LKF : OP_LKP, nonconst.RegNum, op2.RegNum); + op2 = nonconst; + } + if (op2.RegType == REGT_FLOAT) cast = op2.RegCount == 1 ? CAST_F2S : op2.RegCount == 2 ? CAST_V22S : CAST_V32S; + else if (right->ValueType == TypeUInt32) cast = CAST_U2S; + else if (right->ValueType == TypeName) cast = CAST_N2S; + else if (right->ValueType == TypeSound) cast = CAST_So2S; + else if (right->ValueType == TypeColor) cast = CAST_Co2S; + else if (op2.RegType == REGT_POINTER) cast = CAST_P2S; + else if (op2.RegType == REGT_INT) cast = CAST_I2S; + else assert(false && "Bad type for string concatenation"); + build->Emit(OP_CAST, strng2.RegNum, op2.RegNum, cast); + op2.Free(build); + } + strng.Free(build); + strng2.Free(build); + ExpEmit dest(build, REGT_STRING); + assert(strng.RegType == strng2.RegType && strng.RegType == REGT_STRING); + build->Emit(OP_CONCAT, dest.RegNum, strng.RegNum, strng2.RegNum); + return dest; +} + +//========================================================================== +// +// +// +//========================================================================== + FxBinaryLogical::FxBinaryLogical(int o, FxExpression *l, FxExpression *r) : FxExpression(EFX_BinaryLogical, l->ScriptPosition) { @@ -8854,9 +8985,11 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) break; case REGT_POINTER: - build->Emit(OP_LKP, RegNum, build->GetConstantAddress(constval->GetValue().GetPointer(), ATAG_GENERIC)); + { + bool isobject = ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass))); + build->Emit(OP_LKP, RegNum, build->GetConstantAddress(constval->GetValue().GetPointer(), isobject ? ATAG_OBJECT : ATAG_GENERIC)); break; - + } case REGT_STRING: build->Emit(OP_LKS, RegNum, build->GetConstantString(constval->GetValue().GetString())); } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index df0634b43d..66a0137b1b 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -937,6 +937,21 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxConcat : public FxBinary +{ +public: + FxConcat(FxExpression*, FxExpression*); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxBinaryLogical diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 4e833cf0ba..deca91a803 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -125,6 +125,8 @@ enum CAST_S2So, CAST_Co2S, CAST_So2S, + CAST_V22S, + CAST_V32S, }; // Register types for VMParam diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index d39723dea9..07d6fb8e32 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -396,6 +396,8 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction mode = MODE_AI | MODE_BF | MODE_CUNUSED; break; case CAST_F2S: + case CAST_V22S: + case CAST_V32S: mode = MODE_AS | MODE_BF | MODE_CUNUSED; break; case CAST_P2S: diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 673582bda9..918dc69492 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -704,16 +704,7 @@ begin: OP(CONCAT): ASSERTS(a); ASSERTS(B); ASSERTS(C); - { - FString *rB = ®.s[B]; - FString *rC = ®.s[C]; - FString concat(*rB); - for (++rB; rB <= rC; ++rB) - { - concat += *rB; - } - reg.s[a] = concat; - } + reg.s[a] = reg.s[B] + reg.s[C]; NEXTOP; OP(LENS): ASSERTD(a); ASSERTS(B); @@ -1680,8 +1671,16 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c reg.d[a] = (int)(unsigned)reg.f[b]; break; case CAST_F2S: - ASSERTS(a); ASSERTD(b); - reg.s[a].Format("%.14g", reg.f[b]); + ASSERTS(a); ASSERTF(b); + reg.s[a].Format("%.5f", reg.f[b]); // keep this small. For more precise conversion there should be a conversion function. + break; + case CAST_V22S: + ASSERTS(a); ASSERTF(b+1); + reg.s[a].Format("(%.5f, %.5f)", reg.f[b], reg.f[b + 1]); + break; + case CAST_V32S: + ASSERTS(a); ASSERTF(b + 2); + reg.s[a].Format("(%.5f, %.5f, %.5f)", reg.f[b], reg.f[b + 1], reg.f[b + 2]); break; case CAST_P2S: diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 368f143bdf..210ff9c493 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -101,7 +101,7 @@ xx(CATCH, catch, CATCH), // A == 0: continue search on next try xx(BOUND, bound, RII16), // if rA >= BC, throw exception // String instructions. -xx(CONCAT, concat, RSRSRS), // sA = sB.. ... ..sC +xx(CONCAT, concat, RSRSRS), // sA = sB..sC xx(LENS, lens, RIRS), // dA = sB.Length xx(CMPS, cmps, I8RXRX), // if ((skB op skC) != (A & 1)) then pc++ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 206e2dd887..ebe70c3407 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2959,8 +2959,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_Is: return new FxTypeCheck(left, right); - // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_Concat: + return new FxConcat(left, right); default: I_Error("Binary operator %d not implemented yet", op); From aa32d8970b703904618eb7e267990e61c0ee9f26 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 21:34:06 +0100 Subject: [PATCH 290/471] - scriptified a_hereticmisc.cpp. --- src/g_heretic/a_hereticmisc.cpp | 188 ------------------ src/p_map.cpp | 9 + src/p_mobj.cpp | 7 + wadsrc/static/zscript/actor.txt | 7 +- wadsrc/static/zscript/heretic/hereticmisc.txt | 152 +++++++++++++- 5 files changed, 163 insertions(+), 200 deletions(-) diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 17cd4df097..64de3ef843 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -25,191 +25,3 @@ #include "a_hereticweaps.cpp" #include "a_ironlich.cpp" - -static FRandom pr_podpain ("PodPain"); -static FRandom pr_makepod ("MakePod"); -static FRandom pr_teleg ("TeleGlitter"); -static FRandom pr_teleg2 ("TeleGlitter2"); -static FRandom pr_volcano ("VolcanoSet"); -static FRandom pr_blast ("VolcanoBlast"); -static FRandom pr_volcimpact ("VolcBallImpact"); - -//---------------------------------------------------------------------------- -// -// PROC A_PodPain -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_PodPain) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_DEF (gootype, AActor) - - int count; - int chance; - AActor *goo; - - chance = pr_podpain (); - if (chance < 128) - { - return 0; - } - for (count = chance > 240 ? 2 : 1; count; count--) - { - goo = Spawn(gootype, self->PosPlusZ(48.), ALLOW_REPLACE); - goo->target = self; - goo->Vel.X = pr_podpain.Random2() / 128.; - goo->Vel.Y = pr_podpain.Random2() / 128.; - goo->Vel.Z = 0.5 + pr_podpain() / 128.; - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_RemovePod -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_RemovePod) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - if ( (mo = self->master) ) - { - if (mo->special1 > 0) - { - mo->special1--; - } - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MakePod -// -//---------------------------------------------------------------------------- - -#define MAX_GEN_PODS 16 - -DEFINE_ACTION_FUNCTION(AActor, A_MakePod) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_DEF(podtype, AActor) - - AActor *mo; - - if (self->special1 == MAX_GEN_PODS) - { // Too many generated pods - return 0; - } - mo = Spawn(podtype, self->PosAtZ(ONFLOORZ), ALLOW_REPLACE); - if (!P_CheckPosition (mo, mo->Pos())) - { // Didn't fit - mo->Destroy (); - return 0; - } - mo->SetState (mo->FindState("Grow")); - mo->Thrust(pr_makepod() * (360. / 256), 4.5); - S_Sound (mo, CHAN_BODY, self->AttackSound, 1, ATTN_IDLE); - self->special1++; // Increment generated pod count - mo->master = self; // Link the generator to the pod - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_AccTeleGlitter -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_AccTeleGlitter) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (++self->health > 35) - { - self->Vel.Z *= 1.5; - } - return 0; -} - - -//---------------------------------------------------------------------------- -// -// PROC A_VolcanoSet -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_VolcanoSet) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->tics = 105 + (pr_volcano() & 127); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_VolcanoBlast -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_VolcanoBlast) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - int count; - AActor *blast; - - count = 1 + (pr_blast() % 3); - for (i = 0; i < count; i++) - { - blast = Spawn("VolcanoBlast", self->PosPlusZ(44.), ALLOW_REPLACE); - blast->target = self; - blast->Angles.Yaw = pr_blast() * (360 / 256.); - blast->VelFromAngle(1.); - blast->Vel.Z = 2.5 + pr_blast() / 64.; - S_Sound (blast, CHAN_BODY, "world/volcano/shoot", 1, ATTN_NORM); - P_CheckMissileSpawn (blast, self->radius); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_VolcBallImpact -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_VolcBallImpact) -{ - PARAM_SELF_PROLOGUE(AActor); - - unsigned int i; - AActor *tiny; - - if (self->Z() <= self->floorz) - { - self->flags |= MF_NOGRAVITY; - self->Gravity = 1; - self->AddZ(28); - //self->Vel.Z = 3; - } - P_RadiusAttack (self, self->target, 25, 25, NAME_Fire, RADF_HURTSOURCE); - for (i = 0; i < 4; i++) - { - tiny = Spawn("VolcanoTBlast", self->Pos(), ALLOW_REPLACE); - tiny->target = self; - tiny->Angles.Yaw = 90.*i; - tiny->VelFromAngle(0.7); - tiny->Vel.Z = 1. + pr_volcimpact() / 128.; - P_CheckMissileSpawn (tiny, self->radius); - } - return 0; -} - diff --git a/src/p_map.cpp b/src/p_map.cpp index 3f0edc8d74..26dc3d4731 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1738,6 +1738,15 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, bool actorsonly) return P_CheckPosition(thing, pos, tm, actorsonly); } +DEFINE_ACTION_FUNCTION(AActor, CheckPosition) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_BOOL_DEF(actorsonly); + ACTION_RETURN_BOOL(P_CheckPosition(self, DVector2(x, y), actorsonly)); +} + //---------------------------------------------------------------------------- // // FUNC P_TestMobjLocation diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 59b4c43e96..c998bcf919 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6022,6 +6022,13 @@ bool P_CheckMissileSpawn (AActor* th, double maxdist) return true; } +DEFINE_ACTION_FUNCTION(AActor, CheckMissileSpawn) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(add); + ACTION_RETURN_BOOL(P_CheckMissileSpawn(self, add)); +} + //--------------------------------------------------------------------------- // diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 043ab3ed49..137fedbec3 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -1,7 +1,10 @@ class Actor : Thinker native { const DEFAULT_HEALTH = 1000; - + const ONFLOORZ = -2147483648.0; + const ONCEILINGZ = 2147483647.0; + const FLOATRANDZ = ONCEILINGZ-1; + Default { Scale 1; @@ -76,6 +79,8 @@ class Actor : Thinker native native Actor GetPointer(int aaptr); native void FaceMovementDirection(); native Actor AimTarget(); + native bool CheckMissileSpawn(double maxdist); + native bool CheckPosition(Vector2 pos, bool actorsonly = false); 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); diff --git a/wadsrc/static/zscript/heretic/hereticmisc.txt b/wadsrc/static/zscript/heretic/hereticmisc.txt index f858a6fa25..4cb094d06b 100644 --- a/wadsrc/static/zscript/heretic/hereticmisc.txt +++ b/wadsrc/static/zscript/heretic/hereticmisc.txt @@ -16,9 +16,7 @@ class Pod : Actor DeathSound "world/podexplode"; PushFactor 0.5; } - native void A_PodPain (class podtype = "PodGoo"); - native void A_RemovePod (); - + States { Spawn: @@ -37,6 +35,44 @@ class Pod : Actor PPOD IJKLMNOP 3; Goto Spawn; } + + //---------------------------------------------------------------------------- + // + // PROC A_PodPain + // + //---------------------------------------------------------------------------- + + void A_PodPain (class gootype = "PodGoo") + { + int chance = Random[PodPain](); + if (chance < 128) + { + return; + } + for (int count = chance > 240 ? 2 : 1; count; count--) + { + Actor goo = Spawn(gootype, pos + (0, 0, 48), ALLOW_REPLACE); + goo.target = self; + goo.Vel.X = Random2[PodPain]() / 128.; + goo.Vel.Y = Random2[PodPain]() / 128.; + goo.Vel.Z = 0.5 + random[PodPain]() / 128.; + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_RemovePod + // + //---------------------------------------------------------------------------- + + void A_RemovePod () + { + if (master && master.special1 > 0) + { + master.special1--; + } + } + } @@ -75,7 +111,6 @@ class PodGenerator : Actor AttackSound "world/podgrow"; } - native void A_MakePod (class podtype = "Pod"); States { @@ -83,6 +118,34 @@ class PodGenerator : Actor TNT1 A 35 A_MakePod; Loop; } + + //---------------------------------------------------------------------------- + // + // PROC A_MakePod + // + //---------------------------------------------------------------------------- + + const MAX_GEN_PODS = 16; + + void A_MakePod (class podtype = "Pod") + { + if (special1 >= MAX_GEN_PODS) + { // Too many generated pods + return; + } + Actor mo = Spawn(podtype, (pos.xy, ONFLOORZ), ALLOW_REPLACE); + if (!mo) return; + if (!mo.CheckPosition (mo.Pos.xy)) + { // Didn't fit + mo.Destroy (); + return; + } + mo.SetStateLabel("Grow"); + mo.Thrust(4.5, random[MakePod]() * (360. / 256)); + A_PlaySound (AttackSound, CHAN_BODY); + special1++; // Increment generated pod count + mo.master = self; // Link the generator to the pod + } } @@ -136,7 +199,6 @@ class TeleGlitter1 : Actor Damage 0; } - native void A_AccTeleGlitter (); States { @@ -148,6 +210,20 @@ class TeleGlitter1 : Actor TGLT E 2 BRIGHT; Loop; } + + //---------------------------------------------------------------------------- + // + // PROC A_AccTeleGlitter + // + //---------------------------------------------------------------------------- + + void A_AccTeleGlitter () + { + if (++health > 35) + { + Vel.Z *= 1.5; + } + } } // Teleglitter 2 ------------------------------------------------------------ @@ -178,9 +254,6 @@ class Volcano : Actor +SOLID } - native void A_VolcanoSet (); - native void A_VolcanoBlast (); - States { Spawn: @@ -190,7 +263,38 @@ class Volcano : Actor VLCO E 10 A_VolcanoBlast; Goto Spawn+1; } + + //---------------------------------------------------------------------------- + // + // PROC A_VolcanoSet + // + //---------------------------------------------------------------------------- + void A_VolcanoSet () + { + tics = 105 + (random[VolcanoSet]() & 127); + } + + //---------------------------------------------------------------------------- + // + // PROC A_VolcanoBlast + // + //---------------------------------------------------------------------------- + + void A_VolcanoBlast () + { + int count = random[VolcanoBlast](1,3); + for (int i = 0; i < count; i++) + { + Actor blast = Spawn("VolcanoBlast", pos + (0, 0, 44), ALLOW_REPLACE); + blast.target = self; + blast.Angle = random[VolcanoBlast]() * (360 / 256.); + blast.VelFromAngle(1.); + blast.Vel.Z = 2.5 + random[VolcanoBlast]() / 64.; + blast.A_PlaySound ("world/volcano/shoot", CHAN_BODY); + blast.CheckMissileSpawn (radius); + } + } } // Volcano blast ------------------------------------------------------------ @@ -210,8 +314,6 @@ class VolcanoBlast : Actor DeathSound "world/volcano/blast"; } - native void A_VolcBallImpact (); - States { Spawn: @@ -224,6 +326,35 @@ class VolcanoBlast : Actor XPL1 BCDEF 4 BRIGHT; Stop; } + + //---------------------------------------------------------------------------- + // + // PROC A_VolcBallImpact + // + //---------------------------------------------------------------------------- + + void A_VolcBallImpact () + { + if (pos.Z <= floorz) + { + bNoGravity = true; + Gravity = 1; + AddZ(28); + } + A_Explode(25, 25, XF_NOSPLASH|XF_HURTSOURCE, false, 0, 0, 0, "BulletPuff", 'Fire'); + for (int i = 0; i < 4; i++) + { + Actor tiny = Spawn("VolcanoTBlast", Pos, ALLOW_REPLACE); + if (tiny) + { + tiny.target = self; + tiny.Angle = 90.*i; + tiny.VelFromAngle(0.7); + tiny.Vel.Z = 1. + random[VolcBallImpact]() / 128.; + tiny.CheckMissileSpawn (radius); + } + } + } } // Volcano T Blast ---------------------------------------------------------- @@ -252,4 +383,3 @@ class VolcanoTBlast : Actor } } - From 7ff506961761773026cbb4f683029f54c8d5494e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Nov 2016 22:12:53 +0100 Subject: [PATCH 291/471] - added all missing things to enable the scriptified version of A_BrainSpit. This uses a global function, this has been placed into DObject for now because the scripting interface does not allow non-class-owned functions yet. --- src/CMakeLists.txt | 1 - src/g_doom/a_bossbrain.cpp | 80 ------------------------ src/g_doom/a_doommisc.cpp | 1 - src/g_shared/a_specialspot.cpp | 15 ++++- src/g_skill.cpp | 14 +++++ wadsrc/static/zscript/base.txt | 9 +++ wadsrc/static/zscript/constants.txt | 28 +++++++++ wadsrc/static/zscript/doom/bossbrain.txt | 9 +-- 8 files changed, 68 insertions(+), 89 deletions(-) delete mode 100644 src/g_doom/a_bossbrain.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5f307d56f..b7f2eb3b2e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -866,7 +866,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_doom/a_bossbrain.cpp g_doom/a_doomweaps.cpp g_doom/a_painelemental.cpp g_doom/a_scriptedmarine.cpp diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp deleted file mode 100644 index 8adb5c1dfc..0000000000 --- a/src/g_doom/a_bossbrain.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "statnums.h" -#include "a_specialspot.h" -#include "vm.h" -#include "doomstat.h" -#include "g_level.h" -*/ - -static FRandom pr_spawnfly ("SpawnFly"); - -DEFINE_ACTION_FUNCTION(AActor, A_BrainSpit) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_DEF(spawntype, AActor); - - DSpotState *state = DSpotState::GetSpotState(); - AActor *targ; - AActor *spit; - bool isdefault = false; - - // shoot a cube at current target - targ = state->GetNextInList(PClass::FindActor("BossTarget"), G_SkillProperty(SKILLP_EasyBossBrain)); - - if (targ != NULL) - { - if (spawntype == NULL) - { - spawntype = PClass::FindActor("SpawnShot"); - isdefault = true; - } - - // spawn brain missile - spit = P_SpawnMissile (self, targ, spawntype); - - if (spit != NULL) - { - // Boss cubes should move freely to their destination so it's - // probably best to disable all collision detection for them. - if (spit->flags & MF_NOCLIP) spit->flags5 |= MF5_NOINTERACTION; - - 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.X == 0 && spit->Vel.Y == 0) - { - spit->special2 = 0; - } - else if (fabs(spit->Vel.Y) > fabs(spit->Vel.X)) - { - spit->special2 = int((targ->Y() - self->Y()) / spit->Vel.Y); - } - else - { - spit->special2 = int((targ->X() - self->X()) / spit->Vel.X); - } - // [GZ] Calculates when the projectile will have reached destination - spit->special2 += level.maptime; - spit->flags6 |= MF6_BOSSCUBE; - } - - if (!isdefault) - { - S_Sound(self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NONE); - } - else - { - // compatibility fallback - S_Sound (self, CHAN_WEAPON, "brain/spit", 1, ATTN_NONE); - } - } - return 0; -} - diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 30fd6c671e..4672977614 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -20,7 +20,6 @@ #include "g_shared/a_pickups.h" // Include all the other Doom stuff here to reduce compile time -#include "a_bossbrain.cpp" #include "a_doomweaps.cpp" #include "a_painelemental.cpp" #include "a_scriptedmarine.cpp" diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index c094ee8ba3..e96f5a9036 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -251,6 +251,12 @@ DSpotState *DSpotState::GetSpotState(bool create) return SpotState; } +DEFINE_ACTION_FUNCTION(DSpotState, GetSpotState) +{ + PARAM_PROLOGUE; + ACTION_RETURN_OBJECT(DSpotState::GetSpotState()); +} + //---------------------------------------------------------------------------- // // @@ -317,6 +323,14 @@ ASpecialSpot *DSpotState::GetNextInList(PClassActor *type, int skipcounter) return NULL; } +DEFINE_ACTION_FUNCTION(DSpotState, GetNextInList) +{ + PARAM_SELF_PROLOGUE(DSpotState); + PARAM_CLASS(type, AActor); + PARAM_INT(skipcounter); + ACTION_RETURN_OBJECT(self->GetNextInList(type, skipcounter)); +} + //---------------------------------------------------------------------------- // // @@ -371,7 +385,6 @@ void ASpecialSpot::Destroy() // Mace spawn spot ---------------------------------------------------------- - // Every mace spawn spot will execute this action. The first one // will build a list of all mace spots in the level and spawn a // mace. The rest of the spots will do nothing. diff --git a/src/g_skill.cpp b/src/g_skill.cpp index 44c2cef8c7..70daadc23f 100644 --- a/src/g_skill.cpp +++ b/src/g_skill.cpp @@ -388,6 +388,13 @@ int G_SkillProperty(ESkillProperty prop) return 0; } +DEFINE_ACTION_FUNCTION(DObject, G_SkillPropertyInt) +{ + PARAM_PROLOGUE; + PARAM_INT(which); + ACTION_RETURN_INT(G_SkillProperty((ESkillProperty)which)); +} + //========================================================================== // // @@ -433,6 +440,13 @@ double G_SkillProperty(EFSkillProperty prop) return 0; } +DEFINE_ACTION_FUNCTION(DObject, G_SkillPropertyFloat) +{ + PARAM_PROLOGUE; + PARAM_INT(which); + ACTION_RETURN_FLOAT(G_SkillProperty((EFSkillProperty)which)); +} + //========================================================================== diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 6cf2835e81..1089476a1a 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -1,5 +1,9 @@ class Object native { + // These really should be global functions... + native static int G_SkillPropertyInt(int p); + native static double G_SkillPropertyFloat(int p); + virtual native void Destroy(); native class GetClass(); } @@ -37,3 +41,8 @@ class DropItem : Object native */ } +class SpotState : Object native +{ + native static SpotState GetSpotState(); + native SpecialSpot GetNextInList(class type, int skipcounter); +} \ No newline at end of file diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 3f7a26461d..08eee789e4 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -917,3 +917,31 @@ enum EMapThingFlags MTF_SECRET = 0x080000, // Secret pickup MTF_NOINFIGHTING = 0x100000, }; + +enum ESkillProperty +{ + SKILLP_FastMonsters, + SKILLP_Respawn, + SKILLP_RespawnLimit, + SKILLP_DisableCheats, + SKILLP_AutoUseHealth, + SKILLP_SpawnFilter, + SKILLP_EasyBossBrain, + SKILLP_ACSReturn, + SKILLP_NoPain, + SKILLP_EasyKey, + SKILLP_SlowMonsters, + SKILLP_Infight, +}; +enum EFSkillProperty // floating point properties +{ + SKILLP_AmmoFactor, + SKILLP_DropAmmoFactor, + SKILLP_ArmorFactor, + SKILLP_HealthFactor, + SKILLP_DamageFactor, + SKILLP_Aggressiveness, + SKILLP_MonsterHealth, + SKILLP_FriendlyHealth, +}; + diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 6a72de2bfb..9a2ad759c3 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -212,9 +212,7 @@ extend class Actor Exit_Normal(0); } - native - void A_BrainSpit(class spawntype = null) // needs special treatment for default - ;/* + void A_BrainSpit(class spawntype = null) { SpotState spstate = SpotState.GetSpotState(); Actor targ; @@ -222,7 +220,7 @@ extend class Actor bool isdefault = false; // shoot a cube at current target - targ = spstate.GetNextInList("BossTarget", G_SkillProperty(SKILLP_EasyBossBrain)); + targ = spstate.GetNextInList("BossTarget", G_SkillPropertyInt(SKILLP_EasyBossBrain)); if (targ) { @@ -249,7 +247,7 @@ extend class Actor { spit.special2 = 0; } - else if (abs(spit.Vel.y) > fabs(spit.Vel.x)) + else if (abs(spit.Vel.y) > abs(spit.Vel.x)) { spit.special2 = int((targ.pos.y - pos.y) / spit.Vel.y); } @@ -273,7 +271,6 @@ extend class Actor } } } - */ private void SpawnFly(class spawntype, sound snd) { From 3ce699bf9b465dc222a81e1dcdd8d80bca7368e4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 01:23:56 +0100 Subject: [PATCH 292/471] - implemented pass-by-reference arguments - so far only for memory based variables. - changed Dehacked weapon function lookup to check the symbol table instead of directly referencing the VM functions. Once scriptified these pointers will no longer be available. - removed all special ATAGs from the VM. While well intentioned any pointer tagged with them is basically unusable because it'd trigger asserts all over the place. - scriptified A_Punch for testing pass-by-reference parameters and stack variables. --- src/d_dehacked.cpp | 44 ++++++------ src/d_player.h | 9 ++- src/dobjtype.h | 1 + src/g_doom/a_doomweaps.cpp | 42 ------------ src/g_shared/a_pickups.h | 1 + src/g_shared/a_weapons.cpp | 34 ++++++++- src/namedef.h | 12 ++++ src/p_mobj.cpp | 8 +++ src/scripting/codegeneration/codegen.cpp | 30 ++++++-- src/scripting/thingdef.cpp | 2 +- src/scripting/thingdef_data.cpp | 8 ++- src/scripting/vm/vm.h | 4 +- src/scripting/vm/vmexec.h | 10 +-- src/scripting/zscript/zcc_compile.cpp | 1 + wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/constants.txt | 2 +- wadsrc/static/zscript/doom/doomweapons.txt | 38 ---------- wadsrc/static/zscript/doom/weaponfist.txt | 80 ++++++++++++++++++++++ wadsrc/static/zscript/shared/inventory.txt | 2 + 20 files changed, 205 insertions(+), 126 deletions(-) create mode 100644 wadsrc/static/zscript/doom/weaponfist.txt diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 8d3a135803..7f546b1ee7 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -166,36 +166,27 @@ static TArray MBFCodePointers; struct AmmoPerAttack { - VMNativeFunction **func; + ENamedName func; int ammocount; + VMFunction *ptr; }; DECLARE_ACTION(A_Punch) -DECLARE_ACTION(A_FirePistol) -DECLARE_ACTION(A_FireShotgun) -DECLARE_ACTION(A_FireShotgun2) -DECLARE_ACTION(A_FireCGun) -DECLARE_ACTION(A_FireMissile) -DECLARE_ACTION(A_Saw) -DECLARE_ACTION(A_FirePlasma) -DECLARE_ACTION(A_FireBFG) -DECLARE_ACTION(A_FireOldBFG) -DECLARE_ACTION(A_FireRailgun) // Default ammo use of the various weapon attacks static AmmoPerAttack AmmoPerAttacks[] = { - { &AActor_A_Punch_VMPtr, 0}, - { &AActor_A_FirePistol_VMPtr, 1}, - { &AActor_A_FireShotgun_VMPtr, 1}, - { &AActor_A_FireShotgun2_VMPtr, 2}, - { &AActor_A_FireCGun_VMPtr, 1}, - { &AActor_A_FireMissile_VMPtr, 1}, - { &AActor_A_Saw_VMPtr, 0}, - { &AActor_A_FirePlasma_VMPtr, 1}, - { &AActor_A_FireBFG_VMPtr, -1}, // uses deh.BFGCells - { &AActor_A_FireOldBFG_VMPtr, 1}, - { &AActor_A_FireRailgun_VMPtr, 1}, - { NULL, 0} + { NAME_A_Punch, 0}, + { NAME_A_FirePistol, 1}, + { NAME_A_FireShotgun, 1}, + { NAME_A_FireShotgun2, 2}, + { NAME_A_FireCGun, 1}, + { NAME_A_FireMissile, 1}, + { NAME_A_Saw, 0}, + { NAME_A_FirePlasma, 1}, + { NAME_A_FireBFG, -1}, // uses deh.BFGCells + { NAME_A_FireOldBFG, 1}, + { NAME_A_FireRailgun, 1}, + { NAME_None, 0} }; @@ -3095,7 +3086,12 @@ void FinishDehPatch () StateVisited[state] = true; for(unsigned j = 0; AmmoPerAttacks[j].func != NULL; j++) { - if (state->ActionFunc == *AmmoPerAttacks[j].func) + if (AmmoPerAttacks[i].ptr == nullptr) + { + auto p = dyn_cast(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(AmmoPerAttacks[i].func, true)); + if (p != nullptr) AmmoPerAttacks[i].ptr = p->Variants[0].Implementation; + } + if (state->ActionFunc == AmmoPerAttacks[j].ptr) { found = true; int use = AmmoPerAttacks[j].ammocount; diff --git a/src/d_player.h b/src/d_player.h index 7f57837c70..20a78c9321 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -253,11 +253,10 @@ enum WF_USER4OK = 1 << 11, }; -#define WPIECE1 1 -#define WPIECE2 2 -#define WPIECE3 4 - -#define WP_NOCHANGE ((AWeapon*)~0) +// The VM cannot deal with this as an invalid pointer because it performs a read barrier on every object pointer read. +// This doesn't have to point to a valid weapon, though, because WP_NOCHANGE is never dereferenced, but it must point to a valid object +// and the class descriptor just works fine for that. +#define WP_NOCHANGE ((AWeapon*)RUNTIME_CLASS_CASTLESS(AWeapon)) #define MAXPLAYERNAME 15 diff --git a/src/dobjtype.h b/src/dobjtype.h index bf4608c7b5..bd64832580 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -32,6 +32,7 @@ enum 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. + VARF_Ref = (1<<16), // argument is passed by reference. }; // Symbol information ------------------------------------------------------- diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 108a730c47..95ae4dfb61 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -15,7 +15,6 @@ #include "doomstat.h" */ -static FRandom pr_punch ("Punch"); static FRandom pr_saw ("Saw"); static FRandom pr_fireshotgun2 ("FireSG2"); static FRandom pr_fireplasma ("FirePlasma"); @@ -23,47 +22,6 @@ static FRandom pr_firerail ("FireRail"); static FRandom pr_bfgspray ("BFGSpray"); static FRandom pr_oldbfg ("OldBFG"); -// -// A_Punch -// -DEFINE_ACTION_FUNCTION(AActor, A_Punch) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - DAngle pitch; - FTranslatedLineTarget t; - - if (self->player != NULL) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - } - - damage = (pr_punch()%10+1)<<1; - - if (self->FindInventory()) - damage *= 10; - - angle = self->Angles.Yaw + pr_punch.Random2() * (5.625 / 256); - pitch = P_AimLineAttack (self, angle, MELEERANGE); - - P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, LAF_ISMELEEATTACK, &t); - - // turn to face target - if (t.linetarget) - { - S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM); - self->Angles.Yaw = t.angleFromSource; - } - return 0; -} - // // A_FirePistol // diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 6dc2d0bc59..e50c7f3d82 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -289,6 +289,7 @@ public: class AWeapon : public AStateProvider { DECLARE_CLASS_WITH_META(AWeapon, AStateProvider, PClassWeapon) + HAS_FIELDS HAS_OBJECT_POINTERS public: DWORD WeaponFlags; diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 4a947cbee9..9af5c6de27 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -17,10 +17,13 @@ #include "g_level.h" #include "d_net.h" #include "serializer.h" +#include "thingdef.h" #define BONUSADD 6 -IMPLEMENT_CLASS(AWeapon, false, true, false, false) +extern FFlagDef WeaponFlagDefs[]; + +IMPLEMENT_CLASS(AWeapon, false, true, true, false) IMPLEMENT_POINTERS_START(AWeapon) IMPLEMENT_POINTER(Ammo1) @@ -28,6 +31,26 @@ IMPLEMENT_POINTERS_START(AWeapon) IMPLEMENT_POINTER(SisterWeapon) IMPLEMENT_POINTERS_END +void AWeapon::InitNativeFields() +{ + auto meta = RUNTIME_CLASS(AWeapon); + + meta->AddNativeField("bAltFire", TypeBool, myoffsetof(AWeapon, bAltFire)); + + + // synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them. + for (size_t i = 0; WeaponFlagDefs[i].flagbit != 0xffffffff; i++) + { + if (WeaponFlagDefs[i].structoffset > 0) + { + meta->AddNativeField(FStringf("b%s", WeaponFlagDefs[i].name), (WeaponFlagDefs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), WeaponFlagDefs[i].structoffset, WeaponFlagDefs[i].varflags, WeaponFlagDefs[i].flagbit); + } + } + // This flag is not accessible through actor definitions. + meta->AddNativeField("bDehAmmo", TypeSInt32, myoffsetof(AWeapon, WeaponFlags), VARF_ReadOnly, WIF_DEHAMMO); + +} + FString WeaponSection; TArray KeyConfWeapons; FWeaponSlots *PlayingKeyConf; @@ -651,6 +674,15 @@ bool AWeapon::DepleteAmmo (bool altFire, bool checkEnough, int ammouse) return true; } +DEFINE_ACTION_FUNCTION(AWeapon, DepleteAmmo) +{ + PARAM_SELF_PROLOGUE(AWeapon); + PARAM_BOOL(altfire); + PARAM_BOOL_DEF(checkenough); + PARAM_INT_DEF(ammouse); + ACTION_RETURN_BOOL(self->DepleteAmmo(altfire, checkenough, ammouse)); +} + //=========================================================================== // diff --git a/src/namedef.h b/src/namedef.h index 01859d01a8..d4206e2bba 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -738,3 +738,15 @@ xx(Length) xx(Unit) xx(StateLabel) xx(Overlay) + +xx(A_Punch) +xx(A_FirePistol) +xx(A_FireShotgun) +xx(A_FireShotgun2) +xx(A_FireCGun) +xx(A_FireMissile) +xx(A_Saw) +xx(A_FirePlasma) +xx(A_FireBFG) +xx(A_FireOldBFG) +xx(A_FireRailgun) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index c998bcf919..09d850af58 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1035,6 +1035,14 @@ AInventory *AActor::FindInventory (FName type) return FindInventory(PClass::FindActor(type)); } +DEFINE_ACTION_FUNCTION(AActor, FindInventory) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(type, AInventory); + PARAM_BOOL_DEF(subclass); + ACTION_RETURN_OBJECT(self->FindInventory(type, subclass)); +} + //============================================================================ // // AActor :: GiveInventoryType diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index a5f6a3bc7f..c58167bab0 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3547,7 +3547,7 @@ ExpEmit FxShift::Emit(VMFunctionBuilder *build) if (!op1.Konst) { op1.Free(build); - instr = InstrMap[index][op2.Konst? 0:2]; + instr = InstrMap[index][op2.Konst? 2:0]; } else { @@ -7067,7 +7067,8 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) SAFE_RESOLVE_OPT(Self, ctx); bool failed = false; auto proto = Function->Variants[0].Proto; - auto argtypes = proto->ArgumentTypes; + auto &argtypes = proto->ArgumentTypes; + auto &argflags = Function->Variants[0].ArgFlags; int implicit = Function->GetImplicitArgs(); @@ -7100,8 +7101,29 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } assert(type != nullptr); - FxExpression *x = new FxTypeCast(ArgList[i], type, false); - x = x->Resolve(ctx); + FxExpression *x; + if (!(argflags[i + implicit] & VARF_Ref)) + { + x = new FxTypeCast(ArgList[i], type, false); + x = x->Resolve(ctx); + } + else + { + bool writable; + ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested. + ArgList[i]->RequestAddress(ctx, &writable); + ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType); + // For a reference argument the types must match 100%. + if (type != ArgList[i]->ValueType) + { + ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument", Function->SymbolName.GetChars()); + x = nullptr; + } + else + { + x = ArgList[i]; + } + } failed |= (x == nullptr); ArgList[i] = x; } diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 3abce216db..7f0d988465 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -131,7 +131,7 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArrayPush(NewPointer(cls)); } - args->Push(TypeState/*Info*/); // fixme: TypeState is not the correct type here!!! + args->Push(NewPointer(NewStruct("FStateParamInfo", nullptr))); } if (argflags != nullptr) { diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 95dc0bdce9..8c4220b0ec 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -388,7 +388,7 @@ static FFlagDef InventoryFlagDefs[] = DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP), }; -static FFlagDef WeaponFlagDefs[] = +FFlagDef WeaponFlagDefs[] = { // Weapon flags DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags), @@ -411,12 +411,14 @@ static FFlagDef WeaponFlagDefs[] = DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, NODEATHDESELECT, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, NODEATHINPUT, AWeapon, WeaponFlags), - - DEFINE_DUMMY_FLAG(NOLMS, false), DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags), + + DEFINE_DUMMY_FLAG(NOLMS, false), DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false), }; + + static FFlagDef PlayerPawnFlagDefs[] = { // PlayerPawn flags diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index deca91a803..407080f2c5 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -157,13 +157,15 @@ enum ATAG_OBJECT, // pointer to an object; will be followed by GC // The following are all for documentation during debugging and are - // functionally no different than ATAG_GENERIC. + // functionally no different than ATAG_GENERIC (meaning they are useless because they trigger asserts all over the place.) + /* ATAG_FRAMEPOINTER, // pointer to extra stack frame space for this function ATAG_DREGISTER, // pointer to a data register ATAG_FREGISTER, // pointer to a float register ATAG_SREGISTER, // pointer to a string register ATAG_AREGISTER, // pointer to an address register + */ 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.) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 918dc69492..e4ab959460 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -87,7 +87,7 @@ begin: OP(LFP): ASSERTA(a); assert(sfunc != NULL); assert(sfunc->ExtraSpace > 0); reg.a[a] = f->GetExtra(); - reg.atag[a] = ATAG_FRAMEPOINTER; + reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts. NEXTOP; OP(LB): @@ -461,7 +461,7 @@ begin: break; case REGT_INT | REGT_ADDROF: assert(C < f->NumRegD); - ::new(param) VMValue(®.d[C], ATAG_DREGISTER); + ::new(param) VMValue(®.d[C], ATAG_GENERIC); break; case REGT_INT | REGT_KONST: assert(C < sfunc->NumKonstD); @@ -473,7 +473,7 @@ begin: break; case REGT_STRING | REGT_ADDROF: assert(C < f->NumRegS); - ::new(param) VMValue(®.s[C], ATAG_SREGISTER); + ::new(param) VMValue(®.s[C], ATAG_GENERIC); break; case REGT_STRING | REGT_KONST: assert(C < sfunc->NumKonstS); @@ -485,7 +485,7 @@ begin: break; case REGT_POINTER | REGT_ADDROF: assert(C < f->NumRegA); - ::new(param) VMValue(®.a[C], ATAG_AREGISTER); + ::new(param) VMValue(®.a[C], ATAG_GENERIC); break; case REGT_POINTER | REGT_KONST: assert(C < sfunc->NumKonstA); @@ -512,7 +512,7 @@ begin: break; case REGT_FLOAT | REGT_ADDROF: assert(C < f->NumRegF); - ::new(param) VMValue(®.f[C], ATAG_FREGISTER); + ::new(param) VMValue(®.f[C], ATAG_GENERIC); break; case REGT_FLOAT | REGT_KONST: assert(C < sfunc->NumKonstF); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index ebe70c3407..5dd430f9af 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2160,6 +2160,7 @@ void ZCCCompiler::InitFunctions() if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3)) { type = NewPointer(type); + flags |= VARF_Ref; } else if (type == TypeVector2) { diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 42f32a4476..14493875a6 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -48,6 +48,7 @@ zscript/doom/cyberdemon.txt zscript/doom/spidermaster.txt zscript/doom/keen.txt zscript/doom/bossbrain.txt +zscript/doom/weaponfist.txt zscript/doom/deadthings.txt zscript/doom/doomammo.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 137fedbec3..744128cdd0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -133,6 +133,7 @@ class Actor : Thinker native // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); + native Inventory FindInventory(class itemtype, bool subclass = 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); @@ -471,7 +472,6 @@ class Actor : Thinker native 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(); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 08eee789e4..cf0cbdc5c9 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -829,7 +829,7 @@ enum EStateType struct FStateParamInfo { state mCallingState; - EStateType mStateType; + /*EStateType*/int mStateType; int mPSPIndex; } diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index a6eecd1891..b75cfa9673 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -12,44 +12,6 @@ class DoomWeapon : Weapon } } -// -------------------------------------------------------------------------- -// -// 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; - } -} - // -------------------------------------------------------------------------- // diff --git a/wadsrc/static/zscript/doom/weaponfist.txt b/wadsrc/static/zscript/doom/weaponfist.txt new file mode 100644 index 0000000000..3c1cc992f5 --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponfist.txt @@ -0,0 +1,80 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + action void A_Punch() + { + FTranslatedLineTarget t; + + if (player != null) + { + Weapon weap = player.ReadyWeapon; + if (weap != null && !weap.bDehAmmo && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire)) + return; + } + } + + int damage = random[Punch](1, 10) << 1; + + if (FindInventory("PowerStrength")) + damage *= 10; + + double ang = angle + Random2[Punch]() * (5.625 / 256); + double pitch = AimLineAttack (ang, MELEERANGE); + + LineAttack (ang, MELEERANGE, pitch, damage, 'Melee', "BulletPuff", LAF_ISMELEEATTACK, t); + + // turn to face target + if (t.linetarget) + { + A_PlaySound ("*fist", CHAN_WEAPON); + angle = t.angleFromSource; + } + } + +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 12f30c4848..8337c5399f 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -473,6 +473,8 @@ class Weapon : StateProvider native Stop; } + native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); + native action void A_ZoomFactor(float scale = 1, int flags = 0); native action void A_SetCrosshair(int xhair); const ZOOM_INSTANT = 1; From 10bc01c000016be55c1e7bb9d6dc32eab4ab75b4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 09:10:31 +0100 Subject: [PATCH 293/471] - fixed yet another place where VS did not warn about improper use of NULL. --- src/d_dehacked.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 7f546b1ee7..3ad1b2cd91 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3084,7 +3084,7 @@ void FinishDehPatch () break; // State has already been checked so we reached a loop } StateVisited[state] = true; - for(unsigned j = 0; AmmoPerAttacks[j].func != NULL; j++) + for(unsigned j = 0; AmmoPerAttacks[j].func != NAME_None; j++) { if (AmmoPerAttacks[i].ptr == nullptr) { From df4e9324c9f3d48b15d39f7b95ff04285c856385 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 09:24:54 +0100 Subject: [PATCH 294/471] - added terminators to all flag lists. --- src/scripting/thingdef_data.cpp | 47 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 8c4220b0ec..f2fec2972d 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -386,6 +386,7 @@ static FFlagDef InventoryFlagDefs[] = DEFINE_DEPRECATED_FLAG(PICKUPFLASH), DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP), + { 0xffffffff } }; FFlagDef WeaponFlagDefs[] = @@ -415,6 +416,7 @@ FFlagDef WeaponFlagDefs[] = DEFINE_DUMMY_FLAG(NOLMS, false), DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false), + { 0xffffffff } }; @@ -425,22 +427,24 @@ static FFlagDef PlayerPawnFlagDefs[] = DEFINE_FLAG(PPF, NOTHRUSTWHENINVUL, APlayerPawn, PlayerFlags), DEFINE_FLAG(PPF, CANSUPERMORPH, APlayerPawn, PlayerFlags), DEFINE_FLAG(PPF, CROUCHABLEMORPH, APlayerPawn, PlayerFlags), + { 0xffffffff } }; static FFlagDef PowerSpeedFlagDefs[] = { // PowerSpeed flags DEFINE_FLAG(PSF, NOTRAIL, APowerSpeed, SpeedFlags), + { 0xffffffff } }; static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] = { { &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) }, - { &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs) }, + { &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs)-1 }, + { &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs)-1 }, + { &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs)-1 }, + { &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs)-1 }, }; #define NUM_FLAG_LISTS (countof(FlagLists)) @@ -647,6 +651,23 @@ void P_InitPlayerForScript(); void InitThingdef() { + 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(); + P_InitPlayerForScript(); + + FAutoSegIterator probe(CRegHead, CRegTail); + + while (*++probe != NULL) + { + if (((ClassReg *)*probe)->InitNatives) + ((ClassReg *)*probe)->InitNatives(); + } + // Sort the flag lists for (size_t i = 0; i < NUM_FLAG_LISTS; ++i) { @@ -682,22 +703,4 @@ void InitThingdef() AFTable.ShrinkToFit(); qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp); } - - 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(); - P_InitPlayerForScript(); - - FAutoSegIterator probe(CRegHead, CRegTail); - - while (*++probe != NULL) - { - if (((ClassReg *)*probe)->InitNatives) - ((ClassReg *)*probe)->InitNatives(); - } - } From f11f020b6cb361ee7a8e88d38f9feb6e95583676 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 12:12:29 +0100 Subject: [PATCH 295/471] - allow functions in structs. This is needed for several internal data types like players, sectors, lines, etc. - added a new type 'NativeStruct'. This will be used for types that cannot be instantiated, and is also needed to cleanly handle many internal types that only can exist as reference. --- src/dobjtype.cpp | 18 + src/dobjtype.h | 19 +- src/scripting/codegeneration/codegen.cpp | 49 +- src/scripting/codegeneration/codegen.h | 6 +- src/scripting/thingdef.cpp | 4 +- src/scripting/thingdef.h | 6 +- src/scripting/thingdef_data.cpp | 7 +- src/scripting/zscript/zcc-parse.lemon | 17 +- src/scripting/zscript/zcc_compile.cpp | 650 ++++++++++++----------- src/scripting/zscript/zcc_compile.h | 29 +- src/scripting/zscript/zcc_parser.h | 18 +- 11 files changed, 453 insertions(+), 370 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 32fd30c679..682cc0fd56 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2334,6 +2334,24 @@ PStruct *NewStruct(FName name, PTypeBase *outer) return static_cast(stype); } +/* PNativeStruct ****************************************************************/ + +IMPLEMENT_CLASS(PNativeStruct, false, false, false, false) + +//========================================================================== +// +// PNativeStruct - Parameterized Constructor +// +//========================================================================== + +PNativeStruct::PNativeStruct(FName name) + : PStruct(name, nullptr) +{ + mDescriptiveName.Format("NativeStruct<%s>", name.GetChars()); + Size = 0; + HasNativeFields = true; +} + /* PField *****************************************************************/ IMPLEMENT_CLASS(PField, false, false, false, false) diff --git a/src/dobjtype.h b/src/dobjtype.h index bd64832580..aeb042ebb4 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -694,6 +694,15 @@ protected: PStruct(); }; +// a native struct will always be abstract and cannot be instantiated. All variables are references. +// In addition, native structs can have methods (but no virtual ones.) +class PNativeStruct : public PStruct +{ + DECLARE_CLASS(PNativeStruct, PStruct); +public: + PNativeStruct(FName name = NAME_None); +}; + class PPrototype : public PCompoundType { DECLARE_CLASS(PPrototype, PCompoundType); @@ -723,10 +732,10 @@ public: TArray ArgNames; // we need the names to access them later when the function gets compiled. uint32_t Flags; int UseFlags; - PClass *SelfClass; + PStruct *SelfClass; }; TArray Variants; - PClass *OwningClass = nullptr; + PStruct *OwningClass = nullptr; unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags, int useflags); int GetImplicitArgs() @@ -738,7 +747,7 @@ public: size_t PropagateMark(); - PFunction(PClass *owner = nullptr, FName name = NAME_None) : PSymbol(name), OwningClass(owner) {} + PFunction(PStruct *owner = nullptr, FName name = NAME_None) : PSymbol(name), OwningClass(owner) {} }; // Meta-info for every class derived from DObject --------------------------- @@ -749,9 +758,9 @@ enum }; class PClassClass; -class PClass : public PStruct +class PClass : public PNativeStruct { - DECLARE_CLASS(PClass, PStruct); + DECLARE_CLASS(PClass, PNativeStruct); HAS_OBJECT_POINTERS; protected: // We unravel _WITH_META here just as we did for PType. diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c58167bab0..a7be26f291 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -101,7 +101,7 @@ FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecor if (fnc != nullptr) Class = fnc->OwningClass; } -FCompileContext::FCompileContext(PClass *cls, bool fromdecorate) +FCompileContext::FCompileContext(PStruct *cls, bool fromdecorate) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1) { } @@ -5335,7 +5335,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) delete this; return nullptr; } - if (!ctx.Function->Variants[0].SelfClass->IsDescendantOf(RUNTIME_CLASS(AActor))) + if (!ctx.Function->Variants[0].SelfClass->IsKindOf(RUNTIME_CLASS(PClassActor))) { ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type."); delete this; @@ -5441,7 +5441,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) // //========================================================================== -FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PClass *classctx, FxExpression *&object, PStruct *objtype) +FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classctx, FxExpression *&object, PStruct *objtype) { PSymbol *sym; PSymbolTable *symtbl; @@ -6379,7 +6379,15 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction { auto callingself = caller->Variants[0].SelfClass; auto calledself = callee->Variants[0].SelfClass; - if (!callingself->IsDescendantOf(calledself)) + bool match = (callingself == calledself); + if (!match) + { + auto callingselfcls = dyn_cast(caller->Variants[0].SelfClass); + auto calledselfcls = dyn_cast(callee->Variants[0].SelfClass); + match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->IsDescendantOf(calledselfcls); + } + + if (!match) { ScriptPosition.Message(MSG_ERROR, "Call to member function %s with incompatible self pointer.", callee->SymbolName.GetChars()); return false; @@ -6717,11 +6725,19 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& 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 + auto clstype = dyn_cast(ctx.Function->Variants[0].SelfClass); + if (clstype != nullptr) + { + // give the node the proper value type now that we know it's properly used. + cls = clstype->ParentClass; + Self->ValueType = NewPointer(cls); + Self->ExprType = EFX_Self; + novirtual = true; // super calls are always non-virtual + } + else + { + ScriptPosition.Message(MSG_ERROR, "Super requires a class type"); + } } if (Self->IsVector()) @@ -6775,7 +6791,8 @@ isresolved: if (staticonly && (afd->Variants[0].Flags & VARF_Method)) { - if (!ctx.Class->IsDescendantOf(cls)) + auto clstype = dyn_cast(ctx.Class); + if (clstype == nullptr || !clstype->IsDescendantOf(cls)) { ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here\n", cls->TypeName.GetChars(), MethodName.GetChars()); delete this; @@ -8876,14 +8893,22 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) CHECKRESOLVED(); ABORT(ctx.Class); int symlabel; + auto clstype = dyn_cast(ctx.Class); if (names[0] == NAME_None) { scope = nullptr; } + else if (clstype == nullptr) + { + // not in an actor, so any further checks are pointless. + ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars()); + delete this; + return nullptr; + } else if (names[0] == NAME_Super) { - scope = dyn_cast(ctx.Class->ParentClass); + scope = dyn_cast(clstype->ParentClass); } else { @@ -8894,7 +8919,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) delete this; return nullptr; } - else if (!scope->IsAncestorOf(ctx.Class)) + else if (!scope->IsAncestorOf(clstype)) { ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars()); delete this; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 66a0137b1b..5ad351d6b6 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -75,7 +75,7 @@ struct FCompileContext FxCompoundStatement *Block = nullptr; PPrototype *ReturnProto; PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) - PClass *Class; // The type of the owning class. + PStruct *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.) @@ -84,7 +84,7 @@ struct FCompileContext TDeletingArray FunctionArgs; 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! + FCompileContext(PStruct *cls, bool fromdecorate); // only to be used to resolve constants! PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); @@ -346,7 +346,7 @@ public: FxIdentifier(FName i, const FScriptPosition &p); FxExpression *Resolve(FCompileContext&); - FxExpression *ResolveMember(FCompileContext&, PClass*, FxExpression*&, PStruct*); + FxExpression *ResolveMember(FCompileContext&, PStruct*, FxExpression*&, PStruct*); }; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 7f0d988465..9dcf3a16fb 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -104,7 +104,7 @@ FScriptPosition & GetStateSource(FState *state) // //========================================================================== -void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags, int useflags) +void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PStruct *cls, DWORD funcflags, int useflags) { // Must be called before adding any other arguments. assert(args == nullptr || args->Size() == 0); @@ -182,7 +182,7 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i // //========================================================================== -PFunction *FindClassMemberFunction(PClass *selfcls, PClass *funccls, FName name, FScriptPosition &sc, bool *error) +PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *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; diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index a2c2245580..5bad10c36a 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -146,7 +146,7 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) // //========================================================================== -AFuncDesc *FindFunction(PClass *cls, const char * string); +AFuncDesc *FindFunction(PStruct *cls, const char * string); FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, bool mustresolve = false); @@ -156,9 +156,9 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray *args, TArray *argflags, TArray *argnames, PClass *cls, DWORD funcflags, int useflags); +void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PStruct *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); +PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error); void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate); //========================================================================== diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index f2fec2972d..76770272d4 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -577,11 +577,14 @@ FPropertyInfo *FindProperty(const char * string) // //========================================================================== -AFuncDesc *FindFunction(PClass *cls, const char * string) +AFuncDesc *FindFunction(PStruct *cls, const char * string) { for (int i = 0; i < 2; i++) { - if (i == 1 && !cls->IsDescendantOf(RUNTIME_CLASS(AActor))) break; + // Since many functions have been declared with Actor as owning class, despited being members of something else, let's hack around this until they have been fixed or exported. + // Since most of these are expected to be scriptified anyway, there's no point fixing them all before they get exported. + if (i == 1 && !cls->IsKindOf(RUNTIME_CLASS(PClassActor))) break; + FStringf fullname("%s_%s", i == 0 ? cls->TypeName.GetChars() : "Actor", string); int min = 0, max = AFTable.Size() - 1; diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index c88cab481c..2d3605532d 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -278,16 +278,21 @@ class_member(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ } %type struct_body{ZCC_TreeNode *} %type struct_member{ZCC_TreeNode *} -struct_def(X) ::= STRUCT(T) IDENTIFIER(A) LBRACE opt_struct_body(B) RBRACE opt_semicolon. +struct_def(X) ::= STRUCT(T) IDENTIFIER(A) struct_flags(S) LBRACE opt_struct_body(B) RBRACE opt_semicolon. { NEW_AST_NODE(Struct,def,T); def->NodeName = A.Name(); def->Body = B; def->Type = nullptr; def->Symbol = nullptr; + def->Flags = S.Flags; X = def; } +%type struct_flags{ClassFlagsBlock} +struct_flags(X) ::= . { X.Flags = 0; } +struct_flags(X) ::= NATIVE. { X.Flags = ZCC_Native; } + opt_struct_body(X) ::= . { X = NULL; } opt_struct_body(X) ::= struct_body(X). @@ -295,7 +300,7 @@ struct_body(X) ::= error. { X = NULL; } struct_body(X) ::= struct_member(X). struct_body(X) ::= struct_member(A) struct_body(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); } -struct_member(X) ::= declarator_no_fun(A). { X = A; /*X-overwrites-A*/ } +struct_member(X) ::= declarator(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ } @@ -844,14 +849,6 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C). X = NULL; } } -declarator_no_fun(X) ::= decl_flags(A) type(B) variable_list(C) SEMICOLON. -{ - NEW_AST_NODE(VarDeclarator, decl, A != nullptr? A->SourceLoc : B->SourceLoc); - decl->Type = B; - decl->Names = C; - decl->Flags = A == nullptr? 0 : A->Flags; - X = decl; -} // Need to split it up like this to avoid parsing conflicts. variables_or_function(X) ::= IDENTIFIER(A) LPAREN func_params(B) RPAREN func_const(C) opt_func_body(D). /* Function */ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 5dd430f9af..e50e8b822d 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -196,6 +196,10 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC cls->Fields.Push(static_cast(node)); break; + case AST_FuncDeclarator: + cls->Functions.Push(static_cast(node)); + break; + case AST_EnumTerminator: enumType = nullptr; break; @@ -411,7 +415,7 @@ void ZCCCompiler::CreateStructTypes() { for(auto s : Structs) { - s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->Type; + s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->CType(); s->strct->Type = NewStruct(s->NodeName(), s->Outer); s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type()); GlobalSymbols.AddSymbol(s->strct->Symbol); @@ -1989,6 +1993,331 @@ void ZCCCompiler::InitDefaults() } } + +void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass) +{ + TArray rets(1); + TArray args; + TArray argflags; + TArray argdefaults; + TArray argnames; + + 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; + int useflags = SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM; + if (f->UseFlags != nullptr) + { + useflags = 0; + auto p = f->UseFlags; + do + { + switch (p->Id) + { + case NAME_Actor: + useflags |= SUF_ACTOR; + break; + case NAME_Overlay: + useflags |= SUF_OVERLAY; + break; + case NAME_Weapon: + useflags |= SUF_WEAPON; + break; + case NAME_Item: + useflags |= SUF_ITEM; + break; + default: + Error(p, "Unknown Action qualifier %s", FName(p->Id).GetChars()); + break; + } + + p = static_cast(p->SiblingNext); + } while (p != f->UseFlags); + } + + // 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) + { + // Non-Actors cannot have action functions. + if (!c->Type()->IsKindOf(RUNTIME_CLASS(PClassActor))) + { + Error(f, "'Action' can only be used in child classes of Actor"); + } + + varflags |= VARF_Final; // Action implies Final. + if (useflags & (SUF_OVERLAY | SUF_WEAPON | SUF_ITEM)) + { + varflags |= VARF_Action; + implicitargs = 3; + } + else + { + implicitargs = 1; + } + } + 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(c->Type(), 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); + } + } + SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags, useflags); + 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); + flags |= VARF_Ref; + } + 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, useflags); + 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; + } + if (forclass) + { + PClass *clstype = static_cast(c->Type()); + int vindex = clstype->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 = clstype->Virtuals[vindex]; + if (oldfunc->Final) + { + Error(p, "Attempt to override final function %s", FName(f->Name).GetChars()); + } + clstype->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 = clstype->Virtuals.Push(sym->Variants[0].Implementation); + } + } + else + { + Error(p, "Virtual functions can only be defined for classes"); + } + } + } +} + //========================================================================== // // Parses the functions list @@ -1997,11 +2326,13 @@ void ZCCCompiler::InitDefaults() void ZCCCompiler::InitFunctions() { - TArray rets(1); - TArray args; - TArray argflags; - TArray argdefaults; - TArray argnames; + for (auto s : Structs) + { + for (auto f : s->Functions) + { + CompileFunction(s, f, false); + } + } for (auto c : Classes) { @@ -2017,306 +2348,7 @@ void ZCCCompiler::InitFunctions() } 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; - int useflags = SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM; - if (f->UseFlags != nullptr) - { - useflags = 0; - auto p = f->UseFlags; - do - { - switch (p->Id) - { - case NAME_Actor: - useflags |= SUF_ACTOR; - break; - case NAME_Overlay: - useflags |= SUF_OVERLAY; - break; - case NAME_Weapon: - useflags |= SUF_WEAPON; - break; - case NAME_Item: - useflags |= SUF_ITEM; - break; - default: - Error(p, "Unknown Action qualifier %s", FName(p->Id).GetChars()); - break; - } - - p = static_cast(p->SiblingNext); - } while (p != f->UseFlags); - } - - // 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_Final; // Action implies Final. - if (useflags & (SUF_OVERLAY | SUF_WEAPON | SUF_ITEM)) - { - varflags |= VARF_Action; - implicitargs = 3; - } - else - { - implicitargs = 1; - } - } - 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(c->Type(), 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); - } - } - SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags, useflags); - 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); - flags |= VARF_Ref; - } - 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, useflags); - 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); - } - } - } + CompileFunction(c, f, true); } } } @@ -2368,7 +2400,9 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) { 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))) + auto selfclass = dyn_cast(afd->Variants[0].SelfClass); + assert(selfclass != nullptr); // non classes are not supposed to get here. + if ((afd->Variants[0].Flags & VARF_Action) || !cls->IsDescendantOf(RUNTIME_CLASS(AStateProvider)) || !selfclass->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) { return new FxVMFunctionCall(new FxSelf(*af), afd, argumentlist, *af, false); } @@ -2663,7 +2697,7 @@ void ZCCCompiler::CompileStates() // //========================================================================== -FxExpression *ZCCCompiler::ConvertAST(PClass *cls, ZCC_TreeNode *ast) +FxExpression *ZCCCompiler::ConvertAST(PStruct *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. diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 2e8840a467..84e3143530 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -20,6 +20,11 @@ struct ZCC_StructWork TArray Enums; TArray Constants; TArray Fields; + TArray Functions; + + ZCC_StructWork() + { + } ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n, ZCC_Class *outer) { @@ -41,34 +46,25 @@ struct ZCC_StructWork }; -struct ZCC_ClassWork +struct ZCC_ClassWork : public ZCC_StructWork { 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) { + strct = s; cls = s; node = n; - } - - FName NodeName() const - { - return cls->NodeName; + OuterDef = nullptr; + Outer = nullptr; } PClass *Type() { - return cls->Type; + return static_cast(strct->Type); } - }; struct ZCC_ConstantWork @@ -108,6 +104,7 @@ private: int GetInt(ZCC_Expression *expr); double GetDouble(ZCC_Expression *expr); const char *GetString(ZCC_Expression *expr, bool silent = false); + void CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass); void InitFunctions(); void CompileStates(); @@ -142,12 +139,12 @@ private: 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 *ConvertAST(PStruct *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 + PStruct *ConvertClass; // class type to be used when resoving symbols while converting an AST PSymbolTable *GlobalTreeNodes; PSymbolTable *OutputSymbols; ZCC_AST &AST; diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 070bef449d..dd777eb6ce 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -202,19 +202,19 @@ struct ZCC_NamedNode : ZCC_TreeNode PSymbolType *Symbol; }; -struct ZCC_Class : ZCC_NamedNode +struct ZCC_Struct : ZCC_NamedNode +{ + VM_UWORD Flags; + ZCC_TreeNode *Body; + PStruct *Type; +}; + +struct ZCC_Class : ZCC_Struct { ZCC_Identifier *ParentName; ZCC_Identifier *Replaces; - VM_UWORD Flags; - ZCC_TreeNode *Body; - PClass *Type; -}; -struct ZCC_Struct : ZCC_NamedNode -{ - ZCC_TreeNode *Body; - PStruct *Type; + PClass *CType() { return static_cast(Type); } }; struct ZCC_Enum : ZCC_NamedNode From 9fab8380ffeb6a59a4dfa4afa8ed2fca178370fd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 12:22:58 +0100 Subject: [PATCH 296/471] - fixed: FxVMFunctionCall::GetDirectFunction did not check if the function could be called with no arguments. --- src/scripting/codegeneration/codegen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index a7be26f291..fe571ee416 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7066,6 +7066,8 @@ VMFunction *FxVMFunctionCall::GetDirectFunction() // it inside VM code. if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) { + unsigned imp = Function->GetImplicitArgs(); + if (Function->Variants[0].ArgFlags.Size() <= imp || !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr; return Function->Variants[0].Implementation; } From 25e285b65d2e6f2ebef361267c89c83e828f5b1b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 12:25:53 +0100 Subject: [PATCH 297/471] - fixed bad conversion from FString to const char * in state label type cast. --- src/scripting/codegeneration/codegen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index fe571ee416..8fa8f4554e 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1440,8 +1440,8 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) // 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. + FString s= static_cast(basex)->GetValue().GetString(); + if (s.Len() == 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; From de8cacc4653ceebe19e33b6555834afd5a53dd55 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 12:41:00 +0100 Subject: [PATCH 298/471] - for struct member calls an address request is needed. --- src/scripting/codegeneration/codegen.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8fa8f4554e..4a8f4b55b6 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7185,6 +7185,12 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { ValueType = TypeVoid; } + // If self is a struct, it will be a value type, not a reference, so we need to make an addresss request. + if (Self != nullptr && Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClass))) + { + bool writable; + Self->RequestAddress(ctx, &writable); + } return this; } From d50da34664d40b4789d53d7146e422c13b1390e0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 13:56:29 +0100 Subject: [PATCH 299/471] - scriptified the pistol to test if struct member functions work. - made APlayerPawn::PlayAttacking(2) virtual script functions so that mods have better control over player animations. Note that these have no native base so they skip the templated interface for managing virtual functions. --- src/dobjtype.cpp | 2 +- src/g_doom/a_doomweaps.cpp | 57 +++++------ src/p_pspr.cpp | 39 ++++---- src/p_pspr.h | 2 - src/p_user.cpp | 14 ++- src/scripting/codegeneration/codegen.cpp | 29 ++++-- src/scripting/vm/vm.h | 6 +- src/virtual.h | 20 ++-- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/constants.txt | 1 + wadsrc/static/zscript/doom/doomweapons.txt | 47 --------- wadsrc/static/zscript/doom/weaponpistol.txt | 100 ++++++++++++++++++++ wadsrc/static/zscript/shared/inventory.txt | 1 - wadsrc/static/zscript/shared/player.txt | 20 ++++ 15 files changed, 214 insertions(+), 126 deletions(-) create mode 100644 wadsrc/static/zscript/doom/weaponpistol.txt diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 682cc0fd56..5154d1689f 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2535,7 +2535,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra assert(proto->ArgumentTypes.Size() > 0); auto selftypeptr = dyn_cast(proto->ArgumentTypes[0]); assert(selftypeptr != nullptr); - variant.SelfClass = dyn_cast(selftypeptr->PointedType); + variant.SelfClass = dyn_cast(selftypeptr->PointedType); assert(variant.SelfClass != nullptr); } else diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 95ae4dfb61..77085f5b58 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -22,40 +22,6 @@ static FRandom pr_firerail ("FireRail"); static FRandom pr_bfgspray ("BFGSpray"); static FRandom pr_oldbfg ("OldBFG"); -// -// A_FirePistol -// -DEFINE_ACTION_FUNCTION(AActor, A_FirePistol) -{ - PARAM_ACTION_PROLOGUE(AActor); - - bool accurate; - - if (self->player != nullptr) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return 0; - - P_SetPsprite(self->player, PSP_FLASH, weapon->FindState(NAME_Flash), true); - } - self->player->mo->PlayAttacking2 (); - - accurate = !self->player->refire; - } - else - { - accurate = true; - } - - S_Sound (self, CHAN_WEAPON, "weapons/pistol", 1, ATTN_NORM); - - P_GunShot (self, accurate, PClass::FindActor(NAME_BulletPuff), P_BulletSlope (self)); - return 0; -} - // // A_Saw // @@ -71,6 +37,29 @@ enum SAW_Flags SF_STEALARMOR = 128, }; + +static FRandom pr_gunshot("GunShot"); +// +// P_GunShot +// +void P_GunShot(AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch) +{ + DAngle angle; + int damage; + + damage = 5 * (pr_gunshot() % 3 + 1); + angle = mo->Angles.Yaw; + + if (!accurate) + { + angle += pr_gunshot.Random2() * (5.625 / 256); + } + + P_LineAttack(mo, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, pufftype); +} + + + DEFINE_ACTION_FUNCTION(AActor, A_Saw) { PARAM_ACTION_PROLOGUE(AActor); diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 1ba452b2b9..d47156d161 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -79,7 +79,6 @@ CVAR(Int, sv_fastweapons, false, CVAR_SERVERINFO); // PRIVATE DATA DEFINITIONS ------------------------------------------------ static FRandom pr_wpnreadysnd ("WpnReadySnd"); -static FRandom pr_gunshot ("GunShot"); static const FGenericButtons ButtonChecks[] = { @@ -184,6 +183,16 @@ void P_SetPsprite(player_t *player, PSPLayers id, FState *state, bool pending) player->GetPSprite(id)->SetState(state, pending); } +DEFINE_ACTION_FUNCTION(_Player, SetPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_INT(id); + PARAM_POINTER(state, FState); + PARAM_BOOL_DEF(pending); + P_SetPsprite(self, (PSPLayers)id, state, pending); + return 0; +} + DPSprite *player_t::GetPSprite(PSPLayers layer) { AActor *oldcaller = nullptr; @@ -1381,6 +1390,15 @@ DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget, int aimfla return pitch; } +DEFINE_ACTION_FUNCTION(AActor, BulletSlope) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER_DEF(t, FTranslatedLineTarget); + PARAM_INT_DEF(aimflags); + ACTION_RETURN_FLOAT(P_BulletSlope(self, t, aimflags).Degrees); +} + + AActor *P_AimTarget(AActor *mo) { FTranslatedLineTarget t; @@ -1395,25 +1413,6 @@ DEFINE_ACTION_FUNCTION(AActor, AimTarget) } -// -// P_GunShot -// -void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch) -{ - DAngle angle; - int damage; - - damage = 5*(pr_gunshot()%3+1); - angle = mo->Angles.Yaw; - - if (!accurate) - { - angle += pr_gunshot.Random2 () * (5.625 / 256); - } - - P_LineAttack (mo, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, pufftype); -} - DEFINE_ACTION_FUNCTION(AActor, A_Light) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/p_pspr.h b/src/p_pspr.h index d75f08b067..3c8f0097ec 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -111,8 +111,6 @@ 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); - void DoReadyWeapon(AActor *self); void DoReadyWeaponToBob(AActor *self); void DoReadyWeaponToFire(AActor *self, bool primary = true, bool secondary = true); diff --git a/src/p_user.cpp b/src/p_user.cpp index 00e58e5ef1..6f58f3cc84 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1280,12 +1280,22 @@ void APlayerPawn::PlayRunning () void APlayerPawn::PlayAttacking () { - if (MissileState != NULL) SetState (MissileState); + static int VIndex = -1; + if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(APlayerPawn), "PlayAttacking"); + // 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 APlayerPawn::PlayAttacking2 () { - if (MeleeState != NULL) SetState (MeleeState); + static int VIndex = -1; + if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(APlayerPawn), "PlayAttacking2"); + // 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 APlayerPawn::ThrowPoisonBag () diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4a8f4b55b6..3577ac1ecf 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6706,7 +6706,7 @@ FxMemberFunctionCall::~FxMemberFunctionCall() FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) { ABORT(ctx.Class); - PClass *cls; + PStruct *cls; bool staticonly = false; bool novirtual = false; @@ -6714,11 +6714,19 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) { // 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) + PClass *ccls = PClass::FindClass(static_cast(Self)->Identifier); + if (ccls != nullptr) { - staticonly = true; - goto isresolved; + if (ccls->bExported) + { + cls = ccls; + staticonly = true; + goto isresolved; + } + } + else + { + // Todo: static struct members need to work as well. } } SAFE_RESOLVE(Self, ctx); @@ -6755,9 +6763,9 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { auto ptype = static_cast(Self->ValueType)->PointedType; - if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) + if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) { - cls = static_cast(ptype); + cls = static_cast(ptype); } else { @@ -6773,6 +6781,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } + // Todo: handle member calls from instantiated structs. + isresolved: bool error = false; PFunction *afd = FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error); @@ -6792,7 +6802,8 @@ isresolved: if (staticonly && (afd->Variants[0].Flags & VARF_Method)) { auto clstype = dyn_cast(ctx.Class); - if (clstype == nullptr || !clstype->IsDescendantOf(cls)) + auto ccls = dyn_cast(cls); + if (clstype == nullptr || ccls == nullptr || !clstype->IsDescendantOf(ccls)) { ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here\n", cls->TypeName.GetChars(), MethodName.GetChars()); delete this; @@ -7067,7 +7078,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction() if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) { unsigned imp = Function->GetImplicitArgs(); - if (Function->Variants[0].ArgFlags.Size() <= imp || !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr; + if (Function->Variants[0].ArgFlags.Size() > imp && !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr; return Function->Variants[0].Implementation; } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 407080f2c5..670c5a982e 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1032,8 +1032,6 @@ struct AFuncDesc // change every single use in case the parameters change. #define DECLARE_ACTION(name) extern VMNativeFunction *AActor_##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_##cls##_##name(VM_ARGS); \ VMNativeFunction *cls##_##name##_VMPtr; \ @@ -1077,6 +1075,10 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); PARAM_PROLOGUE; \ PARAM_OBJECT(self, type); +// for structs we need to check for ATAG_GENERIC instead of ATAG_OBJECT +#define PARAM_SELF_STRUCT_PROLOGUE(type) \ + PARAM_PROLOGUE; \ + PARAM_POINTER(self, type); class PFunction; diff --git a/src/virtual.h b/src/virtual.h index d3a2bfa3a7..e0679df740 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -37,6 +37,17 @@ VMEXPORTED_NATIVES_START VMEXPORTED_NATIVES_FUNC(PostBeginPlay) VMEXPORTED_NATIVES_END + +inline int GetVirtualIndex(PClass *cls, const char *funcname) +{ + // 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(cls->Symbols.FindSymbol(funcname, false)); + assert(sym != nullptr); + auto VIndex = sym->Variants[0].Implementation->VirtualIndex; + assert(VIndex >= 0); + return VIndex; +} + template class DVMObject : public T { @@ -79,14 +90,7 @@ public: 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); - } + if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(DObject), "Destroy"); // Without the type cast this picks the 'void *' assignment... VMValue params[1] = { (DObject*)this }; VMFrameStack stack; diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 14493875a6..2f5a420a3b 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -49,6 +49,7 @@ zscript/doom/spidermaster.txt zscript/doom/keen.txt zscript/doom/bossbrain.txt zscript/doom/weaponfist.txt +zscript/doom/weaponpistol.txt zscript/doom/deadthings.txt zscript/doom/doomammo.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 744128cdd0..0fd6d2282a 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -78,6 +78,7 @@ class Actor : Thinker native native void SetXYZ(vector3 newpos); native Actor GetPointer(int aaptr); native void FaceMovementDirection(); + native double BulletSlope(out FTranslatedLineTarget pLineTarget = null, int aimflags = 0); native Actor AimTarget(); native bool CheckMissileSpawn(double maxdist); native bool CheckPosition(Vector2 pos, bool actorsonly = false); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index cf0cbdc5c9..cfdc98425b 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -711,6 +711,7 @@ enum EPSpriteFlags // Default psprite layers enum EPSPLayers { + PSP_STRIFEHANDS = -1, PSP_WEAPON = 1, PSP_FLASH = 1000, }; diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index b75cfa9673..60b5ba1577 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -13,53 +13,6 @@ class DoomWeapon : Weapon } -// -------------------------------------------------------------------------- -// -// 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 diff --git a/wadsrc/static/zscript/doom/weaponpistol.txt b/wadsrc/static/zscript/doom/weaponpistol.txt new file mode 100644 index 0000000000..45a1ebecdf --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponpistol.txt @@ -0,0 +1,100 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + +//=========================================================================== +// +// Code (must be attached to StateProvider) +// +//=========================================================================== + +extend class StateProvider +{ + //=========================================================================== + // This is also used by the shotgun and chaingun + //=========================================================================== + + protected action void GunShot(bool accurate, Class pufftype, double pitch) + { + int damage = 5 * random[GunShot](1, 3); + double ang = angle; + + if (!accurate) + { + ang += Random2[GunShot]() * (5.625 / 256); + } + + LineAttack(ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', pufftype); + } + + //=========================================================================== + action void A_FirePistol() + { + bool accurate; + + if (player != null) + { + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + + player.SetPsprite(PSP_FLASH, weap.FindState('Flash'), true); + } + player.mo.PlayAttacking2 (); + + accurate = !player.refire; + } + else + { + accurate = true; + } + + A_PlaySound ("weapons/pistol", CHAN_WEAPON); + GunShot (accurate, "BulletPuff", BulletSlope ()); + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 8337c5399f..d66843593c 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -49,7 +49,6 @@ class StateProvider : Inventory native 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(); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 224011acdc..e2bbefbea5 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -38,6 +38,17 @@ class PlayerPawn : Actor native Player.ViewBob 1; Obituary "$OB_MPDEFAULT"; } + + virtual void PlayAttacking () + { + if (MissileState != null) SetState (MissileState); + } + + virtual void PlayAttacking2 () + { + if (MeleeState != null) SetState (MeleeState); + } + } class PlayerChunk : PlayerPawn native @@ -57,3 +68,12 @@ class PlayerChunk : PlayerPawn native -TELESTOMP } } + +class PSprite : Object native +{ +} + +struct Player native +{ + native void SetPsprite(int id, State stat, bool pending = false); +} \ No newline at end of file From 0b70df88d8c92039184bf8bfd37f3dda458f7f88 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 16:39:45 +0100 Subject: [PATCH 300/471] - scriptified A_FireShotgun and A_FireChaingun. --- src/g_doom/a_doomweaps.cpp | 149 +----------------- src/p_pspr.cpp | 75 ++++++++- src/p_pspr.h | 1 + wadsrc/static/zscript.txt | 2 + wadsrc/static/zscript/doom/doomweapons.txt | 92 ----------- wadsrc/static/zscript/doom/weaponchaingun.txt | 82 ++++++++++ wadsrc/static/zscript/doom/weaponshotgun.txt | 85 ++++++++++ wadsrc/static/zscript/shared/inventory.txt | 2 - wadsrc/static/zscript/shared/player.txt | 2 + 9 files changed, 247 insertions(+), 243 deletions(-) create mode 100644 wadsrc/static/zscript/doom/weaponchaingun.txt create mode 100644 wadsrc/static/zscript/doom/weaponshotgun.txt diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 77085f5b58..f7a73a4ce6 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -15,6 +15,7 @@ #include "doomstat.h" */ +void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index); static FRandom pr_saw ("Saw"); static FRandom pr_fireshotgun2 ("FireSG2"); static FRandom pr_fireplasma ("FirePlasma"); @@ -38,28 +39,6 @@ enum SAW_Flags }; -static FRandom pr_gunshot("GunShot"); -// -// P_GunShot -// -void P_GunShot(AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch) -{ - DAngle angle; - int damage; - - damage = 5 * (pr_gunshot() % 3 + 1); - angle = mo->Angles.Yaw; - - if (!accurate) - { - angle += pr_gunshot.Random2() * (5.625 / 256); - } - - P_LineAttack(mo, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, pufftype); -} - - - DEFINE_ACTION_FUNCTION(AActor, A_Saw) { PARAM_ACTION_PROLOGUE(AActor); @@ -199,40 +178,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_Saw) return 0; } -// -// A_FireShotgun -// -DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun) -{ - PARAM_ACTION_PROLOGUE(AActor); - - int i; - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - - S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM); - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return 0; - P_SetPsprite(player, PSP_FLASH, weapon->FindState(NAME_Flash), true); - } - player->mo->PlayAttacking2 (); - - DAngle pitch = P_BulletSlope (self); - - for (i = 0; i < 7; i++) - { - P_GunShot (self, false, PClass::FindActor(NAME_BulletPuff), pitch); - } - return 0; -} - // // A_FireShotgun2 // @@ -283,98 +228,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) return 0; } -//------------------------------------------------------------------------------------ -// -// Setting a random flash like some of Doom's weapons can easily crash when the -// definition is overridden incorrectly so let's check that the state actually exists. -// Be aware though that this will not catch all DEHACKED related problems. But it will -// find all DECORATE related ones. -// -//------------------------------------------------------------------------------------ - -void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index) -{ - - PClassActor *cls = weapon->GetClass(); - while (cls != RUNTIME_CLASS(AWeapon)) - { - if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates) - { - // The flash state belongs to this class. - // Now let's check if the actually wanted state does also - if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates) - { - // we're ok so set the state - P_SetPsprite(player, PSP_FLASH, flashstate + index, true); - return; - } - else - { - // oh, no! The state is beyond the end of the state table so use the original flash state. - P_SetPsprite(player, PSP_FLASH, flashstate, true); - return; - } - } - // try again with parent class - cls = static_cast(cls->ParentClass); - } - // if we get here the state doesn't seem to belong to any class in the inheritance chain - // This can happen with Dehacked if the flash states are remapped. - // The only way to check this would be to go through all Dehacked modifiable actors, convert - // their states into a single flat array and find the correct one. - // Rather than that, just check to make sure it belongs to something. - if (FState::StaticFindStateOwner(flashstate + index) == NULL) - { // Invalid state. With no index offset, it should at least be valid. - index = 0; - } - P_SetPsprite(player, PSP_FLASH, flashstate + index, true); -} - -// -// A_FireCGun -// -DEFINE_ACTION_FUNCTION(AActor, A_FireCGun) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (self == nullptr || nullptr == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return 0; - - S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM); - - FState *flash = weapon->FindState(NAME_Flash); - if (flash != nullptr) - { - // [RH] Fix for Sparky's messed-up Dehacked patch! Blargh! - FState * atk = weapon->FindState(NAME_Fire); - - int theflash = clamp (int(player->GetPSprite(PSP_WEAPON)->GetState() - atk), 0, 1); - - if (flash[theflash].sprite != flash->sprite) - { - theflash = 0; - } - - P_SetSafeFlash (weapon, player, flash, theflash); - } - - } - player->mo->PlayAttacking2 (); - - P_GunShot (self, !player->refire, PClass::FindActor(NAME_BulletPuff), P_BulletSlope (self)); - return 0; -} - // // A_FireMissile // diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index d47156d161..3bc2dfbe1d 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -29,6 +29,7 @@ #include "d_player.h" #include "serializer.h" #include "v_text.h" +#include "cmdlib.h" // MACROS ------------------------------------------------------------------ @@ -98,13 +99,20 @@ static const FGenericButtons ButtonChecks[] = // //------------------------------------------------------------------------ -IMPLEMENT_CLASS(DPSprite, false, true, false, false) +IMPLEMENT_CLASS(DPSprite, false, true, true, false) IMPLEMENT_POINTERS_START(DPSprite) IMPLEMENT_POINTER(Caller) IMPLEMENT_POINTER(Next) IMPLEMENT_POINTERS_END +void DPSprite::InitNativeFields() +{ + auto meta = RUNTIME_CLASS(DPSprite); + + meta->AddNativeField("State", TypeState, myoffsetof(DPSprite, State), VARF_ReadOnly); +} + //------------------------------------------------------------------------ // // @@ -254,6 +262,14 @@ DPSprite *player_t::GetPSprite(PSPLayers layer) return pspr; } +DEFINE_ACTION_FUNCTION(_Player, GetPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_INT(id); + ACTION_RETURN_OBJECT(self->GetPSprite((PSPLayers)id)); +} + + //--------------------------------------------------------------------------- // // PROC P_NewPspriteTick @@ -1561,6 +1577,63 @@ void player_t::DestroyPSprites() } } +//------------------------------------------------------------------------------------ +// +// Setting a random flash like some of Doom's weapons can easily crash when the +// definition is overridden incorrectly so let's check that the state actually exists. +// Be aware though that this will not catch all DEHACKED related problems. But it will +// find all DECORATE related ones. +// +//------------------------------------------------------------------------------------ + +void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index) +{ + + PClassActor *cls = weapon->GetClass(); + while (cls != RUNTIME_CLASS(AWeapon)) + { + if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates) + { + // The flash state belongs to this class. + // Now let's check if the actually wanted state does also + if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates) + { + // we're ok so set the state + P_SetPsprite(player, PSP_FLASH, flashstate + index, true); + return; + } + else + { + // oh, no! The state is beyond the end of the state table so use the original flash state. + P_SetPsprite(player, PSP_FLASH, flashstate, true); + return; + } + } + // try again with parent class + cls = static_cast(cls->ParentClass); + } + // if we get here the state doesn't seem to belong to any class in the inheritance chain + // This can happen with Dehacked if the flash states are remapped. + // The only way to check this would be to go through all Dehacked modifiable actors, convert + // their states into a single flat array and find the correct one. + // Rather than that, just check to make sure it belongs to something. + if (FState::StaticFindStateOwner(flashstate + index) == NULL) + { // Invalid state. With no index offset, it should at least be valid. + index = 0; + } + P_SetPsprite(player, PSP_FLASH, flashstate + index, true); +} + +DEFINE_ACTION_FUNCTION(_Player, SetSafeFlash) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_OBJECT(weapon, AWeapon); + PARAM_POINTER(state, FState); + PARAM_INT(index); + P_SetSafeFlash(weapon, self, state, index); + return 0; +} + //------------------------------------------------------------------------ // // diff --git a/src/p_pspr.h b/src/p_pspr.h index 3c8f0097ec..4c019c7d4d 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -59,6 +59,7 @@ enum PSPFlags class DPSprite : public DObject { DECLARE_CLASS (DPSprite, DObject) + HAS_FIELDS HAS_OBJECT_POINTERS public: DPSprite(player_t *owner, AActor *caller, int id); diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 2f5a420a3b..9244b9bdb9 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -50,6 +50,8 @@ zscript/doom/keen.txt zscript/doom/bossbrain.txt zscript/doom/weaponfist.txt zscript/doom/weaponpistol.txt +zscript/doom/weaponshotgun.txt +zscript/doom/weaponchaingun.txt zscript/doom/deadthings.txt zscript/doom/doomammo.txt diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index 60b5ba1577..ee7a821eaa 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -54,54 +54,6 @@ class Chainsaw : Weapon } -// -------------------------------------------------------------------------- -// -// 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 @@ -157,50 +109,6 @@ class SuperShotgun : DoomWeapon } } -// -------------------------------------------------------------------------- -// -// 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 diff --git a/wadsrc/static/zscript/doom/weaponchaingun.txt b/wadsrc/static/zscript/doom/weaponchaingun.txt new file mode 100644 index 0000000000..92b3aec463 --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponchaingun.txt @@ -0,0 +1,82 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + +//=========================================================================== +// +// Code (must be attached to StateProvider) +// +//=========================================================================== + +extend class StateProvider +{ + action void A_FireCGun() + { + if (player == null) + { + return; + } + + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + + A_PlaySound ("weapons/chngun", CHAN_WEAPON); + + State flash = weap.FindState('Flash'); + if (flash != null) + { + // Removed most of the mess that was here in the C++ code because SetSafeFlash already does some thorough validation. + State atk = weap.FindState('Fire'); + State cur = player.GetPSprite(PSP_WEAPON).State; + int theflash = atk == cur? 0:1; + player.SetSafeFlash(weap, flash, theflash); + } + } + player.mo.PlayAttacking2 (); + + GunShot (!player.refire, "BulletPuff", BulletSlope ()); + } +} diff --git a/wadsrc/static/zscript/doom/weaponshotgun.txt b/wadsrc/static/zscript/doom/weaponshotgun.txt new file mode 100644 index 0000000000..6a08afc11d --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponshotgun.txt @@ -0,0 +1,85 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + +//=========================================================================== +// +// Code (must be attached to StateProvider) +// +//=========================================================================== + +extend class StateProvider +{ + + action void A_FireShotgun() + { + if (player == null) + { + return; + } + + A_PlaySound ("weapons/shotgf", CHAN_WEAPON); + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + + player.SetPsprite(PSP_FLASH, weap.FindState('Flash'), true); + } + player.mo.PlayAttacking2 (); + + double pitch = BulletSlope (); + + for (int i = 0; i < 7; i++) + { + GunShot (false, "BulletPuff", pitch); + } + } + +} + diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index d66843593c..64c649ad64 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -49,14 +49,12 @@ class StateProvider : Inventory native action native void A_WeaponReady(int flags = 0); action native void A_Lower(); action native void A_Raise(); - 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(); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index e2bbefbea5..c8485cebde 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -76,4 +76,6 @@ class PSprite : Object native struct Player native { native void SetPsprite(int id, State stat, bool pending = false); + native void SetSafeFlash(Weapon weap, State flashstate, int index); + native PSprite GetPSprite(int id); } \ No newline at end of file From 7595343aaac23ed4e374a900723f020d8ab89fa5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 18:02:07 +0100 Subject: [PATCH 301/471] - fixed: Completely empty if statements left the code generator in a broken state. --- src/scripting/codegeneration/codegen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 3577ac1ecf..e38b6bd6bc 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7946,7 +7946,8 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) if (WhenTrue == nullptr && WhenFalse == nullptr) { // We don't do anything either way, so disappear delete this; - return nullptr; + ScriptPosition.Message(MSG_WARNING, "empty if statement"); + return new FxNop(ScriptPosition); } SAFE_RESOLVE(Condition, ctx); From 74c5659fc586e59d495e2295f1833a44ed26479b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Nov 2016 18:09:34 +0100 Subject: [PATCH 302/471] - explicitly call Destroy in PClass::StaticShutdown because some class type objects were no longer automatically collected. --- src/dobjtype.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 5154d1689f..965a0d8fd9 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2765,6 +2765,7 @@ void PClass::StaticShutdown () uniqueFPs.Push(const_cast(type->FlatPointers)); } } + type->Destroy(); } for (i = 0; i < uniqueFPs.Size(); ++i) { From af34d82888ba4a362902d5e03635c5d1a6ae436f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 00:25:38 +0100 Subject: [PATCH 303/471] - scriptified A_Saw. - implemented multiple-return-value assignment. Due to some grammar conflicts the originally intended Lua-inspired syntax of 'a, b = Function()' could not be done, so it's '[a, b] = Function()' --- src/g_doom/a_doomweaps.cpp | 155 ---------------- src/g_shared/a_armor.cpp | 16 +- src/g_shared/a_pickups.cpp | 35 +++- src/g_shared/a_pickups.h | 1 + src/p_mobj.cpp | 6 + src/scripting/codegeneration/codegen.cpp | 150 ++++++++++++++-- src/scripting/codegeneration/codegen.h | 38 +++- src/scripting/zscript/zcc-parse.lemon | 9 +- src/scripting/zscript/zcc_compile.cpp | 31 +++- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 4 + wadsrc/static/zscript/doom/doomweapons.txt | 41 ----- wadsrc/static/zscript/doom/weaponchainsaw.txt | 166 ++++++++++++++++++ wadsrc/static/zscript/shared/inventory.txt | 4 +- 14 files changed, 426 insertions(+), 231 deletions(-) create mode 100644 wadsrc/static/zscript/doom/weaponchainsaw.txt diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index f7a73a4ce6..e802a6103b 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -16,167 +16,12 @@ */ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index); -static FRandom pr_saw ("Saw"); static FRandom pr_fireshotgun2 ("FireSG2"); static FRandom pr_fireplasma ("FirePlasma"); static FRandom pr_firerail ("FireRail"); static FRandom pr_bfgspray ("BFGSpray"); static FRandom pr_oldbfg ("OldBFG"); -// -// A_Saw -// -enum SAW_Flags -{ - SF_NORANDOM = 1, - SF_RANDOMLIGHTMISS = 2, - SF_RANDOMLIGHTHIT = 4, - SF_NOUSEAMMOMISS = 8, - SF_NOUSEAMMO = 16, - SF_NOPULLIN = 32, - SF_NOTURN = 64, - SF_STEALARMOR = 128, -}; - - -DEFINE_ACTION_FUNCTION(AActor, A_Saw) -{ - 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; - player_t *player; - FTranslatedLineTarget t; - int actualdamage; - - if (NULL == (player = self->player)) - { - return 0; - } - - if (pufftype == NULL) - { - pufftype = PClass::FindActor(NAME_BulletPuff); - } - if (damage == 0) - { - damage = 2; - } - if (!(flags & SF_NORANDOM)) - { - damage *= (pr_saw()%10+1); - } - if (range == 0) - { - range = SAWRANGE; - } - - angle = self->Angles.Yaw + spread_xy * (pr_saw.Random2() / 255.); - slope = P_AimLineAttack (self, angle, range, &t) + spread_z * (pr_saw.Random2() / 255.); - - AWeapon *weapon = self->player->ReadyWeapon; - if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!t.linetarget && (flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - - P_LineAttack (self, angle, range, slope, damage, NAME_Melee, pufftype, false, &t, &actualdamage); - - if (!t.linetarget) - { - if ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64)) - { - player->extralight = !player->extralight; - } - S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); - return 0; - } - - if (flags & SF_RANDOMLIGHTHIT) - { - int randVal = pr_saw(); - if (randVal < 64) - { - player->extralight = 0; - } - else if (randVal < 160) - { - player->extralight = 1; - } - else - { - player->extralight = 2; - } - } - - if (lifesteal && !(t.linetarget->flags5 & MF5_DONTDRAIN)) - { - if (flags & SF_STEALARMOR) - { - if (armorbonustype == NULL) - { - armorbonustype = dyn_cast(PClass::FindClass("ArmorBonus")); - } - if (armorbonustype != NULL) - { - assert(armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))); - ABasicArmorBonus *armorbonus = static_cast(Spawn(armorbonustype)); - armorbonus->SaveAmount = int(armorbonus->SaveAmount * actualdamage * lifesteal); - armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax; - armorbonus->flags |= MF_DROPPED; - armorbonus->ClearCounters(); - - if (!armorbonus->CallTryPickup (self)) - { - armorbonus->Destroy (); - } - } - } - - else - { - P_GiveBody (self, int(actualdamage * lifesteal), lifestealmax); - } - } - - S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM); - - // turn to face target - if (!(flags & SF_NOTURN)) - { - DAngle anglediff = deltaangle(self->Angles.Yaw, t.angleFromSource); - - if (anglediff < 0.0) - { - if (anglediff < -4.5) - self->Angles.Yaw = angle + 90.0 / 21; - else - self->Angles.Yaw -= 4.5; - } - else - { - if (anglediff > 4.5) - self->Angles.Yaw = angle - 90.0 / 21; - else - self->Angles.Yaw += 4.5; - } - } - if (!(flags & SF_NOPULLIN)) - self->flags |= MF_JUSTATTACKED; - return 0; -} // // A_FireShotgun2 diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 636441a9db..c05cc2c6a8 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -7,11 +7,12 @@ #include "g_level.h" #include "d_player.h" #include "serializer.h" +#include "cmdlib.h" 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(ABasicArmorBonus, false, false, true, false) IMPLEMENT_CLASS(AHexenArmor, false, false, false, false) //=========================================================================== @@ -278,6 +279,19 @@ bool ABasicArmorPickup::Use (bool pickup) return true; } +//=========================================================================== +// +// ABasicArmorBonus :: InitNativeFields +// +//=========================================================================== + +void ABasicArmorBonus::InitNativeFields() +{ + auto meta = RUNTIME_CLASS(ABasicArmorBonus); + meta->AddNativeField("SaveAmount", TypeSInt32, myoffsetof(ABasicArmorBonus, SaveAmount)); + meta->AddNativeField("MaxSaveAmount", TypeSInt32, myoffsetof(ABasicArmorBonus, MaxSaveAmount)); +} + //=========================================================================== // // ABasicArmorBonus :: Serialize diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index fbc5ea509d..a3abe7cf4c 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -344,6 +344,14 @@ bool P_GiveBody (AActor *actor, int num, int max) return false; } +DEFINE_ACTION_FUNCTION(AActor, GiveBody) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(num); + PARAM_INT_DEF(max); + ACTION_RETURN_BOOL(P_GiveBody(self, num, max)); +} + //--------------------------------------------------------------------------- // // PROC A_RestoreSpecialThing1 @@ -352,12 +360,12 @@ bool P_GiveBody (AActor *actor, int num, int max) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialThing1) +DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialThing1) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_SELF_PROLOGUE(AInventory); self->renderflags &= ~RF_INVISIBLE; - if (static_cast(self)->DoRespawn ()) + if (self->DoRespawn ()) { S_Sound (self, CHAN_VOICE, "misc/spawn", 1, ATTN_IDLE); } @@ -370,9 +378,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialThing1) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialThing2) +DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialThing2) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_SELF_PROLOGUE(AInventory); self->flags |= MF_SPECIAL; if (!(self->GetDefault()->flags & MF_NOGRAVITY)) @@ -390,9 +398,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialThing2) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialDoomThing) +DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialDoomThing) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_SELF_PROLOGUE(AInventory); self->renderflags &= ~RF_INVISIBLE; self->flags |= MF_SPECIAL; @@ -400,7 +408,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialDoomThing) { self->flags &= ~MF_NOGRAVITY; } - if (static_cast(self)->DoRespawn ()) + if (self->DoRespawn ()) { self->SetState (self->SpawnState); S_Sound (self, CHAN_VOICE, "misc/spawn", 1, ATTN_IDLE); @@ -1547,6 +1555,17 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) return res; } +DEFINE_ACTION_FUNCTION(AInventory, CallTryPickup) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_OBJECT(toucher, AActor); + AActor *t_ret; + bool res = self->CallTryPickup(toucher, &t_ret); + if (numret > 0) ret[0].SetInt(res); + if (numret > 1) ret[1].SetPointer(t_ret, ATAG_OBJECT), numret = 2; + return numret; +} + //=========================================================================== // diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index e50c7f3d82..9e1caaf5b0 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -500,6 +500,7 @@ public: class ABasicArmorBonus : public AArmor { DECLARE_CLASS (ABasicArmorBonus, AArmor) + HAS_FIELDS public: virtual void Serialize(FSerializer &arc); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 09d850af58..f28ea4b5f8 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6884,6 +6884,12 @@ void AActor::ClearCounters() } } +DEFINE_ACTION_FUNCTION(AActor, ClearCounters) +{ + PARAM_SELF_PROLOGUE(AActor); + self->ClearCounters(); + return 0; +} int AActor::ApplyDamageFactor(FName damagetype, int damage) const { diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index e38b6bd6bc..12acc438b4 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2331,6 +2331,95 @@ ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) } } + +//========================================================================== +// +// +// +//========================================================================== + +FxMultiAssign::FxMultiAssign(FArgumentList &base, FxExpression *right, const FScriptPosition &pos) + :FxExpression(EFX_MultiAssign, pos) +{ + Base = std::move(base); + Right = right; + LocalVarContainer = new FxCompoundStatement(ScriptPosition); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMultiAssign::~FxMultiAssign() +{ + SAFE_DELETE(Right); + SAFE_DELETE(LocalVarContainer); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Right, ctx); + if (Right->ExprType != EFX_VMFunctionCall) + { + Right->ScriptPosition.Message(MSG_ERROR, "Function call expected on right side of multi-assigment"); + delete this; + return nullptr; + } + auto VMRight = static_cast(Right); + auto rets = VMRight->GetReturnTypes(); + if (rets.Size() < Base.Size()) + { + Right->ScriptPosition.Message(MSG_ERROR, "Insufficient returns in function %s", VMRight->Function->SymbolName.GetChars()); + delete this; + return nullptr; + } + // Pack the generated data (temp local variables for the results and necessary type casts and single assignments) into a compound statement for easier management. + for (unsigned i = 0; i < Base.Size(); i++) + { + auto singlevar = new FxLocalVariableDeclaration(rets[i], NAME_None, nullptr, 0, ScriptPosition); + LocalVarContainer->Add(singlevar); + Base[i] = Base[i]->Resolve(ctx); + ABORT(Base[i]); + auto varaccess = new FxLocalVariable(singlevar, ScriptPosition); + auto assignee = new FxTypeCast(varaccess, Base[i]->ValueType, false); + LocalVarContainer->Add(new FxAssign(Base[i], assignee, false)); + } + auto x = LocalVarContainer->Resolve(ctx); + LocalVarContainer = nullptr; + ABORT(x); + LocalVarContainer = static_cast(x); + static_cast(Right)->AssignCount = Base.Size(); + ValueType = TypeVoid; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxMultiAssign::Emit(VMFunctionBuilder *build) +{ + Right->Emit(build); + for (unsigned i = 0; i < Base.Size(); i++) + { + LocalVarContainer->LocalVars[i]->SetReg(static_cast(Right)->ReturnRegs[i]); + } + static_cast(Right)->ReturnRegs.Clear(); + static_cast(Right)->ReturnRegs.ShrinkToFit(); + return LocalVarContainer->Emit(build); +} + //========================================================================== // // @@ -5398,6 +5487,13 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } } + if (noglobal) + { + // This is needed to properly resolve class names on the left side of the member access operator + ValueType = TypeError; + return this; + } + // now check the global identifiers. if (newex == nullptr && (sym = ctx.FindGlobal(Identifier)) != nullptr) { @@ -6710,11 +6806,20 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) bool staticonly = false; bool novirtual = false; + PClass *ccls = nullptr; + if (Self->ExprType == EFX_Identifier) { + ccls = PClass::FindClass(static_cast(Self)->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. - PClass *ccls = PClass::FindClass(static_cast(Self)->Identifier); + if (ccls != nullptr)static_cast(Self)->noglobal = true; + } + + SAFE_RESOLVE(Self, ctx); + + if (Self->ValueType == TypeError) + { if (ccls != nullptr) { if (ccls->bExported) @@ -6729,7 +6834,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) // Todo: static struct members need to work as well. } } - SAFE_RESOLVE(Self, ctx); if (Self->ExprType == EFX_Super) { @@ -7282,10 +7386,8 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } 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; + build->Emit(OP_CALL_K, funcaddr, count, MAX(1, AssignCount)); + goto handlereturns; } else { // Call, expecting no results @@ -7307,18 +7409,34 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } 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; + build->Emit(OP_CALL, funcreg.RegNum, count, MAX(1, AssignCount)); + goto handlereturns; } else { // Call, expecting no results build->Emit(OP_CALL, funcreg.RegNum, count, 0); return ExpEmit(); } - - + } +handlereturns: + if (AssignCount == 0) + { + // Regular call, will not write to ReturnRegs + ExpEmit reg(build, vmfunc->Proto->ReturnTypes[0]->GetRegType(), vmfunc->Proto->ReturnTypes[0]->GetRegCount()); + build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum); + return reg; + } + else + { + // Multi-Assignment call, this must fill in the ReturnRegs array so that the multi-assignment operator can dispatch the return values. + assert((unsigned)AssignCount <= vmfunc->Proto->ReturnTypes.Size()); + for (int i = 0; i < AssignCount; i++) + { + ExpEmit reg(build, vmfunc->Proto->ReturnTypes[i]->GetRegType(), vmfunc->Proto->ReturnTypes[i]->GetRegCount()); + build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum); + ReturnRegs.Push(reg); + } + return ExpEmit(); } } @@ -9018,13 +9136,19 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) return this; } +void FxLocalVariableDeclaration::SetReg(ExpEmit emit) +{ + assert(ValueType->GetRegType() == emit.RegType && ValueType->GetRegCount() == emit.RegCount); + RegNum = emit.RegNum; +} + ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) { if (ValueType->RegType != REGT_NIL) { if (Init == nullptr) { - RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); + if (RegNum == -1) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); } else { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 5ad351d6b6..03b256970d 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -68,6 +68,7 @@ struct FScriptPosition; class FxLoopStatement; class FxCompoundStatement; class FxLocalVariableDeclaration; +typedef TDeletingArray FArgumentList; struct FCompileContext { @@ -280,6 +281,7 @@ enum EFxType EFX_GlobalVariable, EFX_Super, EFX_StackVariable, + EFX_MultiAssign, EFX_COUNT }; @@ -343,6 +345,7 @@ class FxIdentifier : public FxExpression { public: FName Identifier; + bool noglobal = false; FxIdentifier(FName i, const FScriptPosition &p); FxExpression *Resolve(FCompileContext&); @@ -782,6 +785,28 @@ public: ExpEmit Address; }; +//========================================================================== +// +// FxAssign +// +//========================================================================== +class FxCompoundStatement; + +class FxMultiAssign : public FxExpression +{ + FxCompoundStatement *LocalVarContainer; // for handling the temporary variables of the results, which may need type casts. + FArgumentList Base; + FxExpression *Right; + bool AddressRequested = false; + bool AddressWritable = false; + +public: + FxMultiAssign(FArgumentList &base, FxExpression *right, const FScriptPosition &pos); + ~FxMultiAssign(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxAssignSelf @@ -1344,8 +1369,6 @@ public: // //========================================================================== -typedef TDeletingArray FArgumentList; - class FxFunctionCall : public FxExpression { FName MethodName; @@ -1448,11 +1471,16 @@ public: class FxVMFunctionCall : public FxExpression { + friend class FxMultiAssign; + bool EmitTail; bool NoVirtual; FxExpression *Self; PFunction *Function; FArgumentList ArgList; + // for multi assignment + int AssignCount = 0; + TArray ReturnRegs; public: FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual); @@ -1462,6 +1490,10 @@ public: VMFunction *GetDirectFunction(); ExpEmit Emit(VMFunctionBuilder *build); bool CheckEmitCast(VMFunctionBuilder *build, bool returnit, ExpEmit ®); + TArray &GetReturnTypes() const + { + return Function->Variants[0].Proto->ReturnTypes; + } }; //========================================================================== @@ -1497,6 +1529,7 @@ class FxCompoundStatement : public FxSequence FxCompoundStatement *Outer = nullptr; friend class FxLocalVariableDeclaration; + friend class FxMultiAssign; public: FxCompoundStatement(const FScriptPosition &pos) : FxSequence(pos) {} @@ -1822,6 +1855,7 @@ public: FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build); + void SetReg(ExpEmit reginfo); }; diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 2d3605532d..8bd9686e36 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -1556,7 +1556,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; } @@ -1767,11 +1767,11 @@ 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) EQ expr_list(B). [EQ] +// The grammar won't let this pass without some syntactic help. +// Parentheses and braces aren't accepted either so brackets are the only way to get this through the parser without a conflict. +assign_statement(X) ::= LBRACKET expr_list(A) RBRACKET EQ expr(B). [EQ] { NEW_AST_NODE(AssignStmt,stmt,A); stmt->AssignOp = ZCC_EQ; @@ -1779,7 +1779,6 @@ assign_statement(X) ::= expr_list(A) EQ expr_list(B). [EQ] stmt->Sources = B; X = stmt; } -*/ /*----- Local Variable Definition "Statements" -----*/ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e50e8b822d..7c78b3c1e2 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2262,10 +2262,18 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool if (!(f->Flags & ZCC_Native)) { - auto code = ConvertAST(c->Type(), f->Body); - if (code != nullptr) + if (f->Body == nullptr) { - sym->Variants[0].Implementation = FunctionBuildList.AddFunction(sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump); + Error(f, "Empty function %s", FName(f->Name).GetChars()); + return; + } + else + { + 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. @@ -3149,7 +3157,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_CaseStmt: { auto cases = static_cast(ast); - return new FxCaseStatement(ConvertNode(cases->Condition), *ast); + return new FxCaseStatement(ConvertNode(cases->Condition), *ast); } case AST_CompoundStmt: @@ -3164,6 +3172,21 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } while (node != compound->Content); return x; } + + case AST_AssignStmt: + { + auto ass = static_cast(ast); + FArgumentList args; + ConvertNodeList(args, ass->Dests); + assert(ass->Sources->SiblingNext == ass->Sources); // right side should be a single function call - nothing else + if (ass->Sources->NodeType != AST_ExprFuncCall) + { + // don't let this through to the code generator. This node is only used to assign multiple returns of a function to more than one variable. + Error(ass, "Right side of multi-assignment must be a function call"); + return new FxNop(*ast); // allow compiler to continue looking for errors. + } + return new FxMultiAssign(args, ConvertNode(ass->Sources), *ast); + } } // only for development. I_Error is more convenient here than a normal error. I_Error("ConvertNode encountered unsupported node of type %d", ast->NodeType); diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 9244b9bdb9..6832c70f09 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -52,6 +52,7 @@ zscript/doom/weaponfist.txt zscript/doom/weaponpistol.txt zscript/doom/weaponshotgun.txt zscript/doom/weaponchaingun.txt +zscript/doom/weaponchainsaw.txt zscript/doom/deadthings.txt zscript/doom/doomammo.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0fd6d2282a..7f845472a4 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -71,6 +71,9 @@ class Actor : Thinker native native void RemoveFromHash(); native string GetTag(string defstr = ""); native float GetBobOffset(float frac = 0); + native void ClearCounters(); + native bool GiveBody (int num, int max=0); + native void SetDamage(int dmg); native static bool isDehState(state st); native double Distance2D(Actor other); @@ -469,6 +472,7 @@ class Actor : Thinker native 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_RestoreSpecialPosition(); native void A_QueueCorpse(); native void A_DeQueueCorpse(); native void A_ClearLastHeard(); diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index ee7a821eaa..d7eb835ce0 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -13,47 +13,6 @@ class DoomWeapon : Weapon } -// -------------------------------------------------------------------------- -// -// 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 diff --git a/wadsrc/static/zscript/doom/weaponchainsaw.txt b/wadsrc/static/zscript/doom/weaponchainsaw.txt new file mode 100644 index 0000000000..b2583efa53 --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponchainsaw.txt @@ -0,0 +1,166 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + + +extend class StateProvider +{ + action 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") + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + if (pufftype == null) + { + pufftype = 'BulletPuff'; + } + if (damage == 0) + { + damage = 2; + } + if (!(flags & SF_NORANDOM)) + { + damage *= random[Saw](1, 10); + } + if (range == 0) + { + range = SAWRANGE; + } + + double ang = angle + spread_xy * (Random2[Saw]() / 255.); + double slope = AimLineAttack (ang, range, t) + spread_z * (Random2[Saw]() / 255.); + + Weapon weap = player.ReadyWeapon; + if (weap != null && !(flags & SF_NOUSEAMMO) && !(!t.linetarget && (flags & SF_NOUSEAMMOMISS)) && !weap.bDehAmmo && + invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire)) + return; + } + + Actor puff; + int actualdamage; + [puff, actualdamage] = LineAttack (ang, range, slope, damage, 'Melee', pufftype, false, t); + + if (!t.linetarget) + { + if ((flags & SF_RANDOMLIGHTMISS) && (Random[Saw]() > 64)) + { + player.extralight = !player.extralight; + } + A_PlaySound (fullsound, CHAN_WEAPON); + return; + } + + if (flags & SF_RANDOMLIGHTHIT) + { + int randVal = Random[Saw](); + if (randVal < 64) + { + player.extralight = 0; + } + else if (randVal < 160) + { + player.extralight = 1; + } + else + { + player.extralight = 2; + } + } + + if (lifesteal && !t.linetarget.bDontDrain) + { + if (flags & SF_STEALARMOR) + { + if (armorbonustype == null) + { + armorbonustype = "ArmorBonus"; + } + if (armorbonustype != null) + { + BasicArmorBonus armorbonus = BasicArmorBonus(Spawn(armorbonustype)); + armorbonus.SaveAmount = int(armorbonus.SaveAmount * actualdamage * lifesteal); + armorbonus.MaxSaveAmount = lifestealmax <= 0 ? armorbonus.MaxSaveAmount : lifestealmax; + armorbonus.bDropped = true; + armorbonus.ClearCounters(); + + if (!armorbonus.CallTryPickup (self)) + { + armorbonus.Destroy (); + } + } + } + + else + { + GiveBody (int(actualdamage * lifesteal), lifestealmax); + } + } + + A_PlaySound (hitsound, CHAN_WEAPON); + + // turn to face target + if (!(flags & SF_NOTURN)) + { + double anglediff = deltaangle(angle, t.angleFromSource); + + if (anglediff < 0.0) + { + if (anglediff < -4.5) + angle = ang + 90.0 / 21; + else + angle -= 4.5; + } + else + { + if (anglediff > 4.5) + angle = ang - 90.0 / 21; + else + angle += 4.5; + } + } + if (!(flags & SF_NOPULLIN)) + bJustAttacked = true; + } +} diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 64c649ad64..67bb840dda 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -11,10 +11,11 @@ class Inventory : Actor native } // 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(); + + native bool, Actor CallTryPickup(Actor toucher); States(Actor, Overlay, Weapon, Item) { @@ -70,7 +71,6 @@ class StateProvider : Inventory native 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(); } From 814493b68d07813d4c3e332cb0514966554297c2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 00:45:06 +0100 Subject: [PATCH 304/471] - scriptified the Super Shotgun. --- src/g_doom/a_doomweaps.cpp | 51 --------- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/doom/doomweapons.txt | 55 ---------- wadsrc/static/zscript/doom/weaponssg.txt | 116 +++++++++++++++++++++ wadsrc/static/zscript/shared/inventory.txt | 5 - 5 files changed, 117 insertions(+), 111 deletions(-) create mode 100644 wadsrc/static/zscript/doom/weaponssg.txt diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index e802a6103b..c23bd7f1ff 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -16,63 +16,12 @@ */ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index); -static FRandom pr_fireshotgun2 ("FireSG2"); static FRandom pr_fireplasma ("FirePlasma"); static FRandom pr_firerail ("FireRail"); static FRandom pr_bfgspray ("BFGSpray"); static FRandom pr_oldbfg ("OldBFG"); -// -// A_FireShotgun2 -// -DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - int i; - DAngle angle; - int damage; - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - - S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM); - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != nullptr && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2)) - return 0; - P_SetPsprite(player, PSP_FLASH, weapon->FindState(NAME_Flash), true); - } - player->mo->PlayAttacking2 (); - - - DAngle pitch = P_BulletSlope (self); - - for (i=0 ; i<20 ; i++) - { - damage = 5*(pr_fireshotgun2()%3+1); - angle = self->Angles.Yaw + pr_fireshotgun2.Random2() * (11.25 / 256); - - // Doom adjusts the bullet slope by shifting a random number [-255,255] - // left 5 places. At 2048 units away, this means the vertical position - // of the shot can deviate as much as 255 units from nominal. So using - // some simple trigonometry, that means the vertical angle of the shot - // can deviate by as many as ~7.097 degrees or ~84676099 BAMs. - - P_LineAttack (self, - angle, - PLAYERMISSILERANGE, - pitch + pr_fireshotgun2.Random2() * (7.097 / 256), damage, - NAME_Hitscan, NAME_BulletPuff); - } - return 0; -} - // // A_FireMissile // diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 6832c70f09..e911764331 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -51,6 +51,7 @@ zscript/doom/bossbrain.txt zscript/doom/weaponfist.txt zscript/doom/weaponpistol.txt zscript/doom/weaponshotgun.txt +zscript/doom/weaponssg.txt zscript/doom/weaponchaingun.txt zscript/doom/weaponchainsaw.txt diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index d7eb835ce0..55f3f3bcfc 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -13,61 +13,6 @@ class DoomWeapon : Weapon } -// -------------------------------------------------------------------------- -// -// 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; - } -} - // -------------------------------------------------------------------------- // // Rocket launcher diff --git a/wadsrc/static/zscript/doom/weaponssg.txt b/wadsrc/static/zscript/doom/weaponssg.txt new file mode 100644 index 0000000000..75ac9f09e7 --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponssg.txt @@ -0,0 +1,116 @@ +// -------------------------------------------------------------------------- +// +// Super 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; + } +} + + + +//=========================================================================== +// +// Code (must be attached to StateProvider) +// +//=========================================================================== + +extend class StateProvider +{ + action void A_FireShotgun2() + { + if (player == null) + { + return; + } + + A_PlaySound ("weapons/sshotf", CHAN_WEAPON); + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 2)) + return; + + player.SetPsprite(PSP_FLASH, weap.FindState('Flash'), true); + } + player.mo.PlayAttacking2 (); + + double pitch = BulletSlope (); + + for (int i = 0 ; i < 20 ; i++) + { + int damage = 5 * random[FireSG2](1, 3); + double ang = angle + Random2[FireSG2]() * (11.25 / 256); + + // Doom adjusts the bullet slope by shifting a random number [-255,255] + // left 5 places. At 2048 units away, this means the vertical position + // of the shot can deviate as much as 255 units from nominal. So using + // some simple trigonometry, that means the vertical angle of the shot + // can deviate by as many as ~7.097 degrees. + + LineAttack (ang, PLAYERMISSILERANGE, pitch + Random2[FireSG2]() * (7.097 / 256), damage, 'Hitscan', "BulletPuff"); + } + } + + + 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); + } +} diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 67bb840dda..8509001a90 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -50,11 +50,6 @@ class StateProvider : Inventory native action native void A_WeaponReady(int flags = 0); action native void A_Lower(); action native void A_Raise(); - 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_FireSTGrenade(class grenadetype = "Grenade"); action native void A_FireMissile(); From fdab994fcbc9834d09a41f010c13d1cbc6593acf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 01:11:01 +0100 Subject: [PATCH 305/471] - scriptified the Rocket launcher. --- src/g_doom/a_doomweaps.cpp | 55 ------ src/p_mobj.cpp | 21 +++ wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/doom/doomweapons.txt | 129 ------------- wadsrc/static/zscript/doom/weaponrlaunch.txt | 189 +++++++++++++++++++ wadsrc/static/zscript/shared/inventory.txt | 2 - 7 files changed, 212 insertions(+), 186 deletions(-) create mode 100644 wadsrc/static/zscript/doom/weaponrlaunch.txt diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index c23bd7f1ff..cce1161cf1 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -22,61 +22,6 @@ static FRandom pr_bfgspray ("BFGSpray"); static FRandom pr_oldbfg ("OldBFG"); -// -// A_FireMissile -// -DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return 0; - } - P_SpawnPlayerMissile (self, PClass::FindActor("Rocket")); - return 0; -} - -// -// A_FireSTGrenade: not exactly backported from ST, but should work the same -// -DEFINE_ACTION_FUNCTION(AActor, A_FireSTGrenade) -{ - PARAM_ACTION_PROLOGUE(AActor); - PARAM_CLASS_DEF(grenade, AActor); - - player_t *player; - - if (grenade == NULL) - return 0; - - if (NULL == (player = self->player)) - { - return 0; - } - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - - // Temporarily raise the pitch to send the grenade slightly upwards - DAngle SavedPlayerPitch = self->Angles.Pitch; - self->Angles.Pitch -= 6.328125; //(1152 << F RACBITS); - P_SpawnPlayerMissile(self, grenade); - self->Angles.Pitch = SavedPlayerPitch; - return 0; -} - // // A_FirePlasma // diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f28ea4b5f8..964736fed1 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6463,6 +6463,27 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z, return NULL; } +DEFINE_ACTION_FUNCTION(AActor, SpawnPlayerMissile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(type, AActor); + PARAM_ANGLE_DEF(angle); + PARAM_FLOAT_DEF(x); + PARAM_FLOAT_DEF(y); + PARAM_FLOAT_DEF(z); + PARAM_POINTER_DEF(lt, FTranslatedLineTarget); + PARAM_BOOL_DEF(nofreeaim); + PARAM_BOOL_DEF(noautoaim); + PARAM_INT_DEF(aimflags); + AActor *missileactor; + if (numparam == 2) angle = self->Angles.Yaw; + AActor *misl = P_SpawnPlayerMissile(self, x, y, z, type, angle, lt, &missileactor, nofreeaim, noautoaim, aimflags); + if (numret > 0) ret[0].SetPointer(misl, ATAG_OBJECT); + if (numret > 1) ret[1].SetPointer(missileactor, ATAG_OBJECT), numret = 2; + return numret; +} + + int AActor::GetTeam() { if (player) diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index e911764331..aec7e80896 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -54,6 +54,7 @@ zscript/doom/weaponshotgun.txt zscript/doom/weaponssg.txt zscript/doom/weaponchaingun.txt zscript/doom/weaponchainsaw.txt +zscript/doom/weaponrlaunch.txt zscript/doom/deadthings.txt zscript/doom/doomammo.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 7f845472a4..2288b6c1b6 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -89,6 +89,7 @@ class Actor : Thinker native 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, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void A_Light(int extralight); void A_Light0() { A_Light(0); } diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index 55f3f3bcfc..ade261d33f 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -13,135 +13,6 @@ class DoomWeapon : Weapon } -// -------------------------------------------------------------------------- -// -// 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 diff --git a/wadsrc/static/zscript/doom/weaponrlaunch.txt b/wadsrc/static/zscript/doom/weaponrlaunch.txt new file mode 100644 index 0000000000..906db38239 --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponrlaunch.txt @@ -0,0 +1,189 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + +//=========================================================================== +// +// Code (must be attached to StateProvider) +// +//=========================================================================== + +extend class StateProvider +{ + + //=========================================================================== + // + // A_FireMissile + // + //=========================================================================== + + action void A_FireMissile() + { + if (player == null) + { + return; + } + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + } + + SpawnPlayerMissile ("Rocket"); + } + + //=========================================================================== + // + // A_FireSTGrenade: not exactly backported from ST, but should work the same + // + //=========================================================================== + + action void A_FireSTGrenade(class grenadetype = "Grenade") + { + if (grenadetype == null) + return; + + if (player == null) + { + return; + } + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + } + + // Temporarily raise the pitch to send the grenadetype slightly upwards + double savedpitch = pitch; + pitch -= 6.328125; + SpawnPlayerMissile(grenadetype); + pitch = SavedPitch; + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 8509001a90..c1f40fd1f1 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -51,8 +51,6 @@ class StateProvider : Inventory native action native void A_Lower(); action native void A_Raise(); - 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(); From 3c726aa57073f02f74e13faea92b5114b8bf9614 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 01:18:21 +0100 Subject: [PATCH 306/471] - scriptified A_FirePlasma. --- src/g_doom/a_doomweaps.cpp | 31 ---- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/doom/doomweapons.txt | 109 -------------- wadsrc/static/zscript/doom/weaponplasma.txt | 148 ++++++++++++++++++++ wadsrc/static/zscript/shared/inventory.txt | 1 - 5 files changed, 149 insertions(+), 141 deletions(-) create mode 100644 wadsrc/static/zscript/doom/weaponplasma.txt diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index cce1161cf1..067a106be5 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -16,42 +16,11 @@ */ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index); -static FRandom pr_fireplasma ("FirePlasma"); static FRandom pr_firerail ("FireRail"); static FRandom pr_bfgspray ("BFGSpray"); static FRandom pr_oldbfg ("OldBFG"); -// -// A_FirePlasma -// -DEFINE_ACTION_FUNCTION(AActor, A_FirePlasma) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return 0; - - FState *flash = weapon->FindState(NAME_Flash); - if (flash != NULL) - { - P_SetSafeFlash(weapon, player, flash, (pr_fireplasma()&1)); - } - } - - P_SpawnPlayerMissile (self, PClass::FindActor("PlasmaBall")); - return 0; -} - // // [RH] A_FireRailgun // diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index aec7e80896..192089d856 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -55,6 +55,7 @@ zscript/doom/weaponssg.txt zscript/doom/weaponchaingun.txt zscript/doom/weaponchainsaw.txt zscript/doom/weaponrlaunch.txt +zscript/doom/weaponplasma.txt zscript/doom/deadthings.txt zscript/doom/doomammo.txt diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index ade261d33f..7f8d7478fb 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -13,115 +13,6 @@ class DoomWeapon : Weapon } -// -------------------------------------------------------------------------- -// -// 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 diff --git a/wadsrc/static/zscript/doom/weaponplasma.txt b/wadsrc/static/zscript/doom/weaponplasma.txt new file mode 100644 index 0000000000..945339a356 --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponplasma.txt @@ -0,0 +1,148 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + + +//=========================================================================== +// +// Code (must be attached to StateProvider) +// +//=========================================================================== + +extend class StateProvider +{ + + //=========================================================================== + // + // A_FirePlasma + // + //=========================================================================== + + action void A_FirePlasma() + { + if (player == null) + { + return; + } + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + + State flash = weap.FindState('Flash'); + if (flash != null) + { + player.SetSafeFlash(weap, flash, random[FirePlasma]()&1); + } + + } + + SpawnPlayerMissile ("PlasmaBall"); + } +} diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index c1f40fd1f1..270d5e6d70 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -51,7 +51,6 @@ class StateProvider : Inventory native action native void A_Lower(); action native void A_Raise(); - action native void A_FirePlasma(); action native void A_FireRailgun(); action native void A_FireRailgunLeft(); action native void A_FireRailgunRight(); From ab6b2f369ead21a8741381eae911a72291f0f890 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 09:47:46 +0100 Subject: [PATCH 307/471] - fixed: For varargs, not only the type but also the flag of the last specified argument need to be stored for later parameters. --- src/scripting/codegeneration/codegen.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 12acc438b4..56ee12eaf7 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7218,6 +7218,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { bool foundvarargs = false; PType * type = nullptr; + int flag = 0; if (argtypes.Last() != nullptr && ArgList.Size() + implicit > argtypes.Size()) { ScriptPosition.Message(MSG_ERROR, "Too many arguments in call to %s", Function->SymbolName.GetChars()); @@ -7231,12 +7232,16 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) if (!foundvarargs) { if (argtypes[i + implicit] == nullptr) foundvarargs = true; - else type = argtypes[i + implicit]; + else + { + type = argtypes[i + implicit]; + flag = argflags[i + implicit]; + } } assert(type != nullptr); FxExpression *x; - if (!(argflags[i + implicit] & VARF_Ref)) + if (!(flag & VARF_Ref)) { x = new FxTypeCast(ArgList[i], type, false); x = x->Resolve(ctx); From bb25c5faaaccdfa029d56b08127e0bae3732ab85 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 12:27:26 +0100 Subject: [PATCH 308/471] - scriptified the remaining Doom weapon code. - implemented method calls from struct instances. - optimized disassembly of VM call instructions to print the function's name at the end where it is more visible and does not need to be truncated. Also use the printable name for script functions here. --- src/g_doom/a_doommisc.cpp | 1 - src/g_doom/a_doomweaps.cpp | 251 -------------------- src/p_map.cpp | 11 + src/scripting/codegeneration/codegen.cpp | 54 +++-- src/scripting/vm/vmdisasm.cpp | 9 +- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/constants.txt | 2 + wadsrc/static/zscript/doom/doomweapons.txt | 139 ++++------- wadsrc/static/zscript/doom/weaponbfg.txt | 259 +++++++++++++++++++++ wadsrc/static/zscript/shared/inventory.txt | 7 - 11 files changed, 359 insertions(+), 376 deletions(-) delete mode 100644 src/g_doom/a_doomweaps.cpp create mode 100644 wadsrc/static/zscript/doom/weaponbfg.txt diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 4672977614..ca13ac7ee4 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -20,7 +20,6 @@ #include "g_shared/a_pickups.h" // Include all the other Doom stuff here to reduce compile time -#include "a_doomweaps.cpp" #include "a_painelemental.cpp" #include "a_scriptedmarine.cpp" diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp deleted file mode 100644 index 067a106be5..0000000000 --- a/src/g_doom/a_doomweaps.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "s_sound.h" -#include "m_random.h" -#include "a_pickups.h" -#include "d_player.h" -#include "p_pspr.h" -#include "p_local.h" -#include "gstrings.h" -#include "p_effect.h" -#include "gi.h" -#include "templates.h" -#include "vm.h" -#include "doomstat.h" -*/ - -void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index); -static FRandom pr_firerail ("FireRail"); -static FRandom pr_bfgspray ("BFGSpray"); -static FRandom pr_oldbfg ("OldBFG"); - - -// -// [RH] A_FireRailgun -// -static void FireRailgun(AActor *self, int offset_xy, bool fromweapon) -{ - int damage; - player_t *player; - - if (NULL == (player = self->player)) - { - return; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && fromweapon) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return; - - FState *flash = weapon->FindState(NAME_Flash); - if (flash != NULL) - { - P_SetSafeFlash(weapon, player, flash, (pr_firerail()&1)); - } - } - - damage = deathmatch ? 100 : 150; - - FRailParams p; - p.source = self; - p.damage = damage; - p.offset_xy = offset_xy; - P_RailAttack (&p); -} - - -DEFINE_ACTION_FUNCTION(AActor, A_FireRailgun) -{ - PARAM_ACTION_PROLOGUE(AActor); - FireRailgun(self, 0, ACTION_CALL_FROM_PSPRITE()); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunRight) -{ - PARAM_ACTION_PROLOGUE(AActor); - FireRailgun(self, 10, ACTION_CALL_FROM_PSPRITE()); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunLeft) -{ - PARAM_ACTION_PROLOGUE(AActor); - FireRailgun(self, -10, ACTION_CALL_FROM_PSPRITE()); - return 0; -} - -// -// A_FireBFG -// - -DEFINE_ACTION_FUNCTION(AActor, A_FireBFG) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, deh.BFGCells)) - return 0; - } - - P_SpawnPlayerMissile (self, 0, 0, 0, PClass::FindActor("BFGBall"), self->Angles.Yaw, NULL, NULL, !!(dmflags2 & DF2_NO_FREEAIMBFG)); - return 0; -} - - -// -// A_BFGSpray -// Spawn a BFG explosion on every monster in view -// -enum BFG_Flags -{ - BFGF_HURTSOURCE = 1, - BFGF_MISSILEORIGIN = 2, -}; - -DEFINE_ACTION_FUNCTION(AActor, A_BFGSpray) -{ - 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; - int damage; - DAngle an; - FTranslatedLineTarget t; - AActor *originator; - - if (spraytype == NULL) spraytype = PClass::FindActor("BFGExtra"); - if (numrays <= 0) numrays = 40; - if (damagecnt <= 0) damagecnt = 15; - if (angle == 0) angle = 90.; - if (distance <= 0) distance = 16 * 64; - if (vrange == 0) vrange = 32.; - - // [RH] Don't crash if no target - if (!self->target) - return 0; - - // [XA] Set the originator of the rays to the projectile (self) if - // the new flag is set, else set it to the player (self->target) - originator = (flags & BFGF_MISSILEORIGIN) ? self : (AActor *)(self->target); - - // offset angles from its attack angle - for (i = 0; i < numrays; i++) - { - an = self->Angles.Yaw - angle / 2 + angle / numrays*i; - - P_AimLineAttack(originator, an, distance, &t, vrange); - - if (t.linetarget != NULL) - { - AActor *spray = Spawn(spraytype, t.linetarget->PosPlusZ(t.linetarget->Height / 4), ALLOW_REPLACE); - - int dmgFlags = 0; - FName dmgType = NAME_BFGSplash; - - if (spray != NULL) - { - if ((spray->flags6 & MF6_MTHRUSPECIES && self->target->GetSpecies() == t.linetarget->GetSpecies()) || - (!(flags & BFGF_HURTSOURCE) && self->target == t.linetarget)) // [XA] Don't hit oneself unless we say so. - { - spray->Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them. - continue; - } - if (spray->flags5 & MF5_PUFFGETSOWNER) spray->target = self->target; - if (spray->flags3 & MF3_FOILINVUL) dmgFlags |= DMG_FOILINVUL; - if (spray->flags7 & MF7_FOILBUDDHA) dmgFlags |= DMG_FOILBUDDHA; - dmgType = spray->DamageType; - } - - if (defdamage == 0) - { - damage = 0; - for (j = 0; j < damagecnt; ++j) - damage += (pr_bfgspray() & 7) + 1; - } - else - { - // if this is used, damagecnt will be ignored - damage = defdamage; - } - - int newdam = P_DamageMobj(t.linetarget, originator, self->target, damage, dmgType, dmgFlags|DMG_USEANGLE, t.angleFromSource.Degrees); - P_TraceBleed(newdam > 0 ? newdam : damage, &t, self); - } - } - return 0; -} - -// -// A_FireOldBFG -// -// This function emulates Doom's Pre-Beta BFG -// By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98 -// -// This code may not be used in other mods without appropriate credit given. -// Code leeches will be telefragged. - -DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG) -{ - PARAM_ACTION_PROLOGUE(AActor); - PClassActor *plasma[] = { PClass::FindActor("PlasmaBall1"), PClass::FindActor("PlasmaBall2") }; - AActor * mo = NULL; - - player_t *player; - bool doesautoaim = false; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (!ACTION_CALL_FROM_PSPRITE()) weapon = NULL; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) - return 0; - - doesautoaim = !(weapon->WeaponFlags & WIF_NOAUTOAIM); - weapon->WeaponFlags |= WIF_NOAUTOAIM; // No autoaiming that gun - } - self->player->extralight = 2; - - // Save values temporarily - DAngle SavedPlayerAngle = self->Angles.Yaw; - DAngle SavedPlayerPitch = self->Angles.Pitch; - for (int i = 0; i < 2; i++) // Spawn two plasma balls in sequence - { - self->Angles.Yaw += ((pr_oldbfg()&127) - 64) * (90./768); - self->Angles.Pitch += ((pr_oldbfg()&127) - 64) * (90./640); - mo = P_SpawnPlayerMissile (self, plasma[i]); - // Restore saved values - self->Angles.Yaw = SavedPlayerAngle; - self->Angles.Pitch = SavedPlayerPitch; - } - if (doesautoaim && weapon != NULL) - { // Restore autoaim setting - weapon->WeaponFlags &= ~WIF_NOAUTOAIM; - } - return 0; -} diff --git a/src/p_map.cpp b/src/p_map.cpp index 26dc3d4731..eedd503d8b 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4660,6 +4660,17 @@ void P_TraceBleed(int damage, FTranslatedLineTarget *t, AActor *puff) P_TraceBleed(damage, t->linetarget->PosPlusZ(t->linetarget->Height/2), t->linetarget, t->angleFromSource, pitch); } +DEFINE_ACTION_FUNCTION(_FTranslatedLineTarget, TraceBleed) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTranslatedLineTarget); + PARAM_INT(damage); + PARAM_OBJECT(missile, AActor); + + P_TraceBleed(damage, self, missile); + return 0; +} + + //========================================================================== // // diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 56ee12eaf7..6dac05d7b5 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6878,6 +6878,22 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } } + else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) + { + bool writable; + if (Self->RequestAddress(ctx, &writable) && writable) + { + cls = static_cast(Self->ValueType); + Self->ValueType = NewPointer(Self->ValueType); + } + else + { + // Cannot be made writable so we cannot use its methods. + ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s\n", MethodName.GetChars()); + delete this; + return nullptr; + } + } else { ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s\n", MethodName.GetChars()); @@ -7250,18 +7266,22 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { bool writable; ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested. - ArgList[i]->RequestAddress(ctx, &writable); - ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType); - // For a reference argument the types must match 100%. - if (type != ArgList[i]->ValueType) + if (ArgList[i]->ValueType != TypeNullPtr) { - ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument", Function->SymbolName.GetChars()); - x = nullptr; - } - else - { - x = ArgList[i]; + ArgList[i]->RequestAddress(ctx, &writable); + ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType); + // For a reference argument the types must match 100%. + if (type != ArgList[i]->ValueType) + { + ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument", Function->SymbolName.GetChars()); + x = nullptr; + } + else + { + x = ArgList[i]; + } } + else x = ArgList[i]; } failed |= (x == nullptr); ArgList[i] = x; @@ -7305,13 +7325,6 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { ValueType = TypeVoid; } - // If self is a struct, it will be a value type, not a reference, so we need to make an addresss request. - if (Self != nullptr && Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClass))) - { - bool writable; - Self->RequestAddress(ctx, &writable); - } - return this; } @@ -8852,6 +8865,13 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx) return this; } } + else if (basex->ValueType == TypeString || basex->ValueType == TypeName) + { + FxExpression *x = new FxClassTypeCast(to, basex); + basex = nullptr; + delete this; + return x->Resolve(ctx); + } // Everything else is an error. ScriptPosition.Message(MSG_ERROR, "Cannot cast %s to %s. The types are incompatible.", basex->ValueType->DescriptiveName(), to->DescriptiveName()); delete this; diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 07d6fb8e32..031f3328b7 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -323,15 +323,15 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction case OP_CALL_K: case OP_TAIL_K: + { callfunc = (VMFunction *)func->KonstA[code[i].a].o; - callname = callfunc->Name != NAME_None ? callfunc->Name : "[anonfunc]"; - col = printf_wrapper(out, "%.23s,%d", callname, code[i].b); + col = printf_wrapper(out, "[%p],%d", callfunc, code[i].b); if (code[i].op == OP_CALL_K) { col += printf_wrapper(out, ",%d", code[i].c); } break; - + } case OP_RET: if (code[i].b != REGT_NIL) { @@ -494,7 +494,8 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction } else if (code[i].op == OP_CALL_K || code[i].op == OP_TAIL_K) { - printf_wrapper(out, " [%p]\n", callfunc); + callname = callfunc->IsKindOf(RUNTIME_CLASS(VMScriptFunction)) ? static_cast(callfunc)->PrintableName : callfunc->Name != NAME_None ? callfunc->Name : "[anonfunc]"; + printf_wrapper(out, " [%s]\n", callname); } else { diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 192089d856..fdf057b58c 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -56,6 +56,7 @@ zscript/doom/weaponchaingun.txt zscript/doom/weaponchainsaw.txt zscript/doom/weaponrlaunch.txt zscript/doom/weaponplasma.txt +zscript/doom/weaponbfg.txt zscript/doom/deadthings.txt zscript/doom/doomammo.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2288b6c1b6..7f088154f0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -364,7 +364,6 @@ class Actor : Thinker native // 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(); } diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index cfdc98425b..29c60450c2 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -840,6 +840,8 @@ struct FTranslatedLineTarget Actor linetarget; double angleFromSource; bool unlinked; // found by a trace that went through an unlinked portal. + + native void TraceBleed(int damage, Actor missile); } enum EAimFlags diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index 7f8d7478fb..75f8562181 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -1,6 +1,6 @@ // -------------------------------------------------------------------------- // -// Doom weapon base class +// Doom weap base class // // -------------------------------------------------------------------------- @@ -13,102 +13,51 @@ class DoomWeapon : Weapon } -// -------------------------------------------------------------------------- -// -// BFG 9000 -// -// -------------------------------------------------------------------------- -class BFG9000 : DoomWeapon +extend class StateProvider { - 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; - } -} + // + // [RH] A_FireRailgun + // + action void A_FireRailgun(int offset_xy = 0) + { + if (player == null) + { + return; + } -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; - } -} + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + + State flash = weap.FindState('Flash'); + if (flash != null) + { + player.SetSafeFlash(weap, flash, random[FireRail]()&1); + } + + } + int damage = GetCVar("deathmatch") ? 100 : 150; + A_RailAttack(damage, offset_xy, false); // note that this function handles ammo depletion itself for Dehacked compatibility purposes. + } + + action void A_FireRailgunLeft() + { + A_FireRailgun(-10); + } + + action void A_FireRailgunRight() + { + A_FireRailgun(10); + } + + action void A_RailWait() + { + // only here to satisfy old Dehacked patches. + } + +} \ No newline at end of file diff --git a/wadsrc/static/zscript/doom/weaponbfg.txt b/wadsrc/static/zscript/doom/weaponbfg.txt new file mode 100644 index 0000000000..27f318daf9 --- /dev/null +++ b/wadsrc/static/zscript/doom/weaponbfg.txt @@ -0,0 +1,259 @@ +// -------------------------------------------------------------------------- +// +// 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; + } +} + +//=========================================================================== +// +// Weapon code (must be attached to StateProvider) +// +//=========================================================================== + +extend class StateProvider +{ + action void A_BFGsound() + { + A_PlaySound("weapons/bfgf", CHAN_WEAPON); + } + + + // + // A_FireBFG + // + + action void A_FireBFG() + { + if (player == null) + { + return; + } + Weapon weap = player.ReadyWeapon; + if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + } + + SpawnPlayerMissile("BFGBall", angle, 0, 0, 0, null, false, GetCVar("sv_nobfgaim")); + } + + + // + // A_FireOldBFG + // + // This function emulates Doom's Pre-Beta BFG + // By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98 + // + // This code may not be used in other mods without appropriate credit given. + // Code leeches will be telefragged. + + action void A_FireOldBFG() + { + bool doesautoaim = false; + + if (player == null) + { + return; + } + Weapon weap = player.ReadyWeapon; + + if (invoker != weap || stateinfo == null || stateinfo.mStateType != STATE_Psprite) weap = null; + if (weap != null) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + return; + + doesautoaim = weap.bNoAutoaim; + weap.bNoAutoaim = true; + } + player.extralight = 2; + + // Save values temporarily + double SavedPlayerAngle = angle; + double SavedPlayerPitch = pitch; + for (int i = 0; i < 2; i++) // Spawn two plasma balls in sequence + { + angle += ((random[OldBFG]() & 127) - 64) * (90./768); + pitch += ((random[OldBFG]() & 127) - 64) * (90./640); + SpawnPlayerMissile (i == 0? (class)("PlasmaBall1") : (class)("PlasmaBall2")); + // Restore saved values + angle = SavedPlayerAngle; + pitch = SavedPlayerPitch; + } + // Restore autoaim setting + if (weap != null) weap.bNoAutoaim = doesautoaim; + } +} + +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; + } +} + + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + // + // A_BFGSpray + // Spawn a BFG explosion on every monster in view + // + void A_BFGSpray(class spraytype = "BFGExtra", int numrays = 40, int damagecnt = 15, double ang = 90, double distance = 16*64, double vrange = 32, int defdamage = 0, int flags = 0) + { + int damage; + FTranslatedLineTarget t; + + // validate parameters + if (spraytype == null) spraytype = "BFGExtra"; + if (numrays <= 0) numrays = 40; + if (damagecnt <= 0) damagecnt = 15; + if (ang == 0) ang = 90.; + if (distance <= 0) distance = 16 * 64; + if (vrange == 0) vrange = 32.; + + // [RH] Don't crash if no target + if (!target) return; + + // [XA] Set the originator of the rays to the projectile (self) if + // the new flag is set, else set it to the player (target) + Actor originator = (flags & BFGF_MISSILEORIGIN) ? self : target; + + // offset angles from its attack ang + for (int i = 0; i < numrays; i++) + { + double an = angle - ang / 2 + ang / numrays*i; + + originator.AimLineAttack(an, distance, t, vrange); + + if (t.linetarget != null) + { + Actor spray = Spawn(spraytype, t.linetarget.pos + (0, 0, t.linetarget.Height / 4), ALLOW_REPLACE); + + int dmgFlags = 0; + Name dmgType = 'BFGSplash'; + + if (spray != null) + { + if ((spray.bMThruSpecies && target.GetSpecies() == t.linetarget.GetSpecies()) || + (!(flags & BFGF_HURTSOURCE) && target == t.linetarget)) // [XA] Don't hit oneself unless we say so. + { + spray.Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them. + continue; + } + if (spray.bPuffGetsOwner) spray.target = target; + if (spray.bFoilInvul) dmgFlags |= DMG_FOILINVUL; + if (spray.bFoilBuddha) dmgFlags |= DMG_FOILBUDDHA; + dmgType = spray.DamageType; + } + + if (defdamage == 0) + { + damage = 0; + for (int j = 0; j < damagecnt; ++j) + damage += Random[BFGSpray](1, 8); + } + else + { + // if this is used, damagecnt will be ignored + damage = defdamage; + } + + int newdam = t.linetarget.DamageMobj(originator, target, damage, dmgType, dmgFlags|DMG_USEANGLE, t.angleFromSource); + t.TraceBleed(newdam > 0 ? newdam : damage, self); + } + } + } +} diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 270d5e6d70..d5734e1499 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -51,13 +51,6 @@ class StateProvider : Inventory native action native void A_Lower(); action native void A_Raise(); - 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(); From 5951a9449c37115778ea56ac5c514a62343a8d33 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 18:00:37 +0100 Subject: [PATCH 309/471] - added static constant arrays. At the moment they can only be defined inside functions due to lack of dedicated storage inside classes for static data. - added new VM instructions to access the constant tables with a variable index. - refactored VMFunctionBuilder's constant tables so that they are not limited to one entry per value. While this works fine for single values, it makes it impossible to store constant arrays in here. --- src/scripting/codegeneration/codegen.cpp | 216 +++++++++++++++++++---- src/scripting/codegeneration/codegen.h | 44 +++++ src/scripting/vm/vmbuilder.cpp | 147 +++++++++------ src/scripting/vm/vmbuilder.h | 35 ++-- src/scripting/vm/vmdisasm.cpp | 3 + src/scripting/vm/vmexec.h | 20 +++ src/scripting/vm/vmops.h | 4 + src/scripting/zscript/ast.cpp | 10 ++ src/scripting/zscript/zcc-parse.lemon | 23 +++ src/scripting/zscript/zcc_compile.cpp | 9 + src/scripting/zscript/zcc_parser.h | 8 + 11 files changed, 413 insertions(+), 106 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 6dac05d7b5..7be1b9cf2f 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5402,7 +5402,13 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) FxLocalVariableDeclaration *local = ctx.FindLocalVariable(Identifier); if (local != nullptr) { - if (local->ValueType->GetRegType() != REGT_NIL) + if (local->ExprType == EFX_StaticArray) + { + auto x = new FxStaticArrayVariable(local, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + else if (local->ValueType->GetRegType() != REGT_NIL) { auto x = new FxLocalVariable(local, ScriptPosition); delete this; @@ -5693,6 +5699,38 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +FxStaticArrayVariable::FxStaticArrayVariable(FxLocalVariableDeclaration *var, const FScriptPosition &sc) + : FxExpression(EFX_StaticArrayVariable, sc) +{ + Variable = static_cast(var); + ValueType = Variable->ValueType; +} + +FxExpression *FxStaticArrayVariable::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + return this; +} + +bool FxStaticArrayVariable::RequestAddress(FCompileContext &ctx, bool *writable) +{ + AddressRequested = true; + if (writable != nullptr) *writable = false; + return true; +} + +ExpEmit FxStaticArrayVariable::Emit(VMFunctionBuilder *build) +{ + // returns the first const register for this array + return ExpEmit(Variable->StackOffset, Variable->ElementType->GetRegType(), true, false); +} + //========================================================================== // @@ -6357,6 +6395,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) ExpEmit start = Array->Emit(build); PArray *const arraytype = static_cast(Array->ValueType); + /* what was this for? if (start.Konst) { ExpEmit tmpstart(build, REGT_POINTER); @@ -6364,16 +6403,17 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) 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) { + indexval *= arraytype->ElementSize; if (!start.Fixed) { build->Emit(OP_ADDA_RK, start.RegNum, start.RegNum, build->GetConstantInt(indexval)); @@ -6389,61 +6429,90 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) } return start; } - else + else if (!start.Konst) { start.Free(build); ExpEmit dest(build, ValueType->GetRegType()); - build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum, start.RegNum, build->GetConstantInt(indexval)); + build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum, start.RegNum, build->GetConstantInt(indexval* arraytype->ElementSize)); + return dest; + } + else + { + static int LK_Ops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; + assert(start.RegType == ValueType->GetRegType()); + ExpEmit dest(build, start.RegType); + build->Emit(LK_Ops[start.RegType], dest.RegNum, start.RegNum + indexval); return dest; } } else { ExpEmit indexv(index->Emit(build)); - ExpEmit indexwork = indexv.Fixed ? ExpEmit(build, indexv.RegType) : indexv; build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); - int shiftbits = 0; - while (1u << shiftbits < arraytype->ElementSize) - { - shiftbits++; - } - if (1u << shiftbits == arraytype->ElementSize) + if (!start.Konst) { - if (shiftbits > 0) + ExpEmit indexwork = indexv.Fixed ? ExpEmit(build, indexv.RegType) : indexv; + int shiftbits = 0; + while (1u << shiftbits < arraytype->ElementSize) { - build->Emit(OP_SLL_RI, indexwork.RegNum, indexv.RegNum, shiftbits); + shiftbits++; } - } - else - { - // A shift won't do, so use a multiplication - build->Emit(OP_MUL_RK, indexwork.RegNum, indexv.RegNum, build->GetConstantInt(arraytype->ElementSize)); - } - - indexwork.Free(build); - if (AddressRequested) - { - if (!start.Fixed) + if (1u << shiftbits == arraytype->ElementSize) { - build->Emit(OP_ADDA_RR, start.RegNum, start.RegNum, indexwork.RegNum); + if (shiftbits > 0) + { + build->Emit(OP_SLL_RI, indexwork.RegNum, indexv.RegNum, shiftbits); + } + } + else + { + // A shift won't do, so use a multiplication + build->Emit(OP_MUL_RK, indexwork.RegNum, indexv.RegNum, build->GetConstantInt(arraytype->ElementSize)); + } + indexwork.Free(build); + + if (AddressRequested) + { + if (!start.Fixed) + { + build->Emit(OP_ADDA_RR, start.RegNum, start.RegNum, indexwork.RegNum); + } + else + { + start.Free(build); + // do not clobber local variables. + ExpEmit temp(build, start.RegType); + build->Emit(OP_ADDA_RR, temp.RegNum, start.RegNum, indexwork.RegNum); + start = temp; + } + return start; } else { start.Free(build); - // do not clobber local variables. - ExpEmit temp(build, start.RegType); - build->Emit(OP_ADDA_RR, temp.RegNum, start.RegNum, indexwork.RegNum); - start = temp; + ExpEmit dest(build, ValueType->GetRegType()); + // added 1 to use the *_R version that takes the offset from a register + build->Emit(arraytype->ElementType->GetLoadOp() + 1, dest.RegNum, start.RegNum, indexwork.RegNum); + return dest; } - return start; } else { - start.Free(build); - ExpEmit dest(build, ValueType->GetRegType()); - // added 1 to use the *_R version that takes the offset from a register - build->Emit(arraytype->ElementType->GetLoadOp() + 1, dest.RegNum, start.RegNum, indexwork.RegNum); + static int LKR_Ops[] = { OP_LK_R, OP_LKF_R, OP_LKS_R, OP_LKP_R }; + assert(start.RegType == ValueType->GetRegType()); + ExpEmit dest(build, start.RegType); + if (start.RegNum <= 255) + { + // Since large constant tables are the exception, the constant component in C is an immediate value here. + build->Emit(LKR_Ops[start.RegType], dest.RegNum, indexv.RegNum, start.RegNum); + } + else + { + build->Emit(OP_ADD_RK, indexv.RegNum, indexv.RegNum, build->GetConstantInt(start.RegNum)); + build->Emit(LKR_Ops[start.RegType], dest.RegNum, indexv.RegNum, 0); + } + indexv.Free(build); return dest; } } @@ -9241,3 +9310,82 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) // Stack space will not be released because that would make controlled destruction impossible. // For that all local stack variables need to live for the entire execution of a function. } + + +FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos) + : FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos) +{ + ElementType = type; + ExprType = EFX_StaticArray; + values = std::move(args); +} + +FxExpression *FxStaticArray::Resolve(FCompileContext &ctx) +{ + bool fail = false; + for (unsigned i = 0; i < values.Size(); i++) + { + values[i] = new FxTypeCast(values[i], ElementType, false); + values[i] = values[i]->Resolve(ctx); + if (values[i] == nullptr) fail = true; + else if (!values[i]->isConstant()) + { + ScriptPosition.Message(MSG_ERROR, "Initializer must be constant"); + fail = true; + } + } + if (fail) + { + delete this; + return nullptr; + } + if (ElementType->GetRegType() == REGT_NIL) + { + ScriptPosition.Message(MSG_ERROR, "Invalid type for constant array"); + delete this; + return nullptr; + } + + ctx.Block->LocalVars.Push(this); + return this; +} + +ExpEmit FxStaticArray::Emit(VMFunctionBuilder *build) +{ + switch (ElementType->GetRegType()) + { + default: + assert(false && "Invalid register type"); + break; + + case REGT_INT: + { + TArray cvalues; + for (auto v : values) cvalues.Push(static_cast(v)->GetValue().GetInt()); + StackOffset = build->AllocConstantsInt(cvalues.Size(), &cvalues[0]); + break; + } + case REGT_FLOAT: + { + TArray cvalues; + for (auto v : values) cvalues.Push(static_cast(v)->GetValue().GetFloat()); + StackOffset = build->AllocConstantsFloat(cvalues.Size(), &cvalues[0]); + break; + } + case REGT_STRING: + { + TArray cvalues; + for (auto v : values) cvalues.Push(static_cast(v)->GetValue().GetString()); + StackOffset = build->AllocConstantsString(cvalues.Size(), &cvalues[0]); + break; + } + case REGT_POINTER: + { + TArray cvalues; + for (auto v : values) cvalues.Push(static_cast(v)->GetValue().GetPointer()); + StackOffset = build->AllocConstantsAddress(cvalues.Size(), &cvalues[0], ElementType->GetLoadOp() == OP_LO ? ATAG_OBJECT : ATAG_GENERIC); + break; + } + } + return ExpEmit(); +} diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 03b256970d..7f588a0eb1 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -282,6 +282,8 @@ enum EFxType EFX_Super, EFX_StackVariable, EFX_MultiAssign, + EFX_StaticArray, + EFX_StaticArrayVariable, EFX_COUNT }; @@ -1308,6 +1310,25 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxLocalVariable +// +//========================================================================== +class FxStaticArray; + +class FxStaticArrayVariable : public FxExpression +{ +public: + FxStaticArray *Variable; + bool AddressRequested; + + FxStaticArrayVariable(FxLocalVariableDeclaration*, const FScriptPosition&); + FxExpression *Resolve(FCompileContext&); + bool RequestAddress(FCompileContext &ctx, bool *writable); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxSelf @@ -1529,6 +1550,7 @@ class FxCompoundStatement : public FxSequence FxCompoundStatement *Outer = nullptr; friend class FxLocalVariableDeclaration; + friend class FxStaticArray; friend class FxMultiAssign; public: @@ -1841,6 +1863,7 @@ class FxLocalVariableDeclaration : public FxExpression { friend class FxCompoundStatement; friend class FxLocalVariable; + friend class FxStaticArrayVariable; FName Name; FxExpression *Init; @@ -1859,4 +1882,25 @@ public: }; +//========================================================================== +// +// +// +//========================================================================== + +class FxStaticArray : public FxLocalVariableDeclaration +{ + friend class FxStaticArrayVariable; + + PType *ElementType; + FArgumentList values; + +public: + + FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + + #endif diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 721ff5fab7..042753d325 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -45,10 +45,6 @@ VMFunctionBuilder::VMFunctionBuilder(int numimplicits) { - NumIntConstants = 0; - NumFloatConstants = 0; - NumAddressConstants = 0; - NumStringConstants = 0; MaxParam = 0; ActiveParam = 0; NumImplicits = numimplicits; @@ -74,25 +70,25 @@ VMFunctionBuilder::~VMFunctionBuilder() void VMFunctionBuilder::MakeFunction(VMScriptFunction *func) { - func->Alloc(Code.Size(), NumIntConstants, NumFloatConstants, NumStringConstants, NumAddressConstants); + func->Alloc(Code.Size(), IntConstantList.Size(), FloatConstantList.Size(), StringConstantList.Size(), AddressConstantList.Size()); // Copy code block. memcpy(func->Code, &Code[0], Code.Size() * sizeof(VMOP)); // Create constant tables. - if (NumIntConstants > 0) + if (IntConstantList.Size() > 0) { FillIntConstants(func->KonstD); } - if (NumFloatConstants > 0) + if (FloatConstantList.Size() > 0) { FillFloatConstants(func->KonstF); } - if (NumAddressConstants > 0) + if (AddressConstantList.Size() > 0) { FillAddressConstants(func->KonstA, func->KonstATags()); } - if (NumStringConstants > 0) + if (StringConstantList.Size() > 0) { FillStringConstants(func->KonstS); } @@ -118,13 +114,7 @@ void VMFunctionBuilder::MakeFunction(VMScriptFunction *func) void VMFunctionBuilder::FillIntConstants(int *konst) { - TMapIterator it(IntConstants); - TMap::Pair *pair; - - while (it.NextPair(pair)) - { - konst[pair->Value] = pair->Key; - } + memcpy(konst, &IntConstantList[0], sizeof(int) * IntConstantList.Size()); } //========================================================================== @@ -135,13 +125,7 @@ void VMFunctionBuilder::FillIntConstants(int *konst) void VMFunctionBuilder::FillFloatConstants(double *konst) { - TMapIterator it(FloatConstants); - TMap::Pair *pair; - - while (it.NextPair(pair)) - { - konst[pair->Value] = pair->Key; - } + memcpy(konst, &FloatConstantList[0], sizeof(double) * FloatConstantList.Size()); } //========================================================================== @@ -152,14 +136,8 @@ void VMFunctionBuilder::FillFloatConstants(double *konst) void VMFunctionBuilder::FillAddressConstants(FVoidObj *konst, VM_ATAG *tags) { - TMapIterator it(AddressConstants); - TMap::Pair *pair; - - while (it.NextPair(pair)) - { - konst[pair->Value.KonstNum].v = pair->Key; - tags[pair->Value.KonstNum] = pair->Value.Tag; - } + memcpy(konst, &AddressConstantList[0], sizeof(void*) * AddressConstantList.Size()); + memcpy(tags, &AtagConstantList[0], sizeof(VM_ATAG) * AtagConstantList.Size()); } //========================================================================== @@ -170,12 +148,9 @@ void VMFunctionBuilder::FillAddressConstants(FVoidObj *konst, VM_ATAG *tags) void VMFunctionBuilder::FillStringConstants(FString *konst) { - TMapIterator it(StringConstants); - TMap::Pair *pair; - - while (it.NextPair(pair)) + for (auto &s : StringConstantList) { - konst[pair->Value] = pair->Key; + *konst++ = s; } } @@ -183,22 +158,21 @@ void VMFunctionBuilder::FillStringConstants(FString *konst) // // VMFunctionBuilder :: GetConstantInt // -// Returns a constant register initialized with the given value, or -1 if -// there were no more constants free. +// Returns a constant register initialized with the given value. // //========================================================================== -int VMFunctionBuilder::GetConstantInt(int val) +unsigned VMFunctionBuilder::GetConstantInt(int val) { - int *locp = IntConstants.CheckKey(val); + unsigned int *locp = IntConstantMap.CheckKey(val); if (locp != NULL) { return *locp; } else { - int loc = NumIntConstants++; - IntConstants.Insert(val, loc); + unsigned loc = IntConstantList.Push(val); + IntConstantMap.Insert(val, loc); return loc; } } @@ -207,22 +181,21 @@ int VMFunctionBuilder::GetConstantInt(int val) // // VMFunctionBuilder :: GetConstantFloat // -// Returns a constant register initialized with the given value, or -1 if -// there were no more constants free. +// Returns a constant register initialized with the given value. // //========================================================================== -int VMFunctionBuilder::GetConstantFloat(double val) +unsigned VMFunctionBuilder::GetConstantFloat(double val) { - int *locp = FloatConstants.CheckKey(val); + unsigned *locp = FloatConstantMap.CheckKey(val); if (locp != NULL) { return *locp; } else { - int loc = NumFloatConstants++; - FloatConstants.Insert(val, loc); + unsigned loc = FloatConstantList.Push(val); + FloatConstantMap.Insert(val, loc); return loc; } } @@ -231,22 +204,21 @@ int VMFunctionBuilder::GetConstantFloat(double val) // // VMFunctionBuilder :: GetConstantString // -// Returns a constant register initialized with the given value, or -1 if -// there were no more constants free. +// Returns a constant register initialized with the given value. // //========================================================================== -int VMFunctionBuilder::GetConstantString(FString val) +unsigned VMFunctionBuilder::GetConstantString(FString val) { - int *locp = StringConstants.CheckKey(val); + unsigned *locp = StringConstantMap.CheckKey(val); if (locp != NULL) { return *locp; } else { - int loc = NumStringConstants++; - StringConstants.Insert(val, loc); + int loc = StringConstantList.Push(val); + StringConstantMap.Insert(val, loc); return loc; } } @@ -260,13 +232,13 @@ int VMFunctionBuilder::GetConstantString(FString val) // //========================================================================== -int VMFunctionBuilder::GetConstantAddress(void *ptr, VM_ATAG tag) +unsigned VMFunctionBuilder::GetConstantAddress(void *ptr, VM_ATAG tag) { if (ptr == NULL) { // Make all NULL pointers generic. (Or should we allow typed NULLs?) tag = ATAG_GENERIC; } - AddrKonst *locp = AddressConstants.CheckKey(ptr); + AddrKonst *locp = AddressConstantMap.CheckKey(ptr); if (locp != NULL) { // There should only be one tag associated with a memory location. @@ -275,12 +247,71 @@ int VMFunctionBuilder::GetConstantAddress(void *ptr, VM_ATAG tag) } else { - AddrKonst loc = { NumAddressConstants++, tag }; - AddressConstants.Insert(ptr, loc); + unsigned locc = AddressConstantList.Push(ptr); + AtagConstantList.Push(tag); + + AddrKonst loc = { locc, tag }; + AddressConstantMap.Insert(ptr, loc); return loc.KonstNum; } } +//========================================================================== +// +// VMFunctionBuilder :: AllocConstants* +// +// Returns a range of constant register initialized with the given values. +// +//========================================================================== + +unsigned VMFunctionBuilder::AllocConstantsInt(unsigned count, int *values) +{ + unsigned addr = IntConstantList.Reserve(count); + memcpy(&IntConstantList[addr], values, count * sizeof(int)); + for (unsigned i = 0; i < count; i++) + { + IntConstantMap.Insert(values[i], addr + i); + } + return addr; +} + +unsigned VMFunctionBuilder::AllocConstantsFloat(unsigned count, double *values) +{ + unsigned addr = FloatConstantList.Reserve(count); + memcpy(&FloatConstantList[addr], values, count * sizeof(double)); + for (unsigned i = 0; i < count; i++) + { + FloatConstantMap.Insert(values[i], addr + i); + } + return addr; +} + +unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs, VM_ATAG tag) +{ + unsigned addr = AddressConstantList.Reserve(count); + AtagConstantList.Reserve(count); + memcpy(&AddressConstantList[addr], ptrs, count * sizeof(void *)); + for (unsigned i = 0; i < count; i++) + { + AtagConstantList[addr + i] = tag; + AddrKonst loc = { addr+i, tag }; + AddressConstantMap.Insert(ptrs[i], loc); + } + return addr; +} + +unsigned VMFunctionBuilder::AllocConstantsString(unsigned count, FString *ptrs) +{ + unsigned addr = StringConstantList.Reserve(count); + for (unsigned i = 0; i < count; i++) + { + StringConstantList[addr + i] = ptrs[i]; + StringConstantMap.Insert(ptrs[i], addr + i); + } + return addr; +} + + //========================================================================== // // VMFunctionBuilder :: ParamChange diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index d69c97707f..5991d07116 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -42,10 +42,16 @@ public: void MakeFunction(VMScriptFunction *func); // Returns the constant register holding the value. - int GetConstantInt(int val); - int GetConstantFloat(double val); - int GetConstantAddress(void *ptr, VM_ATAG tag); - int GetConstantString(FString str); + unsigned GetConstantInt(int val); + unsigned GetConstantFloat(double val); + unsigned GetConstantAddress(void *ptr, VM_ATAG tag); + unsigned GetConstantString(FString str); + + unsigned AllocConstantsInt(unsigned int count, int *values); + unsigned AllocConstantsFloat(unsigned int count, double *values); + unsigned AllocConstantsAddress(unsigned int count, void **ptrs, VM_ATAG tag); + unsigned AllocConstantsString(unsigned int count, FString *ptrs); + // Returns the address of the next instruction to be emitted. size_t GetAddress(); @@ -82,19 +88,20 @@ public: private: struct AddrKonst { - int KonstNum; + unsigned KonstNum; VM_ATAG Tag; }; - // These map from the constant value to its position in the constant table. - TMap IntConstants; - TMap FloatConstants; - TMap AddressConstants; - TMap StringConstants; - int NumIntConstants; - int NumFloatConstants; - int NumAddressConstants; - int NumStringConstants; + TArray IntConstantList; + TArray FloatConstantList; + TArray AddressConstantList; + TArray AtagConstantList; + TArray StringConstantList; + // These map from the constant value to its position in the constant table. + TMap IntConstantMap; + TMap FloatConstantMap; + TMap AddressConstantMap; + TMap StringConstantMap; int MaxParam; int ActiveParam; diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 031f3328b7..c95699613d 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -97,6 +97,9 @@ #define RIRIRI MODE_AI | MODE_BI | MODE_CI #define RIRII8 MODE_AI | MODE_BI | MODE_CIMMZ +#define RFRII8 MODE_AF | MODE_BI | MODE_CIMMZ +#define RPRII8 MODE_AP | MODE_BI | MODE_CIMMZ +#define RSRII8 MODE_AS | MODE_BI | MODE_CIMMZ #define RIRIKI MODE_AI | MODE_BI | MODE_CKI #define RIKIRI MODE_AI | MODE_BKI | MODE_CI #define RIKII8 MODE_AI | MODE_BKI | MODE_CIMMZ diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index e4ab959460..6202de3bbf 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -84,6 +84,26 @@ begin: reg.a[a] = konsta[BC].v; reg.atag[a] = konstatag[BC]; NEXTOP; + + OP(LK_R) : + ASSERTD(a); ASSERTD(B); + reg.d[a] = konstd[reg.d[B] + C]; + NEXTOP; + OP(LKF_R) : + ASSERTF(a); ASSERTD(B); + reg.f[a] = konstf[reg.d[B] + C]; + NEXTOP; + OP(LKS_R) : + ASSERTS(a); ASSERTD(B); + reg.s[a] = konsts[reg.d[B] + C]; + NEXTOP; + OP(LKP_R) : + ASSERTA(a); ASSERTD(B); + b = reg.d[B] + C; + reg.a[a] = konsta[b].v; + reg.atag[a] = konstatag[b]; + NEXTOP; + OP(LFP): ASSERTA(a); assert(sfunc != NULL); assert(sfunc->ExtraSpace > 0); reg.a[a] = f->GetExtra(); diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 210ff9c493..6f78e9e4e0 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -10,6 +10,10 @@ xx(LK, lk, LKI), // load integer constant xx(LKF, lk, LKF), // load float constant xx(LKS, lk, LKS), // load string constant xx(LKP, lk, LKP), // load pointer constant +xx(LK_R, lk, RIRII8), // load integer constant indexed +xx(LKF_R, lk, RFRII8), // load float constant indexed +xx(LKS_R, lk, RSRII8), // load string constant indexed +xx(LKP_R, lk, RPRII8), // load pointer constant indexed xx(LFP, lf, LFP), // load frame pointer // Load from memory. rA = *(rB + rkC) diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index d8945ca3b0..3bdc2e2440 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -595,6 +595,16 @@ static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node) out.Close(); } +static void PrintStaticArray(FLispString &out, ZCC_TreeNode *node) +{ + ZCC_StaticArrayStatement *enode = (ZCC_StaticArrayStatement *)node; + out.Open("static-array-stmt"); + PrintNodes(out, enode->Type, false); + out.AddName(enode->Id); + PrintNodes(out, enode->Values, false); + out.Close(); +} + static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node) { ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node; diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 8bd9686e36..3380959ec9 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -1559,6 +1559,29 @@ statement(X) ::= jump_statement(X). 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; } +statement(X) ::= staticarray_statement(A). { X = A; /*X-overwrites-A*/ } + +/*----- Static array Statements -----*/ + +%type staticarray_statement{ZCC_StaticArrayStatement *} + +staticarray_statement(X) ::= STATIC CONST type(A) IDENTIFIER(B) LBRACKET RBRACKET EQ LBRACE expr_list(C) RBRACE. +{ + NEW_AST_NODE(StaticArrayStatement, stmt, A); + stmt->Type = A; + stmt->Id = ENamedName(B.Int); + stmt->Values = C; + X = stmt; +} + +staticarray_statement(X) ::= STATIC CONST type(A) LBRACKET RBRACKET IDENTIFIER(B) EQ LBRACE expr_list(C) RBRACE. +{ + NEW_AST_NODE(StaticArrayStatement, stmt, A); + stmt->Type = A; + stmt->Id = ENamedName(B.Int); + stmt->Values = C; + X = stmt; +} /*----- Jump Statements -----*/ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 7c78b3c1e2..291387617e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2826,6 +2826,15 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) return new FxClassPtrCast(cls, ConvertNode(cc->Parameters)); } + case AST_StaticArrayStatement: + { + auto sas = static_cast(ast); + PType *ztype = DetermineType(ConvertClass, sas, sas->Id, sas->Type, false, false); + FArgumentList args; + ConvertNodeList(args, sas->Values); + // This has to let the code generator resolve the constants, not the Simplifier, which lacks all the necessary type info. + return new FxStaticArray(ztype, sas->Id, args, *ast); + } case AST_ExprMemberAccess: { diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index dd777eb6ce..a19249208f 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -103,6 +103,7 @@ enum EZCCTreeNodeType AST_VectorValue, AST_DeclFlags, AST_ClassCast, + AST_StaticArrayStatement, NUM_AST_NODE_TYPES }; @@ -406,6 +407,13 @@ struct ZCC_Statement : ZCC_TreeNode { }; +struct ZCC_StaticArrayStatement : ZCC_Statement +{ + ZCC_Type *Type; + ENamedName Id; + ZCC_Expression *Values; +}; + struct ZCC_CompoundStmt : ZCC_Statement { ZCC_Statement *Content; From 159f09105e1d96b5eabc3c5aa1a6fefa2ac6ea01 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 18:34:27 +0100 Subject: [PATCH 310/471] - used static constant arrays to shorten some code. --- wadsrc/static/zscript/actor.txt | 14 ++------------ wadsrc/static/zscript/hexen/demons.txt | 16 ++++++---------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 7f088154f0..5c824d7bb4 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -282,21 +282,11 @@ class Actor : Thinker native void SpawnDirt (double radius) { - class dtype; - switch (random[Dirt](0, 5)) - { - case 0: dtype = "Dirt1"; break; - case 1: dtype = "Dirt2"; break; - case 2: dtype = "Dirt3"; break; - case 3: dtype = "Dirt4"; break; - case 4: dtype = "Dirt5"; break; - default: dtype = "Dirt6"; break; - } - + static const class chunks[] = { "Dirt1", "Dirt2", "Dirt3", "Dirt4", "Dirt5", "Dirt6" }; double zo = random[Dirt]() / 128. + 1; Vector3 pos = Vec3Angle(radius, random[Dirt]() * (360./256), zo); - Actor mo = Spawn (dtype, pos, ALLOW_REPLACE); + Actor mo = Spawn (chunks[random[Dirt](0, 5)], pos, ALLOW_REPLACE); if (mo) { mo.Vel.Z = random[Dirt]() / 64.; diff --git a/wadsrc/static/zscript/hexen/demons.txt b/wadsrc/static/zscript/hexen/demons.txt index 8aa65629de..25e078509b 100644 --- a/wadsrc/static/zscript/hexen/demons.txt +++ b/wadsrc/static/zscript/hexen/demons.txt @@ -58,11 +58,9 @@ class Demon1 : Actor 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); + static const class chunks[] = { "Demon1Chunk1", "Demon1Chunk2", "Demon1Chunk3", "Demon1Chunk4", "Demon1Chunk5" }; + for(int i = 0; i < 5; i++) + A_SpawnItemEx(chunks[i], 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle+90), frandom[DemonChunks](1,4.984375)*sin(Angle+90), 8, 90, ChunkFlags); } Goto Death+2; Ice: @@ -266,11 +264,9 @@ class Demon2 : Demon1 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); + static const class chunks[] = { "Demon2Chunk1", "Demon2Chunk2", "Demon2Chunk3", "Demon2Chunk4", "Demon2Chunk5" }; + for(int i = 0; i < 5; i++) + A_SpawnItemEx(chunks[i], 0,0,45, frandom[DemonChunks](1,4.984375)*cos(Angle+90), frandom[DemonChunks](1,4.984375)*sin(Angle+90), 8, 90, ChunkFlags); } Goto Death+2; } From 1c2c26eb0860981adfd3494d3919ea9e318c97ce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 20:24:39 +0100 Subject: [PATCH 311/471] - implemented direct CVar access. --- src/c_cvars.cpp | 4 +- src/c_cvars.h | 13 ++- src/scripting/codegeneration/codegen.cpp | 128 ++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 10 ++ 4 files changed, 148 insertions(+), 7 deletions(-) diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index c8f1ee4c62..fe859cb49c 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -1093,7 +1093,7 @@ BitVal (bitval) ECVarType FFlagCVar::GetRealType () const { - return CVAR_Dummy; + return CVAR_DummyBool; } UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const @@ -1197,7 +1197,7 @@ BitVal (bitval) ECVarType FMaskCVar::GetRealType () const { - return CVAR_Dummy; + return CVAR_DummyInt; } UCVarValue FMaskCVar::GetGenericRep (ECVarType type) const diff --git a/src/c_cvars.h b/src/c_cvars.h index be7676e895..cf6975b866 100644 --- a/src/c_cvars.h +++ b/src/c_cvars.h @@ -81,13 +81,17 @@ enum ECVarType CVAR_Float, CVAR_String, CVAR_Color, // stored as CVAR_Int - CVAR_Dummy, // just redirects to another cvar + CVAR_DummyBool, // just redirects to another cvar + CVAR_DummyInt, // just redirects to another cvar + CVAR_Dummy, // Unknown CVAR_GUID }; class FConfigFile; class AActor; +class FxCVar; + class FBaseCVar { public: @@ -211,6 +215,7 @@ void C_DeinitConsole(); class FBoolCVar : public FBaseCVar { + friend class FxCVar; public: FBoolCVar (const char *name, bool def, uint32 flags, void (*callback)(FBoolCVar &)=NULL); @@ -236,6 +241,7 @@ protected: class FIntCVar : public FBaseCVar { + friend class FxCVar; public: FIntCVar (const char *name, int def, uint32 flags, void (*callback)(FIntCVar &)=NULL); @@ -263,6 +269,7 @@ protected: class FFloatCVar : public FBaseCVar { + friend class FxCVar; public: FFloatCVar (const char *name, float def, uint32 flags, void (*callback)(FFloatCVar &)=NULL); @@ -289,6 +296,7 @@ protected: class FStringCVar : public FBaseCVar { + friend class FxCVar; public: FStringCVar (const char *name, const char *def, uint32 flags, void (*callback)(FStringCVar &)=NULL); ~FStringCVar (); @@ -315,6 +323,7 @@ protected: class FColorCVar : public FIntCVar { + friend class FxCVar; public: FColorCVar (const char *name, int def, uint32 flags, void (*callback)(FColorCVar &)=NULL); @@ -339,6 +348,7 @@ protected: class FFlagCVar : public FBaseCVar { + friend class FxCVar; public: FFlagCVar (const char *name, FIntCVar &realvar, uint32 bitval); @@ -367,6 +377,7 @@ protected: class FMaskCVar : public FBaseCVar { + friend class FxCVar; public: FMaskCVar (const char *name, FIntCVar &realvar, uint32 bitval); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7be1b9cf2f..9ca96de05d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1993,7 +1993,7 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) if (regtype == REGT_INT) { - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, value.RegNum, value.RegNum, build->GetConstantInt(1)); + build->Emit(OP_ADDI, value.RegNum, value.RegNum, (Token == TK_Incr) ? 1 : -1); } else { @@ -2077,7 +2077,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) 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)); + build->Emit(OP_ADDI, assign.RegNum, out.RegNum, (Token == TK_Incr) ? 1 : -1); } else { @@ -2094,7 +2094,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) 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)); + build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, (Token == TK_Incr) ? 1 : -1); } else { @@ -2108,7 +2108,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) { if (regtype == REGT_INT) { - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, pointer.RegNum, pointer.RegNum, build->GetConstantInt(1)); + build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, (Token == TK_Incr) ? 1 : -1); } else { @@ -5526,6 +5526,18 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num); newex = new FxConstant(num, ScriptPosition); } + + auto cvar = FindCVar(Identifier.GetChars(), nullptr); + if (cvar != nullptr) + { + if (cvar->GetFlags() & CVAR_USERINFO) + { + ScriptPosition.Message(MSG_ERROR, "Cannot access userinfo CVARs directly. Use GetCVar() instead."); + delete this; + return nullptr; + } + newex = new FxCVar(cvar, ScriptPosition); + } if (newex == nullptr) { @@ -5956,6 +5968,114 @@ ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +FxCVar::FxCVar(FBaseCVar *cvar, const FScriptPosition &pos) + : FxExpression(EFX_CVar, pos) +{ + CVar = cvar; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxCVar::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + switch (CVar->GetRealType()) + { + case CVAR_Bool: + case CVAR_DummyBool: + ValueType = TypeBool; + break; + + case CVAR_Int: + case CVAR_DummyInt: + ValueType = TypeSInt32; + break; + + case CVAR_Color: + ValueType = TypeColor; + break; + + case CVAR_Float: + ValueType = TypeFloat64; + break; + + case CVAR_String: + ValueType = TypeString; + break; + + default: + ScriptPosition.Message(MSG_ERROR, "Unknown CVar type for %s", CVar->GetName()); + delete this; + return nullptr; + } + return this; +} + +ExpEmit FxCVar::Emit(VMFunctionBuilder *build) +{ + ExpEmit dest(build, ValueType->GetRegType()); + ExpEmit addr(build, REGT_POINTER); + int nul = build->GetConstantInt(0); + switch (CVar->GetRealType()) + { + case CVAR_Int: + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); + break; + + case CVAR_Color: + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); + break; + + case CVAR_Float: + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LSP, dest.RegNum, addr.RegNum, nul); + break; + + case CVAR_Bool: + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LBU, dest.RegNum, addr.RegNum, nul); + break; + + case CVAR_String: + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LS, dest.RegNum, addr.RegNum, nul); + break; + + case CVAR_DummyBool: + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->ValueVar.Value, ATAG_GENERIC)); + build->Emit(OP_LBIT, dest.RegNum, addr.RegNum, static_cast(CVar)->BitNum); + break; + + case CVAR_DummyInt: + { + auto cv = static_cast(CVar); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC)); + build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); + build->Emit(OP_AND_RK, dest.RegNum, dest.RegNum, build->GetConstantInt(cv->BitVal)); + build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum); + break; + } + + default: + assert(false && "Unsupported CVar type"); + break; + } + return dest; +} + + //========================================================================== // // diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 7f588a0eb1..a3b6451766 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -284,6 +284,7 @@ enum EFxType EFX_MultiAssign, EFX_StaticArray, EFX_StaticArrayVariable, + EFX_CVar, EFX_COUNT }; @@ -1236,6 +1237,15 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +class FxCVar : public FxExpression +{ + FBaseCVar *CVar; +public: + FxCVar(FBaseCVar*, const FScriptPosition&); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxClassMember From e93961da96b40c375e690060af92a28d15829d0b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 23:00:05 +0100 Subject: [PATCH 312/471] - removed all constant versions of vector instructions. The vector code does not use compound constants so there's no need to have instructions for them. - fixed: The code generator had no good safeguards for exceeding the maximum amount of registers. All there was was a handful of pitiful asserts which in production code do nothing at all but generate broken output. Even worse, the VM was hardwired to at most 255 constants per type per function by storing the constant count in a byte! This has been extended to 65535, but since many instructions only have a byte available for the constant index, a workaround had to be added to do a two-instruction setup if larger indices are needed. --- src/scripting/codegeneration/codegen.cpp | 8 +- src/scripting/vm/vm.h | 8 +- src/scripting/vm/vmbuilder.cpp | 120 ++++++- src/scripting/vm/vmdisasm.cpp | 2 +- src/scripting/vm/vmexec.h | 71 +--- src/scripting/vm/vmframe.cpp | 8 +- src/scripting/vm/vmops.h | 440 +++++++++++------------ 7 files changed, 336 insertions(+), 321 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9ca96de05d..593737065c 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1993,7 +1993,7 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) if (regtype == REGT_INT) { - build->Emit(OP_ADDI, value.RegNum, value.RegNum, (Token == TK_Incr) ? 1 : -1); + build->Emit(OP_ADDI, value.RegNum, value.RegNum, uint8_t((Token == TK_Incr) ? 1 : -1)); } else { @@ -2077,7 +2077,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) ExpEmit assign(build, regtype); if (regtype == REGT_INT) { - build->Emit(OP_ADDI, assign.RegNum, out.RegNum, (Token == TK_Incr) ? 1 : -1); + build->Emit(OP_ADDI, assign.RegNum, out.RegNum, uint8_t((Token == TK_Incr) ? 1 : -1)); } else { @@ -2094,7 +2094,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) if (regtype == REGT_INT) { build->Emit(OP_MOVE, out.RegNum, pointer.RegNum); - build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, (Token == TK_Incr) ? 1 : -1); + build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, uint8_t((Token == TK_Incr) ? 1 : -1)); } else { @@ -2108,7 +2108,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) { if (regtype == REGT_INT) { - build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, (Token == TK_Incr) ? 1 : -1); + build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, uint8_t((Token == TK_Incr) ? 1 : -1)); } else { diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 670c5a982e..ab1708e088 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -814,10 +814,10 @@ public: VM_UBYTE NumRegF; VM_UBYTE NumRegS; VM_UBYTE NumRegA; - VM_UBYTE NumKonstD; - VM_UBYTE NumKonstF; - VM_UBYTE NumKonstS; - VM_UBYTE NumKonstA; + VM_UHALF NumKonstD; + VM_UHALF NumKonstF; + VM_UHALF NumKonstS; + VM_UHALF 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. diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 042753d325..3ccf67f959 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -36,6 +36,19 @@ #include "info.h" #include "m_argv.h" #include "thingdef.h" +#include "doomerrors.h" + +struct VMRemap +{ + BYTE altOp, kReg, kType; +}; + + +#define xx(op, name, mode, alt, kreg, ktype) {OP_##alt, kreg, ktype } +VMRemap opRemap[NUM_OPS] = { +#include "vmops.h" +}; +#undef xx //========================================================================== // @@ -523,10 +536,75 @@ size_t VMFunctionBuilder::GetAddress() size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc) { + static BYTE opcodes[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; + assert(opcode >= 0 && opcode < NUM_OPS); - assert(opa >= 0 && opa <= 255); - assert(opb >= 0 && opb <= 255); - assert(opc >= 0 && opc <= 255); + assert(opa >= 0); + assert(opb >= 0); + assert(opc >= 0); + + + // The following were just asserts, meaning this would silently create broken code if there was an overflow + // if this happened in a release build. Not good. + // These are critical errors that need to be reported to the user. + // In addition, the limit of 256 constants can easily be exceeded with arrays so this had to be extended to + // 65535 by adding some checks here that map byte-limited instructions to alternatives that can handle larger indices. + // (See vmops.h for the remapping info.) + + // Note: OP_CMPS also needs treatment, but I do not expect constant overflow to become an issue with strings, so for now there is no handling. + + if (opa > 255) + { + if (opRemap[opcode].kReg != 1 || opa > 32767) + { + I_Error("Register limit exceeded"); + } + int regtype = opRemap[opcode].kType; + ExpEmit emit(this, regtype); + Emit(opcodes[regtype], emit.RegNum, opa); + opcode = opRemap[opcode].altOp; + opa = emit.RegNum; + emit.Free(this); + } + if (opb > 255) + { + if (opRemap[opcode].kReg != 2 || opb > 32767) + { + I_Error("Register limit exceeded"); + } + int regtype = opRemap[opcode].kType; + ExpEmit emit(this, regtype); + Emit(opcodes[regtype], emit.RegNum, opb); + opcode = opRemap[opcode].altOp; + opb = emit.RegNum; + emit.Free(this); + } + if (opc > 255) + { + if (opcode == OP_PARAM && (opb & REGT_KONST) && opc <= 32767) + { + int regtype = opb & REGT_TYPE; + opb = regtype; + ExpEmit emit(this, regtype); + Emit(opcodes[regtype], emit.RegNum, opc); + opc = emit.RegNum; + emit.Free(this); + } + else + { + if (opRemap[opcode].kReg != 4 || opc > 32767) + { + I_Error("Register limit exceeded"); + } + int regtype = opRemap[opcode].kType; + ExpEmit emit(this, regtype); + Emit(opcodes[regtype], emit.RegNum, opc); + opcode = opRemap[opcode].altOp; + opc = emit.RegNum; + emit.Free(this); + } + } + if (opcode == OP_PARAM) { int chg; @@ -784,23 +862,31 @@ void FFunctionBuildList::Build() } // 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) + try { - sfunc->NumArgs += s->GetRegCount(); - } + 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; + if (dump != nullptr) + { + DumpFunction(dump, sfunc, item.PrintableName.GetChars(), (int)item.PrintableName.Len()); + codesize += sfunc->CodeSize; + } + sfunc->PrintableName = item.PrintableName; + sfunc->Unsafe = ctx.Unsafe; + } + catch (CRecoverableError &err) + { + // catch errors from the code generator and pring something meaningful. + item.Code->ScriptPosition.Message(MSG_ERROR, "%s in %s", err.GetMessage(), item.PrintableName); } - sfunc->PrintableName = item.PrintableName; - sfunc->Unsafe = ctx.Unsafe; } delete item.Code; if (dump != nullptr) diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index c95699613d..d8fc16433a 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -147,7 +147,7 @@ const VMOpInfo OpInfo[NUM_OPS] = { -#define xx(op, name, mode) { #name, mode } +#define xx(op, name, mode, alt, kreg, ktype) { #name, mode } #include "vmops.h" }; diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 6202de3bbf..477c5ac97a 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -8,7 +8,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) #if COMPGOTO static const void * const ops[256] = { -#define xx(op,sym,mode) &&op +#define xx(op,sym,mode,alt,kreg,ktype) &&op #include "vmops.h" }; #endif @@ -425,12 +425,6 @@ begin: DoCast(reg, f, a, B, C); } NEXTOP; - OP(DYNCAST_R): - // UNDONE - NEXTOP; - OP(DYNCAST_K): - // UNDONE - NEXTOP; OP(TEST): ASSERTD(a); @@ -1315,42 +1309,23 @@ begin: 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); @@ -1414,50 +1389,30 @@ begin: OP(ADDV3_RR): ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C+2); fcp = ®.f[C]; - 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(ADDV3_RK): - fcp = &konstf[C]; - goto Do_ADDV3; OP(SUBV3_RR): ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C+2); fbp = ®.f[B]; fcp = ®.f[C]; - 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(SUBV3_RK): - ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C+2); - fbp = ®.f[B]; - fcp = &konstf[C]; - goto Do_SUBV3; - OP(SUBV3_KR): - ASSERTF(A+2); ASSERTKF(B+2); ASSERTF(C+2); - fbp = &konstf[B]; - fcp = ®.f[C]; - goto Do_SUBV3; 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(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; OP(CROSSV_RR): ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C+2); fbp = ®.f[B]; fcp = ®.f[C]; - Do_CROSSV: { double t[3]; t[2] = fbp[0] * fcp[1] - fbp[1] * fcp[0]; @@ -1466,46 +1421,24 @@ begin: reg.f[a] = t[0]; reg.f[a+1] = t[1]; reg.f[a+2] = t[2]; } NEXTOP; - OP(CROSSV_RK): - ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C+2); - fbp = ®.f[B]; - fcp = &konstf[C]; - goto Do_CROSSV; - OP(CROSSV_KR): - ASSERTF(a+2); ASSERTKF(B+2); ASSERTF(C+2); - fbp = ®.f[B]; - fcp = &konstf[C]; - goto Do_CROSSV; OP(MULVF3_RR): ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C); fc = reg.f[C]; fbp = ®.f[B]; - Do_MULV3: reg.f[a] = fbp[0] * fc; reg.f[a+1] = fbp[1] * fc; reg.f[a+2] = fbp[2] * fc; NEXTOP; - OP(MULVF3_RK): - ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C); - fc = konstf[C]; - fbp = ®.f[B]; - goto Do_MULV3; - OP(DIVVF3_RR): + 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); diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index b20c8ac898..f35c3718d5 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -86,10 +86,10 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko { assert(Code == NULL); assert(numops > 0); - assert(numkonstd >= 0 && numkonstd <= 255); - assert(numkonstf >= 0 && numkonstf <= 255); - assert(numkonsts >= 0 && numkonsts <= 255); - assert(numkonsta >= 0 && numkonsta <= 255); + assert(numkonstd >= 0 && numkonstd <= 65535); + assert(numkonstf >= 0 && numkonstf <= 65535); + assert(numkonsts >= 0 && numkonsts <= 65535); + assert(numkonsta >= 0 && numkonsta <= 65535); void *mem = M_Malloc(numops * sizeof(VMOP) + numkonstd * sizeof(int) + numkonstf * sizeof(double) + diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 6f78e9e4e0..cf2a757469 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -1,251 +1,247 @@ #ifndef xx -#define xx(op, name, mode) OP_##op +#define xx(op, name, mode, alt, kreg, ktype) OP_##op #endif -xx(NOP, nop, NOP), // no operation +// first row is the opcode +// second row is the disassembly name +// third row is the disassembly flags +// fourth row is the alternative opcode if all 256 constant registers are exhausted. +// fifth row is the constant register index in the opcode +// sixth row is the constant register type. +// OP_PARAM and OP_CMPS need special treatment because they encode this information in the instruction. + +xx(NOP, nop, NOP, NOP, 0, 0), // no operation // Load constants. -xx(LI, li, LI), // load immediate signed 16-bit constant -xx(LK, lk, LKI), // load integer constant -xx(LKF, lk, LKF), // load float constant -xx(LKS, lk, LKS), // load string constant -xx(LKP, lk, LKP), // load pointer constant -xx(LK_R, lk, RIRII8), // load integer constant indexed -xx(LKF_R, lk, RFRII8), // load float constant indexed -xx(LKS_R, lk, RSRII8), // load string constant indexed -xx(LKP_R, lk, RPRII8), // load pointer constant indexed -xx(LFP, lf, LFP), // load frame pointer +xx(LI, li, LI, NOP, 0, 0), // load immediate signed 16-bit constant +xx(LK, lk, LKI, NOP, 0, 0), // load integer constant +xx(LKF, lk, LKF, NOP, 0, 0), // load float constant +xx(LKS, lk, LKS, NOP, 0, 0), // load string constant +xx(LKP, lk, LKP, NOP, 0, 0), // load pointer constant +xx(LK_R, lk, RIRII8, NOP, 0, 0), // load integer constant indexed +xx(LKF_R, lk, RFRII8, NOP, 0, 0), // load float constant indexed +xx(LKS_R, lk, RSRII8, NOP, 0, 0), // load string constant indexed +xx(LKP_R, lk, RPRII8, NOP, 0, 0), // load pointer constant indexed +xx(LFP, lf, LFP, NOP, 0, 0), // load frame pointer // Load from memory. rA = *(rB + rkC) -xx(LB, lb, RIRPKI), // load byte -xx(LB_R, lb, RIRPRI), -xx(LH, lh, RIRPKI), // load halfword -xx(LH_R, lh, RIRPRI), -xx(LW, lw, RIRPKI), // load word -xx(LW_R, lw, RIRPRI), -xx(LBU, lbu, RIRPKI), // load byte unsigned -xx(LBU_R, lbu, RIRPRI), -xx(LHU, lhu, RIRPKI), // load halfword unsigned -xx(LHU_R, lhu, RIRPRI), -xx(LSP, lsp, RFRPKI), // load single-precision fp -xx(LSP_R, lsp, RFRPRI), -xx(LDP, ldp, RFRPKI), // load double-precision fp -xx(LDP_R, ldp, RFRPRI), -xx(LS, ls, RSRPKI), // load string -xx(LS_R, ls, RSRPRI), -xx(LO, lo, RPRPKI), // load object -xx(LO_R, lo, RPRPRI), -xx(LP, lp, RPRPKI), // load pointer -xx(LP_R, lp, RPRPRI), -xx(LV2, lv2, RVRPKI), // load vector2 -xx(LV2_R, lv2, RVRPRI), -xx(LV3, lv3, RVRPKI), // load vector3 -xx(LV3_R, lv3, RVRPRI), +xx(LB, lb, RIRPKI, LB_R, 4, REGT_INT), // load byte +xx(LB_R, lb, RIRPRI, NOP, 0, 0), +xx(LH, lh, RIRPKI, LH_R, 4, REGT_INT), // load halfword +xx(LH_R, lh, RIRPRI, NOP, 0, 0), +xx(LW, lw, RIRPKI, LW_R, 4, REGT_INT), // load word +xx(LW_R, lw, RIRPRI, NOP, 0, 0), +xx(LBU, lbu, RIRPKI, LBU_R, 4, REGT_INT), // load byte unsigned +xx(LBU_R, lbu, RIRPRI, NOP, 0, 0), +xx(LHU, lhu, RIRPKI, LHU_R, 4, REGT_INT), // load halfword unsigned +xx(LHU_R, lhu, RIRPRI, NOP, 0, 0), +xx(LSP, lsp, RFRPKI, LSP_R, 4, REGT_INT), // load single-precision fp +xx(LSP_R, lsp, RFRPRI, NOP, 0, 0), +xx(LDP, ldp, RFRPKI, LDP_R, 4, REGT_INT), // load double-precision fp +xx(LDP_R, ldp, RFRPRI, NOP, 0, 0), +xx(LS, ls, RSRPKI, LS_R, 4, REGT_INT), // load string +xx(LS_R, ls, RSRPRI, NOP, 0, 0), +xx(LO, lo, RPRPKI, LO_R, 4, REGT_INT), // load object +xx(LO_R, lo, RPRPRI, NOP, 0, 0), +xx(LP, lp, RPRPKI, LP_R, 4, REGT_INT), // load pointer +xx(LP_R, lp, RPRPRI, NOP, 0, 0), +xx(LV2, lv2, RVRPKI, LV2_R, 4, REGT_INT), // load vector2 +xx(LV2_R, lv2, RVRPRI, NOP, 0, 0), +xx(LV3, lv3, RVRPKI, LV3_R, 4, REGT_INT), // load vector3 +xx(LV3_R, lv3, RVRPRI, NOP, 0, 0), -xx(LBIT, lbit, RIRPI8), // rA = !!(*rB & C) -- *rB is a byte +xx(LBIT, lbit, RIRPI8, NOP, 0, 0), // rA = !!(*rB & C) -- *rB is a byte // Store instructions. *(rA + rkC) = rB -xx(SB, sb, RPRIKI), // store byte -xx(SB_R, sb, RPRIRI), -xx(SH, sh, RPRIKI), // store halfword -xx(SH_R, sh, RPRIRI), -xx(SW, sw, RPRIKI), // store word -xx(SW_R, sw, RPRIRI), -xx(SSP, ssp, RPRFKI), // store single-precision fp -xx(SSP_R, ssp, RPRFRI), -xx(SDP, sdp, RPRFKI), // store double-precision fp -xx(SDP_R, sdp, RPRFRI), -xx(SS, ss, RPRSKI), // store string -xx(SS_R, ss, RPRSRI), -xx(SP, sp, RPRPKI), // store pointer -xx(SP_R, sp, RPRPRI), -xx(SV2, sv2, RPRVKI), // store vector2 -xx(SV2_R, sv2, RPRVRI), -xx(SV3, sv3, RPRVKI), // store vector3 -xx(SV3_R, sv3, RPRVRI), +xx(SB, sb, RPRIKI, SB_R, 4, REGT_INT), // store byte +xx(SB_R, sb, RPRIRI, NOP, 0, 0), +xx(SH, sh, RPRIKI, SH_R, 4, REGT_INT), // store halfword +xx(SH_R, sh, RPRIRI, NOP, 0, 0), +xx(SW, sw, RPRIKI, SW_R, 4, REGT_INT), // store word +xx(SW_R, sw, RPRIRI, NOP, 0, 0), +xx(SSP, ssp, RPRFKI, SSP_R, 4, REGT_INT), // store single-precision fp +xx(SSP_R, ssp, RPRFRI, NOP, 0, 0), +xx(SDP, sdp, RPRFKI, SDP_R, 4, REGT_INT), // store double-precision fp +xx(SDP_R, sdp, RPRFRI, NOP, 0, 0), +xx(SS, ss, RPRSKI, SS_R, 4, REGT_INT), // store string +xx(SS_R, ss, RPRSRI, NOP, 0, 0), +xx(SP, sp, RPRPKI, SP_R, 4, REGT_INT), // store pointer +xx(SP_R, sp, RPRPRI, NOP, 0, 0), +xx(SV2, sv2, RPRVKI, SV2_R, 4, REGT_INT), // store vector2 +xx(SV2_R, sv2, RPRVRI, NOP, 0, 0), +xx(SV3, sv3, RPRVKI, SV3_R, 4, REGT_INT), // store vector3 +xx(SV3_R, sv3, RPRVRI, NOP, 0, 0), -xx(SBIT, sbit, RPRII8), // *rA |= C if rB is true, *rA &= ~C otherwise +xx(SBIT, sbit, RPRII8, NOP, 0, 0), // *rA |= C if rB is true, *rA &= ~C otherwise // Move instructions. -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), +xx(MOVE, mov, RIRI, NOP, 0, 0), // dA = dB +xx(MOVEF, mov, RFRF, NOP, 0, 0), // fA = fB +xx(MOVES, mov, RSRS, NOP, 0, 0), // sA = sB +xx(MOVEA, mov, RPRP, NOP, 0, 0), // aA = aB +xx(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements) +xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements) +xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C // 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) -xx(RET, ret, I8BCP), // Copy value from register encoded in BC to return value A, possibly returning -xx(RETI, reti, I8I16), // Copy immediate from BC to return value A, possibly returning -xx(TRY, try, I24), // When an exception is thrown, start searching for a handler at pc + ABC -xx(UNTRY, untry, I8), // Pop A entries off the exception stack -xx(THROW, throw, THROW), // A == 0: Throw exception object pB - // A == 1: Throw exception object pkB - // A >= 2: Throw VM exception of type BC -xx(CATCH, catch, CATCH), // A == 0: continue search on next try - // A == 1: continue execution at instruction immediately following CATCH (catches any exception) - // A == 2: (pB == ) then pc++ ; next instruction must JMP to another CATCH - // A == 3: (pkB == ) then pc++ ; next instruction must JMP to another CATCH - // for A > 0, exception is stored in pC -xx(BOUND, bound, RII16), // if rA >= BC, throw exception +xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++ +xx(TESTN, testn, RII16, NOP, 0, 0), // if (dA != -BC) then pc++ +xx(JMP, jmp, I24, NOP, 0, 0), // pc += ABC -- The ABC fields contain a signed 24-bit offset. +xx(IJMP, ijmp, RII16, NOP, 0, 0), // pc += dA + BC -- BC is a signed offset. The target instruction must be a JMP. +xx(PARAM, param, __BCP, NOP, 0, 0), // push parameter encoded in BC for function call (B=regtype, C=regnum) +xx(PARAMI, parami, I24, NOP, 0, 0), // push immediate, signed integer for function call +xx(CALL, call, RPI8I8, NOP, 0, 0), // Call function pkA with parameter count B and expected result count C +xx(CALL_K, call, KPI8I8, CALL, 1, REGT_POINTER), +xx(VTBL, vtbl, RPRPI8, NOP, 0, 0), // dereferences a virtual method table. +xx(TAIL, tail, RPI8, NOP, 0, 0), // Call+Ret in a single instruction +xx(TAIL_K, tail, KPI8, TAIL, 1, REGT_POINTER), +xx(RESULT, result, __BCP, NOP, 0, 0), // Result should go in register encoded in BC (in caller, after CALL) +xx(RET, ret, I8BCP, NOP, 0, 0), // Copy value from register encoded in BC to return value A, possibly returning +xx(RETI, reti, I8I16, NOP, 0, 0), // Copy immediate from BC to return value A, possibly returning +xx(TRY, try, I24, NOP, 0, 0), // When an exception is thrown, start searching for a handler at pc + ABC +xx(UNTRY, untry, I8, NOP, 0, 0), // Pop A entries off the exception stack +xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB + // A == 1: Throw exception object pkB + // A >= 2: Throw VM exception of type BC +xx(CATCH, catch, CATCH, NOP, 0, 0), // A == 0: continue search on next try + // A == 1: continue execution at instruction immediately following CATCH (catches any exception) + // A == 2: (pB == ) then pc++ ; next instruction must JMP to another CATCH + // A == 3: (pkB == ) then pc++ ; next instruction must JMP to another CATCH + // for A > 0, exception is stored in pC +xx(BOUND, bound, RII16, NOP, 0, 0), // if rA >= BC, throw exception // String instructions. -xx(CONCAT, concat, RSRSRS), // sA = sB..sC -xx(LENS, lens, RIRS), // dA = sB.Length -xx(CMPS, cmps, I8RXRX), // if ((skB op skC) != (A & 1)) then pc++ +xx(CONCAT, concat, RSRSRS, NOP, 0, 0), // sA = sB..sC +xx(LENS, lens, RIRS, NOP, 0, 0), // dA = sB.Length +xx(CMPS, cmps, I8RXRX, NOP, 0, 0), // if ((skB op skC) != (A & 1)) then pc++ // Integer math. -xx(SLL_RR, sll, RIRIRI), // dA = dkB << diC -xx(SLL_RI, sll, RIRII8), -xx(SLL_KR, sll, RIKIRI), -xx(SRL_RR, srl, RIRIRI), // dA = dkB >> diC -- unsigned -xx(SRL_RI, srl, RIRII8), -xx(SRL_KR, srl, RIKIRI), -xx(SRA_RR, sra, RIRIRI), // dA = dkB >> diC -- signed -xx(SRA_RI, sra, RIRII8), -xx(SRA_KR, sra, RIKIRI), -xx(ADD_RR, add, RIRIRI), // dA = dB + dkC -xx(ADD_RK, add, RIRIKI), -xx(ADDI, addi, RIRIIs), // dA = dB + C -- C is a signed 8-bit constant -xx(SUB_RR, sub, RIRIRI), // dA = dkB - dkC -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 (signed) -xx(DIV_RK, div, RIRIKI), -xx(DIV_KR, div, RIKIRI), -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 -xx(OR_RK, or, RIRIKI), -xx(XOR_RR, xor, RIRIRI), // dA = dB ^ dkC -xx(XOR_RK, xor, RIRIKI), -xx(MIN_RR, min, RIRIRI), // dA = min(dB,dkC) -xx(MIN_RK, min, RIRIKI), -xx(MAX_RR, max, RIRIRI), // dA = max(dB,dkC) -xx(MAX_RK, max, RIRIKI), -xx(ABS, abs, RIRI), // dA = abs(dB) -xx(NEG, neg, RIRI), // dA = -dB -xx(NOT, not, RIRI), // dA = ~dB -xx(SEXT, sext, RIRII8), // dA = dB, sign extended by shifting left then right by C -xx(ZAP_R, zap, RIRIRI), // dA = dB, with bytes zeroed where bits in C/dC are one -xx(ZAP_I, zap, RIRII8), -xx(ZAPNOT_R, zapnot, RIRIRI), // dA = dB, with bytes zeroed where bits in C/dC are zero -xx(ZAPNOT_I, zapnot, RIRII8), -xx(EQ_R, beq, CIRR), // if ((dB == dkC) != A) then pc++ -xx(EQ_K, beq, CIRK), -xx(LT_RR, blt, CIRR), // if ((dkB < dkC) != A) then pc++ -xx(LT_RK, blt, CIRK), -xx(LT_KR, blt, CIKR), -xx(LE_RR, ble, CIRR), // if ((dkB <= dkC) != A) then pc++ -xx(LE_RK, ble, CIRK), -xx(LE_KR, ble, CIKR), -xx(LTU_RR, bltu, CIRR), // if ((dkB < dkC) != A) then pc++ -- unsigned -xx(LTU_RK, bltu, CIRK), -xx(LTU_KR, bltu, CIKR), -xx(LEU_RR, bleu, CIRR), // if ((dkB <= dkC) != A) then pc++ -- unsigned -xx(LEU_RK, bleu, CIRK), -xx(LEU_KR, bleu, CIKR), +xx(SLL_RR, sll, RIRIRI, NOP, 0, 0), // dA = dkB << diC +xx(SLL_RI, sll, RIRII8, NOP, 0, 0), +xx(SLL_KR, sll, RIKIRI, SLL_RR, 2, REGT_INT), +xx(SRL_RR, srl, RIRIRI, NOP, 0, 0), // dA = dkB >> diC -- unsigned +xx(SRL_RI, srl, RIRII8, NOP, 0, 0), +xx(SRL_KR, srl, RIKIRI, SRL_RR, 2, REGT_INT), +xx(SRA_RR, sra, RIRIRI, NOP, 0, 0), // dA = dkB >> diC -- signed +xx(SRA_RI, sra, RIRII8, NOP, 0, 0), +xx(SRA_KR, sra, RIKIRI, SRA_RR, 2, REGT_INT), +xx(ADD_RR, add, RIRIRI, NOP, 0, 0), // dA = dB + dkC +xx(ADD_RK, add, RIRIKI, ADD_RR, 4, REGT_INT), +xx(ADDI, addi, RIRIIs, NOP, 0, 0), // dA = dB + C -- C is a signed 8-bit constant +xx(SUB_RR, sub, RIRIRI, NOP, 0, 0), // dA = dkB - dkC +xx(SUB_RK, sub, RIRIKI, SUB_RR, 4, REGT_INT), +xx(SUB_KR, sub, RIKIRI, SUB_RR, 2, REGT_INT), +xx(MUL_RR, mul, RIRIRI, NOP, 0, 0), // dA = dB * dkC +xx(MUL_RK, mul, RIRIKI, MUL_RR, 4, REGT_INT), +xx(DIV_RR, div, RIRIRI, NOP, 0, 0), // dA = dkB / dkC (signed) +xx(DIV_RK, div, RIRIKI, DIV_RR, 4, REGT_INT), +xx(DIV_KR, div, RIKIRI, DIV_RR, 2, REGT_INT), +xx(DIVU_RR, divu, RIRIRI, NOP, 0, 0), // dA = dkB / dkC (unsigned) +xx(DIVU_RK, divu, RIRIKI, DIVU_RR,4, REGT_INT), +xx(DIVU_KR, divu, RIKIRI, DIVU_RR,2, REGT_INT), +xx(MOD_RR, mod, RIRIRI, NOP, 0, 0), // dA = dkB % dkC (signed) +xx(MOD_RK, mod, RIRIKI, MOD_RR, 4, REGT_INT), +xx(MOD_KR, mod, RIKIRI, MOD_RR, 2, REGT_INT), +xx(MODU_RR, modu, RIRIRI, NOP, 0, 0), // dA = dkB % dkC (unsigned) +xx(MODU_RK, modu, RIRIKI, MODU_RR,4, REGT_INT), +xx(MODU_KR, modu, RIKIRI, MODU_RR,2, REGT_INT), +xx(AND_RR, and, RIRIRI, NOP, 0, 0), // dA = dB & dkC +xx(AND_RK, and, RIRIKI, AND_RR, 4, REGT_INT), +xx(OR_RR, or, RIRIRI, NOP, 0, 0), // dA = dB | dkC +xx(OR_RK, or, RIRIKI, OR_RR, 4, REGT_INT), +xx(XOR_RR, xor, RIRIRI, NOP, 0, 0), // dA = dB ^ dkC +xx(XOR_RK, xor, RIRIKI, XOR_RR, 4, REGT_INT), +xx(MIN_RR, min, RIRIRI, NOP, 0, 0), // dA = min(dB,dkC) +xx(MIN_RK, min, RIRIKI, MIN_RR, 4, REGT_INT), +xx(MAX_RR, max, RIRIRI, NOP, 0, 0), // dA = max(dB,dkC) +xx(MAX_RK, max, RIRIKI, MAX_RR, 4, REGT_INT), +xx(ABS, abs, RIRI, NOP, 0, 0), // dA = abs(dB) +xx(NEG, neg, RIRI, NOP, 0, 0), // dA = -dB +xx(NOT, not, RIRI, NOP, 0, 0), // dA = ~dB +xx(SEXT, sext, RIRII8, NOP, 0, 0), // dA = dB, sign extended by shifting left then right by C +xx(ZAP_R, zap, RIRIRI, NOP, 0, 0), // dA = dB, with bytes zeroed where bits in C/dC are one +xx(ZAP_I, zap, RIRII8, NOP, 0, 0), +xx(ZAPNOT_R, zapnot, RIRIRI, NOP, 0, 0), // dA = dB, with bytes zeroed where bits in C/dC are zero +xx(ZAPNOT_I, zapnot, RIRII8, NOP, 0, 0), +xx(EQ_R, beq, CIRR, NOP, 0, 0), // if ((dB == dkC) != A) then pc++ +xx(EQ_K, beq, CIRK, EQ_R, 4, REGT_INT), +xx(LT_RR, blt, CIRR, NOP, 0, 0), // if ((dkB < dkC) != A) then pc++ +xx(LT_RK, blt, CIRK, LT_RR, 4, REGT_INT), +xx(LT_KR, blt, CIKR, LT_RR, 2, REGT_INT), +xx(LE_RR, ble, CIRR, NOP, 0, 0), // if ((dkB <= dkC) != A) then pc++ +xx(LE_RK, ble, CIRK, LE_RR, 4, REGT_INT), +xx(LE_KR, ble, CIKR, LE_RR, 2, REGT_INT), +xx(LTU_RR, bltu, CIRR, NOP, 0, 0), // if ((dkB < dkC) != A) then pc++ -- unsigned +xx(LTU_RK, bltu, CIRK, LTU_RR, 4, REGT_INT), +xx(LTU_KR, bltu, CIKR, LTU_RR, 2, REGT_INT), +xx(LEU_RR, bleu, CIRR, NOP, 0, 0), // if ((dkB <= dkC) != A) then pc++ -- unsigned +xx(LEU_RK, bleu, CIRK, LEU_RR, 4, REGT_INT), +xx(LEU_KR, bleu, CIKR, LEU_RR, 2, REGT_INT), // Double-precision floating point math. -xx(ADDF_RR, add, RFRFRF), // fA = fB + fkC -xx(ADDF_RK, add, RFRFKF), -xx(SUBF_RR, sub, RFRFRF), // fA = fkB - fkC -xx(SUBF_RK, sub, RFRFKF), -xx(SUBF_KR, sub, RFKFRF), -xx(MULF_RR, mul, RFRFRF), // fA = fB * fkC -xx(MULF_RK, mul, RFRFKF), -xx(DIVF_RR, div, RFRFRF), // fA = fkB / fkC -xx(DIVF_RK, div, RFRFKF), -xx(DIVF_KR, div, RFKFRF), -xx(MODF_RR, mod, RFRFRF), // fA = fkB % fkC -xx(MODF_RK, mod, RFRFKF), -xx(MODF_KR, mod, RFKFRF), -xx(POWF_RR, pow, RFRFRF), // fA = fkB ** fkC -xx(POWF_RK, pow, RFRFKF), -xx(POWF_KR, pow, RFKFRF), -xx(MINF_RR, min, RFRFRF), // fA = min(fB),fkC) -xx(MINF_RK, min, RFRFKF), -xx(MAXF_RR, max, RFRFRF), // fA = max(fB),fkC) -xx(MAXF_RK, max, RFRFKF), -xx(ATAN2, atan2, RFRFRF), // fA = atan2(fB,fC), result is in degrees -xx(FLOP, flop, RFRFI8), // fA = f(fB), where function is selected by C -xx(EQF_R, beq, CFRR), // if ((fB == fkC) != (A & 1)) then pc++ -xx(EQF_K, beq, CFRK), -xx(LTF_RR, blt, CFRR), // if ((fkB < fkC) != (A & 1)) then pc++ -xx(LTF_RK, blt, CFRK), -xx(LTF_KR, blt, CFKR), -xx(LEF_RR, ble, CFRR), // if ((fkb <= fkC) != (A & 1)) then pc++ -xx(LEF_RK, ble, CFRK), -xx(LEF_KR, ble, CFKR), +xx(ADDF_RR, add, RFRFRF, NOP, 0, 0), // fA = fB + fkC +xx(ADDF_RK, add, RFRFKF, ADDF_RR,4, REGT_FLOAT), +xx(SUBF_RR, sub, RFRFRF, NOP, 0, 0), // fA = fkB - fkC +xx(SUBF_RK, sub, RFRFKF, SUBF_RR,4, REGT_FLOAT), +xx(SUBF_KR, sub, RFKFRF, SUBF_RR,2, REGT_FLOAT), +xx(MULF_RR, mul, RFRFRF, NOP, 0, 0), // fA = fB * fkC +xx(MULF_RK, mul, RFRFKF, MULF_RR,4, REGT_FLOAT), +xx(DIVF_RR, div, RFRFRF, NOP, 0, 0), // fA = fkB / fkC +xx(DIVF_RK, div, RFRFKF, DIVF_RR,4, REGT_FLOAT), +xx(DIVF_KR, div, RFKFRF, DIVF_RR,2, REGT_FLOAT), +xx(MODF_RR, mod, RFRFRF, NOP, 0, 0), // fA = fkB % fkC +xx(MODF_RK, mod, RFRFKF, MODF_RR,4, REGT_FLOAT), +xx(MODF_KR, mod, RFKFRF, MODF_RR,4, REGT_FLOAT), +xx(POWF_RR, pow, RFRFRF, NOP, 0, 0), // fA = fkB ** fkC +xx(POWF_RK, pow, RFRFKF, POWF_RR,4, REGT_FLOAT), +xx(POWF_KR, pow, RFKFRF, POWF_RR,2, REGT_FLOAT), +xx(MINF_RR, min, RFRFRF, NOP, 0, 0), // fA = min(fB),fkC) +xx(MINF_RK, min, RFRFKF, MINF_RR,4, REGT_FLOAT), +xx(MAXF_RR, max, RFRFRF, NOP, 0, 0), // fA = max(fB),fkC) +xx(MAXF_RK, max, RFRFKF, MAXF_RR,4, REGT_FLOAT), +xx(ATAN2, atan2, RFRFRF, NOP, 0, 0), // fA = atan2(fB,fC), result is in degrees +xx(FLOP, flop, RFRFI8, NOP, 0, 0), // fA = f(fB), where function is selected by C +xx(EQF_R, beq, CFRR, NOP, 0, 0), // if ((fB == fkC) != (A & 1)) then pc++ +xx(EQF_K, beq, CFRK, EQF_R, 4, REGT_FLOAT), +xx(LTF_RR, blt, CFRR, NOP, 0, 0), // if ((fkB < fkC) != (A & 1)) then pc++ +xx(LTF_RK, blt, CFRK, LTF_RR, 4, REGT_FLOAT), +xx(LTF_KR, blt, CFKR, LTF_RR, 2, REGT_FLOAT), +xx(LEF_RR, ble, CFRR, NOP, 0, 0), // if ((fkb <= fkC) != (A & 1)) then pc++ +xx(LEF_RK, ble, CFRK, LEF_RR, 4, REGT_FLOAT), +xx(LEF_KR, ble, CFKR, LEF_RR, 2, REGT_FLOAT), // 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), +xx(NEGV2, negv2, RVRV, NOP, 0, 0), // vA = -vB +xx(ADDV2_RR, addv2, RVRVRV, NOP, 0, 0), // vA = vB + vkC +xx(SUBV2_RR, subv2, RVRVRV, NOP, 0, 0), // vA = vkB - vkC +xx(DOTV2_RR, dotv2, RVRVRV, NOP, 0, 0), // va = vB dot vkC +xx(MULVF2_RR, mulv2, RVRVRF, NOP, 0, 0), // vA = vkB * fkC +xx(MULVF2_RK, mulv2, RVRVKF, MULVF2_RR,4, REGT_FLOAT), +xx(DIVVF2_RR, divv2, RVRVRF, NOP, 0, 0), // vA = vkB / fkC +xx(DIVVF2_RK, divv2, RVRVKF, DIVVF2_RR,4, REGT_FLOAT), +xx(LENV2, lenv2, RFRV, NOP, 0, 0), // fA = vB.Length +xx(EQV2_R, beqv2, CVRR, NOP, 0, 0), // if ((vB == vkC) != A) then pc++ (inexact if A & 32) +xx(EQV2_K, beqv2, CVRK, NOP, 0, 0), // this will never be used. // 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(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), +xx(NEGV3, negv3, RVRV, NOP, 0, 0), // vA = -vB +xx(ADDV3_RR, addv3, RVRVRV, NOP, 0, 0), // vA = vB + vkC +xx(SUBV3_RR, subv3, RVRVRV, NOP, 0, 0), // vA = vkB - vkC +xx(DOTV3_RR, dotv3, RVRVRV, NOP, 0, 0), // va = vB dot vkC +xx(CROSSV_RR, crossv, RVRVRV, NOP, 0, 0), // vA = vkB cross vkC +xx(MULVF3_RR, mulv3, RVRVRF, NOP, 0, 0), // vA = vkB * fkC +xx(MULVF3_RK, mulv3, RVRVKF, MULVF3_RR,4, REGT_FLOAT), +xx(DIVVF3_RR, divv3, RVRVRF, NOP, 0, 0), // vA = vkB / fkC +xx(DIVVF3_RK, divv3, RVRVKF, DIVVF3_RR,4, REGT_FLOAT), +xx(LENV3, lenv3, RFRV, NOP, 0, 0), // fA = vB.Length +xx(EQV3_R, beqv3, CVRR, NOP, 0, 0), // if ((vB == vkC) != A) then pc++ (inexact if A & 33) +xx(EQV3_K, beqv3, CVRK, NOP, 0, 0), // this will never be used. // Pointer math. -xx(ADDA_RR, add, RPRPRI), // pA = pB + dkC -xx(ADDA_RK, add, RPRPKI), -xx(SUBA, sub, RIRPRP), // dA = pB - pC -xx(EQA_R, beq, CPRR), // if ((pB == pkC) != A) then pc++ -xx(EQA_K, beq, CPRK), +xx(ADDA_RR, add, RPRPRI, NOP, 0, 0), // pA = pB + dkC +xx(ADDA_RK, add, RPRPKI, ADDA_RR,4, REGT_POINTER), +xx(SUBA, sub, RIRPRP, NOP, 0, 0), // dA = pB - pC +xx(EQA_R, beq, CPRR, NOP, 0, 0), // if ((pB == pkC) != A) then pc++ +xx(EQA_K, beq, CPRK, EQA_R, 4, REGT_POINTER), #undef xx From 8f722a3633cda80c8749e465b97bf9c36ddc7ebe Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 23:26:32 +0100 Subject: [PATCH 313/471] - fixed: FxCVar must free its address register. --- src/scripting/codegeneration/codegen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 593737065c..1b70a1e0c0 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6072,6 +6072,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) assert(false && "Unsupported CVar type"); break; } + addr.Free(build); return dest; } From 0cbd260f965139ac410304a4ea11383d5aa31bc8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2016 23:39:37 +0100 Subject: [PATCH 314/471] - replaced all calls to GetCVar with direct CVar accesses. --- wadsrc/static/zscript/doom/bossbrain.txt | 4 ++-- wadsrc/static/zscript/doom/doommisc.txt | 2 +- wadsrc/static/zscript/doom/doomweapons.txt | 2 +- wadsrc/static/zscript/doom/fatso.txt | 2 +- wadsrc/static/zscript/doom/weaponbfg.txt | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 9a2ad759c3..cde600701c 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -186,11 +186,11 @@ extend class Actor void A_BrainDie() { // [RH] If noexit, then don't end the level. - if ((GetCVar("deathmatch") || GetCVar("alwaysapplydmflags")) && GetCVar("sv_noexit")) + if ((deathmatch || alwaysapplydmflags) && sv_noexit) return; // New dmflag: Kill all boss spawned monsters before ending the level. - if (GetCVar("sv_killbossmonst")) + if (sv_killbossmonst) { int count; // Repeat until we have no more boss-spawned monsters. ThinkerIterator it = ThinkerIterator.Create(); diff --git a/wadsrc/static/zscript/doom/doommisc.txt b/wadsrc/static/zscript/doom/doommisc.txt index a11c411f8c..7d4c9dec4e 100644 --- a/wadsrc/static/zscript/doom/doommisc.txt +++ b/wadsrc/static/zscript/doom/doommisc.txt @@ -38,7 +38,7 @@ extend class Actor { void A_BarrelDestroy() { - if (GetCVar("sv_barrelrespawn")) + if (sv_barrelrespawn) { Height = Default.Height; bInvisible = true; diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index 75f8562181..731740ac64 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -41,7 +41,7 @@ extend class StateProvider } - int damage = GetCVar("deathmatch") ? 100 : 150; + int damage = deathmatch ? 100 : 150; A_RailAttack(damage, offset_xy, false); // note that this function handles ammo depletion itself for Dehacked compatibility purposes. } diff --git a/wadsrc/static/zscript/doom/fatso.txt b/wadsrc/static/zscript/doom/fatso.txt index d1a456d16a..59e0d4c634 100644 --- a/wadsrc/static/zscript/doom/fatso.txt +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -192,7 +192,7 @@ extend class Actor aimtarget.Height = Height; bool shootmode = ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options - (flags == 0 && isDehState(CurState) && GetCVar("compat_mushroom"))); + (flags == 0 && isDehState(CurState) && compat_mushroom)); for (i = -numspawns; i <= numspawns; i += 8) { diff --git a/wadsrc/static/zscript/doom/weaponbfg.txt b/wadsrc/static/zscript/doom/weaponbfg.txt index 27f318daf9..3543b9cdb0 100644 --- a/wadsrc/static/zscript/doom/weaponbfg.txt +++ b/wadsrc/static/zscript/doom/weaponbfg.txt @@ -81,7 +81,7 @@ extend class StateProvider return; } - SpawnPlayerMissile("BFGBall", angle, 0, 0, 0, null, false, GetCVar("sv_nobfgaim")); + SpawnPlayerMissile("BFGBall", angle, 0, 0, 0, null, false, sv_nobfgaim); } From 7d8143224ee8f425a27c4378ae0ed21f2f60ef58 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 00:33:55 +0100 Subject: [PATCH 315/471] - restored two accidentally deleted VM instructions. --- src/scripting/vm/vmexec.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 477c5ac97a..e460ef29cf 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1426,19 +1426,31 @@ begin: ASSERTF(a+2); ASSERTF(B+2); ASSERTF(C); fc = reg.f[C]; fbp = ®.f[B]; + Do_MULV3: reg.f[a] = fbp[0] * fc; reg.f[a+1] = fbp[1] * fc; reg.f[a+2] = fbp[2] * fc; NEXTOP; + OP(MULVF3_RK): + ASSERTF(a+2); ASSERTF(B+2); ASSERTKF(C); + fc = konstf[C]; + fbp = ®.f[B]; + goto Do_MULV3; - OP(DIVVF3_RR): + 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); From e7f6bae83e23725b260f5ff7e562ac51356bf532 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 01:32:01 +0100 Subject: [PATCH 316/471] - implemented named arguments. - fixed flag CVAR access. As it turned out, OP_LBIT is a bit messy to set up properly when accessing integers that may or may not be big endian, so it now uses a shift and bit masking to do its work. - used the SpawnPlayerMissile call in A_FireBFG to test named arguments. --- src/scripting/codegeneration/codegen.cpp | 72 +++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 45 +++++++++++++++ src/scripting/zscript/zcc_compile.cpp | 5 +- wadsrc/static/zscript/doom/weaponbfg.txt | 2 +- 4 files changed, 119 insertions(+), 5 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 1b70a1e0c0..43d5f81745 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6054,9 +6054,14 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) break; case CVAR_DummyBool: - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->ValueVar.Value, ATAG_GENERIC)); - build->Emit(OP_LBIT, dest.RegNum, addr.RegNum, static_cast(CVar)->BitNum); + { + auto cv = static_cast(CVar); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC)); + build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); + build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum); + build->Emit(OP_AND_RK, dest.RegNum, dest.RegNum, build->GetConstantInt(1)); break; + } case CVAR_DummyInt: { @@ -7408,7 +7413,9 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) bool failed = false; auto proto = Function->Variants[0].Proto; auto &argtypes = proto->ArgumentTypes; + auto &argnames = Function->Variants[0].ArgNames; auto &argflags = Function->Variants[0].ArgFlags; + auto &defaults = Function->Variants[0].Implementation->DefaultArgs; int implicit = Function->GetImplicitArgs(); @@ -7446,6 +7453,67 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } assert(type != nullptr); + if (ArgList[i]->ExprType == EFX_NamedNode) + { + if (!(flag & VARF_Optional)) + { + ScriptPosition.Message(MSG_ERROR, "Cannot use a named argument here - not all required arguments have been passed."); + delete this; + return nullptr; + } + if (foundvarargs) + { + ScriptPosition.Message(MSG_ERROR, "Cannot use a named argument in the varargs part of the parameter list."); + delete this; + return nullptr; + } + unsigned j; + bool done = false; + FName name = static_cast(ArgList[i])->name; + for (j = 0; j < argnames.Size() - implicit; j++) + { + if (argnames[j + implicit] == name) + { + if (j < i) + { + ScriptPosition.Message(MSG_ERROR, "Named argument %s comes before current position in argument list.", name.GetChars()); + delete this; + return nullptr; + } + // copy the original argument into the list + auto old = static_cast(ArgList[i]); + ArgList[i] = old->value; + old->value = nullptr; + delete old; + // now fill the gap with constants created from the default list so that we got a full list of arguments. + int insert = j - i; + for (int k = 0; k < insert; k++) + { + auto ntype = argtypes[i + k + implicit]; + // If this is a reference argument, the pointer type must be undone because the code below expects the pointed type as value type. + if (argflags[i + k + implicit] & VARF_Ref) + { + assert(ntype->IsKindOf(RUNTIME_CLASS(PPointer))); + ntype = TypeNullPtr; // the default of a reference type can only be a null pointer + } + auto x = new FxConstant(ntype, defaults[i + k + implicit], ScriptPosition); + ArgList.Insert(i + k, x); + } + done = true; + break; + } + } + if (!done) + { + ScriptPosition.Message(MSG_ERROR, "Named argument %s not found.", name.GetChars()); + delete this; + return nullptr; + } + // re-get the proper info for the inserted node. + type = argtypes[i + implicit]; + flag = argflags[i + implicit]; + } + FxExpression *x; if (!(flag & VARF_Ref)) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index a3b6451766..f004e469a3 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -285,6 +285,7 @@ enum EFxType EFX_StaticArray, EFX_StaticArrayVariable, EFX_CVar, + EFX_NamedNode, EFX_COUNT }; @@ -472,6 +473,31 @@ public: ValueType = value.Type = TypeNullPtr; isresolved = true; } + + FxConstant(PType *type, VMValue &vmval, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) + { + ValueType = value.Type = type; + isresolved = true; + switch (vmval.Type) + { + default: + case REGT_INT: + value.Int = vmval.i; + break; + + case REGT_FLOAT: + value.Float = vmval.f; + break; + + case REGT_STRING: + value = ExpVal(vmval.s()); + break; + + case REGT_POINTER: + value.pointer = vmval.a; + break; + } + } static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos); @@ -1912,5 +1938,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +class FxNamedNode : public FxExpression +{ +public: + FName name; + FxExpression *value; + FxNamedNode(FName n, FxExpression *x, const FScriptPosition &pos) + : FxExpression(EFX_NamedNode, pos), name(n), value(x) + { + } + + FxExpression *Resolve(FCompileContext&) + { + // This should never reach the backend in a supported context, + // it's just needed to extend argument lists with the skipped parameters and needs to be resolved by the parent node. + ScriptPosition.Message(MSG_ERROR, "Named arguments not supported here"); + delete this; + return nullptr; + } +}; #endif diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 291387617e..f2d847325f 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2845,8 +2845,9 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *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); + auto node = ConvertNode(fparm->Value); + if (fparm->Label != NAME_None) node = new FxNamedNode(fparm->Label, node, *ast); + return node; } case AST_ExprID: diff --git a/wadsrc/static/zscript/doom/weaponbfg.txt b/wadsrc/static/zscript/doom/weaponbfg.txt index 3543b9cdb0..1b96bfc29d 100644 --- a/wadsrc/static/zscript/doom/weaponbfg.txt +++ b/wadsrc/static/zscript/doom/weaponbfg.txt @@ -81,7 +81,7 @@ extend class StateProvider return; } - SpawnPlayerMissile("BFGBall", angle, 0, 0, 0, null, false, sv_nobfgaim); + SpawnPlayerMissile("BFGBall", angle, nofreeaim:sv_nobfgaim); } From 3270b200454613871613b9ac977992521cc9201a Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 20 Nov 2016 21:33:23 -0600 Subject: [PATCH 317/471] Remove non-existant source file --- src/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7f2eb3b2e..87c875d16f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -866,7 +866,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_doom/a_doomweaps.cpp g_doom/a_painelemental.cpp g_doom/a_scriptedmarine.cpp g_heretic/a_chicken.cpp From 188c0ee932302706b71b7f1b6b248349448f631e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 10:28:06 +0100 Subject: [PATCH 318/471] - removed the REGT_NIL check from the PARAM_EXISTS macro, because with the implemented handling of named arguments it isn't possible that REGT_NIL can end up in the parameters without a programming error.. --- src/scripting/vm/vm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index ab1708e088..b8885e0a1a 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -956,7 +956,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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))); -#define PARAM_EXISTS(p) ((p) < numparam && param[p].Type != REGT_NIL) +#define PARAM_EXISTS(p) ((p) < numparam) #define ASSERTINT(p) assert((p).Type == REGT_INT) #define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT) #define ASSERTSTRING(p) assert((p).Type == REGT_STRING) From 393bcf9e91c3fe4a67e7d365be9f43923051446c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 10:50:09 +0100 Subject: [PATCH 319/471] - extended ExpEmit::RegNum to 16 bits so that it can hold larger values for constant registers. --- src/scripting/vm/vmbuilder.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 5991d07116..d533935183 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -13,7 +13,10 @@ struct ExpEmit void Free(VMFunctionBuilder *build); void Reuse(VMFunctionBuilder *build); - BYTE RegNum, RegType, RegCount, Konst:1, Fixed : 1, Final : 1, Target : 1; + uint16_t RegNum; + uint8_t RegType, RegCount; + // We are at 8 bytes for this struct, no matter what, so it's rather pointless to squeeze these flags into bitfields. + bool Konst, Fixed, Final, Target; }; class VMFunctionBuilder From de2eb1872714badda166445df005c7b4d8f34931 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 12:38:39 +0100 Subject: [PATCH 320/471] - added per-channel access for color variables. However, since they are locally stored in registers, it required a minor bit of fudging for this case. - make sure that a PFunction's implementation is always initialized before starting the code generator. --- src/dobjtype.cpp | 14 ++++++++++++++ src/dobjtype.h | 1 + src/namedef.h | 6 ++++++ src/scripting/codegeneration/codegen.cpp | 24 ++++++++++++++++++++++++ src/scripting/vm/vmbuilder.cpp | 2 ++ src/scripting/zscript/zcc_compile.cpp | 2 +- 6 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 965a0d8fd9..e84504015c 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -85,6 +85,7 @@ PStatePointer *TypeState; PStateLabel *TypeStateLabel; PStruct *TypeVector2; PStruct *TypeVector3; +PStruct *TypeColorStruct; PPointer *TypeNullPtr; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -578,6 +579,19 @@ void PType::StaticInit() TypeTable.AddType(TypeStateLabel = new PStateLabel); TypeTable.AddType(TypeNullPtr = new PPointer); + TypeColorStruct = new PStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. +#ifdef __BIG_ENDIAN__ + TypeColorStruct->AddField(NAME_a, TypeUInt8); + TypeColorStruct->AddField(NAME_r, TypeUInt8); + TypeColorStruct->AddField(NAME_g, TypeUInt8); + TypeColorStruct->AddField(NAME_b, TypeUInt8); +#else + TypeColorStruct->AddField(NAME_b, TypeUInt8); + TypeColorStruct->AddField(NAME_g, TypeUInt8); + TypeColorStruct->AddField(NAME_r, TypeUInt8); + TypeColorStruct->AddField(NAME_a, TypeUInt8); +#endif + TypeVector2 = new PStruct(NAME_Vector2, nullptr); TypeVector2->AddField(NAME_X, TypeFloat64); TypeVector2->AddField(NAME_Y, TypeFloat64); diff --git a/src/dobjtype.h b/src/dobjtype.h index aeb042ebb4..b8fc1cbf66 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -919,6 +919,7 @@ extern PSound *TypeSound; extern PColor *TypeColor; extern PStruct *TypeVector2; extern PStruct *TypeVector3; +extern PStruct *TypeColorStruct; extern PStatePointer *TypeState; extern PStateLabel *TypeStateLabel; extern PPointer *TypeNullPtr; diff --git a/src/namedef.h b/src/namedef.h index d4206e2bba..0418e0f875 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -750,3 +750,9 @@ xx(A_FirePlasma) xx(A_FireBFG) xx(A_FireOldBFG) xx(A_FireRailgun) + +// color channels +xx(a) +xx(r) +xx(g) +xx(b) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 43d5f81745..c040403d8e 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5652,6 +5652,10 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) SAFE_RESOLVE(Object, ctx); + // allow accessing the color chanels by mapping the type to a matching struct which defines them. + if (Object->ValueType == TypeColor) + Object->ValueType = TypeColorStruct; + if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { auto ptype = static_cast(Object->ValueType)->PointedType; @@ -6305,6 +6309,26 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) delete this; return locvar; } + else if (classx->ExprType == EFX_LocalVariable && classx->ValueType == TypeColorStruct) + { + // This needs special treatment because it'd require accessing the register via address. + // Fortunately this is the only place where this kind of access is ever needed so an explicit handling is acceptable. + int bits; + switch (membervar->SymbolName.GetIndex()) + { + case NAME_a: bits = 24; break; + case NAME_r: bits = 16; break; + case NAME_g: bits = 8; break; + case NAME_b: default: bits = 0; break; + } + classx->ValueType = TypeColor; // need to set it back. + FxExpression *x = classx; + if (bits > 0) x = new FxShift(TK_URShift, x, new FxConstant(bits, ScriptPosition)); + x = new FxBitOp('&', x, new FxConstant(255, ScriptPosition)); + classx = nullptr; + delete this; + return x->Resolve(ctx); + } else { if (!(classx->RequestAddress(ctx, &AddressWritable))) diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 3ccf67f959..04339f6eb1 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -785,6 +785,8 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c it.StateIndex = stateindex; it.StateCount = statecount; it.Lump = lumpnum; + assert(it.Func->Variants.Size() == 1); + it.Func->Variants[0].Implementation = it.Function; // set prototype for named functions. if (it.Func->SymbolName != NAME_None) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f2d847325f..3d8cc18b5f 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2272,7 +2272,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool 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); + FunctionBuildList.AddFunction(sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump); } } } From 7c122d03e9d17eeb79ec02fb4e2e2d8a703c58d3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 13:04:27 +0100 Subject: [PATCH 321/471] - renamed all instances of 'float' parameters to 'double', so that the Float32 type can be made usable for structs. --- wadsrc/static/zscript/actor.txt | 158 +++++++++--------- wadsrc/static/zscript/actor_checks.txt | 38 ++--- wadsrc/static/zscript/doom/archvile.txt | 4 +- wadsrc/static/zscript/doom/fatso.txt | 2 +- wadsrc/static/zscript/doom/lostsoul.txt | 2 +- wadsrc/static/zscript/doom/painelemental.txt | 4 +- wadsrc/static/zscript/doom/weaponchainsaw.txt | 2 +- wadsrc/static/zscript/shared/inventory.txt | 10 +- .../static/zscript/strife/strifeweapons.txt | 2 +- 9 files changed, 111 insertions(+), 111 deletions(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5c824d7bb4..99ca89c8e8 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -65,12 +65,12 @@ class Actor : Thinker native native static readonly GetDefaultByType(class cls); - native static float deltaangle(float ang1, float ang2); - native static float absangle(float ang1, float ang2); - native static float GetDefaultSpeed(class type); + native static double deltaangle(double ang1, double ang2); + native static double absangle(double ang1, double ang2); + native static double GetDefaultSpeed(class type); native void RemoveFromHash(); native string GetTag(string defstr = ""); - native float GetBobOffset(float frac = 0); + native double GetBobOffset(double frac = 0); native void ClearCounters(); native bool GiveBody (int num, int max=0); @@ -88,7 +88,7 @@ class Actor : Thinker native 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 SpawnMissileAngleZSpeed (double z, class type, double angle, double vz, double speed, Actor owner = null, bool checkspawn = true); native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void A_Light(int extralight); @@ -98,7 +98,7 @@ class Actor : Thinker native void A_LightInverse() { A_Light(0x80000000); } 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 Actor SpawnPuff(class pufftype, vector3 pos, double hitdir, double particledir, int updown, int flags = 0, Actor vict = null); native void TraceBleed(int damage, Actor missile); native bool CheckMeleeRange(); @@ -119,13 +119,13 @@ class Actor : Thinker native native void UnlinkFromWorld(); native bool CanSeek(Actor target); native double AngleTo(Actor target, bool absolute = false); - native void AddZ(float zadd, bool moving = true); - 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 void AddZ(double zadd, bool moving = true); + native void SetZ(double z); + native vector3 Vec3Offset(double x, double y, double z, bool absolute = false); + native vector3 Vec3Angle(double length, double angle, double z = 0, bool absolute = false); + native vector3 Vec2OffsetZ(double x, double y, double atz, bool absolute = false); + native void VelFromAngle(double speed = 0, double angle = 0); + native void Thrust(double speed = 0, double angle = 0); native bool isFriend(Actor other); native void AdjustFloorClip(); native DropItem GetDropItems(); @@ -140,21 +140,21 @@ class Actor : Thinker native native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native Inventory FindInventory(class itemtype, bool subclass = 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 double GetDistance(bool checkz, int ptr = AAPTR_TARGET); + native double GetAngle(int flags, int ptr = AAPTR_DEFAULT); + native double GetZAt(double px = 0, double py = 0, double 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 double GetCrouchFactor(int ptr = AAPTR_PLAYER1); + native double 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 CountProximity(class classname, double distance, int flags = 0, int ptr = AAPTR_DEFAULT); + native double GetSpriteAngle(int ptr = AAPTR_DEFAULT); + native double 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 native double OverlayX(int layer = 0); + action native double OverlayY(int layer = 0); // DECORATE setters - it probably makes more sense to set these values directly now... void A_SetMass(int newmass) { mass = newmass; } @@ -169,13 +169,13 @@ class Actor : Thinker native 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_SetGravity(double 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_Turn(double turn = 0) { angle += turn; } void A_SetDamageType(name newdamagetype) { damagetype = newdamagetype; } void A_SetSolid() { bSolid = true; } void A_UnsetSolid() { bSolid = false; } @@ -197,7 +197,7 @@ class Actor : Thinker native // //--------------------------------------------------------------------------- - Actor SpawnMissileAngle (class type, float angle, double vz) + Actor SpawnMissileAngle (class type, double angle, double vz) { return SpawnMissileAngleZSpeed (pos.z + 32 + GetBobOffset(), type, angle, vz, GetDefaultSpeed (type)); } @@ -208,7 +208,7 @@ class Actor : Thinker native } - void A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false) + void A_SetScale(double scalex, double scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false) { Actor aptr = GetPointer(ptr); if (aptr) @@ -217,12 +217,12 @@ class Actor : Thinker native 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) + void A_SetSpeed(double speed, int ptr = AAPTR_DEFAULT) { Actor aptr = GetPointer(ptr); if (aptr) aptr.Speed = speed; } - void A_SetFloatSpeed(float speed, int ptr = AAPTR_DEFAULT) + void A_SetFloatSpeed(double speed, int ptr = AAPTR_DEFAULT) { Actor aptr = GetPointer(ptr); if (aptr) aptr.FloatSpeed = speed; @@ -232,14 +232,14 @@ class Actor : Thinker native Actor aptr = GetPointer(ptr); if (aptr) aptr.PainThreshold = threshold; } - bool A_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT) + bool A_SetSpriteAngle(double 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) + bool A_SetSpriteRotation(double angle = 0, int ptr = AAPTR_DEFAULT) { Actor aptr = GetPointer(ptr); if (!aptr) return false; @@ -247,7 +247,7 @@ class Actor : Thinker native return true; } - deprecated void A_FaceConsolePlayer(float MaxTurnAngle = 0) {} + deprecated void A_FaceConsolePlayer(double MaxTurnAngle = 0) {} void A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0) { @@ -333,17 +333,17 @@ class Actor : Thinker native } - 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); + native void A_Face(Actor faceto, double max_turn = 0, double max_pitch = 270, double ang_offset = 0, double pitch_offset = 0, int flags = 0, double 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) + void A_FaceTarget(double max_turn = 0, double max_pitch = 270, double ang_offset = 0, double pitch_offset = 0, int flags = 0, double 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) + void A_FaceTracer(double max_turn = 0, double max_pitch = 270, double ang_offset = 0, double pitch_offset = 0, int flags = 0, double 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) + void A_FaceMaster(double max_turn = 0, double max_pitch = 270, double ang_offset = 0, double pitch_offset = 0, int flags = 0, double z_ofs = 0) { A_Face(master, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_ofs); } @@ -392,7 +392,7 @@ class Actor : Thinker native 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_AlertMonsters(double maxdist = 0, int flags = 0); native void A_ClearSoundTarget(); native void A_CheckTerrain(); @@ -400,8 +400,8 @@ class Actor : Thinker native 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); + native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class pufftype = "BulletPuff"); + native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double 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(); @@ -410,55 +410,55 @@ class Actor : Thinker native 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 void A_CustomMissile(class missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET); + native void A_CustomBulletAttack(double spread_xy, double spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", double range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = null, double Spawnheight = 32, double 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, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = null, double 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"); + action native bool A_SpawnItem(class itemtype = "Unknown", double distance = 0, double zheight = 0, bool useammo = true, bool transfer_translation = false); + native bool A_SpawnItemEx(class itemtype, double xofs = 0, double yofs = 0, double zofs = 0, double xvel = 0, double yvel = 0, double zvel = 0, double angle = 0, int flags = 0, int failchance = 0, int tid=0); + native void A_Print(string whattoprint, double time = 0, name fontname = "none"); + native void A_PrintBold(string whattoprint, double 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_LogFloat(double whattoprint); + native void A_SetTranslucent(double alpha, int style = 0); + native void A_SetRenderStyle(double alpha, int style); + native void A_FadeIn(double reduce = 0.1, int flags = 0); + native void A_FadeOut(double reduce = 0.1, int flags = 1); //bool remove == true + native void A_FadeTo(double target, double amount = 0.1, int flags = 0); + native void A_SpawnDebris(class spawntype, bool transfer_translation = false, double mult_h = 1, double mult_v = 1); + native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, double size = 1, double angle = 0, double xoff = 0, double yoff = 0, double zoff = 0, double velx = 0, double vely = 0, double velz = 0, double accelx = 0, double accely = 0, double accelz = 0, double startalphaf = 1, double fadestepf = -1, double 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); + native void A_SetBlend(color color1, double 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); + deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, double missileheight); + action native bool A_ThrowGrenade(class itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true); + native void A_Weave(int xspeed, int yspeed, double xdist, double 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); + action native state, bool A_Teleport(statelabel teleportstate = null, class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, double mindist = 0, double maxdist = 128, int ptr = AAPTR_DEFAULT); + action native state, bool A_Warp(int ptr_destination, double xofs = 0, double yofs = 0, double zofs = 0, double angle = 0, int flags = 0, statelabel success_state = null, double heightoffset = 0, double radiusoffset = 0, double 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_LookEx(int flags = 0, double minseedist = 0, double maxseedist = 0, double maxheardist = 0, double fov = 0, statelabel label = null); - native void A_Recoil(float xyvel); + native void A_Recoil(double 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 int A_RadiusGive(class itemtype, double distance, int flags, int amount = 0, class filter = null, name species = "None", double 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_CustomComboAttack(class missiletype, double 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"); + action native void A_Blast(int flags = 0, double strength = 255, double radius = 255, double 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 void A_RadiusDamageSelf(int damage = 128, double 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); @@ -477,17 +477,17 @@ class Actor : Thinker native 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); + native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); + native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT); + native void A_ScaleVelocity(double scale, int ptr = AAPTR_DEFAULT); + native void A_ChangeVelocity(double x = 0, double y = 0, double 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); + deprecated native void A_SetUserVarFloat(name varname, double value); + deprecated native void A_SetUserArrayFloat(name varname, int index, double 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); + native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, int falloff = 0, int highpoint = 0, double rollIntensity = 0, double 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); @@ -517,10 +517,10 @@ class Actor : Thinker native 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 bool A_FaceMovementDirection(double offset = 0, double anglelimit = 0, double 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 bool A_SetVisibleRotation(double anglestart = 0, double angleend = 0, double pitchstart = 0, double 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); @@ -528,8 +528,8 @@ class Actor : Thinker native 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); + native void A_WeaponOffset(double wx = 0, double wy = 32, int flags = 0); + action native void A_OverlayOffset(int layer = PSP_WEAPON, double wx = 0, double 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) @@ -582,5 +582,5 @@ class Actor : Thinker native // 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); + deprecated private native double __decorate_internal_float__(double f); } diff --git a/wadsrc/static/zscript/actor_checks.txt b/wadsrc/static/zscript/actor_checks.txt index 3ad4255d72..a4f7da1d8e 100644 --- a/wadsrc/static/zscript/actor_checks.txt +++ b/wadsrc/static/zscript/actor_checks.txt @@ -31,7 +31,7 @@ extend class Actor // //========================================================================== - bool CheckIfCloser(Actor targ, float dist, bool noz = false) + bool CheckIfCloser(Actor targ, double dist, bool noz = false) { if (!targ) return false; return @@ -42,7 +42,7 @@ extend class Actor )); } - action state A_JumpIfCloser(float distance, statelabel label, bool noz = false) + action state A_JumpIfCloser(double distance, statelabel label, bool noz = false) { Actor targ; @@ -59,12 +59,12 @@ extend class Actor return CheckIfCloser(targ, distance, noz)? ResolveState(label) : null; } - action state A_JumpIfTracerCloser(float distance, statelabel label, bool noz = false) + action state A_JumpIfTracerCloser(double 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) + action state A_JumpIfMasterCloser(double distance, statelabel label, bool noz = false) { return CheckIfCloser(master, distance, noz)? ResolveState(label) : null; } @@ -124,20 +124,20 @@ extend class Actor //========================================================================== native bool CheckIfSeen(); - native bool CheckSightOrRange(float distance, bool two_dimension = false); - native bool CheckRange(float distance, bool two_dimension = false); + native bool CheckSightOrRange(double distance, bool two_dimension = false); + native bool CheckRange(double 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) + action state A_CheckSightOrRange(double 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) + action state A_CheckRange(double distance, statelabel label, bool two_dimension = false) { return CheckRange(distance, two_dimension)? ResolveState(label) : null; } @@ -202,28 +202,28 @@ extend class Actor // //========================================================================== - 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); + native bool CheckLOF(int flags = 0, double range = 0, double minrange = 0, double angle = 0, double pitch = 0, double offsetheight = 0, double offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, double offsetforward = 0); + native bool CheckIfTargetInLOS (double fov = 0, int flags = 0, double dist_max = 0, double dist_close = 0); + native bool CheckIfInTargetLOS (double fov = 0, int flags = 0, double dist_max = 0, double dist_close = 0); + native bool CheckProximity(class classname, double distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT); + native bool CheckBlock(int flags = 0, int ptr = AAPTR_DEFAULT, double xofs = 0, double yofs = 0, double zofs = 0, double 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) + action state A_CheckLOF(statelabel label, int flags = 0, double range = 0, double minrange = 0, double angle = 0, double pitch = 0, double offsetheight = 0, double offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, double 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) + action state A_JumpIfTargetInLOS (statelabel label, double fov = 0, int flags = 0, double dist_max = 0, double 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) + action state A_JumpIfInTargetLOS (statelabel label, double fov = 0, int flags = 0, double dist_max = 0, double 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) + action state A_CheckProximity(statelabel label, class classname, double 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); @@ -237,7 +237,7 @@ extend class Actor 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) + action state A_CheckBlock(statelabel label, int flags = 0, int ptr = AAPTR_DEFAULT, double xofs = 0, double yofs = 0, double zofs = 0, double angle = 0) { return CheckBlock(flags, ptr, xofs, yofs, zofs, angle)? ResolveState(label) : null; } @@ -253,7 +253,7 @@ extend class Actor // if its lower. //=========================================================================== - action state A_JumpIfHigherOrLower(statelabel high, statelabel low, float offsethigh = 0, float offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET) + action state A_JumpIfHigherOrLower(statelabel high, statelabel low, double offsethigh = 0, double offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET) { Actor mobj = GetPointer(ptr); diff --git a/wadsrc/static/zscript/doom/archvile.txt b/wadsrc/static/zscript/doom/archvile.txt index 0e9008570f..9faa804954 100644 --- a/wadsrc/static/zscript/doom/archvile.txt +++ b/wadsrc/static/zscript/doom/archvile.txt @@ -123,7 +123,7 @@ extend class Actor } } - 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) + void A_VileAttack(sound snd = "vile/stop", int initialdmg = 20, int blastdmg = 70, int blastradius = 70, double thrust = 1.0, name damagetype = "Fire", int flags = 0) { if (target) { @@ -158,7 +158,7 @@ extend class Actor // A_Fire // Keep fire in front of player unless out of sight // - void A_Fire(float spawnheight = 0) + void A_Fire(double spawnheight = 0) { Actor dest = tracer; if (!dest || !target) return; diff --git a/wadsrc/static/zscript/doom/fatso.txt b/wadsrc/static/zscript/doom/fatso.txt index 59e0d4c634..98bcc3fc9b 100644 --- a/wadsrc/static/zscript/doom/fatso.txt +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -175,7 +175,7 @@ extend class Actor // Original idea: Linguica // - void A_Mushroom(class spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5) + void A_Mushroom(class spawntype = "FatShot", int numspawns = 0, int flags = 0, double vrange = 4.0, double hrange = 0.5) { int i, j; diff --git a/wadsrc/static/zscript/doom/lostsoul.txt b/wadsrc/static/zscript/doom/lostsoul.txt index 7ef8b4cf0e..89cefc42a9 100644 --- a/wadsrc/static/zscript/doom/lostsoul.txt +++ b/wadsrc/static/zscript/doom/lostsoul.txt @@ -92,7 +92,7 @@ extend class Actor { const SKULLSPEED = 20; - void A_SkullAttack(float skullspeed = SKULLSPEED) + void A_SkullAttack(double skullspeed = SKULLSPEED) { if (target == null) return; diff --git a/wadsrc/static/zscript/doom/painelemental.txt b/wadsrc/static/zscript/doom/painelemental.txt index fde690b394..03a4d82c4c 100644 --- a/wadsrc/static/zscript/doom/painelemental.txt +++ b/wadsrc/static/zscript/doom/painelemental.txt @@ -61,9 +61,9 @@ class PainElemental : Actor extend class Actor { - native void A_PainShootSkull(Class spawntype, float angle, int flags = 0, int limit = -1); + native void A_PainShootSkull(Class spawntype, double angle, int flags = 0, int limit = -1); - void A_PainAttack(class spawntype = "LostSoul", float addangle = 0, int flags = 0, int limit = -1) + void A_PainAttack(class spawntype = "LostSoul", double addangle = 0, int flags = 0, int limit = -1) { if (target) { diff --git a/wadsrc/static/zscript/doom/weaponchainsaw.txt b/wadsrc/static/zscript/doom/weaponchainsaw.txt index b2583efa53..0653bc16d7 100644 --- a/wadsrc/static/zscript/doom/weaponchainsaw.txt +++ b/wadsrc/static/zscript/doom/weaponchainsaw.txt @@ -41,7 +41,7 @@ class Chainsaw : Weapon extend class StateProvider { - action 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 void A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff", int flags = 0, double range = 0, double spread_xy = 2.8125, double spread_z = 0, double lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus") { FTranslatedLineTarget t; diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index d5734e1499..f906ca01c5 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -43,10 +43,10 @@ class Inventory : Actor native 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); + action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = ""); + action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, double range = 0, class missile = null, double Spawnheight = 32, double Spawnofs_xy = 0); + action native void A_FireCustomMissile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double 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, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); action native void A_WeaponReady(int flags = 0); action native void A_Lower(); action native void A_Raise(); @@ -457,7 +457,7 @@ class Weapon : StateProvider native native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); - native action void A_ZoomFactor(float scale = 1, int flags = 0); + native action void A_ZoomFactor(double scale = 1, int flags = 0); native action void A_SetCrosshair(int xhair); const ZOOM_INSTANT = 1; const ZOOM_NOSCALETURNING = 2; diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index 9e44638937..968e4c4c54 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -816,7 +816,7 @@ class StrifeGrenadeLauncher : StrifeWeapon Inventory.PickupMessage "$TXT_GLAUNCHER"; } - action native void A_FireGrenade (class grenadetype, float angleofs, statelabel flash); + action native void A_FireGrenade (class grenadetype, double angleofs, statelabel flash); States { From 7d9955290380995af858d6f0ebd47b1aded99b4c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 13:45:33 +0100 Subject: [PATCH 322/471] - added two new integral types SpriteID and TextureID, both are needed to allow proper serialization as they require something different to be written out than a regular integer. --- src/dobjtype.cpp | 91 ++++++++++++++++++++++++ src/dobjtype.h | 22 ++++++ src/namedef.h | 2 + src/p_mobj.cpp | 4 +- src/scripting/codegeneration/codegen.cpp | 8 +++ src/scripting/vm/vm.h | 2 + src/scripting/vm/vmexec.cpp | 2 + src/scripting/vm/vmexec.h | 13 ++++ src/scripting/zscript/zcc_compile.cpp | 34 +++++---- src/scripting/zscript/zcc_parser.h | 3 +- 10 files changed, 164 insertions(+), 17 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index e84504015c..4354e08852 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -81,6 +81,8 @@ PString *TypeString; PName *TypeName; PSound *TypeSound; PColor *TypeColor; +PTextureID *TypeTextureID; +PSpriteID *TypeSpriteID; PStatePointer *TypeState; PStateLabel *TypeStateLabel; PStruct *TypeVector2; @@ -546,6 +548,8 @@ void PType::StaticInit() RUNTIME_CLASS(PString)->TypeTableType = RUNTIME_CLASS(PString); RUNTIME_CLASS(PName)->TypeTableType = RUNTIME_CLASS(PName); RUNTIME_CLASS(PSound)->TypeTableType = RUNTIME_CLASS(PSound); + RUNTIME_CLASS(PSpriteID)->TypeTableType = RUNTIME_CLASS(PSpriteID); + RUNTIME_CLASS(PTextureID)->TypeTableType = RUNTIME_CLASS(PTextureID); RUNTIME_CLASS(PColor)->TypeTableType = RUNTIME_CLASS(PColor); RUNTIME_CLASS(PPointer)->TypeTableType = RUNTIME_CLASS(PPointer); RUNTIME_CLASS(PClassPointer)->TypeTableType = RUNTIME_CLASS(PClassPointer); @@ -578,6 +582,8 @@ void PType::StaticInit() TypeTable.AddType(TypeState = new PStatePointer); TypeTable.AddType(TypeStateLabel = new PStateLabel); TypeTable.AddType(TypeNullPtr = new PPointer); + TypeTable.AddType(TypeSpriteID = new PSpriteID); + TypeTable.AddType(TypeTextureID = new PTextureID); TypeColorStruct = new PStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. #ifdef __BIG_ENDIAN__ @@ -1373,6 +1379,91 @@ bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const } } +/* PSpriteID ******************************************************************/ + +IMPLEMENT_CLASS(PSpriteID, false, false, false, false) + +//========================================================================== +// +// PName Default Constructor +// +//========================================================================== + +PSpriteID::PSpriteID() + : PInt(sizeof(int), true, true) +{ + mDescriptiveName = "SpriteID"; +} + +//========================================================================== +// +// PName :: WriteValue +// +//========================================================================== + +void PSpriteID::WriteValue(FSerializer &ar, const char *key, const void *addr) const +{ + int32_t val = *(int*)addr; + ar.Sprite(key, val, nullptr); +} + +//========================================================================== +// +// PName :: ReadValue +// +//========================================================================== + +bool PSpriteID::ReadValue(FSerializer &ar, const char *key, void *addr) const +{ + int32_t val; + ar.Sprite(key, val, nullptr); + *(int*)addr = val; + return true; +} + +/* PTextureID ******************************************************************/ + +IMPLEMENT_CLASS(PTextureID, false, false, false, false) + +//========================================================================== +// +// PTextureID Default Constructor +// +//========================================================================== + +PTextureID::PTextureID() + : PInt(sizeof(FTextureID), true, false) +{ + mDescriptiveName = "TextureID"; + assert(sizeof(FTextureID) == alignof(FTextureID)); +} + +//========================================================================== +// +// PTextureID :: WriteValue +// +//========================================================================== + +void PTextureID::WriteValue(FSerializer &ar, const char *key, const void *addr) const +{ + FTextureID val = *(FTextureID*)addr; + ar(key, val); +} + +//========================================================================== +// +// PTextureID :: ReadValue +// +//========================================================================== + +bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const +{ + FTextureID val; + ar(key, val); + *(FTextureID*)addr = val; + return true; +} + /* PSound *****************************************************************/ IMPLEMENT_CLASS(PSound, false, false, false, false) diff --git a/src/dobjtype.h b/src/dobjtype.h index b8fc1cbf66..be192225b2 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -515,6 +515,26 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; }; +class PSpriteID : public PInt +{ + DECLARE_CLASS(PSpriteID, PInt); +public: + PSpriteID(); + + void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; + bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; +}; + +class PTextureID : public PInt +{ + DECLARE_CLASS(PTextureID, PInt); +public: + PTextureID(); + + void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; + bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; +}; + class PColor : public PInt { DECLARE_CLASS(PColor, PInt); @@ -917,6 +937,8 @@ extern PString *TypeString; extern PName *TypeName; extern PSound *TypeSound; extern PColor *TypeColor; +extern PTextureID *TypeTextureID; +extern PSpriteID *TypeSpriteID; extern PStruct *TypeVector2; extern PStruct *TypeVector3; extern PStruct *TypeColorStruct; diff --git a/src/namedef.h b/src/namedef.h index 0418e0f875..5ee98119a4 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -737,6 +737,8 @@ xx(DamageFunction) xx(Length) xx(Unit) xx(StateLabel) +xx(SpriteID) +xx(TextureID) xx(Overlay) xx(A_Punch) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 964736fed1..313052c6b1 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -191,7 +191,7 @@ void AActor::InitNativeFields() 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("sprite", TypeSpriteID, myoffsetof(AActor, sprite)); 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); @@ -206,7 +206,7 @@ void AActor::InitNativeFields() meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz)); 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("floorpic", TypeTextureID, myoffsetof(AActor, floorpic)); 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? diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c040403d8e..cae95da34d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3825,6 +3825,8 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) else if (left->ValueType == TypeName) cast = CAST_N2S; else if (left->ValueType == TypeSound) cast = CAST_So2S; else if (left->ValueType == TypeColor) cast = CAST_Co2S; + else if (left->ValueType == TypeSpriteID) cast = CAST_SID2S; + else if (left->ValueType == TypeTextureID) cast = CAST_TID2S; else if (op1.RegType == REGT_POINTER) cast = CAST_P2S; else if (op1.RegType == REGT_INT) cast = CAST_I2S; else assert(false && "Bad type for string concatenation"); @@ -3856,6 +3858,8 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) else if (right->ValueType == TypeName) cast = CAST_N2S; else if (right->ValueType == TypeSound) cast = CAST_So2S; else if (right->ValueType == TypeColor) cast = CAST_Co2S; + else if (right->ValueType == TypeSpriteID) cast = CAST_SID2S; + else if (right->ValueType == TypeTextureID) cast = CAST_TID2S; else if (op2.RegType == REGT_POINTER) cast = CAST_P2S; else if (op2.RegType == REGT_INT) cast = CAST_I2S; else assert(false && "Bad type for string concatenation"); @@ -6880,6 +6884,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Color: case NAME_Sound: case NAME_State: + case NAME_SpriteID: + case NAME_TextureID: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { PType *type = @@ -6889,6 +6895,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) MethodName == NAME_Float ? TypeFloat64 : MethodName == NAME_Double ? TypeFloat64 : MethodName == NAME_Name ? TypeName : + MethodName == NAME_SpriteID ? TypeSpriteID : + MethodName == NAME_TextureID ? TypeTextureID : MethodName == NAME_State ? TypeState : MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index b8885e0a1a..ad42ee1ddc 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -127,6 +127,8 @@ enum CAST_So2S, CAST_V22S, CAST_V32S, + CAST_SID2S, + CAST_TID2S, }; // Register types for VMParam diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 8f8559d93e..24beb7f9c6 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -36,6 +36,8 @@ #include #include "dobject.h" #include "xs_Float.h" +#include "r_state.h" +#include "textures/textures.h" #include "math/cmath.h" #define IMPLEMENT_VMEXEC diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index e460ef29cf..2e77716808 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1695,6 +1695,19 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c reg.s[a] = S_sfx[reg.d[b]].name; break; + case CAST_SID2S: + ASSERTS(a); ASSERTD(b); + reg.s[a] = unsigned(reg.d[b]) >= sprites.Size() ? "TNT1" : sprites[reg.d[b]].name; + break; + + case CAST_TID2S: + { + ASSERTS(a); ASSERTD(b); + auto tex = TexMan[*(FTextureID*)&(reg.d[b])]; + reg.s[a] = tex == nullptr ? "(null)" : tex->Name.GetChars(); + break; + } + default: assert(0); } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 3d8cc18b5f..27a02a9190 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1367,19 +1367,19 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n switch (btype->Type) { case ZCC_SInt8: - retval = TypeSInt8; + retval = formember? TypeSInt8 : (PType*)TypeError; break; case ZCC_UInt8: - retval = TypeUInt8; + retval = formember ? TypeUInt8 : (PType*)TypeError; break; case ZCC_SInt16: - retval = TypeSInt16; + retval = formember ? TypeSInt16 : (PType*)TypeError; break; case ZCC_UInt16: - retval = TypeUInt16; + retval = formember ? TypeUInt16 : (PType*)TypeError; break; case ZCC_SInt32: @@ -1395,11 +1395,9 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n 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; + retval = formember ? TypeFloat32 : TypeFloat64; + case ZCC_Float64: retval = TypeFloat64; break; @@ -1433,14 +1431,24 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n 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) + // statelabel et.al. are not tokens - 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? + switch (btype->UserType->Id) { + case NAME_StateLabel: retval = TypeStateLabel; - } - else - { + break; + + case NAME_SpriteID: + retval = TypeSpriteID; + break; + + case NAME_TextureID: + retval = TypeTextureID; + break; + + default: retval = ResolveUserType(btype, &outertype->Symbols); + break; } break; } diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index a19249208f..e000da06c5 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -113,13 +113,12 @@ enum EZCCBuiltinType ZCC_SInt8, ZCC_UInt8, ZCC_SInt16, - ZCC_UInt16, + ZCC_UInt16, // smaller than 32 bit types are only valid in structs, classes and arrays. ZCC_SInt32, ZCC_UInt32, ZCC_IntAuto, // for enums, autoselect appropriately sized int ZCC_Bool, - ZCC_Float32, ZCC_Float64, ZCC_FloatAuto, // 32-bit in structs/classes, 64-bit everywhere else ZCC_String, From 97763b5a2b12fb053a479da51b1813c74259fda8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 14:59:17 +0100 Subject: [PATCH 323/471] - added scriptable virtual overrides for PostBeginPlay, Tick, BeginPlay, Activate and Deactivate. --- src/dthinker.cpp | 16 +++++ src/p_mobj.cpp | 36 +++++++++++ src/p_user.cpp | 12 ++-- src/virtual.h | 107 +++++++++++++++++++++++++++++--- wadsrc/static/zscript/actor.txt | 5 +- wadsrc/static/zscript/base.txt | 2 + 6 files changed, 162 insertions(+), 16 deletions(-) diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 06cd5dbfab..9478393c0e 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -258,6 +258,14 @@ void DThinker::PostBeginPlay () { } +DEFINE_ACTION_FUNCTION(DThinker, PostBeginPlay) +{ + PARAM_SELF_PROLOGUE(DThinker); + self->VMSuperCall(); + self->PostBeginPlay(); + return 0; +} + void DThinker::PostSerialize() { } @@ -421,6 +429,14 @@ void DThinker::Tick () { } +DEFINE_ACTION_FUNCTION(DThinker, Tick) +{ + PARAM_SELF_PROLOGUE(DThinker); + self->VMSuperCall(); + self->Tick(); + return 0; +} + size_t DThinker::PropagateMark() { // Do not choke on partially initialized objects (as happens when loading a savegame fails) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 313052c6b1..d1a273ef25 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4112,6 +4112,15 @@ void AActor::Tick () } } +DEFINE_ACTION_FUNCTION(AActor, Tick) +{ + PARAM_SELF_PROLOGUE(AActor); + self->VMSuperCall(); + self->Tick(); + return 0; +} + + //========================================================================== // // AActor :: CheckNoDelay @@ -4580,6 +4589,15 @@ void AActor::BeginPlay () } } +DEFINE_ACTION_FUNCTION(AActor, BeginPlay) +{ + PARAM_SELF_PROLOGUE(AActor); + self->VMSuperCall(); + self->BeginPlay(); + return 0; +} + + void AActor::PostBeginPlay () { if (Renderer != NULL) @@ -4635,6 +4653,15 @@ void AActor::Activate (AActor *activator) } } +DEFINE_ACTION_FUNCTION(AActor, Activate) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(activator, AActor); + self->VMSuperCall(); + self->Activate(activator); + return 0; +} + void AActor::Deactivate (AActor *activator) { if ((flags3 & MF3_ISMONSTER) && (health > 0 || (flags & MF_ICECORPSE))) @@ -4655,6 +4682,15 @@ void AActor::Deactivate (AActor *activator) } } +DEFINE_ACTION_FUNCTION(AActor, Deactivate) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(activator, AActor); + self->VMSuperCall(); + self->Deactivate(activator); + return 0; +} + // // P_RemoveMobj diff --git a/src/p_user.cpp b/src/p_user.cpp index 6f58f3cc84..ad0bb6ba4a 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1280,22 +1280,18 @@ void APlayerPawn::PlayRunning () void APlayerPawn::PlayAttacking () { - static int VIndex = -1; - if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(APlayerPawn), "PlayAttacking"); - // Without the type cast this picks the 'void *' assignment... + VINDEX(APlayerPawn, PlayAttacking); VMValue params[1] = { (DObject*)this }; VMFrameStack stack; - stack.Call(this->GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); + stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); } void APlayerPawn::PlayAttacking2 () { - static int VIndex = -1; - if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(APlayerPawn), "PlayAttacking2"); - // Without the type cast this picks the 'void *' assignment... + VINDEX(APlayerPawn, PlayAttacking2); VMValue params[1] = { (DObject*)this }; VMFrameStack stack; - stack.Call(this->GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); + stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); } void APlayerPawn::ThrowPoisonBag () diff --git a/src/virtual.h b/src/virtual.h index e0679df740..01541cebab 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -35,6 +35,9 @@ VMEXPORTED_NATIVES_START VMEXPORTED_NATIVES_FUNC(Destroy) VMEXPORTED_NATIVES_FUNC(Tick) VMEXPORTED_NATIVES_FUNC(PostBeginPlay) + VMEXPORTED_NATIVES_FUNC(BeginPlay) + VMEXPORTED_NATIVES_FUNC(Activate) + VMEXPORTED_NATIVES_FUNC(Deactivate) VMEXPORTED_NATIVES_END @@ -48,6 +51,15 @@ inline int GetVirtualIndex(PClass *cls, const char *funcname) return VIndex; } +#define VINDEX(cls, funcname) \ + static int VIndex = -1; \ + if (VIndex < 0) { \ + VIndex = GetVirtualIndex(RUNTIME_CLASS(cls), #funcname); \ + if (VIndex < 0) I_Error("Unable to find virtual function in " #cls, #funcname); \ + } + +#define VFUNC this->GetClass()->Virtuals[VIndex] + template class DVMObject : public T { @@ -84,28 +96,103 @@ public: { if (this->ObjectFlags & OF_SuperCall) { - this->ObjectFlags &= OF_SuperCall; + this->ObjectFlags &= ~OF_SuperCall; ExportedNatives::Get()->template Destroy(this); } else { - static int VIndex = -1; - if (VIndex < 0) VIndex = GetVirtualIndex(RUNTIME_CLASS(DObject), "Destroy"); + VINDEX(DObject, Destroy); // 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); + stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); } } void Tick() { - ExportedNatives::Get()->template Tick(this); + if (this->ObjectFlags & OF_SuperCall) + { + this->ObjectFlags &= ~OF_SuperCall; + ExportedNatives::Get()->template Tick(this); + } + else + { + VINDEX(DThinker, Tick); + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); + } } void PostBeginPlay() { - ExportedNatives::Get()->template PostBeginPlay(this); + if (this->ObjectFlags & OF_SuperCall) + { + this->ObjectFlags &= ~OF_SuperCall; + ExportedNatives::Get()->template PostBeginPlay(this); + } + else + { + VINDEX(DThinker, PostBeginPlay); + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); + } } + + void BeginPlay() + { + if (this->ObjectFlags & OF_SuperCall) + { + this->ObjectFlags &= ~OF_SuperCall; + ExportedNatives::Get()->template BeginPlay(this); + } + else + { + VINDEX(AActor, BeginPlay); + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); + } + } + + void Activate(AActor *activator) + { + if (this->ObjectFlags & OF_SuperCall) + { + this->ObjectFlags &= ~OF_SuperCall; + ExportedNatives::Get()->template Activate(this, activator); + } + else + { + VINDEX(AActor, Activate); + // Without the type cast this picks the 'void *' assignment... + VMValue params[2] = { (DObject*)this, (DObject*)activator }; + VMFrameStack stack; + stack.Call(VFUNC, params, 2, nullptr, 0, nullptr); + } + } + + void Deactivate(AActor *activator) + { + if (this->ObjectFlags & OF_SuperCall) + { + this->ObjectFlags &= ~OF_SuperCall; + ExportedNatives::Get()->template Deactivate(this, activator); + } + else + { + VINDEX(AActor, Deactivate); + // Without the type cast this picks the 'void *' assignment... + VMValue params[2] = { (DObject*)this, (DObject*)activator }; + VMFrameStack stack; + stack.Call(VFUNC, params, 2, nullptr, 0, nullptr); + } + } + }; template @@ -130,7 +217,13 @@ VMEXPORT_NATIVES_END(DObject) VMEXPORT_NATIVES_START(DThinker, DObject) VMEXPORT_NATIVES_FUNC(Tick) VMEXPORT_NATIVES_FUNC(PostBeginPlay) - VMEXPORT_NATIVES_END(DThinker) +VMEXPORT_NATIVES_END(DThinker) + +VMEXPORT_NATIVES_START(AActor, DThinker) + VMEXPORT_NATIVES_FUNC(BeginPlay) + VMEXPORT_NATIVES_FUNC(Activate) + VMEXPORT_NATIVES_FUNC(Deactivate) +VMEXPORT_NATIVES_END(AActor) /* VMEXPORT_NATIVES_START(AActor, DThinker) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 99ca89c8e8..53f0475135 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -62,7 +62,10 @@ class Actor : Thinker native { return sin(fb * (180./32)) * 8; } - + + virtual native void BeginPlay(); + virtual native void Activate(Actor activator); + virtual native void Deactivate(Actor activator); native static readonly GetDefaultByType(class cls); native static double deltaangle(double ang1, double ang2); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 1089476a1a..7a27907263 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -10,6 +10,8 @@ class Object native class Thinker : Object native { + virtual native void Tick(); + virtual native void PostBeginPlay(); } class ThinkerIterator : Object native From 360436c2013bb2b9a291219f9a1b28546589d665 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 19:09:58 +0100 Subject: [PATCH 324/471] - scriptified the scripted marines. - fixed symbol name generation for native functions. - moved PrintableName to VMFunction so that native functions also have this information. --- src/CMakeLists.txt | 1 - src/g_doom/a_doomglobal.h | 15 - src/g_doom/a_doommisc.cpp | 3 - src/g_doom/a_scriptedmarine.cpp | 654 ------------------ src/info.h | 2 +- src/p_acs.cpp | 50 +- src/p_actionfunctions.cpp | 2 +- src/p_mobj.cpp | 5 +- src/p_pspr.cpp | 2 +- src/p_states.cpp | 9 +- src/scripting/codegeneration/codegen.cpp | 9 + src/scripting/thingdef_data.cpp | 20 +- src/scripting/vm/vm.h | 7 +- src/scripting/vm/vmbuilder.cpp | 2 +- src/scripting/vm/vmdisasm.cpp | 4 +- src/scripting/zscript/zcc-parse.lemon | 4 +- src/scripting/zscript/zcc_compile.cpp | 4 +- src/virtual.h | 2 +- wadsrc/static/zscript/actor.txt | 4 +- wadsrc/static/zscript/doom/scriptedmarine.txt | 615 ++++++++++++++-- 20 files changed, 658 insertions(+), 756 deletions(-) delete mode 100644 src/g_doom/a_scriptedmarine.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 87c875d16f..19179a0c4d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -867,7 +867,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.h sc_man_scanner.re g_doom/a_painelemental.cpp - g_doom/a_scriptedmarine.cpp g_heretic/a_chicken.cpp g_heretic/a_dsparil.cpp g_heretic/a_hereticartifacts.cpp diff --git a/src/g_doom/a_doomglobal.h b/src/g_doom/a_doomglobal.h index 31d41f6c0a..73e3d3239a 100644 --- a/src/g_doom/a_doomglobal.h +++ b/src/g_doom/a_doomglobal.h @@ -7,21 +7,6 @@ class AScriptedMarine : public AActor { DECLARE_CLASS (AScriptedMarine, AActor) public: - enum EMarineWeapon - { - WEAPON_Dummy, - WEAPON_Fist, - WEAPON_BerserkFist, - WEAPON_Chainsaw, - WEAPON_Pistol, - WEAPON_Shotgun, - WEAPON_SuperShotgun, - WEAPON_Chaingun, - WEAPON_RocketLauncher, - WEAPON_PlasmaRifle, - WEAPON_Railgun, - WEAPON_BFG - }; void Activate (AActor *activator); void Deactivate (AActor *activator); diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index ca13ac7ee4..40c8e2f8d0 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -9,7 +9,6 @@ #include "gstrings.h" #include "g_level.h" #include "p_enemy.h" -#include "a_doomglobal.h" #include "a_specialspot.h" #include "templates.h" #include "m_bbox.h" @@ -21,5 +20,3 @@ // Include all the other Doom stuff here to reduce compile time #include "a_painelemental.cpp" -#include "a_scriptedmarine.cpp" - diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp deleted file mode 100644 index e270af6b51..0000000000 --- a/src/g_doom/a_scriptedmarine.cpp +++ /dev/null @@ -1,654 +0,0 @@ -/* -#include "actor.h" -#include "p_enemy.h" -#include "a_action.h" -#include "m_random.h" -#include "p_local.h" -#include "a_doomglobal.h" -#include "s_sound.h" -#include "r_data/r_translate.h" -#include "vm.h" -#include "g_level.h" -*/ - -#define MARINE_PAIN_CHANCE 160 - -static FRandom pr_m_refire ("SMarineRefire"); -static FRandom pr_m_punch ("SMarinePunch"); -static FRandom pr_m_gunshot ("SMarineGunshot"); -static FRandom pr_m_saw ("SMarineSaw"); -static FRandom pr_m_fireshotgun2 ("SMarineFireSSG"); - -IMPLEMENT_CLASS(AScriptedMarine, false, false, false, false) - -void AScriptedMarine::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - - auto def = (AScriptedMarine*)GetDefault(); - - arc.Sprite("spriteoverride", SpriteOverride, &def->SpriteOverride) - ("currentweapon", CurrentWeapon, def->CurrentWeapon); -} - -void AScriptedMarine::Activate (AActor *activator) -{ - if (flags2 & MF2_DORMANT) - { - flags2 &= ~MF2_DORMANT; - tics = 1; - } -} - -void AScriptedMarine::Deactivate (AActor *activator) -{ - if (!(flags2 & MF2_DORMANT)) - { - flags2 |= MF2_DORMANT; - tics = -1; - } -} - -bool AScriptedMarine::GetWeaponStates(int weap, FState *&melee, FState *&missile) -{ - static ENamedName WeaponNames[] = - { - NAME_None, - NAME_Fist, - NAME_Berserk, - NAME_Chainsaw, - NAME_Pistol, - NAME_Shotgun, - NAME_SSG, - NAME_Chaingun, - NAME_Rocket, - NAME_Plasma, - NAME_Railgun, - NAME_BFG - }; - - if (weap < WEAPON_Dummy || weap > WEAPON_BFG) weap = WEAPON_Dummy; - - melee = FindState(NAME_Melee, WeaponNames[weap], true); - missile = FindState(NAME_Missile, WeaponNames[weap], true); - - return melee != NULL || missile != NULL; -} - -void AScriptedMarine::BeginPlay () -{ - Super::BeginPlay (); - - // Set the current weapon - for(int i=WEAPON_Dummy; i<=WEAPON_BFG; i++) - { - FState *melee, *missile; - if (GetWeaponStates(i, melee, missile)) - { - if (melee == MeleeState && missile == MissileState) - { - CurrentWeapon = i; - } - } - } -} - -void AScriptedMarine::Tick () -{ - Super::Tick (); - - // Override the standard sprite, if desired - if (SpriteOverride != 0 && sprite == SpawnState->sprite) - { - sprite = SpriteOverride; - } - - if (special1 != 0) - { - if (CurrentWeapon == WEAPON_SuperShotgun) - { // Play SSG reload sounds - int ticks = level.maptime - special1; - if (ticks < 47) - { - switch (ticks) - { - case 14: - S_Sound (this, CHAN_WEAPON, "weapons/sshoto", 1, ATTN_NORM); - break; - case 28: - S_Sound (this, CHAN_WEAPON, "weapons/sshotl", 1, ATTN_NORM); - break; - case 41: - S_Sound (this, CHAN_WEAPON, "weapons/sshotc", 1, ATTN_NORM); - break; - } - } - else - { - special1 = 0; - } - } - else - { // Wait for a long refire time - if (level.maptime >= special1) - { - special1 = 0; - } - else - { - flags |= MF_JUSTATTACKED; - } - } - } -} - -//============================================================================ -// -// A_M_Refire -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_Refire) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL_DEF(ignoremissile); - - if (self->target == NULL || self->target->health <= 0) - { - if (self->MissileState && pr_m_refire() < 160) - { // Look for a new target most of the time - if (P_LookForPlayers (self, true, NULL) && P_CheckMissileRange (self)) - { // Found somebody new and in range, so don't stop shooting - return 0; - } - } - self->SetState (self->state + 1); - return 0; - } - if (((ignoremissile || self->MissileState == NULL) && !self->CheckMeleeRange ()) || - !P_CheckSight (self, self->target) || - pr_m_refire() < 4) // Small chance of stopping even when target not dead - { - self->SetState (self->state + 1); - } - return 0; -} - -//============================================================================ -// -// A_M_SawRefire -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_SawRefire) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL || self->target->health <= 0) - { - self->SetState (self->state + 1); - return 0; - } - if (!self->CheckMeleeRange ()) - { - self->SetState (self->state + 1); - } - return 0; -} - -//============================================================================ -// -// A_MarineNoise -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MarineNoise) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (static_cast(self)->CurrentWeapon == AScriptedMarine::WEAPON_Chainsaw) - { - S_Sound (self, CHAN_WEAPON, "weapons/sawidle", 1, ATTN_NORM); - } - return 0; -} - -//============================================================================ -// -// A_MarineChase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MarineChase) -{ - PARAM_SELF_PROLOGUE(AActor); - CALL_ACTION(A_MarineNoise, self); - A_Chase (stack, self); - return 0; -} - -//============================================================================ -// -// A_MarineLook -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MarineLook) -{ - PARAM_SELF_PROLOGUE(AActor); - CALL_ACTION(A_MarineNoise, self); - CALL_ACTION(A_Look, self); - return 0; -} - -//============================================================================ -// -// A_M_Saw -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_Saw) -{ - 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; - - if (pufftype == NULL) - { - pufftype = PClass::FindActor(NAME_BulletPuff); - } - if (damage == 0) - { - damage = 2; - } - - A_FaceTarget (self); - if (self->CheckMeleeRange ()) - { - DAngle angle; - FTranslatedLineTarget t; - - damage *= (pr_m_saw()%10+1); - angle = self->Angles.Yaw + pr_m_saw.Random2() * (5.625 / 256); - - P_LineAttack (self, angle, SAWRANGE, - P_AimLineAttack (self, angle, SAWRANGE), damage, - NAME_Melee, pufftype, false, &t); - - if (!t.linetarget) - { - S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); - return 0; - } - S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM); - - // turn to face target - angle = t.angleFromSource; - DAngle anglediff = deltaangle(self->Angles.Yaw, angle); - - if (anglediff < 0.0) - { - if (anglediff < -4.5) - self->Angles.Yaw = angle + 90.0 / 21; - else - self->Angles.Yaw -= 4.5; - } - else - { - if (anglediff > 4.5) - self->Angles.Yaw = angle - 90.0 / 21; - else - self->Angles.Yaw += 4.5; - } - } - else - { - S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); - } - //A_Chase (self); - return 0; -} - -//============================================================================ -// -// A_M_Punch -// -//============================================================================ - -static void MarinePunch(AActor *self, int damagemul) -{ - DAngle angle; - int damage; - DAngle pitch; - FTranslatedLineTarget t; - - if (self->target == NULL) - return; - - damage = ((pr_m_punch()%10+1) << 1) * damagemul; - - A_FaceTarget (self); - angle = self->Angles.Yaw + pr_m_punch.Random2() * (5.625 / 256); - pitch = P_AimLineAttack (self, angle, MELEERANGE); - P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true, &t); - - // turn to face target - if (t.linetarget) - { - S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM); - self->Angles.Yaw = t.angleFromSource; - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_M_Punch) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(mult); - - MarinePunch(self, mult); - return 0; -} - -//============================================================================ -// -// P_GunShot2 -// -//============================================================================ - -void P_GunShot2 (AActor *mo, bool accurate, DAngle pitch, PClassActor *pufftype) -{ - DAngle angle; - int damage; - - damage = 5*(pr_m_gunshot()%3+1); - angle = mo->Angles.Yaw; - - if (!accurate) - { - angle += pr_m_gunshot.Random2() * (5.625 / 256); - } - - P_LineAttack (mo, angle, MISSILERANGE, pitch, damage, NAME_Hitscan, pufftype); -} - -//============================================================================ -// -// A_M_FirePistol -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_FirePistol) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL(accurate); - - if (self->target == NULL) - return 0; - - S_Sound (self, CHAN_WEAPON, "weapons/pistol", 1, ATTN_NORM); - A_FaceTarget (self); - P_GunShot2 (self, accurate, P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE), - PClass::FindActor(NAME_BulletPuff)); - return 0; -} - -//============================================================================ -// -// A_M_FireShotgun -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun) -{ - PARAM_SELF_PROLOGUE(AActor); - - DAngle pitch; - - if (self->target == NULL) - return 0; - - S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM); - A_FaceTarget (self); - pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE); - for (int i = 0; i < 7; ++i) - { - P_GunShot2 (self, false, pitch, PClass::FindActor(NAME_BulletPuff)); - } - self->special1 = level.maptime + 27; - return 0; -} - -//============================================================================ -// -// A_M_CheckAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_CheckAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->special1 != 0 || self->target == NULL) - { - self->SetState (self->FindState("SkipAttack")); - } - else - { - A_FaceTarget (self); - } - return 0; -} - -//============================================================================ -// -// A_M_FireShotgun2 -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun2) -{ - PARAM_SELF_PROLOGUE(AActor); - - DAngle pitch; - - if (self->target == NULL) - return 0; - - S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM); - A_FaceTarget (self); - pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE); - for (int i = 0; i < 20; ++i) - { - int damage = 5*(pr_m_fireshotgun2()%3+1); - DAngle angle = self->Angles.Yaw + pr_m_fireshotgun2.Random2() * (11.25 / 256); - - P_LineAttack (self, angle, MISSILERANGE, - pitch + pr_m_fireshotgun2.Random2() * (7.097 / 256), damage, - NAME_Hitscan, NAME_BulletPuff); - } - self->special1 = level.maptime; - return 0; -} - -//============================================================================ -// -// A_M_FireCGun -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_FireCGun) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL(accurate); - - if (self->target == NULL) - return 0; - - S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM); - A_FaceTarget (self); - P_GunShot2 (self, accurate, P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE), - PClass::FindActor(NAME_BulletPuff)); - return 0; -} - -//============================================================================ -// -// A_M_FireMissile -// -// Giving a marine a rocket launcher is probably a bad idea unless you pump -// up his health, because he's just as likely to kill himself as he is to -// kill anything else with it. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_FireMissile) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - - if (self->CheckMeleeRange ()) - { // If too close, punch it - MarinePunch(self, 1); - } - else - { - A_FaceTarget (self); - P_SpawnMissile (self, self->target, PClass::FindActor("Rocket")); - } - return 0; -} - -//============================================================================ -// -// A_M_FireRailgun -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_FireRailgun) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - - CALL_ACTION(A_MonsterRail, self); - self->special1 = level.maptime + 50; - return 0; -} - -//============================================================================ -// -// A_M_FirePlasma -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_FirePlasma) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - - A_FaceTarget (self); - P_SpawnMissile (self, self->target, PClass::FindActor("PlasmaBall")); - self->special1 = level.maptime + 20; - return 0; -} - -//============================================================================ -// -// A_M_BFGsound -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_BFGsound) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - - if (self->special1 != 0) - { - self->SetState (self->SeeState); - } - else - { - A_FaceTarget (self); - S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM); - // Don't interrupt the firing sequence - self->PainChance = 0; - } - return 0; -} - -//============================================================================ -// -// A_M_FireBFG -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_M_FireBFG) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - - A_FaceTarget (self); - P_SpawnMissile (self, self->target, PClass::FindActor("BFGBall")); - self->special1 = level.maptime + 30; - self->PainChance = MARINE_PAIN_CHANCE; - return 0; -} - -//--------------------------------------------------------------------------- - -void AScriptedMarine::SetWeapon (EMarineWeapon type) -{ - if (GetWeaponStates(type, MeleeState, MissileState)) - { - static const char *classes[] = { - "ScriptedMarine", - "MarineFist", - "MarineBerserk", - "MarineChainsaw", - "MarinePistol", - "MarineShotgun", - "MarineSSG", - "MarineChaingun", - "MarineRocket", - "MarinePlasma", - "MarineRailgun", - "MarineBFG" - }; - - const PClass *cls = PClass::FindClass(classes[type]); - if (cls != NULL) - DecalGenerator = GetDefaultByType(cls)->DecalGenerator; - else - DecalGenerator = NULL; - } -} - -void AScriptedMarine::SetSprite (PClassActor *source) -{ - if (source == NULL) - { // A valid actor class wasn't passed, so use the standard sprite - SpriteOverride = sprite = GetClass()->OwnedStates[0].sprite; - // Copy the standard scaling - Scale = GetDefault()->Scale; - } - else - { // Use the same sprite and scaling the passed class spawns with - SpriteOverride = sprite = GetDefaultByType (source)->SpawnState->sprite; - Scale = GetDefaultByType(source)->Scale; - } -} diff --git a/src/info.h b/src/info.h index 5af51f34b8..4f2b4b2939 100644 --- a/src/info.h +++ b/src/info.h @@ -359,7 +359,7 @@ struct FStateLabelStorage } } - FState *GetState(int pos, PClassActor *cls); + FState *GetState(int pos, PClassActor *cls, bool exact = false); }; extern FStateLabelStorage StateLabels; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index da8f76d7f1..96e20d0227 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -58,7 +58,6 @@ #include "sbar.h" #include "m_swap.h" #include "a_sharedglobal.h" -#include "a_doomglobal.h" #include "a_strifeglobal.h" #include "v_video.h" #include "w_wad.h" @@ -6110,6 +6109,34 @@ static bool CharArrayParms(int &capacity, int &offset, int &a, int *Stack, int & return true; } +static void SetMarineWeapon(AActor *marine, int weapon) +{ + static VMFunction *smw = nullptr; + if (smw == nullptr) + { + auto cls = PClass::FindActor("ScriptedMarine"); + auto func = dyn_cast(cls->Symbols.FindSymbol("SetWeapon", true)); + smw = func->Variants[0].Implementation; + } + VMValue params[2] = { marine, weapon }; + VMFrameStack stack; + stack.Call(smw, params, 2, nullptr, 0, nullptr); +} + +static void SetMarineSprite(AActor *marine, PClassActor *source) +{ + static VMFunction *sms = nullptr; + if (sms == nullptr) + { + auto cls = PClass::FindActor("ScriptedMarine"); + auto func = dyn_cast(cls->Symbols.FindSymbol("SetSprite", true)); + sms = func->Variants[0].Implementation; + } + VMValue params[2] = { marine, source }; + VMFrameStack stack; + stack.Call(sms, params, 2, nullptr, 0, nullptr); +} + int DLevelScript::RunScript () { DACSThinker *controller = DACSThinker::ActiveThinker; @@ -8946,20 +8973,19 @@ scriptwait: case PCD_SETMARINEWEAPON: if (STACK(2) != 0) { - AScriptedMarine *marine; - TActorIterator iterator (STACK(2)); + AActor *marine; + NActorIterator iterator("ScriptedMarine", STACK(2)); while ((marine = iterator.Next()) != NULL) { - marine->SetWeapon ((AScriptedMarine::EMarineWeapon)STACK(1)); + SetMarineWeapon(marine, STACK(1)); } } else { - if (activator != NULL && activator->IsKindOf (RUNTIME_CLASS(AScriptedMarine))) + if (activator != nullptr && activator->IsKindOf (PClass::FindClass("ScriptedMarine"))) { - barrier_cast(activator)->SetWeapon ( - (AScriptedMarine::EMarineWeapon)STACK(1)); + SetMarineWeapon(activator, STACK(1)); } } sp -= 2; @@ -8973,19 +8999,19 @@ scriptwait: { if (STACK(2) != 0) { - AScriptedMarine *marine; - TActorIterator iterator (STACK(2)); + AActor *marine; + NActorIterator iterator("ScriptedMarine", STACK(2)); while ((marine = iterator.Next()) != NULL) { - marine->SetSprite (type); + SetMarineSprite(marine, type); } } else { - if (activator != NULL && activator->IsKindOf (RUNTIME_CLASS(AScriptedMarine))) + if (activator != nullptr && activator->IsKindOf(PClass::FindClass("ScriptedMarine"))) { - barrier_cast(activator)->SetSprite (type); + SetMarineSprite(activator, type); } } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 37a2d533ed..54485d6538 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -143,7 +143,7 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) // 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()); + owner->TypeName.GetChars(), state - owner->OwnedStates, state->ActionFunc->PrintableName.GetChars()); state->ActionFunc = nullptr; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d1a273ef25..1066d985af 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -315,10 +315,11 @@ void AActor::InitNativeFields() 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); + meta->AddNativeField("MeleeState", TypeState, myoffsetof(AActor, MeleeState)); + meta->AddNativeField("MissileState", TypeState, myoffsetof(AActor, MissileState)); //int ConversationRoot; // THe root of the current dialogue //FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is "used." + meta->AddNativeField("DecalGenerator", NewPointer(TypeVoid), myoffsetof(AActor, DecalGenerator)); //FDecalBase *DecalGenerator; // synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them. diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 3bc2dfbe1d..157badd879 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -388,7 +388,7 @@ void DPSprite::SetState(FState *newstate, bool pending) // 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()); + owner->TypeName.GetChars(), newstate - owner->OwnedStates, newstate->ActionFunc->PrintableName.GetChars()); newstate->ActionFunc = nullptr; } if (newstate->CallAction(Owner->mo, Caller, &stp, &nextstate)) diff --git a/src/p_states.cpp b/src/p_states.cpp index a49d30af25..fde7a0276d 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -289,7 +289,7 @@ static bool VerifyJumpTarget(PClassActor *cls, FState *CallingState, int index) // //========================================================================== -FState *FStateLabelStorage::GetState(int pos, PClassActor *cls) +FState *FStateLabelStorage::GetState(int pos, PClassActor *cls, bool exact) { if (pos > 0x10000000) { @@ -322,7 +322,7 @@ FState *FStateLabelStorage::GetState(int pos, PClassActor *cls) else if (cls != nullptr) { FName *labels = (FName*)&Storage[pos + sizeof(int)]; - return cls->FindState(val, labels, false); + return cls->FindState(val, labels, exact); } } return nullptr; @@ -337,8 +337,9 @@ FState *FStateLabelStorage::GetState(int pos, PClassActor *cls) DEFINE_ACTION_FUNCTION(AActor, FindState) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STATE(newstate); - ACTION_RETURN_STATE(newstate); + PARAM_INT(newstate); + PARAM_BOOL_DEF(exact) + ACTION_RETURN_STATE(StateLabels.GetState(newstate, self->GetClass(), exact)); } // same as above but context aware. diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index cae95da34d..8d44e5c184 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -230,6 +230,7 @@ static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCall { PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname); VMNativeFunction *calldec = new VMNativeFunction(func, funcname); + calldec->PrintableName = funcname.GetChars(); symfunc->Function = calldec; sym = symfunc; GlobalSymbols.AddSymbol(sym); @@ -1428,6 +1429,14 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + else if (ValueType == TypeSpriteID && basex->IsInteger()) + { + basex->ValueType = TypeSpriteID; + auto x = basex; + basex = nullptr; + delete this; + return x; + } else if (ValueType == TypeStateLabel) { if (basex->ValueType == TypeNullPtr) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 76770272d4..cdb896902a 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -581,17 +581,21 @@ AFuncDesc *FindFunction(PStruct *cls, const char * string) { for (int i = 0; i < 2; i++) { - // Since many functions have been declared with Actor as owning class, despited being members of something else, let's hack around this until they have been fixed or exported. + // Since many functions have been declared with Actor as owning class, despite being members of something else, let's hack around this until they have been fixed or exported. // Since most of these are expected to be scriptified anyway, there's no point fixing them all before they get exported. - if (i == 1 && !cls->IsKindOf(RUNTIME_CLASS(PClassActor))) break; + if (i == 1) + { + if (!cls->IsKindOf(RUNTIME_CLASS(PClassActor))) break; + cls = RUNTIME_CLASS(AActor); + } - FStringf fullname("%s_%s", i == 0 ? cls->TypeName.GetChars() : "Actor", string); int min = 0, max = AFTable.Size() - 1; while (min <= max) { int mid = (min + max) / 2; - int lexval = stricmp(fullname, AFTable[mid].Name + 1); + int lexval = stricmp(cls->TypeName.GetChars(), AFTable[mid].ClassName + 1); + if (lexval == 0) lexval = stricmp(string, AFTable[mid].FuncName); if (lexval == 0) { return &AFTable[mid]; @@ -641,7 +645,10 @@ static int propcmp(const void * a, const void * b) static int funccmp(const void * a, const void * b) { - return stricmp(((AFuncDesc*)a)->Name + 1, ((AFuncDesc*)b)->Name + 1); // +1 to get past the prefix letter of the native class name, which gets omitted by the FName for the class. + // +1 to get past the prefix letter of the native class name, which gets omitted by the FName for the class. + int res = stricmp(((AFuncDesc*)a)->ClassName + 1, ((AFuncDesc*)b)->ClassName + 1); + if (res == 0) res = stricmp(((AFuncDesc*)a)->FuncName, ((AFuncDesc*)b)->FuncName); + return res; } //========================================================================== @@ -700,7 +707,8 @@ void InitThingdef() { AFuncDesc *afunc = (AFuncDesc *)*probe; assert(afunc->VMPointer != NULL); - *(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->Name); + *(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->FuncName); + (*(afunc->VMPointer))->PrintableName.Format("%s.%s [Native]", afunc->ClassName+1, afunc->FuncName); AFTable.Push(*afunc); } AFTable.ShrinkToFit(); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index ad42ee1ddc..7d56b32dbb 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -669,6 +669,7 @@ public: int VirtualIndex = -1; FName Name; TArray DefaultArgs; + FString PrintableName; // so that the VM can print meaningful info if something in this function goes wrong. class PPrototype *Proto; @@ -822,7 +823,6 @@ public: VM_UHALF 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. TArray SpecialInits; // list of all contents on the extra stack which require construction and destruction void InitExtra(void *addr); @@ -1015,7 +1015,8 @@ typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray &de struct AFuncDesc { - const char *Name; + const char *ClassName; + const char *FuncName; actionf_p Function; VMNativeFunction **VMPointer; }; @@ -1037,7 +1038,7 @@ struct AFuncDesc #define DEFINE_ACTION_FUNCTION(cls, name) \ static int AF_##cls##_##name(VM_ARGS); \ VMNativeFunction *cls##_##name##_VMPtr; \ - static const AFuncDesc cls##_##name##_Hook = { #cls "_" #name, AF_##cls##_##name, &cls##_##name##_VMPtr }; \ + static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##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_##cls##_##name(VM_ARGS) diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 04339f6eb1..74b7a34000 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -887,7 +887,7 @@ void FFunctionBuildList::Build() catch (CRecoverableError &err) { // catch errors from the code generator and pring something meaningful. - item.Code->ScriptPosition.Message(MSG_ERROR, "%s in %s", err.GetMessage(), item.PrintableName); + item.Code->ScriptPosition.Message(MSG_ERROR, "%s in %s", err.GetMessage(), item.PrintableName.GetChars()); } } delete item.Code; diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index d8fc16433a..cba67cbdc9 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -261,7 +261,6 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func) void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func) { VMFunction *callfunc; - const char *callname; const char *name; int col; int mode; @@ -497,8 +496,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction } else if (code[i].op == OP_CALL_K || code[i].op == OP_TAIL_K) { - callname = callfunc->IsKindOf(RUNTIME_CLASS(VMScriptFunction)) ? static_cast(callfunc)->PrintableName : callfunc->Name != NAME_None ? callfunc->Name : "[anonfunc]"; - printf_wrapper(out, " [%s]\n", callname); + printf_wrapper(out, " [%s]\n", callfunc->PrintableName.GetChars()); } else { diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 3380959ec9..80057724cd 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -787,11 +787,11 @@ type_list(X) ::= type_list(A) COMMA type_or_array(B). { X = A; /*X-overwrites-A* type_list_or_void(X) ::= VOID. { X = NULL; } type_list_or_void(X) ::= type_list(X). -array_size_expr(X) ::= LBRACKET opt_expr(A) RBRACKET. +array_size_expr(X) ::= LBRACKET(L) opt_expr(A) RBRACKET. { if (A == NULL) { - NEW_AST_NODE(Expression,nil,A); + NEW_AST_NODE(Expression,nil,L.SourceLoc); nil->Operation = PEX_Nil; nil->Type = NULL; X = nil; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 27a02a9190..9682066b97 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2304,14 +2304,14 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { if (vindex == -1) { - Error(p, "Attempt to override non-existent virtual function %s", FName(f->Name).GetChars()); + Error(f, "Attempt to override non-existent virtual function %s", FName(f->Name).GetChars()); } else { auto oldfunc = clstype->Virtuals[vindex]; if (oldfunc->Final) { - Error(p, "Attempt to override final function %s", FName(f->Name).GetChars()); + Error(f, "Attempt to override final function %s", FName(f->Name).GetChars()); } clstype->Virtuals[vindex] = sym->Variants[0].Implementation; sym->Variants[0].Implementation->VirtualIndex = vindex; diff --git a/src/virtual.h b/src/virtual.h index 01541cebab..8842eb891f 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -55,7 +55,7 @@ inline int GetVirtualIndex(PClass *cls, const char *funcname) static int VIndex = -1; \ if (VIndex < 0) { \ VIndex = GetVirtualIndex(RUNTIME_CLASS(cls), #funcname); \ - if (VIndex < 0) I_Error("Unable to find virtual function in " #cls, #funcname); \ + if (VIndex < 0) I_Error("Unable to find virtual function %s in " #cls, #funcname); \ } #define VFUNC this->GetClass()->Virtuals[VIndex] diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 53f0475135..87d2f8759b 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -115,7 +115,7 @@ class Actor : Thinker native native void NewChaseDir(); native bool CheckMissileRange(); native bool SetState(state st, bool nofunction = false); - native state FindState(statelabel st); // do we need exact later? + native state FindState(statelabel st, bool exact = false); // 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(); @@ -369,8 +369,6 @@ class Actor : Thinker native 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(); diff --git a/wadsrc/static/zscript/doom/scriptedmarine.txt b/wadsrc/static/zscript/doom/scriptedmarine.txt index 7a82513cb8..1096f24b50 100644 --- a/wadsrc/static/zscript/doom/scriptedmarine.txt +++ b/wadsrc/static/zscript/doom/scriptedmarine.txt @@ -1,8 +1,35 @@ // Scriptable marine ------------------------------------------------------- -class ScriptedMarine : Actor native +class ScriptedMarine : Actor { + const MARINE_PAIN_CHANCE = 160; + + enum EMarineWeapon + { + WEAPON_Dummy, + WEAPON_Fist, + WEAPON_BerserkFist, + WEAPON_Chainsaw, + WEAPON_Pistol, + WEAPON_Shotgun, + WEAPON_SuperShotgun, + WEAPON_Chaingun, + WEAPON_RocketLauncher, + WEAPON_PlasmaRifle, + WEAPON_Railgun, + WEAPON_BFG + }; + + struct WeaponStates + { + state melee; + state missile; + } + + int CurrentWeapon; + SpriteID SpriteOverride; + Default { Health 100; @@ -10,7 +37,7 @@ class ScriptedMarine : Actor native Height 56; Mass 100; Speed 8; - Painchance 160; + Painchance MARINE_PAIN_CHANCE; MONSTER; -COUNTKILL Translation 0; @@ -19,23 +46,6 @@ class ScriptedMarine : Actor native 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: @@ -58,25 +68,22 @@ class ScriptedMarine : Actor native PLAY E 4 A_FaceTarget; PLAY E 4 A_M_Punch(1); PLAY A 9; - PLAY A 0 A_M_Refire(1); + PLAY A 0 A_M_Refire(1, "FistEnd"); Loop; + FistEnd: 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); + PLAY A 0 A_M_Refire(1, "FistEnd"); 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: @@ -88,16 +95,15 @@ class ScriptedMarine : Actor native 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 0 A_M_Refire(0, "ShootEnd"); + ShootEnd: 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; + PLAY A 0 A_M_Refire(0, "ShootEnd"); Goto Fireloop.Pistol; - PLAY A 5; - Goto See; Missile.Shotgun: PLAY E 3 A_M_CheckAttack; PLAY F 7 BRIGHT A_M_FireShotgun; @@ -110,26 +116,20 @@ class ScriptedMarine : Actor native 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; + PLAY A 0 A_M_Refire(0, "See"); 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; + PLAY A 0 A_M_Refire(0, "See"); 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; + PLAY A 0 A_M_Refire(0, "See"); Goto Missile.Plasma+1; - PLAY A 0; - Goto See; Missile.Railgun: PLAY E 4 A_M_CheckAttack; PLAY F 6 BRIGHT A_M_FireRailgun; @@ -139,10 +139,8 @@ class ScriptedMarine : Actor native PLAY EEEEE 5 A_FaceTarget; PLAY F 6 BRIGHT A_M_FireBFG; PLAY A 4 A_FaceTarget; - PLAY A 0 A_M_Refire; + PLAY A 0 A_M_Refire(0, "See"); Loop; - PLAY A 0; - Goto See; SkipAttack: PLAY A 1; @@ -169,6 +167,541 @@ class ScriptedMarine : Actor native PLAY MLKJIH 5; Goto See; } + + //============================================================================ + // + // + // + //============================================================================ + + private bool GetWeaponStates(int weap, WeaponStates wstates) + { + static const statelabel MeleeNames[] = + { + "Melee.None", "Melee.Fist", "Melee.Berserk", "Melee.Chainsaw", "Melee.Pistol", "Melee.Shotgun", + "Melee.SSG", "Melee.Chaingun", "Melee.Rocket", "Melee.Plasma", "Melee.Railgun", "Melee.BFG" + }; + + static const statelabel MissileNames[] = + { + "Missile.None", "Missile.Fist", "Missile.Berserk", "Missile.Chainsaw", "Missile.Pistol", "Missile.Shotgun", + "Missile.SSG", "Missile.Chaingun", "Missile.Rocket", "Missile.Plasma", "Missile.Railgun", "Missile.BFG" + }; + + if (weap < WEAPON_Dummy || weap > WEAPON_BFG) weap = WEAPON_Dummy; + + wstates.melee = FindState(MeleeNames[weap], true); + wstates.missile = FindState(MissileNames[weap], true); + + return wstates.melee != null || wstates.missile != null; + } + + //============================================================================ + // + // + // + //============================================================================ + + override void BeginPlay () + { + Super.BeginPlay (); + + // Set the current weapon + for(int i = WEAPON_Dummy; i <= WEAPON_BFG; i++) + { + WeaponStates wstates; + if (GetWeaponStates(i, wstates)) + { + if (wstates.melee == MeleeState && wstates.missile == MissileState) + { + CurrentWeapon = i; + } + } + } + } + + //============================================================================ + // + // + // + //============================================================================ + + // placeholder to make it compile for the time being. + SpriteID GetSprite(State st) + { + return SpriteID(0); + } + + override void Tick () + { + Super.Tick (); + + // Override the standard sprite, if desired + if (SpriteOverride != 0 && sprite == GetSprite(SpawnState)) + { + sprite = SpriteOverride; + } + + if (special1 != 0) + { + if (CurrentWeapon == WEAPON_SuperShotgun) + { // Play SSG reload sounds + int ticks = level.maptime - special1; + if (ticks < 47) + { + switch (ticks) + { + case 14: + A_PlaySound ("weapons/sshoto", CHAN_WEAPON); + break; + case 28: + A_PlaySound ("weapons/sshotl", CHAN_WEAPON); + break; + case 41: + A_PlaySound ("weapons/sshotc", CHAN_WEAPON); + break; + } + } + else + { + special1 = 0; + } + } + else + { // Wait for a long refire time + if (level.maptime >= special1) + { + special1 = 0; + } + else + { + bJustAttacked = true; + } + } + } + } + + //============================================================================ + // + // A_M_Refire + // + //============================================================================ + + void A_M_Refire (bool ignoremissile, statelabel jumpto) + { + if (target == null || target.health <= 0) + { + if (MissileState && random[SMarineRefire]() < 160) + { // Look for a new target most of the time + if (LookForPlayers (true) && CheckMissileRange ()) + { // Found somebody new and in range, so don't stop shooting + return; + } + } + SetStateLabel (jumpto); + return; + } + if (((ignoremissile || MissileState == null) && !CheckMeleeRange ()) || + !CheckSight (target) || random[SMarineRefire]() < 4) // Small chance of stopping even when target not dead + { + SetStateLabel (jumpto); + } + } + + //============================================================================ + // + // A_M_SawRefire + // + //============================================================================ + + void A_M_SawRefire () + { + if (target == null || target.health <= 0 || !CheckMeleeRange ()) + { + SetStateLabel ("See"); + } + } + + //============================================================================ + // + // A_MarineNoise + // + //============================================================================ + + void A_MarineNoise () + { + if (CurrentWeapon == WEAPON_Chainsaw) + { + A_PlaySound ("weapons/sawidle", CHAN_WEAPON); + } + } + + //============================================================================ + // + // A_MarineChase + // + //============================================================================ + + void A_MarineChase () + { + A_MarineNoise(); + A_Chase (); + } + + //============================================================================ + // + // A_MarineLook + // + //============================================================================ + + void A_MarineLook () + { + A_MarineNoise(); + A_Look(); + } + + //============================================================================ + // + // A_M_Punch (also used in the rocket attack.) + // + //============================================================================ + + void A_M_Punch(int damagemul) + { + FTranslatedLineTarget t; + + if (target == null) + return; + + int damage = (random[SMarinePunch](1, 10) << 1) * damagemul; + + A_FaceTarget (); + double ang = angle + random2[SMarinePunch]() * (5.625 / 256); + double pitch = AimLineAttack (ang, MELEERANGE); + LineAttack (ang, MELEERANGE, pitch, damage, 'Melee', "BulletPuff", true, t); + + // turn to face target + if (t.linetarget) + { + A_PlaySound ("*fist", CHAN_WEAPON); + angle = t.angleFromSource; + } + } + + //============================================================================ + // + // P_GunShot2 + // + //============================================================================ + + private void GunShot2 (bool accurate, double pitch, class pufftype) + { + int damage = 5 * random[SMarineGunshot](1,3); + double ang = angle; + + if (!accurate) + { + ang += Random2[SMarineGunshot]() * (5.625 / 256); + } + + LineAttack (ang, MISSILERANGE, pitch, damage, 'Hitscan', pufftype); + } + + //============================================================================ + // + // A_M_FirePistol + // + //============================================================================ + + void A_M_FirePistol (bool accurate) + { + if (target == null) + return; + + A_PlaySound ("weapons/pistol", CHAN_WEAPON); + A_FaceTarget (); + GunShot2 (accurate, AimLineAttack (angle, MISSILERANGE), "BulletPuff"); + } + + //============================================================================ + // + // A_M_FireShotgun + // + //============================================================================ + + void A_M_FireShotgun () + { + if (target == null) + return; + + A_PlaySound ("weapons/shotgf", CHAN_WEAPON); + A_FaceTarget (); + double pitch = AimLineAttack (angle, MISSILERANGE); + for (int i = 0; i < 7; ++i) + { + GunShot2 (false, pitch, "BulletPuff"); + } + special1 = level.maptime + 27; + } + + //============================================================================ + // + // A_M_CheckAttack + // + //============================================================================ + + void A_M_CheckAttack () + { + if (special1 != 0 || target == null) + { + SetStateLabel ("SkipAttack"); + } + else + { + A_FaceTarget (); + } + } + + //============================================================================ + // + // A_M_FireShotgun2 + // + //============================================================================ + + void A_M_FireShotgun2 () + { + if (target == null) + return; + + A_PlaySound ("weapons/sshotf", CHAN_WEAPON); + A_FaceTarget (); + double pitch = AimLineAttack (angle, MISSILERANGE); + for (int i = 0; i < 20; ++i) + { + int damage = 5*(random[SMarineFireSSG]()%3+1); + double ang = angle + Random2[SMarineFireSSG]() * (11.25 / 256); + + LineAttack (ang, MISSILERANGE, pitch + Random2[SMarineFireSSG]() * (7.097 / 256), damage, 'Hitscan', "BulletPuff"); + } + special1 = level.maptime; + } + + //============================================================================ + // + // A_M_FireCGun + // + //============================================================================ + + void A_M_FireCGun(bool accurate) + { + if (target == null) + return; + + A_PlaySound ("weapons/chngun", CHAN_WEAPON); + A_FaceTarget (); + GunShot2 (accurate, AimLineAttack (angle, MISSILERANGE), "BulletPuff"); + } + + //============================================================================ + // + // A_M_FireMissile + // + // Giving a marine a rocket launcher is probably a bad idea unless you pump + // up his health, because he's just as likely to kill himself as he is to + // kill anything else with it. + // + //============================================================================ + + void A_M_FireMissile () + { + if (target == null) + return; + + if (CheckMeleeRange ()) + { // If too close, punch it + A_M_Punch(1); + } + else + { + A_FaceTarget (); + SpawnMissile (target, "Rocket"); + } + } + + //============================================================================ + // + // A_M_FireRailgun + // + //============================================================================ + + void A_M_FireRailgun () + { + if (target == null) + return; + + A_MonsterRail(); + special1 = level.maptime + 50; + } + + //============================================================================ + // + // A_M_FirePlasma + // + //============================================================================ + + void A_M_FirePlasma () + { + if (target == null) + return; + + A_FaceTarget (); + SpawnMissile (target, "PlasmaBall"); + special1 = level.maptime + 20; + } + + //============================================================================ + // + // A_M_BFGsound + // + //============================================================================ + + void A_M_BFGsound () + { + if (target == null) + return; + + if (special1 != 0) + { + SetState (SeeState); + } + else + { + A_FaceTarget (); + A_PlaySound ("weapons/bfgf", CHAN_WEAPON); + // Don't interrupt the firing sequence + PainChance = 0; + } + } + + //============================================================================ + // + // A_M_FireBFG + // + //============================================================================ + + void A_M_FireBFG () + { + if (target == null) + return; + + A_FaceTarget (); + SpawnMissile (target, "BFGBall"); + special1 = level.maptime + 30; + PainChance = MARINE_PAIN_CHANCE; + } + + //--------------------------------------------------------------------------- + + final void SetWeapon (int type) + { + WeaponStates wstates; + if (GetWeaponStates(type, wstates)) + { + static const class classes[] = { + "ScriptedMarine", + "MarineFist", + "MarineBerserk", + "MarineChainsaw", + "MarinePistol", + "MarineShotgun", + "MarineSSG", + "MarineChaingun", + "MarineRocket", + "MarinePlasma", + "MarineRailgun", + "MarineBFG" + }; + + MeleeState = wstates.melee; + MissileState = wstates.missile; + DecalGenerator = GetDefaultByType(classes[type]).DecalGenerator; + } + } + + final void SetSprite (class source) + { + if (source == null) + { // A valid actor class wasn't passed, so use the standard sprite + SpriteOverride = sprite = GetSprite(SpawnState); + // Copy the standard scaling + Scale = Default.Scale; + } + else + { // Use the same sprite and scaling the passed class spawns with + readonly def = GetDefaultByType (source); + SpriteOverride = sprite = GetSprite(def.SpawnState); + Scale = def.Scale; + } + } +} + +extend class Actor +{ + //============================================================================ + // + // A_M_Saw (this is globally exported) + // + //============================================================================ + + void A_M_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff") + { + if (target == null) + return; + + if (pufftype == null) pufftype = "BulletPuff"; + if (damage == 0) damage = 2; + + A_FaceTarget (); + if (CheckMeleeRange ()) + { + FTranslatedLineTarget t; + + damage *= random[SMarineSaw](1, 10); + double ang = angle + Random2[SMarineSaw]() * (5.625 / 256); + + LineAttack (angle, SAWRANGE, AimLineAttack (angle, SAWRANGE), damage, 'Melee', pufftype, false, t); + + if (!t.linetarget) + { + A_PlaySound (fullsound, 1, CHAN_WEAPON); + return; + } + A_PlaySound (hitsound, CHAN_WEAPON); + + // turn to face target + ang = t.angleFromSource; + double anglediff = deltaangle(angle, ang); + + if (anglediff < 0.0) + { + if (anglediff < -4.5) + angle = ang + 90.0 / 21; + else + angle -= 4.5; + } + else + { + if (anglediff > 4.5) + angle = ang - 90.0 / 21; + else + angle += 4.5; + } + } + else + { + A_PlaySound (fullsound, 1, CHAN_WEAPON); + } + } } //--------------------------------------------------------------------------- From 6cc00e79a6dacc444cd0b6401d02b9d98abe1dd4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 19:20:27 +0100 Subject: [PATCH 325/471] - made all internal struct types NativeStructs so that all variables of their types are made references. --- src/dobjtype.cpp | 20 ++++++++++++++++++++ src/dobjtype.h | 1 + src/g_level.cpp | 2 +- src/p_mobj.cpp | 4 ++-- src/p_user.cpp | 2 +- src/scripting/thingdef_data.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 2 +- 7 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 4354e08852..09a3b1c940 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2457,6 +2457,26 @@ PNativeStruct::PNativeStruct(FName name) HasNativeFields = true; } +//========================================================================== +// +// NewNativeStruct +// Returns a PNativeStruct for the given name and container, making sure not to +// create duplicates. +// +//========================================================================== + +PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer) +{ + size_t bucket; + PType *stype = TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, &bucket); + if (stype == NULL) + { + stype = new PStruct(name, outer); + TypeTable.AddType(stype, RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, bucket); + } + return static_cast(stype); +} + /* PField *****************************************************************/ IMPLEMENT_CLASS(PField, false, false, false, false) diff --git a/src/dobjtype.h b/src/dobjtype.h index be192225b2..6134bbf903 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -922,6 +922,7 @@ PPointer *NewPointer(PType *type, bool isconst = false); PClassPointer *NewClassPointer(PClass *restrict); PEnum *NewEnum(FName name, PTypeBase *outer); PStruct *NewStruct(FName name, PTypeBase *outer); +PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer); PPrototype *NewPrototype(const TArray &rettypes, const TArray &argtypes); // Built-in types ----------------------------------------------------------- diff --git a/src/g_level.cpp b/src/g_level.cpp index 9a955a03ed..8987aed6c2 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1858,7 +1858,7 @@ void FLevelLocals::AddScroller (int secnum) void G_InitLevelLocalsForScript() { - PStruct *lstruct = NewStruct("LevelLocals", nullptr); + PStruct *lstruct = NewNativeStruct("LevelLocals", nullptr); PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level); GlobalSymbols.AddSymbol(levelf); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 1066d985af..a97ed61c54 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -161,8 +161,8 @@ void AActor::InitNativeFields() PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); PType *TypeActorClass = NewClassPointer(RUNTIME_CLASS(AActor)); PType *TypeInventory = NewPointer(RUNTIME_CLASS(AInventory)); - PType *TypePlayer = NewPointer(NewStruct("Player", nullptr)); - auto TypeSector = NewPointer(NewStruct("Sector", nullptr)); + PType *TypePlayer = NewPointer(NewNativeStruct("Player", nullptr)); + auto TypeSector = NewPointer(NewNativeStruct("Sector", nullptr)); PType *array5 = NewArray(TypeSInt32, 5); auto meta = RUNTIME_CLASS(AActor); diff --git a/src/p_user.cpp b/src/p_user.cpp index ad0bb6ba4a..6d34037f1e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3137,7 +3137,7 @@ bool P_IsPlayerTotallyFrozen(const player_t *player) void P_InitPlayerForScript() { - PStruct *pstruct = NewStruct("Player", nullptr); + PStruct *pstruct = NewNativeStruct("Player", nullptr); pstruct->Size = sizeof(player_t); pstruct->Align = alignof(player_t); PArray *parray = NewArray(pstruct, MAXPLAYERS); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index cdb896902a..5e8338a272 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -663,7 +663,7 @@ void InitThingdef() { PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); - PStruct *sstruct = NewStruct("Sector", nullptr); + PStruct *sstruct = NewNativeStruct("Sector", nullptr); auto sptr = NewPointer(sstruct); sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 9682066b97..81b1c5ef64 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1533,7 +1533,7 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) { return TypeSInt32; // hack this to an integer until we can resolve the enum mess. } - if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) + if (ptype->IsKindOf(RUNTIME_CLASS(PNativeStruct))) // native structs and classes cannot be instantiated, they always get used as reference. { return NewPointer(ptype, type->isconst); } From ff3baac8a78dd8545c2c21877c33a4da2b3ba802 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 19:36:14 +0100 Subject: [PATCH 326/471] - made PStatePointer a real pointer pointing to a native struct named 'state', because that's what it really is and what it needs to be if we want to use a state as more than an opaque identifier in the VM --- src/dobjtype.cpp | 86 +++++++++++++++++++++++------------------------- src/dobjtype.h | 21 ++++++------ 2 files changed, 53 insertions(+), 54 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 09a3b1c940..2f536c3007 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1547,50 +1547,6 @@ PStateLabel::PStateLabel() mDescriptiveName = "StateLabel"; } -/* PStatePointer **********************************************************/ - -IMPLEMENT_CLASS(PStatePointer, false, false, false, false) - -//========================================================================== -// -// PStatePointer Default Constructor -// -//========================================================================== - -PStatePointer::PStatePointer() -: PBasicType(sizeof(FState *), alignof(FState *)) -{ - mDescriptiveName = "State"; - storeOp = OP_SP; - loadOp = OP_LP; - moveOp = OP_MOVEA; - RegType = REGT_POINTER; -} - -//========================================================================== -// -// PStatePointer :: WriteValue -// -//========================================================================== - -void PStatePointer::WriteValue(FSerializer &ar, const char *key,const void *addr) const -{ - ar(key, *(FState **)addr); -} - -//========================================================================== -// -// PStatePointer :: ReadValue -// -//========================================================================== - -bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) const -{ - bool res = false; - ::Serialize(ar, key, *(FState **)addr, nullptr, &res); - return res; -} - /* PPointer ***************************************************************/ IMPLEMENT_CLASS(PPointer, false, true, false, false) @@ -1736,6 +1692,48 @@ PPointer *NewPointer(PType *type, bool isconst) return static_cast(ptype); } +/* PStatePointer **********************************************************/ + +IMPLEMENT_CLASS(PStatePointer, false, false, false, false) + +//========================================================================== +// +// PStatePointer Default Constructor +// +//========================================================================== + +PStatePointer::PStatePointer() +{ + mDescriptiveName = "Pointer"; + PointedType = NewNativeStruct(NAME_State, nullptr); + IsConst = true; +} + +//========================================================================== +// +// PStatePointer :: WriteValue +// +//========================================================================== + +void PStatePointer::WriteValue(FSerializer &ar, const char *key, const void *addr) const +{ + ar(key, *(FState **)addr); +} + +//========================================================================== +// +// PStatePointer :: ReadValue +// +//========================================================================== + +bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) const +{ + bool res = false; + ::Serialize(ar, key, *(FState **)addr, nullptr, &res); + return res; +} + + /* PClassPointer **********************************************************/ diff --git a/src/dobjtype.h b/src/dobjtype.h index 6134bbf903..f464e36f87 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -551,16 +551,6 @@ public: // Pointers ----------------------------------------------------------------- -class PStatePointer : public PBasicType -{ - DECLARE_CLASS(PStatePointer, PBasicType); -public: - PStatePointer(); - - void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; - bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; -}; - class PPointer : public PBasicType { DECLARE_CLASS(PPointer, PBasicType); @@ -583,6 +573,17 @@ protected: void SetOps(); }; +class PStatePointer : public PPointer +{ + DECLARE_CLASS(PStatePointer, PPointer); +public: + PStatePointer(); + + void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; + bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; +}; + + class PClassPointer : public PPointer { DECLARE_CLASS(PClassPointer, PPointer); From 135cfcf0163a582b89a00f22ae7c65b19146be21 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 21:34:34 +0100 Subject: [PATCH 327/471] - implemented State as an actual native struct, so that its fields can be accessed from scripts. - refactored state bitfield members into a flag word because the address of a bitfield cannot be taken, making such variables inaccessible to scripts. - actually use PNativeStruct for representing native structs defined in a script. --- src/d_dehacked.cpp | 15 ++--- src/dobjtype.cpp | 3 +- src/info.h | 71 ++++++++++++---------- src/p_mobj.cpp | 4 +- src/p_states.cpp | 37 +++++++++-- src/scripting/codegeneration/codegen.cpp | 4 +- src/scripting/decorate/olddecorations.cpp | 2 +- src/scripting/decorate/thingdef_states.cpp | 10 +-- src/scripting/thingdef_data.cpp | 2 + src/scripting/zscript/zcc_compile.cpp | 16 +++-- wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/doom/fatso.txt | 2 +- 12 files changed, 102 insertions(+), 65 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 3ad1b2cd91..508821fd80 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1466,28 +1466,21 @@ static int PatchFrame (int frameNum) if (info != &dummy) { - info->DefineFlags |= SDF_DEHACKED; // Signals the state has been modified by dehacked + info->StateFlags |= STF_DEHACKED; // Signals the state has been modified by dehacked if ((unsigned)(frame & 0x7fff) > 63) { - Printf ("Frame %d: Subnumber must be in range [0,63]\n", frameNum); + Printf("Frame %d: Subnumber must be in range [0,63]\n", frameNum); } info->Tics = tics; info->Misc1 = misc1; info->Frame = frame & 0x3f; - info->Fullbright = frame & 0x8000 ? true : false; + if (frame & 0x8000) info->StateFlags |= STF_FULLBRIGHT; + else info->StateFlags &= STF_FULLBRIGHT; } 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; diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 2f536c3007..420dbc515b 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -558,6 +558,7 @@ void PType::StaticInit() RUNTIME_CLASS(PDynArray)->TypeTableType = RUNTIME_CLASS(PDynArray); RUNTIME_CLASS(PMap)->TypeTableType = RUNTIME_CLASS(PMap); RUNTIME_CLASS(PStruct)->TypeTableType = RUNTIME_CLASS(PStruct); + RUNTIME_CLASS(PNativeStruct)->TypeTableType = RUNTIME_CLASS(PNativeStruct); RUNTIME_CLASS(PPrototype)->TypeTableType = RUNTIME_CLASS(PPrototype); RUNTIME_CLASS(PClass)->TypeTableType = RUNTIME_CLASS(PClass); RUNTIME_CLASS(PStatePointer)->TypeTableType = RUNTIME_CLASS(PStatePointer); @@ -2469,7 +2470,7 @@ PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer) PType *stype = TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, &bucket); if (stype == NULL) { - stype = new PStruct(name, outer); + stype = new PNativeStruct(name); TypeTable.AddType(stype, RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, bucket); } return static_cast(stype); diff --git a/src/info.h b/src/info.h index 4f2b4b2939..a41a6def8d 100644 --- a/src/info.h +++ b/src/info.h @@ -63,7 +63,17 @@ enum EStateDefineFlags SDF_LABEL = 4, SDF_INDEX = 5, SDF_MASK = 7, - SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump +}; + +enum EStateFlags +{ + STF_SLOW = 1, // State duration is extended when slow monsters is on. + STF_FAST = 2, // State duration is shortened when fast monsters is on. + STF_FULLBRIGHT = 4, // State is fullbright + STF_NODELAY = 8, // Spawn states executes its action normally + STF_SAMEFRAME = 16, // Ignore Frame (except when spawning actor) + STF_CANRAISE = 32, // Allows a monster to be resurrected without waiting for an infinate frame + STF_DEHACKED = 64, // Modified by Dehacked }; enum EStateUseFlags @@ -101,33 +111,44 @@ struct FState { FState *NextState; VMFunction *ActionFunc; - 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 - BYTE Fullbright:1; // State is fullbright - BYTE SameFrame:1; // Ignore Frame (except when spawning actor) - BYTE Fast:1; - BYTE NoDelay:1; // Spawn states executes its action normally - BYTE CanRaise:1; // Allows a monster to be resurrected without waiting for an infinate frame - BYTE Slow:1; // Inverse of fast - + int32_t sprite; + int16_t Tics; + uint16_t TicRange; + int16_t Light; + uint16_t StateFlags; + uint8_t Frame; + uint8_t UseFlags; + uint8_t DefineFlags; // Unused byte so let's use it during state creation. + int32_t Misc1; // Was changed to SBYTE, reverted to long for MBF compat + int32_t Misc2; // Was changed to BYTE, reverted to long for MBF compat +public: inline int GetFrame() const { return Frame; } inline bool GetSameFrame() const { - return SameFrame; + return !!(StateFlags & STF_SAMEFRAME); } inline int GetFullbright() const { - return Fullbright ? 0x10 /*RF_FULLBRIGHT*/ : 0; + return (StateFlags & STF_FULLBRIGHT)? 0x10 /*RF_FULLBRIGHT*/ : 0; + } + inline bool GetFast() const + { + return !!(StateFlags & STF_FAST); + } + inline bool GetSlow() const + { + return !!(StateFlags & STF_SLOW); + } + inline bool GetNoDelay() const + { + return !!(StateFlags & STF_NODELAY); + } + inline bool GetCanRaise() const + { + return !!(StateFlags & STF_CANRAISE); } inline int GetTics() const { @@ -149,22 +170,10 @@ struct FState { return NextState; } - inline bool GetNoDelay() const - { - return NoDelay; - } - inline bool GetCanRaise() const - { - return CanRaise; - } inline void SetFrame(BYTE frame) { 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); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a97ed61c54..b7da3e2c54 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -584,11 +584,11 @@ bool AActor::InStateSequence(FState * newstate, FState * basestate) int AActor::GetTics(FState * newstate) { int tics = newstate->GetTics(); - if (isFast() && newstate->Fast) + if (isFast() && newstate->GetFast()) { return tics - (tics>>1); } - else if (isSlow() && newstate->Slow) + else if (isSlow() && newstate->GetSlow()) { return tics<<1; } diff --git a/src/p_states.cpp b/src/p_states.cpp index fde7a0276d..5444bcc3ad 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -924,9 +924,9 @@ int FStateDefinitions::AddStates(FState *state, const char *framechars, const FS if (*framechars == '#') noframe = true; - else if (*framechars == '^') + else if (*framechars == '^') frame = '\\' - 'A'; - else + else frame = (*framechars & 223) - 'A'; framechars++; @@ -937,13 +937,14 @@ int FStateDefinitions::AddStates(FState *state, const char *framechars, const FS } state->Frame = frame; - state->SameFrame = noframe; + if (noframe) state->StateFlags |= STF_SAMEFRAME; + else state->StateFlags &= STF_SAMEFRAME; StateArray.Push(*state); SourceLines.Push(sc); ++count; // NODELAY flag is not carried past the first state - state->NoDelay = false; + state->StateFlags &= STF_NODELAY; } laststate = &StateArray[StateArray.Size() - 1]; laststatebeforelabel = laststate; @@ -1055,3 +1056,31 @@ CCMD(dumpstates) Printf(PRINT_LOG, "----------------------------\n"); } } + +//========================================================================== +// +// sets up the script-side version of states +// +//========================================================================== + +void P_InitStateForScript() +{ + PNativeStruct *pstruct = dyn_cast(TypeState->PointedType); + assert(pstruct != nullptr); + + pstruct->AddNativeField("NextState", TypeState, myoffsetof(FState, NextState), VARF_ReadOnly); + pstruct->AddNativeField("sprite", TypeSInt32, myoffsetof(FState, sprite), VARF_ReadOnly); + pstruct->AddNativeField("Tics", TypeSInt16, myoffsetof(FState, Tics), VARF_ReadOnly); + pstruct->AddNativeField("TicRange", TypeUInt16, myoffsetof(FState, TicRange), VARF_ReadOnly); + pstruct->AddNativeField("Frame", TypeUInt8, myoffsetof(FState, Frame), VARF_ReadOnly); + pstruct->AddNativeField("UseFlags", TypeUInt8, myoffsetof(FState, UseFlags), VARF_ReadOnly); + pstruct->AddNativeField("Misc1", TypeSInt32, myoffsetof(FState, Misc1), VARF_ReadOnly); + pstruct->AddNativeField("Misc2", TypeSInt32, myoffsetof(FState, Misc2), VARF_ReadOnly); + pstruct->AddNativeField("bSlow", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_SLOW); + pstruct->AddNativeField("bFast", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_FAST); + pstruct->AddNativeField("bFullbright", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_FULLBRIGHT); + pstruct->AddNativeField("bNoDelay", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_NODELAY); + pstruct->AddNativeField("bSameFrame", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_SAMEFRAME); + pstruct->AddNativeField("bCanRaise", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_CANRAISE); + pstruct->AddNativeField("bDehacked", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_DEHACKED); +} \ No newline at end of file diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8d44e5c184..75d49801ff 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5679,7 +5679,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) return ret; } } - else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct))) + else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) { auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast(Object->ValueType)); delete this; @@ -6278,7 +6278,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) 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. + else if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) { // 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) diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index a4cf20de40..a2cbc636bf 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -699,7 +699,7 @@ static void ParseSpriteFrames (PClassActor *info, TArray &states, TArray { sc.ScriptError ("* must come after a frame"); } - state.Fullbright = true; + state.StateFlags |= STF_FULLBRIGHT; } else if (*token < 'A' || *token > ']') { diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index cad542d1b8..4f60b85854 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -274,24 +274,24 @@ do_stop: { if (sc.Compare("BRIGHT")) { - state.Fullbright = true; + state.StateFlags |= STF_FULLBRIGHT; continue; } if (sc.Compare("FAST")) { - state.Fast = true; + state.StateFlags |= STF_FAST; continue; } if (sc.Compare("SLOW")) { - state.Slow = true; + state.StateFlags |= STF_SLOW; continue; } if (sc.Compare("NODELAY")) { if (bag.statedef.GetStateLabelIndex(NAME_Spawn) == bag.statedef.GetStateCount()) { - state.NoDelay = true; + state.StateFlags |= STF_NODELAY; } else { @@ -327,7 +327,7 @@ do_stop: } if (sc.Compare("CANRAISE")) { - state.CanRaise = true; + state.StateFlags |= STF_CANRAISE; continue; } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 5e8338a272..23aba902ff 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -658,6 +658,7 @@ static int funccmp(const void * a, const void * b) //========================================================================== void G_InitLevelLocalsForScript(); void P_InitPlayerForScript(); +void P_InitStateForScript(); void InitThingdef() { @@ -669,6 +670,7 @@ void InitThingdef() G_InitLevelLocalsForScript(); P_InitPlayerForScript(); + P_InitStateForScript(); FAutoSegIterator probe(CRegHead, CRegTail); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 81b1c5ef64..c76df32e3b 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -416,7 +416,10 @@ void ZCCCompiler::CreateStructTypes() for(auto s : Structs) { s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->CType(); - s->strct->Type = NewStruct(s->NodeName(), s->Outer); + if (s->strct->Flags & ZCC_Native) + s->strct->Type = NewNativeStruct(s->NodeName(), nullptr); + else + s->strct->Type = NewStruct(s->NodeName(), s->Outer); s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type()); GlobalSymbols.AddSymbol(s->strct->Symbol); @@ -2568,11 +2571,12 @@ void ZCCCompiler::CompileStates() 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 (sl->bBright) state.StateFlags |= STF_FULLBRIGHT; + if (sl->bFast) state.StateFlags |= STF_FAST; + if (sl->bSlow) state.StateFlags |= STF_SLOW; + if (sl->bCanRaise) state.StateFlags |= STF_CANRAISE; + if (sl->bNoDelay) state.StateFlags |= STF_NODELAY; + if (sl->bNoDelay) { if (statedef.GetStateLabelIndex(NAME_Spawn) != statedef.GetStateCount()) { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 87d2f8759b..61bdf49c82 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -78,7 +78,6 @@ class Actor : Thinker native native bool GiveBody (int num, int max=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); diff --git a/wadsrc/static/zscript/doom/fatso.txt b/wadsrc/static/zscript/doom/fatso.txt index 98bcc3fc9b..3831110c0e 100644 --- a/wadsrc/static/zscript/doom/fatso.txt +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -192,7 +192,7 @@ extend class Actor aimtarget.Height = Height; bool shootmode = ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options - (flags == 0 && isDehState(CurState) && compat_mushroom)); + (flags == 0 && CurState.bDehacked && compat_mushroom)); for (i = -numspawns; i <= numspawns; i += 8) { From 3db712cd730fe0e0f23aa56eec44cd79cb2605e7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 22:20:25 +0100 Subject: [PATCH 328/471] - fixed: Switch statement without a default jumped to the first first case label instead. - removed placeholder code from scripted Marine. --- src/scripting/codegeneration/codegen.cpp | 3 +++ wadsrc/static/zscript/doom/scriptedmarine.txt | 13 ++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 75d49801ff..701b998cab 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -8250,6 +8250,7 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) } size_t DefaultAddress = build->Emit(OP_JMP, 0); TArray BreakAddresses; + bool defaultset = false; for (auto line : Content) { @@ -8270,6 +8271,7 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) else { build->BackpatchToHere(DefaultAddress); + defaultset = true; } break; @@ -8290,6 +8292,7 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) { build->BackpatchToHere(addr); } + if (!defaultset) build->BackpatchToHere(DefaultAddress); Content.Clear(); Content.ShrinkToFit(); return ExpEmit(); diff --git a/wadsrc/static/zscript/doom/scriptedmarine.txt b/wadsrc/static/zscript/doom/scriptedmarine.txt index 1096f24b50..3987bc795f 100644 --- a/wadsrc/static/zscript/doom/scriptedmarine.txt +++ b/wadsrc/static/zscript/doom/scriptedmarine.txt @@ -96,6 +96,7 @@ class ScriptedMarine : Actor PLAY F 6 BRIGHT A_M_FirePistol(1); PLAY A 4 A_FaceTarget; PLAY A 0 A_M_Refire(0, "ShootEnd"); + Goto Fireloop.Pistol; ShootEnd: PLAY A 5; Goto See; @@ -226,18 +227,12 @@ class ScriptedMarine : Actor // //============================================================================ - // placeholder to make it compile for the time being. - SpriteID GetSprite(State st) - { - return SpriteID(0); - } - override void Tick () { Super.Tick (); // Override the standard sprite, if desired - if (SpriteOverride != 0 && sprite == GetSprite(SpawnState)) + if (SpriteOverride != 0 && sprite == SpawnState.sprite) { sprite = SpriteOverride; } @@ -632,14 +627,14 @@ class ScriptedMarine : Actor { if (source == null) { // A valid actor class wasn't passed, so use the standard sprite - SpriteOverride = sprite = GetSprite(SpawnState); + SpriteOverride = sprite = SpawnState.sprite; // Copy the standard scaling Scale = Default.Scale; } else { // Use the same sprite and scaling the passed class spawns with readonly def = GetDefaultByType (source); - SpriteOverride = sprite = GetSprite(def.SpawnState); + SpriteOverride = sprite = def.SpawnState.sprite; Scale = def.Scale; } } From bbb0778fd45423a9f893dce2d4b89dcab3b1fc63 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 22 Nov 2016 12:21:55 +0100 Subject: [PATCH 329/471] - scriptified Chicken and Pig - not tested yet, because other things have priority. --- src/CMakeLists.txt | 2 - src/d_player.h | 3 +- src/g_heretic/a_chicken.cpp | 233 --------------------- src/g_heretic/a_hereticmisc.cpp | 1 - src/g_hexen/a_fighterplayer.cpp | 7 + src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_pig.cpp | 107 ---------- src/p_pspr.cpp | 29 +++ src/p_user.cpp | 12 +- src/scripting/codegeneration/codegen.cpp | 20 +- wadsrc/static/zscript/actor.txt | 3 +- wadsrc/static/zscript/constants.txt | 5 + wadsrc/static/zscript/heretic/chicken.txt | 153 +++++++++++++- wadsrc/static/zscript/hexen/pig.txt | 77 ++++++- wadsrc/static/zscript/shared/inventory.txt | 6 + wadsrc/static/zscript/shared/player.txt | 7 +- 16 files changed, 309 insertions(+), 357 deletions(-) delete mode 100644 src/g_heretic/a_chicken.cpp delete mode 100644 src/g_hexen/a_pig.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 19179a0c4d..c1a14d7037 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -867,7 +867,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.h sc_man_scanner.re g_doom/a_painelemental.cpp - g_heretic/a_chicken.cpp g_heretic/a_dsparil.cpp g_heretic/a_hereticartifacts.cpp g_heretic/a_hereticweaps.cpp @@ -892,7 +891,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_magecone.cpp g_hexen/a_magelightning.cpp g_hexen/a_magestaff.cpp - g_hexen/a_pig.cpp g_hexen/a_serpent.cpp g_hexen/a_spike.cpp g_hexen/a_summon.cpp diff --git a/src/d_player.h b/src/d_player.h index 20a78c9321..d3f6841374 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -100,6 +100,7 @@ FString GetPrintableDisplayName(PClassPlayerPawn *cls); class APlayerPawn : public AActor { DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn) + HAS_FIELDS HAS_OBJECT_POINTERS public: @@ -116,7 +117,7 @@ public: virtual void PlayRunning (); virtual void ThrowPoisonBag (); virtual void TweakSpeeds (double &forwardmove, double &sidemove); - virtual void MorphPlayerThink (); + void MorphPlayerThink (); virtual void ActivateMorphWeapon (); AWeapon *PickNewWeapon (PClassAmmo *ammotype); AWeapon *BestWeapon (PClassAmmo *ammotype); diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp deleted file mode 100644 index 8a109d46dd..0000000000 --- a/src/g_heretic/a_chicken.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "a_pickups.h" -#include "p_local.h" -#include "a_sharedglobal.h" -#include "p_enemy.h" -#include "d_event.h" -#include "gstrings.h" -#include "vm.h" -*/ - -void P_UpdateBeak (AActor *actor); - -static FRandom pr_chickenplayerthink ("ChickenPlayerThink"); -static FRandom pr_chicattack ("ChicAttack"); -static FRandom pr_feathers ("Feathers"); -static FRandom pr_beakatkpl1 ("BeakAtkPL1"); -static FRandom pr_beakatkpl2 ("BeakAtkPL2"); - -class AChickenPlayer : public APlayerPawn -{ - DECLARE_CLASS (AChickenPlayer, APlayerPawn) -public: - void MorphPlayerThink (); -}; - -IMPLEMENT_CLASS(AChickenPlayer, false, false, false, false) - -void AChickenPlayer::MorphPlayerThink () -{ - if (health > 0) - { // Handle beak movement - P_UpdateBeak (this); - } - if (player->morphTics & 15) - { - return; - } - if (Vel.X == 0 && Vel.Y == 0 && pr_chickenplayerthink () < 160) - { // Twitch view angle - Angles.Yaw += pr_chickenplayerthink.Random2() * (360. / 256. / 32.); - } - if ((Z() <= floorz) && (pr_chickenplayerthink() < 32)) - { // Jump and noise - Vel.Z += JumpZ; - - FState * painstate = FindState(NAME_Pain); - if (painstate != NULL) SetState (painstate); - } - if (pr_chickenplayerthink () < 48) - { // Just noise - S_Sound (this, CHAN_VOICE, "chicken/active", 1, ATTN_NORM); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_ChicAttack -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ChicAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->target) - { - return 0; - } - if (self->CheckMeleeRange()) - { - int damage = 1 + (pr_chicattack() & 1); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_Feathers -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_Feathers) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - int count; - AActor *mo; - - if (self->health > 0) - { // Pain - count = pr_feathers() < 32 ? 2 : 1; - } - else - { // Death - count = 5 + (pr_feathers()&3); - } - for (i = 0; i < count; i++) - { - mo = Spawn("Feather", self->PosPlusZ(20.), NO_REPLACE); - mo->target = self; - mo->Vel.X = pr_feathers.Random2() / 256.; - mo->Vel.Y = pr_feathers.Random2() / 256.; - mo->Vel.Z = 1. + pr_feathers() / 128.; - mo->SetState (mo->SpawnState + (pr_feathers()&7)); - } - return 0; -} - -//--------------------------------------------------------------------------- -// -// PROC P_UpdateBeak -// -//--------------------------------------------------------------------------- - -void P_UpdateBeak (AActor *self) -{ - DPSprite *pspr; - if (self->player != nullptr && (pspr = self->player->FindPSprite(PSP_WEAPON)) != nullptr) - { - pspr->y = WEAPONTOP + self->player->chickenPeck / 2; - } -} - -//--------------------------------------------------------------------------- -// -// PROC A_BeakRaise -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_BeakRaise) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - player->GetPSprite(PSP_WEAPON)->y = WEAPONTOP; - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetReadyState()); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayPeck -// -//---------------------------------------------------------------------------- - -void P_PlayPeck (AActor *chicken) -{ - S_Sound (chicken, CHAN_VOICE, "chicken/peck", 1, ATTN_NORM); -} - -//---------------------------------------------------------------------------- -// -// PROC A_BeakAttackPL1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - DAngle slope; - player_t *player; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - - damage = 1 + (pr_beakatkpl1()&3); - angle = player->mo->Angles.Yaw; - slope = P_AimLineAttack (player->mo, angle, MELEERANGE); - P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t); - if (t.linetarget) - { - player->mo->Angles.Yaw = t.angleFromSource; - } - P_PlayPeck (player->mo); - player->chickenPeck = 12; - player->GetPSprite(PSP_WEAPON)->Tics -= pr_beakatkpl1() & 7; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_BeakAttackPL2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - DAngle slope; - player_t *player; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - - damage = pr_beakatkpl2.HitDice (4); - angle = player->mo->Angles.Yaw; - slope = P_AimLineAttack (player->mo, angle, MELEERANGE); - P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t); - if (t.linetarget) - { - player->mo->Angles.Yaw = t.angleFromSource; - } - P_PlayPeck (player->mo); - player->chickenPeck = 12; - player->GetPSprite(PSP_WEAPON)->Tics -= pr_beakatkpl2()&3; - return 0; -} diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 64de3ef843..5aa048977a 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -19,7 +19,6 @@ #include "serializer.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_hereticweaps.cpp" diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index 7e1502a1cb..afdbe8a90f 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -49,6 +49,13 @@ void AdjustPlayerAngle (AActor *pmo, FTranslatedLineTarget *t) } } +DEFINE_ACTION_FUNCTION(AActor, AdjustPlayerAngle) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER(t, FTranslatedLineTarget); + AdjustPlayerAngle(self, t); + return 0; +} //============================================================================ // // TryPunch diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index c87c9e46d3..f98305cbaf 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -45,7 +45,6 @@ #include "a_magecone.cpp" #include "a_magelightning.cpp" #include "a_magestaff.cpp" -#include "a_pig.cpp" #include "a_serpent.cpp" #include "a_spike.cpp" #include "a_summon.cpp" diff --git a/src/g_hexen/a_pig.cpp b/src/g_hexen/a_pig.cpp deleted file mode 100644 index 41054da001..0000000000 --- a/src/g_hexen/a_pig.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "a_pickups.h" -#include "p_local.h" -#include "a_sharedglobal.h" -#include "p_enemy.h" -#include "d_event.h" -#include "gstrings.h" -#include "vm.h" -*/ - -static FRandom pr_snoutattack ("SnoutAttack"); -static FRandom pr_pigattack ("PigAttack"); -static FRandom pr_pigplayerthink ("PigPlayerThink"); - -// Pig player --------------------------------------------------------------- - -class APigPlayer : public APlayerPawn -{ - DECLARE_CLASS (APigPlayer, APlayerPawn) -public: - void MorphPlayerThink (); -}; - -IMPLEMENT_CLASS(APigPlayer, false, false, false, false) - -void APigPlayer::MorphPlayerThink () -{ - if (player->morphTics & 15) - { - return; - } - if(Vel.X == 0 && Vel.Y == 0 && pr_pigplayerthink() < 64) - { // Snout sniff - if (player->ReadyWeapon != nullptr) - { - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState("Grunt")); - } - S_Sound (this, CHAN_VOICE, "PigActive1", 1, ATTN_NORM); // snort - return; - } - if (pr_pigplayerthink() < 48) - { - S_Sound (this, CHAN_VOICE, "PigActive", 1, ATTN_NORM); - } -} - -//============================================================================ -// -// A_SnoutAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - DAngle slope; - player_t *player; - AActor *puff; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - - damage = 3+(pr_snoutattack()&3); - angle = player->mo->Angles.Yaw; - slope = P_AimLineAttack(player->mo, angle, MELEERANGE); - puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "SnoutPuff", true, &t); - S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM); - if(t.linetarget) - { - AdjustPlayerAngle(player->mo, &t); - if(puff != NULL) - { // Bit something - S_Sound(player->mo, CHAN_VOICE, "PigAttack", 1, ATTN_NORM); - } - } - return 0; -} - -//============================================================================ -// -// A_PigPain -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_PigPain) -{ - PARAM_SELF_PROLOGUE(AActor); - - CALL_ACTION(A_Pain, self); - if (self->Z() <= self->floorz) - { - self->Vel.Z = 3.5; - } - return 0; -} diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 157badd879..b5f5691089 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -109,8 +109,29 @@ IMPLEMENT_POINTERS_END void DPSprite::InitNativeFields() { auto meta = RUNTIME_CLASS(DPSprite); + PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); + PType *TypePSP = NewPointer(RUNTIME_CLASS(DPSprite)); + PType *TypePlayer = NewPointer(NewNativeStruct("Player", nullptr)); meta->AddNativeField("State", TypeState, myoffsetof(DPSprite, State), VARF_ReadOnly); + meta->AddNativeField("Caller", TypeActor, myoffsetof(DPSprite, Caller), VARF_ReadOnly); + meta->AddNativeField("Next", TypePSP, myoffsetof(DPSprite, Next), VARF_ReadOnly); + meta->AddNativeField("Owner", TypePlayer, myoffsetof(DPSprite, Owner), VARF_ReadOnly); + meta->AddNativeField("Sprite", TypeSpriteID, myoffsetof(DPSprite, Sprite)); + meta->AddNativeField("Frame", TypeSInt32, myoffsetof(DPSprite, Frame)); + meta->AddNativeField("ID", TypePlayer, myoffsetof(DPSprite, ID), VARF_ReadOnly); + meta->AddNativeField("processPending", TypeBool, myoffsetof(DPSprite, processPending)); + meta->AddNativeField("x", TypeFloat64, myoffsetof(DPSprite, x)); + meta->AddNativeField("y", TypeFloat64, myoffsetof(DPSprite, y)); + meta->AddNativeField("oldx", TypeFloat64, myoffsetof(DPSprite, oldx)); + meta->AddNativeField("oldy", TypeFloat64, myoffsetof(DPSprite, oldy)); + meta->AddNativeField("firstTic", TypeBool, myoffsetof(DPSprite, firstTic)); + meta->AddNativeField("Tics", TypeSInt32, myoffsetof(DPSprite, Tics)); + meta->AddNativeField("bAddWeapon", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_ADDWEAPON); + meta->AddNativeField("bAddBob", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_ADDBOB); + meta->AddNativeField("bPowDouble", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_POWDOUBLE); + meta->AddNativeField("bCVarFast", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_CVARFAST); + meta->AddNativeField("bFlip", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_FLIP); } //------------------------------------------------------------------------ @@ -179,6 +200,14 @@ DPSprite *player_t::FindPSprite(int layer) return pspr; } +DEFINE_ACTION_FUNCTION(_Player, FindPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_INT(id); + ACTION_RETURN_OBJECT(self->FindPSprite((PSPLayers)id)); +} + + //------------------------------------------------------------------------ // // diff --git a/src/p_user.cpp b/src/p_user.cpp index 6d34037f1e..84fcbd313c 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -161,6 +161,12 @@ bool ValidatePlayerClass(PClassActor *ti, const char *name) return true; } +void APlayerPawn::InitNativeFields() +{ + auto meta = RUNTIME_CLASS(APlayerPawn); + meta->AddNativeField("JumpZ", TypeFloat64, myoffsetof(APlayerPawn, JumpZ)); +} + void SetupPlayerClasses () { FPlayerClass newclass; @@ -622,7 +628,7 @@ void player_t::SendPitchLimits() const // //=========================================================================== -IMPLEMENT_CLASS(APlayerPawn, false, true, false, true) +IMPLEMENT_CLASS(APlayerPawn, false, true, true, true) IMPLEMENT_POINTERS_START(APlayerPawn) IMPLEMENT_POINTER(InvFirst) @@ -1381,6 +1387,10 @@ void APlayerPawn::GiveDefaultInventory () void APlayerPawn::MorphPlayerThink () { + VINDEX(APlayerPawn, MorphPlayerThink); + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); } void APlayerPawn::ActivateMorphWeapon () diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 701b998cab..3f8f09eb78 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2543,7 +2543,15 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) return nullptr; } - if (left->IsVector() && right->IsVector()) + if (left->ValueType == TypeState && right->IsInteger() && Operator == '+' && !left->isConstant()) + { + // This is the only special case of pointer addition that will be accepted - because it is used quite often in the existing game code. + ValueType = TypeState; + right = new FxMulDiv('*', right, new FxConstant((int)sizeof(FState), ScriptPosition)); // multiply by size here, so that constants can be better optimized. + right = right->Resolve(ctx); + ABORT(right); + } + else if (left->IsVector() && right->IsVector()) { // 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)) @@ -2616,6 +2624,16 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) ExpEmit op2 = right->Emit(build); if (Operator == '+') { + if (op1.RegType == REGT_POINTER) + { + assert(!op1.Konst); + assert(op2.RegType == REGT_INT); + op1.Free(build); + op2.Free(build); + ExpEmit opout(build, REGT_POINTER); + build->Emit(op2.Konst? OP_ADDA_RK : OP_ADDA_RR, opout.RegNum, op1.RegNum, op2.RegNum); + return opout; + } // Since addition is commutative, only the second operand may be a constant. if (op1.Konst) { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 61bdf49c82..db86647c39 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -67,6 +67,7 @@ class Actor : Thinker native virtual native void Activate(Actor activator); virtual native void Deactivate(Actor activator); + native void AdjustPlayerAngle(FTranslatedLineTarget t); native static readonly GetDefaultByType(class cls); native static double deltaangle(double ang1, double ang2); native static double absangle(double ang1, double ang2); @@ -467,7 +468,6 @@ class Actor : Thinker native native void A_DeQueueCorpse(); native void A_ClearLastHeard(); native bool A_SelectWeapon(class whichweapon, int flags = 0); - native void A_Feathers(); native void A_ClassBossHealth(); native void A_ShootGun(); native void A_RocketInFlight(); @@ -476,7 +476,6 @@ class Actor : Thinker native 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(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 29c60450c2..b5b60481aa 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -948,3 +948,8 @@ enum EFSkillProperty // floating point properties SKILLP_FriendlyHealth, }; +enum EWeaponPos +{ + WEAPONBOTTOM = 128, + WEAPONTOP = 32 +} \ No newline at end of file diff --git a/wadsrc/static/zscript/heretic/chicken.txt b/wadsrc/static/zscript/heretic/chicken.txt index 2e5ada81c8..5d6065f66a 100644 --- a/wadsrc/static/zscript/heretic/chicken.txt +++ b/wadsrc/static/zscript/heretic/chicken.txt @@ -26,8 +26,6 @@ class Beak : Weapon Weapon.SisterWeapon "BeakPowered"; } - action native void A_BeakRaise (); - action native void A_BeakAttackPL1(); States { @@ -44,9 +42,56 @@ class Beak : Weapon BEAK A 18 A_BeakAttackPL1; Goto Ready; } + + //--------------------------------------------------------------------------- + // + // PROC A_BeakRaise + // + //--------------------------------------------------------------------------- + + action void A_BeakRaise () + { + + if (player == null) + { + return; + } + player.GetPSprite(PSP_WEAPON).y = WEAPONTOP; + player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.GetReadyState()); + } + + //---------------------------------------------------------------------------- + // + // PROC A_BeakAttackPL1 + // + //---------------------------------------------------------------------------- + + action void A_BeakAttackPL1() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + int damage = random[BeakAtk](1,3); + double ang = angle; + double slope = AimLineAttack (ang, MELEERANGE); + LineAttack (ang, MELEERANGE, slope, damage, 'Melee', "BeakPuff", true, t); + if (t.linetarget) + { + angle = t.angleFromSource; + } + A_PlaySound ("chicken/peck", CHAN_VOICE); + player.chickenPeck = 12; + player.GetPSprite(PSP_WEAPON).Tics -= random[BeakAtk](0,7); + } } +// BeakPowered --------------------------------------------------------------------- + class BeakPowered : Beak { Default @@ -55,7 +100,6 @@ class BeakPowered : Beak Weapon.SisterWeapon "Beak"; } - action native void A_BeakAttackPL2(); States { @@ -63,11 +107,40 @@ class BeakPowered : Beak BEAK A 12 A_BeakAttackPL2; Goto Ready; } + + //---------------------------------------------------------------------------- + // + // PROC A_BeakAttackPL2 + // + //---------------------------------------------------------------------------- + + action void A_BeakAttackPL2() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + int damage = random[BeakAtk](1,8) * 4; + double ang = angle; + double slope = AimLineAttack (ang, MELEERANGE); + LineAttack (ang, MELEERANGE, slope, damage, 'Melee', "BeakPuff", true, t); + if (t.linetarget) + { + angle = t.angleFromSource; + } + A_PlaySound ("chicken/peck", CHAN_VOICE); + player.chickenPeck = 12; + player.GetPSprite(PSP_WEAPON).Tics -= random[BeakAtk](0,3); + } + } // Chicken player ----------------------------------------------------------- -class ChickenPlayer : PlayerPawn native +class ChickenPlayer : PlayerPawn { Default { @@ -118,6 +191,44 @@ class ChickenPlayer : PlayerPawn native CHKN L -1; Stop; } + + //--------------------------------------------------------------------------- + // + // PROC P_UpdateBeak + // + //--------------------------------------------------------------------------- + + override void MorphPlayerThink () + { + if (health > 0) + { // Handle beak movement + PSprite pspr; + if (player != null && (pspr = player.FindPSprite(PSP_WEAPON)) != null) + { + pspr.y = WEAPONTOP + player.chickenPeck / 2; + } + } + if (player.morphTics & 15) + { + return; + } + if (Vel.X == 0 && Vel.Y == 0 && random[ChickenPlayerThink]() < 160) + { // Twitch view ang + angle += Random2[ChickenPlayerThink]() * (360. / 256. / 32.); + } + if ((pos.z <= floorz) && (random[ChickenPlayerThink]() < 32)) + { // Jump and noise + Vel.Z += JumpZ; + + State painstate = FindState('Pain'); + if (painstate != null) SetState (painstate); + } + if (random[ChickenPlayerThink]() < 48) + { // Just noise + A_PlaySound ("chicken/active", CHAN_VOICE); + } + } + } @@ -199,3 +310,37 @@ class Feather : Actor } } +extend class Actor +{ + //---------------------------------------------------------------------------- + // + // PROC A_Feathers + // This is used by both the chicken player and monster and must be in the + // common base class to be accessible by both + // + //---------------------------------------------------------------------------- + + void A_Feathers() + { + int count; + + if (health > 0) + { // Pain + count = random[Feathers]() < 32 ? 2 : 1; + } + else + { // Death + count = 5 + (random[Feathers]()&3); + } + for (int i = 0; i < count; i++) + { + Actor mo = Spawn("Feather", pos + (0, 0, 20), NO_REPLACE); + mo.target = self; + mo.Vel.X = Random2[Feathers]() / 256.; + mo.Vel.Y = Random2[Feathers]() / 256.; + mo.Vel.Z = 1. + random[Feathers]() / 128.; + mo.SetState (mo.SpawnState + (random[Feathers]()&7)); + } + } + +} \ No newline at end of file diff --git a/wadsrc/static/zscript/hexen/pig.txt b/wadsrc/static/zscript/hexen/pig.txt index 8fa4468827..9f62e661ea 100644 --- a/wadsrc/static/zscript/hexen/pig.txt +++ b/wadsrc/static/zscript/hexen/pig.txt @@ -34,8 +34,6 @@ class Snout : Weapon Weapon.YAdjust 10; } - action native void A_SnoutAttack (); - States { Ready: @@ -54,12 +52,43 @@ class Snout : Weapon WPIG B 8; Goto Ready; } + + //============================================================================ + // + // A_SnoutAttack + // + //============================================================================ + + action void A_SnoutAttack () + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + int damage = random[SnoutAttack](3, 6); + double ang = angle; + double slope = AimLineAttack(ang, MELEERANGE); + Actor puff = LineAttack(ang, MELEERANGE, slope, damage, 'Melee', "SnoutPuff", true, t); + A_PlaySound("PigActive", CHAN_VOICE); + if(t.linetarget) + { + AdjustPlayerAngle(t); + if(puff != null) + { // Bit something + A_PlaySound("PigAttack", CHAN_VOICE); + } + } + } + } // Pig player --------------------------------------------------------------- -class PigPlayer : PlayerPawn native +class PigPlayer : PlayerPawn { Default { @@ -112,6 +141,30 @@ class PigPlayer : PlayerPawn native PIGY M 1 A_FreezeDeathChunks; Wait; } + + + override void MorphPlayerThink () + { + if (player.morphTics & 15) + { + return; + } + if(Vel.X == 0 && Vel.Y == 0 && random[PigPlayerThink]() < 64) + { // Snout sniff + if (player.ReadyWeapon != null) + { + player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.FindState('Grunt')); + } + A_PlaySound ("PigActive1", CHAN_VOICE); // snort + return; + } + if (random[PigPlayerThink]() < 48) + { + A_PlaySound ("PigActive", CHAN_VOICE); // snort + } + } + + } @@ -168,3 +221,21 @@ class Pig : MorphedMonster } } + +extend class Actor +{ + //============================================================================ + // + // A_PigPain + // + //============================================================================ + + void A_PigPain () + { + A_Pain(); + if (pos.z <= floorz) + { + Vel.Z = 3.5; + } + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index f906ca01c5..2a9aabe272 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -457,6 +457,12 @@ class Weapon : StateProvider native native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); + virtual State GetReadyState () + { + return FindState('Ready'); + } + + native action void A_ZoomFactor(double scale = 1, int flags = 0); native action void A_SetCrosshair(int xhair); const ZOOM_INSTANT = 1; diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index c8485cebde..4f9e843331 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -49,6 +49,10 @@ class PlayerPawn : Actor native if (MeleeState != null) SetState (MeleeState); } + virtual void MorphPlayerThink() + { + } + } class PlayerChunk : PlayerPawn native @@ -78,4 +82,5 @@ struct Player native native void SetPsprite(int id, State stat, bool pending = false); native void SetSafeFlash(Weapon weap, State flashstate, int index); native PSprite GetPSprite(int id); -} \ No newline at end of file + native PSprite FindPSprite(int id); +} From 03a02a2036203d766f8d97f38b4bda477d955691 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 22 Nov 2016 12:28:11 +0100 Subject: [PATCH 330/471] - updated copyrights in a few files. --- src/scripting/decorate/thingdef_exp.cpp | 1 + src/scripting/decorate/thingdef_parse.cpp | 4 ++-- src/scripting/decorate/thingdef_states.cpp | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index e7d217609a..a0ab095100 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -5,6 +5,7 @@ ** **--------------------------------------------------------------------------- ** Copyright 2005 Jan Cholasta +** Copyright 2005-2016 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 490d9cf799..442e52884f 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -4,8 +4,8 @@ ** Actor definitions - all parser related code ** **--------------------------------------------------------------------------- -** Copyright 2002-2007 Christoph Oelckers -** Copyright 2004-2007 Randy Heit +** Copyright 2002-2016 Christoph Oelckers +** Copyright 2004-2016 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 4f60b85854..3b4abe002e 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -4,8 +4,8 @@ ** Actor definitions - the state parser ** **--------------------------------------------------------------------------- -** Copyright 2002-2007 Christoph Oelckers -** Copyright 2004-2007 Randy Heit +** Copyright 2002-2016 Christoph Oelckers +** Copyright 2004-2016 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -132,7 +132,7 @@ static FString ParseStateString(FScanner &sc) } //========================================================================== -//*** +// // ParseStates // parses a state block // From ab5c11064afd46536345b9dde6243a13e706d0ea Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 22 Nov 2016 13:03:46 +0100 Subject: [PATCH 331/471] - added a few missing tildes. --- src/d_dehacked.cpp | 2 +- src/p_states.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 508821fd80..2e8c56f05c 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1475,7 +1475,7 @@ static int PatchFrame (int frameNum) info->Misc1 = misc1; info->Frame = frame & 0x3f; if (frame & 0x8000) info->StateFlags |= STF_FULLBRIGHT; - else info->StateFlags &= STF_FULLBRIGHT; + else info->StateFlags &= ~STF_FULLBRIGHT; } return result; diff --git a/src/p_states.cpp b/src/p_states.cpp index 5444bcc3ad..6e45db6b0e 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -938,13 +938,13 @@ int FStateDefinitions::AddStates(FState *state, const char *framechars, const FS state->Frame = frame; if (noframe) state->StateFlags |= STF_SAMEFRAME; - else state->StateFlags &= STF_SAMEFRAME; + else state->StateFlags &= ~STF_SAMEFRAME; StateArray.Push(*state); SourceLines.Push(sc); ++count; // NODELAY flag is not carried past the first state - state->StateFlags &= STF_NODELAY; + state->StateFlags &= ~STF_NODELAY; } laststate = &StateArray[StateArray.Size() - 1]; laststatebeforelabel = laststate; From 980c9863058c8ab1d0894f9525676440073c2572 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 22 Nov 2016 19:20:31 +0100 Subject: [PATCH 332/471] - allow defining native fields through scripts. Internally this only requires exporting the address, but not the entire field. - added new VARF_Transient flag so that the decision whether to serialize a field does not depend solely on its native status. It may actually make a lot of sense to use the auto-serializer for native fields, too, as this would eliminate a lot of maintenance code. - defined (u)int8/16 as aliases to the byte and short types (Can't we not just get rid of this naming convention already...?) - exporting the fields of Actor revealed a few name clashes between them and some global types, so Actor.Sector was renamed to CurSector and Actor.Inventory was renamed to Actor.Inv. --- src/__autostart.cpp | 6 +- src/autosegs.h | 4 + src/dobjtype.cpp | 22 +- src/dobjtype.h | 7 +- src/namedef.h | 4 + src/p_mobj.cpp | 317 +++++++++++------------ src/p_pspr.cpp | 8 +- src/p_user.cpp | 2 +- src/sc_man_scanner.re | 4 + src/sc_man_tokens.h | 4 + src/scripting/codegeneration/codegen.cpp | 23 +- src/scripting/thingdef.h | 1 + src/scripting/thingdef_data.cpp | 55 ++++ src/scripting/vm/vm.h | 40 +++ src/scripting/zscript/zcc_compile.cpp | 43 ++- src/scripting/zscript/zcc_compile.h | 2 +- src/scripting/zscript/zcc_parser.cpp | 4 + src/zzautozend.cpp | 4 + wadsrc/static/zscript/actor.txt | 162 ++++++++++++ wadsrc/static/zscript/base.txt | 6 +- wadsrc/static/zscript/doom/bossbrain.txt | 2 +- wadsrc/static/zscript/shared/player.txt | 2 +- 22 files changed, 520 insertions(+), 202 deletions(-) diff --git a/src/__autostart.cpp b/src/__autostart.cpp index 280c3b13d3..3daabbeae3 100644 --- a/src/__autostart.cpp +++ b/src/__autostart.cpp @@ -53,7 +53,7 @@ // for initialized read-only data.) #pragma comment(linker, "/merge:.areg=.rdata /merge:.creg=.rdata /merge:.greg=.rdata") -#pragma comment(linker, "/merge:.yreg=.rdata") +#pragma comment(linker, "/merge:.yreg=.rdata /merge:.freg=.rdata") #pragma section(".areg$a",read) __declspec(allocate(".areg$a")) void *const ARegHead = 0; @@ -64,6 +64,9 @@ __declspec(allocate(".creg$a")) void *const CRegHead = 0; #pragma section(".greg$a",read) __declspec(allocate(".greg$a")) void *const GRegHead = 0; +#pragma section(".freg$a",read) +__declspec(allocate(".freg$a")) void *const FRegHead = 0; + #pragma section(".yreg$a",read) __declspec(allocate(".yreg$a")) void *const YRegHead = 0; @@ -97,6 +100,7 @@ __declspec(allocate(".yreg$a")) void *const YRegHead = 0; void *const ARegHead __attribute__((section(SECTION_AREG))) = 0; void *const CRegHead __attribute__((section(SECTION_CREG))) = 0; +void *const FRegHead __attribute__((section(SECTION_FREG))) = 0; void *const GRegHead __attribute__((section(SECTION_GREG))) = 0; void *const YRegHead __attribute__((section(SECTION_YREG))) = 0; diff --git a/src/autosegs.h b/src/autosegs.h index 08abe7cd31..f38e3628e9 100644 --- a/src/autosegs.h +++ b/src/autosegs.h @@ -49,6 +49,10 @@ extern REGINFO ARegTail; extern REGINFO CRegHead; extern REGINFO CRegTail; +// List of class fields +extern REGINFO FRegHead; +extern REGINFO FRegTail; + // List of properties extern REGINFO GRegHead; extern REGINFO GRegTail; diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 420dbc515b..5afb8a5789 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -613,8 +613,8 @@ void PType::StaticInit() 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)); + // allow accessing xy as a vector2. This is not supposed to be serialized so it's marked transient + TypeVector3->Symbols.AddSymbol(new PField(NAME_XY, TypeVector2, VARF_Transient, 0)); TypeTable.AddType(TypeVector3); TypeVector3->loadOp = OP_LV3; TypeVector3->storeOp = OP_SV3; @@ -2240,7 +2240,7 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArrayFlags & VARF_Native)) + if (!(field->Flags & VARF_Transient)) { field->Type->SetDefaultValue(base, unsigned(offset + field->Offset), special); } @@ -2257,7 +2257,7 @@ void PStruct::SetPointer(void *base, unsigned offset, TArray *special) c { for (const PField *field : Fields) { - if (!(field->Flags & VARF_Native)) + if (!(field->Flags & VARF_Transient)) { field->Type->SetPointer(base, unsigned(offset + field->Offset), special); } @@ -2307,8 +2307,8 @@ void PStruct::WriteFields(FSerializer &ar, const void *addr, const TArrayFlags & VARF_Native)) + // Skip fields without or with native serialization + if (!(field->Flags & VARF_Transient)) { field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const BYTE *)addr + field->Offset); } @@ -2394,7 +2394,7 @@ PField *PStruct::AddField(FName name, PType *type, DWORD flags) 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); + PField *field = new PField(name, type, flags|VARF_Native|VARF_Transient, address, bitvalue); if (Symbols.AddSymbol(field) == nullptr) { // name is already in use @@ -2495,8 +2495,7 @@ 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) + if (bitvalue != 0) { BitValue = 0; unsigned val = bitvalue; @@ -2519,6 +2518,7 @@ PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue I_FatalError("Trying to create an invalid bit field element: %s", name.GetChars()); } } + else BitValue = -1; } /* PPrototype *************************************************************/ @@ -2692,10 +2692,10 @@ static void RecurseWriteFields(const PClass *type, FSerializer &ar, const void * if (type != NULL) { RecurseWriteFields(type->ParentClass, ar, addr); - // Don't write this part if it has no non-native variables + // Don't write this part if it has no non-transient variables for (unsigned i = 0; i < type->Fields.Size(); ++i) { - if (!(type->Fields[i]->Flags & VARF_Native)) + if (!(type->Fields[i]->Flags & VARF_Transient)) { // Tag this section with the class it came from in case // a more-derived class has variables that shadow a less- diff --git a/src/dobjtype.h b/src/dobjtype.h index f464e36f87..76d6e75858 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -19,7 +19,7 @@ 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_Native = (1<<3), // func is native code, field is natively defined 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. @@ -33,6 +33,7 @@ enum VARF_InternalAccess = (1<<14), // overrides VARF_ReadOnly for internal script code. VARF_Override = (1<<15), // overrides a virtual function from the parent class. VARF_Ref = (1<<16), // argument is passed by reference. + VARF_Transient = (1<<17) // don't auto serialize field. }; // Symbol information ------------------------------------------------------- @@ -610,7 +611,7 @@ class PField : public PSymbol DECLARE_CLASS(PField, PSymbol); HAS_OBJECT_POINTERS public: - PField(FName name, PType *type, DWORD flags = 0, size_t offset = 0, int bitvalue = -1); + PField(FName name, PType *type, DWORD flags = 0, size_t offset = 0, int bitvalue = 0); size_t Offset; PType *Type; @@ -700,7 +701,7 @@ public: 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); + virtual PField *AddNativeField(FName name, PType *type, size_t address, DWORD flags = 0, int bitvalue = 0); size_t PropagateMark(); diff --git a/src/namedef.h b/src/namedef.h index 5ee98119a4..545bf02604 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -695,6 +695,10 @@ xx(uShort) xx(Int) xx(uInt) xx(Bool) +xx(uint8) +xx(int8) +xx(uint16) +xx(int16) xx(Float) xx(Float32) xx(Float64) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b7da3e2c54..1813996554 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -156,171 +156,166 @@ AActor::~AActor () extern FFlagDef InternalActorFlagDefs[]; extern FFlagDef ActorFlagDefs[]; +DEFINE_FIELD(AActor, player) +DEFINE_FIELD_NAMED(AActor, __Pos, pos) +DEFINE_FIELD_NAMED(AActor, __Pos.X, x) +DEFINE_FIELD_NAMED(AActor, __Pos.Y, y) +DEFINE_FIELD_NAMED(AActor, __Pos.Z, z) +DEFINE_FIELD(AActor, Prev) +DEFINE_FIELD(AActor, SpriteAngle) +DEFINE_FIELD(AActor, SpriteRotation) +DEFINE_FIELD(AActor, VisibleStartAngle) +DEFINE_FIELD(AActor, VisibleStartPitch) +DEFINE_FIELD(AActor, VisibleEndAngle) +DEFINE_FIELD(AActor, VisibleEndPitch) +DEFINE_FIELD_NAMED(AActor, Angles.Yaw, angle) +DEFINE_FIELD_NAMED(AActor, Angles.Pitch, pitch) +DEFINE_FIELD_NAMED(AActor, Angles.Roll, roll) +DEFINE_FIELD(AActor, Vel) +DEFINE_FIELD_NAMED(AActor, Vel.X, velx) +DEFINE_FIELD_NAMED(AActor, Vel.Y, vely) +DEFINE_FIELD_NAMED(AActor, Vel.Z, velz) +DEFINE_FIELD_NAMED(AActor, Vel.X, momx) +DEFINE_FIELD_NAMED(AActor, Vel.Y, momy) +DEFINE_FIELD_NAMED(AActor, Vel.Z, momz) +DEFINE_FIELD(AActor, Speed) +DEFINE_FIELD(AActor, FloatSpeed) +DEFINE_FIELD(AActor, sprite) +DEFINE_FIELD(AActor, frame) +DEFINE_FIELD(AActor, Scale) +DEFINE_FIELD_NAMED(AActor, Scale.X, scalex) +DEFINE_FIELD_NAMED(AActor, Scale.Y, scaley) +DEFINE_FIELD(AActor, RenderStyle) +DEFINE_FIELD(AActor, picnum) +DEFINE_FIELD(AActor, Alpha) +DEFINE_FIELD(AActor, fillcolor) +DEFINE_FIELD_NAMED(AActor, Sector, CurSector) // clashes with type 'sector'. +DEFINE_FIELD(AActor, subsector) +DEFINE_FIELD(AActor, ceilingz) +DEFINE_FIELD(AActor, floorz) +DEFINE_FIELD(AActor, dropoffz) +DEFINE_FIELD(AActor, floorsector) +DEFINE_FIELD(AActor, floorpic) +DEFINE_FIELD(AActor, floorterrain) +DEFINE_FIELD(AActor, ceilingsector) +DEFINE_FIELD(AActor, ceilingpic) +DEFINE_FIELD(AActor, Height) +DEFINE_FIELD(AActor, radius) +DEFINE_FIELD(AActor, projectilepassheight) +DEFINE_FIELD(AActor, tics) +DEFINE_FIELD_NAMED(AActor, state, curstate) // clashes with type 'state'. +DEFINE_FIELD_NAMED(AActor, DamageVal, Damage) // name differs for historic reasons +DEFINE_FIELD(AActor, projectileKickback) +DEFINE_FIELD(AActor, VisibleToTeam) +DEFINE_FIELD(AActor, special1) +DEFINE_FIELD(AActor, special2) +DEFINE_FIELD(AActor, specialf1) +DEFINE_FIELD(AActor, specialf2) +DEFINE_FIELD(AActor, weaponspecial) +DEFINE_FIELD(AActor, health) +DEFINE_FIELD(AActor, movedir) +DEFINE_FIELD(AActor, visdir) +DEFINE_FIELD(AActor, movecount) +DEFINE_FIELD(AActor, strafecount) +DEFINE_FIELD(AActor, target) +DEFINE_FIELD(AActor, master) +DEFINE_FIELD(AActor, tracer) +DEFINE_FIELD(AActor, LastHeard) +DEFINE_FIELD(AActor, lastenemy) +DEFINE_FIELD(AActor, LastLookActor) +DEFINE_FIELD(AActor, reactiontime) +DEFINE_FIELD(AActor, threshold) +DEFINE_FIELD(AActor, DefThreshold) +DEFINE_FIELD(AActor, SpawnPoint) +DEFINE_FIELD(AActor, SpawnAngle) +DEFINE_FIELD(AActor, StartHealth) +DEFINE_FIELD(AActor, WeaveIndexXY) +DEFINE_FIELD(AActor, WeaveIndexZ) +DEFINE_FIELD(AActor, skillrespawncount) +DEFINE_FIELD(AActor, args) +DEFINE_FIELD(AActor, Mass) +DEFINE_FIELD(AActor, special) +DEFINE_FIELD(AActor, tid) +DEFINE_FIELD(AActor, TIDtoHate) +DEFINE_FIELD(AActor, waterlevel) +DEFINE_FIELD(AActor, Score) +DEFINE_FIELD(AActor, accuracy) +DEFINE_FIELD(AActor, stamina) +DEFINE_FIELD(AActor, meleerange) +DEFINE_FIELD(AActor, PainThreshold) +DEFINE_FIELD(AActor, Gravity) +DEFINE_FIELD(AActor, Floorclip) +DEFINE_FIELD(AActor, DamageType) +DEFINE_FIELD(AActor, DamageTypeReceived) +DEFINE_FIELD(AActor, FloatBobPhase) +DEFINE_FIELD(AActor, RipperLevel) +DEFINE_FIELD(AActor, RipLevelMin) +DEFINE_FIELD(AActor, RipLevelMax) +DEFINE_FIELD(AActor, Species) +DEFINE_FIELD(AActor, alternative) +DEFINE_FIELD(AActor, goal) +DEFINE_FIELD(AActor, MinMissileChance) +DEFINE_FIELD(AActor, LastLookPlayerNumber) +DEFINE_FIELD(AActor, SpawnFlags) +DEFINE_FIELD(AActor, meleethreshold) +DEFINE_FIELD(AActor, maxtargetrange) +DEFINE_FIELD(AActor, bouncefactor) +DEFINE_FIELD(AActor, wallbouncefactor) +DEFINE_FIELD(AActor, bouncecount) +DEFINE_FIELD(AActor, Friction) +DEFINE_FIELD(AActor, FastChaseStrafeCount) +DEFINE_FIELD(AActor, pushfactor) +DEFINE_FIELD(AActor, lastpush) +DEFINE_FIELD(AActor, activationtype) +DEFINE_FIELD(AActor, lastbump) +DEFINE_FIELD(AActor, DesignatedTeam) +DEFINE_FIELD(AActor, BlockingMobj) +DEFINE_FIELD(AActor, BlockingLine) +DEFINE_FIELD(AActor, PoisonDamage) +DEFINE_FIELD(AActor, PoisonDamageType) +DEFINE_FIELD(AActor, PoisonDuration) +DEFINE_FIELD(AActor, PoisonPeriod) +DEFINE_FIELD(AActor, PoisonDamageReceived) +DEFINE_FIELD(AActor, PoisonDamageTypeReceived) +DEFINE_FIELD(AActor, PoisonDurationReceived) +DEFINE_FIELD(AActor, PoisonPeriodReceived) +DEFINE_FIELD(AActor, Poisoner) +DEFINE_FIELD_NAMED(AActor, Inventory, Inv) // clashes with type 'Inventory'. +DEFINE_FIELD(AActor, smokecounter) +DEFINE_FIELD(AActor, FriendPlayer) +DEFINE_FIELD(AActor, Translation) +DEFINE_FIELD(AActor, AttackSound) +DEFINE_FIELD(AActor, DeathSound) +DEFINE_FIELD(AActor, SeeSound) +DEFINE_FIELD(AActor, PainSound) +DEFINE_FIELD(AActor, ActiveSound) +DEFINE_FIELD(AActor, UseSound) +DEFINE_FIELD(AActor, BounceSound) +DEFINE_FIELD(AActor, WallBounceSound) +DEFINE_FIELD(AActor, CrushPainSound) +DEFINE_FIELD(AActor, MaxDropOffHeight) +DEFINE_FIELD(AActor, MaxStepHeight) +DEFINE_FIELD(AActor, PainChance) +DEFINE_FIELD(AActor, PainType) +DEFINE_FIELD(AActor, DeathType) +DEFINE_FIELD(AActor, DamageFactor) +DEFINE_FIELD(AActor, DamageMultiply) +DEFINE_FIELD(AActor, TeleFogSourceType) +DEFINE_FIELD(AActor, TeleFogDestType) +DEFINE_FIELD(AActor, SpawnState) +DEFINE_FIELD(AActor, SeeState) +DEFINE_FIELD(AActor, MeleeState) +DEFINE_FIELD(AActor, MissileState) +DEFINE_FIELD(AActor, ConversationRoot) +DEFINE_FIELD(AActor, Conversation) +DEFINE_FIELD(AActor, DecalGenerator) + + void AActor::InitNativeFields() { - PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); - PType *TypeActorClass = NewClassPointer(RUNTIME_CLASS(AActor)); - PType *TypeInventory = NewPointer(RUNTIME_CLASS(AInventory)); - PType *TypePlayer = NewPointer(NewNativeStruct("Player", nullptr)); - auto TypeSector = NewPointer(NewNativeStruct("Sector", nullptr)); - 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", TypeSpriteID, myoffsetof(AActor, sprite)); - 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)); - meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz)); - meta->AddNativeField("DropoffZ", TypeFloat64, myoffsetof(AActor, dropoffz), VARF_ReadOnly); - meta->AddNativeField("floorsector", TypeSector, myoffsetof(AActor, floorsector)); - meta->AddNativeField("floorpic", TypeTextureID, myoffsetof(AActor, floorpic)); - 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)); - 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)); - meta->AddNativeField("MissileState", TypeState, myoffsetof(AActor, MissileState)); - //int ConversationRoot; // THe root of the current dialogue - //FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is "used." + // needs to be done manually until it can be given a proper type. meta->AddNativeField("DecalGenerator", NewPointer(TypeVoid), myoffsetof(AActor, DecalGenerator)); - //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++) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index b5f5691089..f1cc8e792b 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -200,7 +200,7 @@ DPSprite *player_t::FindPSprite(int layer) return pspr; } -DEFINE_ACTION_FUNCTION(_Player, FindPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) +DEFINE_ACTION_FUNCTION(_PlayerInfo, FindPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) { PARAM_SELF_STRUCT_PROLOGUE(player_t); PARAM_INT(id); @@ -220,7 +220,7 @@ void P_SetPsprite(player_t *player, PSPLayers id, FState *state, bool pending) player->GetPSprite(id)->SetState(state, pending); } -DEFINE_ACTION_FUNCTION(_Player, SetPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) +DEFINE_ACTION_FUNCTION(_PlayerInfo, SetPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) { PARAM_SELF_STRUCT_PROLOGUE(player_t); PARAM_INT(id); @@ -291,7 +291,7 @@ DPSprite *player_t::GetPSprite(PSPLayers layer) return pspr; } -DEFINE_ACTION_FUNCTION(_Player, GetPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) +DEFINE_ACTION_FUNCTION(_PlayerInfo, GetPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit) { PARAM_SELF_STRUCT_PROLOGUE(player_t); PARAM_INT(id); @@ -1653,7 +1653,7 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i P_SetPsprite(player, PSP_FLASH, flashstate + index, true); } -DEFINE_ACTION_FUNCTION(_Player, SetSafeFlash) +DEFINE_ACTION_FUNCTION(_PlayerInfo, SetSafeFlash) { PARAM_SELF_STRUCT_PROLOGUE(player_t); PARAM_OBJECT(weapon, AWeapon); diff --git a/src/p_user.cpp b/src/p_user.cpp index 84fcbd313c..5b25fd7132 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3147,7 +3147,7 @@ bool P_IsPlayerTotallyFrozen(const player_t *player) void P_InitPlayerForScript() { - PStruct *pstruct = NewNativeStruct("Player", nullptr); + PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); pstruct->Size = sizeof(player_t); pstruct->Align = alignof(player_t); PArray *parray = NewArray(pstruct, MAXPLAYERS); diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 194582d73d..59113e4a7d 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -111,6 +111,10 @@ std2: 'sbyte' { RET(TK_SByte); } 'short' { RET(TK_Short); } 'ushort' { RET(TK_UShort); } + 'int8' { RET(TK_Int8); } + 'uint8' { RET(TK_UInt8); } + 'int16' { RET(TK_Int16); } + 'uint16' { RET(TK_UInt16); } 'int' { RET(TK_Int); } 'uint' { RET(TK_UInt); } 'long' { RET(TK_Long); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 801d02be3d..8ea05d7e40 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -55,6 +55,10 @@ xx(TK_Byte, "'byte'") xx(TK_SByte, "'sbyte'") xx(TK_Short, "'short'") xx(TK_UShort, "'ushort'") +xx(TK_Int8, "'int8'") +xx(TK_UInt8, "'uint8'") +xx(TK_Int16, "'int16'") +xx(TK_UInt16, "'uint16'") xx(TK_Int, "'int'") xx(TK_UInt, "'uint'") xx(TK_Long, "'long'") diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 3f8f09eb78..1cc16214ce 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4082,7 +4082,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) 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.DeleteAndClear(); list.ShrinkToFit(); return to; } @@ -5232,6 +5232,8 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) // 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); + choices.DeleteAndClear(); + choices.ShrinkToFit(); return resultreg; } @@ -6303,7 +6305,8 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) { 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); + auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset); + newfield->BitValue = 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); @@ -6313,7 +6316,8 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) 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); + auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset); + newfield->BitValue = 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); @@ -6323,7 +6327,8 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) else if (classx->ExprType == EFX_StackVariable) { auto parentfield = static_cast(classx)->membervar; - auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset, membervar->BitValue); + auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset); + newfield->BitValue = membervar->BitValue; static_cast(classx)->ReplaceField(newfield); classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. auto x = classx->Resolve(ctx); @@ -7382,7 +7387,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; - ArgList.Clear(); + ArgList.DeleteAndClear(); ArgList.ShrinkToFit(); if (EmitTail) @@ -7661,7 +7666,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) ExpEmit reg; if (CheckEmitCast(build, EmitTail, reg)) { - ArgList.Clear(); + ArgList.DeleteAndClear(); ArgList.ShrinkToFit(); return reg; } @@ -7704,7 +7709,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { count += EmitParameter(build, ArgList[i], ScriptPosition); } - ArgList.Clear(); + ArgList.DeleteAndClear(); ArgList.ShrinkToFit(); // Get a constant register for this function @@ -7905,7 +7910,7 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build) } build->Emit(OP_FLOP, to.RegNum, from.RegNum, FxFlops[Index].Flop); - ArgList.Clear(); + ArgList.DeleteAndClear(); ArgList.ShrinkToFit(); return to; } @@ -8311,7 +8316,7 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) build->BackpatchToHere(addr); } if (!defaultset) build->BackpatchToHere(DefaultAddress); - Content.Clear(); + Content.DeleteAndClear(); Content.ShrinkToFit(); return ExpEmit(); } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 5bad10c36a..dd8529252f 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -147,6 +147,7 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) //========================================================================== AFuncDesc *FindFunction(PStruct *cls, const char * string); +FieldDesc *FindField(PStruct *cls, const char * string); FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, bool mustresolve = false); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 23aba902ff..d50f73bd37 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -46,6 +46,7 @@ static TArray properties; static TArray AFTable; +static TArray FieldTable; //========================================================================== // @@ -613,6 +614,37 @@ AFuncDesc *FindFunction(PStruct *cls, const char * string) return nullptr; } +//========================================================================== +// +// Find a function by name using a binary search +// +//========================================================================== + +FieldDesc *FindField(PStruct *cls, const char * string) +{ + int min = 0, max = FieldTable.Size() - 1; + + while (min <= max) + { + int mid = (min + max) / 2; + int lexval = stricmp(cls->TypeName.GetChars(), FieldTable[mid].ClassName + 1); + if (lexval == 0) lexval = stricmp(string, FieldTable[mid].FieldName); + if (lexval == 0) + { + return &FieldTable[mid]; + } + else if (lexval > 0) + { + min = mid + 1; + } + else + { + max = mid - 1; + } + } + return nullptr; +} + //========================================================================== // @@ -651,6 +683,14 @@ static int funccmp(const void * a, const void * b) return res; } +static int fieldcmp(const void * a, const void * b) +{ + // +1 to get past the prefix letter of the native class name, which gets omitted by the FName for the class. + int res = stricmp(((FieldDesc*)a)->ClassName + 1, ((FieldDesc*)b)->ClassName + 1); + if (res == 0) res = stricmp(((FieldDesc*)a)->FieldName, ((FieldDesc*)b)->FieldName); + return res; +} + //========================================================================== // // Initialization @@ -716,4 +756,19 @@ void InitThingdef() AFTable.ShrinkToFit(); qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp); } + + FieldTable.Clear(); + if (FieldTable.Size() == 0) + { + FAutoSegIterator probe(FRegHead, FRegTail); + + while (*++probe != NULL) + { + FieldDesc *afield = (FieldDesc *)*probe; + FieldTable.Push(*afield); + } + FieldTable.ShrinkToFit(); + qsort(&FieldTable[0], FieldTable.Size(), sizeof(FieldTable[0]), fieldcmp); + } + } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 7d56b32dbb..f2edca9b9c 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1013,6 +1013,15 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ +struct FieldDesc +{ + const char *ClassName; + const char *FieldName; + unsigned FieldOffset; + unsigned FieldSize; + int BitValue; +}; + struct AFuncDesc { const char *ClassName; @@ -1023,12 +1032,17 @@ struct AFuncDesc #if defined(_MSC_VER) #pragma section(".areg$u",read) +#pragma section(".freg$u",read) #define MSVC_ASEG __declspec(allocate(".areg$u")) +#define MSVC_FSEG __declspec(allocate(".freg$u")) #define GCC_ASEG +#define GCC_FSEG #else #define MSVC_ASEG +#define MSVC_FSEG #define GCC_ASEG __attribute__((section(SECTION_AREG))) __attribute__((used)) +#define GCC_FSEG __attribute__((section(SECTION_FREG))) __attribute__((used)) #endif // Macros to handle action functions. These are here so that I don't have to @@ -1043,6 +1057,32 @@ struct AFuncDesc MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \ static int AF_##cls##_##name(VM_ARGS) +// cls is the scripted class name, icls the internal one (e.g. player_t vs. Player) +#define DEFINE_FIELD_X(cls, icls, name) \ + static const FieldDesc VMField_##icls##_##name = { "A" #cls, #name, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), 0 }; \ + extern FieldDesc const *const VMField_##icls##_##name##_HookPtr; \ + MSVC_FSEG FieldDesc const *const VMField_##icls##_##name##_HookPtr GCC_FSEG = &VMField_##cls##_##name; + +#define DEFINE_FIELD_X_BIT(cls, icls, name, bitval) \ + static const FieldDesc VMField_##icls##_##name = { "A" #cls, #name, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), bitval }; \ + extern FieldDesc const *const VMField_##icls##_##name##_HookPtr; \ + MSVC_FSEG FieldDesc const *const VMField_##icls##_##name##_HookPtr GCC_FSEG = &VMField_##cls##_##name; + +#define DEFINE_FIELD(cls, name) \ + static const FieldDesc VMField_##cls##_##name = { #cls, #name, (unsigned)myoffsetof(cls, name), (unsigned)sizeof(cls::name), 0 }; \ + extern FieldDesc const *const VMField_##cls##_##name##_HookPtr; \ + MSVC_FSEG FieldDesc const *const VMField_##cls##_##name##_HookPtr GCC_FSEG = &VMField_##cls##_##name; + +#define DEFINE_FIELD_NAMED(cls, name, scriptname) \ + static const FieldDesc VMField_##cls##_##scriptname = { #cls, #scriptname, (unsigned)myoffsetof(cls, name), (unsigned)sizeof(cls::name), 0 }; \ + extern FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr; \ + MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname; + +#define DEFINE_FIELD_BIT(cls, name, scriptname, bitval) \ + static const FieldDesc VMField_##cls##_##scriptname = { #cls, #scriptname, (unsigned)myoffsetof(cls, name), (unsigned)sizeof(cls::name), bitval }; \ + extern FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr; \ + MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname; + class AActor; void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); #define CALL_ACTION(name, self) CallAction(stack, AActor_##name##_VMPtr, self); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index c76df32e3b..72bfcf7355 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1186,6 +1186,7 @@ void ZCCCompiler::CompileAllFields() // Create copies of the arrays which can be altered auto Classes = this->Classes; auto Structs = this->Structs; + TMap HasNativeChildren; // 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. @@ -1200,8 +1201,8 @@ void ZCCCompiler::CompileAllFields() { 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--); + // Only set a marker here, so that we can print a better message when the actual fields get added. + HasNativeChildren.Insert(ac, true); break; } } @@ -1236,7 +1237,7 @@ void ZCCCompiler::CompileAllFields() type->Size = Classes[i]->Type()->ParentClass->Size; } } - if (CompileFields(type, Classes[i]->Fields, nullptr, &Classes[i]->TreeNodes, false)) + if (CompileFields(type, Classes[i]->Fields, nullptr, &Classes[i]->TreeNodes, false, !!HasNativeChildren.CheckKey(type))) { // Remove from the list if all fields got compiled. Classes.Delete(i--); @@ -1263,11 +1264,12 @@ void ZCCCompiler::CompileAllFields() // //========================================================================== -bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct) +bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren) { while (Fields.Size() > 0) { auto field = Fields[0]; + FieldDesc *fd = nullptr; PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, true, true); @@ -1289,8 +1291,9 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel if (field->Flags & ZCC_Native) { - // todo: get the native address of this field. + varflags |= VARF_Native | VARF_Transient; } + if (field->Flags & ZCC_Meta) { varflags |= VARF_ReadOnly; // metadata implies readonly @@ -1312,8 +1315,32 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel { thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, &type->Symbols); } - - type->AddField(name->Name, thisfieldtype, varflags); + + if (varflags & VARF_Native) + { + fd = FindField(type, FName(name->Name).GetChars()); + if (fd == nullptr) + { + Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars()); + } + else if (thisfieldtype->Size != fd->FieldSize) + { + Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size); + } + // Q: Should we check alignment, too? A mismatch may be an indicator for bad assumptions. + else + { + type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue); + } + } + else if (hasnativechildren) + { + Error(field, "Cannot add field %s to %s. %s has native children which means it size may not change.", type->TypeName.GetChars(), fd->FieldSize, FName(name->Name).GetChars()); + } + else + { + type->AddField(name->Name, thisfieldtype, varflags); + } } name = static_cast(name->SiblingNext); } while (name != field->Names); @@ -2133,7 +2160,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool afd = FindFunction(c->Type(), FName(f->Name).GetChars()); if (afd == nullptr) { - Error(f, "The function '%s' has not been exported from the executable.", FName(f->Name).GetChars()); + Error(f, "The function '%s.%s' has not been exported from the executable.", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()); } else { diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 84e3143530..9599b4b968 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -91,7 +91,7 @@ private: bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols); void CompileAllFields(); - bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct); + bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren = false); 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); diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index de3d2c7e15..37fd8ff0c3 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -137,6 +137,10 @@ static void InitTokenMap() TOKENDEF2(TK_Byte, ZCC_BYTE, NAME_Byte); TOKENDEF2(TK_Short, ZCC_SHORT, NAME_Short); TOKENDEF2(TK_UShort, ZCC_USHORT, NAME_uShort); + TOKENDEF2(TK_Int8, ZCC_SBYTE, NAME_int8); + TOKENDEF2(TK_UInt8, ZCC_BYTE, NAME_uint8); + TOKENDEF2(TK_Int16, ZCC_SHORT, NAME_int16); + TOKENDEF2(TK_UInt16, ZCC_USHORT, NAME_uint16); TOKENDEF2(TK_Int, ZCC_INT, NAME_Int); TOKENDEF2(TK_UInt, ZCC_UINT, NAME_uInt); TOKENDEF2(TK_Bool, ZCC_BOOL, NAME_Bool); diff --git a/src/zzautozend.cpp b/src/zzautozend.cpp index 5567b1ddda..18c020310c 100644 --- a/src/zzautozend.cpp +++ b/src/zzautozend.cpp @@ -43,6 +43,9 @@ __declspec(allocate(".areg$z")) void *const ARegTail = 0; #pragma section(".creg$z",read) __declspec(allocate(".creg$z")) void *const CRegTail = 0; +#pragma section(".freg$z",read) +__declspec(allocate(".freg$z")) void *const FRegTail = 0; + #pragma section(".greg$z",read) __declspec(allocate(".greg$z")) void *const GRegTail = 0; @@ -56,6 +59,7 @@ __declspec(allocate(".yreg$z")) void *const YRegTail = 0; void *const ARegTail __attribute__((section(SECTION_AREG))) = 0; void *const CRegTail __attribute__((section(SECTION_CREG))) = 0; +void *const FRegTail __attribute__((section(SECTION_FREG))) = 0; void *const GRegTail __attribute__((section(SECTION_GREG))) = 0; void *const YRegTail __attribute__((section(SECTION_YREG))) = 0; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index db86647c39..da9db687cd 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -5,6 +5,168 @@ class Actor : Thinker native const ONCEILINGZ = 2147483647.0; const FLOATRANDZ = ONCEILINGZ-1; + // flags are not defined here, the native fields for those get synthesized from the internal tables. + + // for some comments on these fields, see their native representations in actor.h. + native PlayerInfo Player; + native readonly vector3 Pos; + native vector3 Prev; + native double spriteAngle; + native double spriteRotation; + native double VisibleStartAngle; + native double VisibleStartPitch; + native double VisibleEndAngle; + native double VisibleEndPitch; + native double Angle; + native double Pitch; + native double Roll; + native vector3 Vel; + native double Speed; + native double FloatSpeed; + native SpriteID sprite; + native uint8 frame; + native vector2 Scale; + native TextureID picnum; + native double Alpha; + native color fillcolor; + native Sector CurSector; + native double CeilingZ; + native double FloorZ; + native double DropoffZ; + native Sector floorsector; + native TextureID floorpic; + native int floorterrain; + native Sector ceilingsector; + native TextureID ceilingpic; + native double Height; + native readonly double Radius; + native double projectilepassheight; + native int tics; + native readonly State CurState; + native readonly int Damage; + native int projectilekickback; + native int special1; + native int special2; + native double specialf1; + native double specialf2; + native int weaponspecial; + native int Health; + native uint8 movedir; + native int8 visdir; + native int16 movecount; + native int16 strafecount; + native Actor Target; + native Actor Master; + native Actor Tracer; + native Actor LastHeard; + native Actor LastEnemy; + native Actor LastLookActor; + native int ReactionTime; + native int Threshold; + native readonly int DefThreshold; + native readonly vector3 SpawnPoint; + native readonly uint16 SpawnAngle; + native int StartHealth; + native uint8 WeaveIndexXY; + native uint8 WeaveIndexZ; + native int skillrespawncount; + native int Args[5]; + native int Mass; + native int Special; + native readonly int TID; + native readonly int TIDtoHate; + native readonly int WaterLevel; + native int Score; + native int Accuracy; + native int Stamina; + native double MeleeRange; + native int PainThreshold; + native double Gravity; + native double FloorClip; + native name DamageType; + native name DamageTypeReceived; + native uint8 FloatBobPhase; + native int RipperLevel; + native int RipLevelMin; + native int RipLevelMax; + native name Species; + native Actor Alternative; + native Actor goal; + native uint8 MinMissileChance; + native int8 LastLookPlayerNumber; + native uint SpawnFlags; + native double meleethreshold; + native double maxtargetrange; + native double bouncefactor; + native double wallbouncefactor; + native int bouncecount; + native double friction; + native int FastChaseStrafeCount; + native double pushfactor; + native int lastpush; + native int activationtype; + native int lastbump; + native int DesignatedTeam; + native Actor BlockingMobj; + native int PoisonDamage; + native name PoisonDamageType; + native int PoisonDuration; + native int PoisonPeriod; + native int PoisonDamageReceived; + native name PoisonDamageTypeReceived; + native int PoisonDurationReceived; + native int PoisonPeriodReceived; + native Actor Poisoner; + native Inventory Inv; + native uint8 smokecounter; + native uint8 FriendPlayer; + native uint Translation; + native sound AttackSound; + native sound DeathSound; + native sound SeeSound; + native sound PainSound; + native sound ActiveSound; + native sound UseSound; + native sound BounceSound; + native sound WallBounceSound; + native sound CrushPainSound; + native double MaxDropoffHeight; + native double MaxStepHeight; + native int16 PainChance; + native name PainType; + native name DeathType; + native double DamageFactor; + native double DamageMultiply; + native Class TelefogSourceType; + native Class TelefogDestType; + native readonly State SpawnState; + native readonly State SeeState; + native State MeleeState; + native State MissileState; + + // need some definition work first + //FRenderStyle RenderStyle; + //line_t *BlockingLine; // Line that blocked the last move + //int ConversationRoot; // THe root of the current dialogue + //DecalBase DecalGenerator; + + // deprecated things. + native readonly deprecated double X; + native readonly deprecated double Y; + native readonly deprecated double Z; + native readonly deprecated double VelX; + native readonly deprecated double VelY; + native readonly deprecated double VelZ; + native readonly deprecated double MomX; + native readonly deprecated double MomY; + native readonly deprecated double MomZ; + native deprecated double ScaleX; + native deprecated double ScaleY; + + //int ConversationRoot; // THe root of the current dialogue; + //FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is used.; + + Default { Scale 1; diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 7a27907263..b3f48acaea 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -47,4 +47,8 @@ class SpotState : Object native { native static SpotState GetSpotState(); native SpecialSpot GetNextInList(class type, int skipcounter); -} \ No newline at end of file +} + +struct Sector native +{ +} diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index cde600701c..e6a13317f0 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -374,7 +374,7 @@ extend class Actor } // 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; + newmobj.LastHeard = newmobj.CurSector.SoundTarget; if (newmobj.SeeState != null && newmobj.LookForPlayers (true)) { diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 4f9e843331..71cdb84799 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -77,7 +77,7 @@ class PSprite : Object native { } -struct Player native +struct PlayerInfo native // this is what internally is player_t { native void SetPsprite(int id, State stat, bool pending = false); native void SetSafeFlash(Weapon weap, State flashstate, int index); From e2167c661c3a036537c536eac3b122b075bdf890 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Tue, 22 Nov 2016 21:16:13 +0100 Subject: [PATCH 333/471] - Fixed GCC/Clang compile errors. --- src/doomtype.h | 2 ++ src/virtual.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doomtype.h b/src/doomtype.h index 129c5f1221..a9818df78c 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -264,12 +264,14 @@ char ( &_ArraySizeHelper( T (&array)[N] ))[N]; #ifdef __MACH__ #define SECTION_AREG "__DATA,areg" #define SECTION_CREG "__DATA,creg" +#define SECTION_FREG "__DATA,freg" #define SECTION_GREG "__DATA,greg" #define SECTION_MREG "__DATA,mreg" #define SECTION_YREG "__DATA,yreg" #else #define SECTION_AREG "areg" #define SECTION_CREG "creg" +#define SECTION_FREG "freg" #define SECTION_GREG "greg" #define SECTION_MREG "mreg" #define SECTION_YREG "yreg" diff --git a/src/virtual.h b/src/virtual.h index 8842eb891f..f3167407d8 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -228,4 +228,4 @@ VMEXPORT_NATIVES_END(AActor) /* VMEXPORT_NATIVES_START(AActor, DThinker) VMEXPORT_NATIVES_END(AActor) -*/ \ No newline at end of file +*/ From e1c4e4939a31b8a875d9206ae2a5597c62b1ceb2 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Tue, 22 Nov 2016 21:20:42 +0100 Subject: [PATCH 334/471] - Fixed the order of the MS sections. --- src/__autostart.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/__autostart.cpp b/src/__autostart.cpp index 3daabbeae3..13e104d753 100644 --- a/src/__autostart.cpp +++ b/src/__autostart.cpp @@ -52,8 +52,8 @@ // a single section during the final link. (.rdata is the standard section // for initialized read-only data.) -#pragma comment(linker, "/merge:.areg=.rdata /merge:.creg=.rdata /merge:.greg=.rdata") -#pragma comment(linker, "/merge:.yreg=.rdata /merge:.freg=.rdata") +#pragma comment(linker, "/merge:.areg=.rdata /merge:.creg=.rdata /merge:.freg=.rdata") +#pragma comment(linker, "/merge:.greg=.rdata /merge:.yreg=.rdata") #pragma section(".areg$a",read) __declspec(allocate(".areg$a")) void *const ARegHead = 0; @@ -61,12 +61,12 @@ __declspec(allocate(".areg$a")) void *const ARegHead = 0; #pragma section(".creg$a",read) __declspec(allocate(".creg$a")) void *const CRegHead = 0; -#pragma section(".greg$a",read) -__declspec(allocate(".greg$a")) void *const GRegHead = 0; - #pragma section(".freg$a",read) __declspec(allocate(".freg$a")) void *const FRegHead = 0; +#pragma section(".greg$a",read) +__declspec(allocate(".greg$a")) void *const GRegHead = 0; + #pragma section(".yreg$a",read) __declspec(allocate(".yreg$a")) void *const YRegHead = 0; From 099b9970efbc00b511a4520e435ccfa29543e751 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 22 Nov 2016 23:42:32 +0100 Subject: [PATCH 335/471] - added proper definitions for all exported native fields. - synthesize native fields for all declared flags, not just for AActor. --- src/actor.h | 2 - src/d_player.h | 1 - src/dobject.cpp | 17 +- src/dobject.h | 6 +- src/dobjtype.cpp | 2 +- src/g_shared/a_armor.cpp | 15 +- src/g_shared/a_pickups.h | 2 - src/g_shared/a_weapons.cpp | 80 +++++-- src/p_mobj.cpp | 35 +-- src/p_pspr.cpp | 48 ++-- src/p_pspr.h | 2 +- src/p_user.cpp | 224 +++++++++--------- src/scripting/thingdef_data.cpp | 57 +++-- src/scripting/vm/vm.h | 7 +- src/scripting/zscript/zcc-parse.lemon | 3 +- src/scripting/zscript/zcc_compile.cpp | 9 +- src/scripting/zscript/zcc_parser.h | 5 + wadsrc/static/zscript/base.txt | 6 +- wadsrc/static/zscript/constants.txt | 1 + wadsrc/static/zscript/doom/weaponchaingun.txt | 2 +- wadsrc/static/zscript/shared/botstuff.txt | 4 + wadsrc/static/zscript/shared/inventory.txt | 34 +++ wadsrc/static/zscript/shared/player.txt | 136 ++++++++++- 23 files changed, 452 insertions(+), 246 deletions(-) diff --git a/src/actor.h b/src/actor.h index d8bb1a8979..83873adc50 100644 --- a/src/actor.h +++ b/src/actor.h @@ -565,7 +565,6 @@ class DDropItem : public DObject { DECLARE_CLASS(DDropItem, DObject) HAS_OBJECT_POINTERS - HAS_FIELDS public: DDropItem *Next; FName Name; @@ -579,7 +578,6 @@ const double MinVel = EQUAL_EPSILON; class AActor : public DThinker { DECLARE_CLASS_WITH_META (AActor, DThinker, PClassActor) - HAS_FIELDS HAS_OBJECT_POINTERS public: AActor () throw(); diff --git a/src/d_player.h b/src/d_player.h index d3f6841374..d1678b6199 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -100,7 +100,6 @@ FString GetPrintableDisplayName(PClassPlayerPawn *cls); class APlayerPawn : public AActor { DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn) - HAS_FIELDS HAS_OBJECT_POINTERS public: diff --git a/src/dobject.cpp b/src/dobject.cpp index ad575bebcc..e3e37432b8 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -64,12 +64,15 @@ ClassReg DObject::RegistrationInfo = &DVMObject::RegistrationInfo, // VMExport nullptr, // Pointers &DObject::InPlaceConstructor, // ConstructNative - &DObject::InitNativeFields, // InitNatives + nullptr, sizeof(DObject), // SizeOf CLASSREG_PClass, // MetaClassNum }; _DECLARE_TI(DObject) +// This bit is needed in the playsim - but give it a less crappy name. +DEFINE_FIELD_BIT(DObject,ObjectFlags, bDestroyed, OF_EuthanizeMe) + //========================================================================== // // @@ -347,18 +350,6 @@ 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; diff --git a/src/dobject.h b/src/dobject.h index d858e577f7..f728713e08 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -150,9 +150,6 @@ protected: \ #define HAS_OBJECT_POINTERS \ static const size_t PointerOffsets[]; -#define HAS_FIELDS \ - static void InitNativeFields(); - #if defined(_MSC_VER) # pragma section(".creg$u",read) # define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo; @@ -187,7 +184,7 @@ protected: \ // 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_true(cls) nullptr #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; } @@ -445,7 +442,6 @@ 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; diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 5afb8a5789..11640ec94b 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2515,7 +2515,7 @@ PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue else { // Just abort. Bit fields should only be defined internally. - I_FatalError("Trying to create an invalid bit field element: %s", name.GetChars()); + I_Error("Trying to create an invalid bit field element: %s", name.GetChars()); } } else BitValue = -1; diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index c05cc2c6a8..8f1116a9e5 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -281,16 +281,17 @@ bool ABasicArmorPickup::Use (bool pickup) //=========================================================================== // -// ABasicArmorBonus :: InitNativeFields +// ABasicArmorBonus // //=========================================================================== -void ABasicArmorBonus::InitNativeFields() -{ - auto meta = RUNTIME_CLASS(ABasicArmorBonus); - meta->AddNativeField("SaveAmount", TypeSInt32, myoffsetof(ABasicArmorBonus, SaveAmount)); - meta->AddNativeField("MaxSaveAmount", TypeSInt32, myoffsetof(ABasicArmorBonus, MaxSaveAmount)); -} +DEFINE_FIELD(ABasicArmorBonus, SavePercent) +DEFINE_FIELD(ABasicArmorBonus, MaxSaveAmount) +DEFINE_FIELD(ABasicArmorBonus, MaxAbsorb) +DEFINE_FIELD(ABasicArmorBonus, MaxFullAbsorb) +DEFINE_FIELD(ABasicArmorBonus, SaveAmount) +DEFINE_FIELD(ABasicArmorBonus, BonusCount) +DEFINE_FIELD(ABasicArmorBonus, BonusMax) //=========================================================================== // diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 9e1caaf5b0..6dc2d0bc59 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -289,7 +289,6 @@ public: class AWeapon : public AStateProvider { DECLARE_CLASS_WITH_META(AWeapon, AStateProvider, PClassWeapon) - HAS_FIELDS HAS_OBJECT_POINTERS public: DWORD WeaponFlags; @@ -500,7 +499,6 @@ public: class ABasicArmorBonus : public AArmor { DECLARE_CLASS (ABasicArmorBonus, AArmor) - HAS_FIELDS public: virtual void Serialize(FSerializer &arc); diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 9af5c6de27..5f221c5bc9 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -31,25 +31,45 @@ IMPLEMENT_POINTERS_START(AWeapon) IMPLEMENT_POINTER(SisterWeapon) IMPLEMENT_POINTERS_END -void AWeapon::InitNativeFields() -{ - auto meta = RUNTIME_CLASS(AWeapon); +DEFINE_FIELD(AWeapon, WeaponFlags) +DEFINE_FIELD(AWeapon, AmmoType1) +DEFINE_FIELD(AWeapon, AmmoType2) +DEFINE_FIELD(AWeapon, AmmoGive1) +DEFINE_FIELD(AWeapon, AmmoGive2) +DEFINE_FIELD(AWeapon, MinAmmo1) +DEFINE_FIELD(AWeapon, MinAmmo2) +DEFINE_FIELD(AWeapon, AmmoUse1) +DEFINE_FIELD(AWeapon, AmmoUse2) +DEFINE_FIELD(AWeapon, Kickback) +DEFINE_FIELD(AWeapon, YAdjust) +DEFINE_FIELD(AWeapon, UpSound) +DEFINE_FIELD(AWeapon, ReadySound) +DEFINE_FIELD(AWeapon, SisterWeaponType) +DEFINE_FIELD(AWeapon, ProjectileType) +DEFINE_FIELD(AWeapon, AltProjectileType) +DEFINE_FIELD(AWeapon, SelectionOrder) +DEFINE_FIELD(AWeapon, MinSelAmmo1) +DEFINE_FIELD(AWeapon, MinSelAmmo2) +DEFINE_FIELD(AWeapon, MoveCombatDist) +DEFINE_FIELD(AWeapon, ReloadCounter) +DEFINE_FIELD(AWeapon, BobStyle) +DEFINE_FIELD(AWeapon, BobSpeed) +DEFINE_FIELD(AWeapon, BobRangeX) +DEFINE_FIELD(AWeapon, BobRangeY) +DEFINE_FIELD(AWeapon, Ammo1) +DEFINE_FIELD(AWeapon, Ammo2) +DEFINE_FIELD(AWeapon, SisterWeapon) +DEFINE_FIELD(AWeapon, FOVScale) +DEFINE_FIELD(AWeapon, Crosshair) +DEFINE_FIELD(AWeapon, GivenAsMorphWeapon) +DEFINE_FIELD(AWeapon, bAltFire) +DEFINE_FIELD_BIT(AWeapon, WeaponFlags, bDehAmmo, WIF_DEHAMMO) - meta->AddNativeField("bAltFire", TypeBool, myoffsetof(AWeapon, bAltFire)); - - - // synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them. - for (size_t i = 0; WeaponFlagDefs[i].flagbit != 0xffffffff; i++) - { - if (WeaponFlagDefs[i].structoffset > 0) - { - meta->AddNativeField(FStringf("b%s", WeaponFlagDefs[i].name), (WeaponFlagDefs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), WeaponFlagDefs[i].structoffset, WeaponFlagDefs[i].varflags, WeaponFlagDefs[i].flagbit); - } - } - // This flag is not accessible through actor definitions. - meta->AddNativeField("bDehAmmo", TypeSInt32, myoffsetof(AWeapon, WeaponFlags), VARF_ReadOnly, WIF_DEHAMMO); - -} +//=========================================================================== +// +// +// +//=========================================================================== FString WeaponSection; TArray KeyConfWeapons; @@ -62,12 +82,24 @@ static int ntoh_cmp(const void *a, const void *b); IMPLEMENT_CLASS(PClassWeapon, false, false, false, false) +//=========================================================================== +// +// +// +//=========================================================================== + PClassWeapon::PClassWeapon() { SlotNumber = -1; SlotPriority = INT_MAX; } +//=========================================================================== +// +// +// +//=========================================================================== + void PClassWeapon::DeriveData(PClass *newclass) { assert(newclass->IsKindOf(RUNTIME_CLASS(PClassWeapon))); @@ -79,6 +111,12 @@ void PClassWeapon::DeriveData(PClass *newclass) } +//=========================================================================== +// +// +// +//=========================================================================== + void PClassWeapon::ReplaceClassRef(PClass *oldclass, PClass *newclass) { Super::ReplaceClassRef(oldclass, newclass); @@ -91,6 +129,12 @@ void PClassWeapon::ReplaceClassRef(PClass *oldclass, PClass *newclass) } } +//=========================================================================== +// +// +// +//=========================================================================== + void PClassWeapon::Finalize(FStateDefinitions &statedef) { Super::Finalize(statedef); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 1813996554..29123590ad 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -131,7 +131,7 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(AActor, false, true, true, true) +IMPLEMENT_CLASS(AActor, false, true, false, true) IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(target) @@ -310,24 +310,6 @@ DEFINE_FIELD(AActor, ConversationRoot) DEFINE_FIELD(AActor, Conversation) DEFINE_FIELD(AActor, DecalGenerator) - -void AActor::InitNativeFields() -{ - auto meta = RUNTIME_CLASS(AActor); - // needs to be done manually until it can be given a proper type. - meta->AddNativeField("DecalGenerator", NewPointer(TypeVoid), myoffsetof(AActor, 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 @@ -7183,18 +7165,13 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) IMPLEMENT_CLASS(DDropItem, false, true, true, false) IMPLEMENT_POINTERS_START(DDropItem) - IMPLEMENT_POINTER(Next) +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)); -} +DEFINE_FIELD(DDropItem, Next) +DEFINE_FIELD(DDropItem, Name) +DEFINE_FIELD(DDropItem, Probability) +DEFINE_FIELD(DDropItem, Amount) void PrintMiscActorInfo(AActor *query) { diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index f1cc8e792b..0e39e259e0 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -99,40 +99,32 @@ static const FGenericButtons ButtonChecks[] = // //------------------------------------------------------------------------ -IMPLEMENT_CLASS(DPSprite, false, true, true, false) +IMPLEMENT_CLASS(DPSprite, false, true, false, false) IMPLEMENT_POINTERS_START(DPSprite) IMPLEMENT_POINTER(Caller) IMPLEMENT_POINTER(Next) IMPLEMENT_POINTERS_END -void DPSprite::InitNativeFields() -{ - auto meta = RUNTIME_CLASS(DPSprite); - PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); - PType *TypePSP = NewPointer(RUNTIME_CLASS(DPSprite)); - PType *TypePlayer = NewPointer(NewNativeStruct("Player", nullptr)); - - meta->AddNativeField("State", TypeState, myoffsetof(DPSprite, State), VARF_ReadOnly); - meta->AddNativeField("Caller", TypeActor, myoffsetof(DPSprite, Caller), VARF_ReadOnly); - meta->AddNativeField("Next", TypePSP, myoffsetof(DPSprite, Next), VARF_ReadOnly); - meta->AddNativeField("Owner", TypePlayer, myoffsetof(DPSprite, Owner), VARF_ReadOnly); - meta->AddNativeField("Sprite", TypeSpriteID, myoffsetof(DPSprite, Sprite)); - meta->AddNativeField("Frame", TypeSInt32, myoffsetof(DPSprite, Frame)); - meta->AddNativeField("ID", TypePlayer, myoffsetof(DPSprite, ID), VARF_ReadOnly); - meta->AddNativeField("processPending", TypeBool, myoffsetof(DPSprite, processPending)); - meta->AddNativeField("x", TypeFloat64, myoffsetof(DPSprite, x)); - meta->AddNativeField("y", TypeFloat64, myoffsetof(DPSprite, y)); - meta->AddNativeField("oldx", TypeFloat64, myoffsetof(DPSprite, oldx)); - meta->AddNativeField("oldy", TypeFloat64, myoffsetof(DPSprite, oldy)); - meta->AddNativeField("firstTic", TypeBool, myoffsetof(DPSprite, firstTic)); - meta->AddNativeField("Tics", TypeSInt32, myoffsetof(DPSprite, Tics)); - meta->AddNativeField("bAddWeapon", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_ADDWEAPON); - meta->AddNativeField("bAddBob", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_ADDBOB); - meta->AddNativeField("bPowDouble", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_POWDOUBLE); - meta->AddNativeField("bCVarFast", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_CVARFAST); - meta->AddNativeField("bFlip", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_FLIP); -} +DEFINE_FIELD_NAMED(DPSprite, State, CurState) // deconflict with same named type +DEFINE_FIELD(DPSprite, Caller) +DEFINE_FIELD(DPSprite, Next) +DEFINE_FIELD(DPSprite, Owner) +DEFINE_FIELD(DPSprite, Sprite) +DEFINE_FIELD(DPSprite, Frame) +DEFINE_FIELD(DPSprite, ID) +DEFINE_FIELD(DPSprite, processPending) +DEFINE_FIELD(DPSprite, x) +DEFINE_FIELD(DPSprite, y) +DEFINE_FIELD(DPSprite, oldx) +DEFINE_FIELD(DPSprite, oldy) +DEFINE_FIELD(DPSprite, firstTic) +DEFINE_FIELD(DPSprite, Tics) +DEFINE_FIELD_BIT(DPSprite, Flags, bAddWeapon, PSPF_ADDWEAPON) +DEFINE_FIELD_BIT(DPSprite, Flags, bAddBob, PSPF_ADDBOB) +DEFINE_FIELD_BIT(DPSprite, Flags, bPowDouble, PSPF_POWDOUBLE) +DEFINE_FIELD_BIT(DPSprite, Flags, bCVarFast, PSPF_CVARFAST) +DEFINE_FIELD_BIT(DPSprite, Flags, bFlip, PSPF_FLIP) //------------------------------------------------------------------------ // diff --git a/src/p_pspr.h b/src/p_pspr.h index 4c019c7d4d..7039b2cc82 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -59,7 +59,6 @@ enum PSPFlags class DPSprite : public DObject { DECLARE_CLASS (DPSprite, DObject) - HAS_FIELDS HAS_OBJECT_POINTERS public: DPSprite(player_t *owner, AActor *caller, int id); @@ -89,6 +88,7 @@ private: void Tick(); void Destroy(); +public: // must be public to be able to generate the field export tables. Grrr... TObjPtr Caller; TObjPtr Next; player_t *Owner; diff --git a/src/p_user.cpp b/src/p_user.cpp index 5b25fd7132..2917db6685 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -161,12 +161,6 @@ bool ValidatePlayerClass(PClassActor *ti, const char *name) return true; } -void APlayerPawn::InitNativeFields() -{ - auto meta = RUNTIME_CLASS(APlayerPawn); - meta->AddNativeField("JumpZ", TypeFloat64, myoffsetof(APlayerPawn, JumpZ)); -} - void SetupPlayerClasses () { FPlayerClass newclass; @@ -628,7 +622,7 @@ void player_t::SendPitchLimits() const // //=========================================================================== -IMPLEMENT_CLASS(APlayerPawn, false, true, true, true) +IMPLEMENT_CLASS(APlayerPawn, false, true, false, true) IMPLEMENT_POINTERS_START(APlayerPawn) IMPLEMENT_POINTER(InvFirst) @@ -3139,112 +3133,118 @@ bool P_IsPlayerTotallyFrozen(const player_t *player) //========================================================================== // -// sets up the script-side version of players -// Since this is a global variable and the script compiler does -// not allow defining them, it will be fully set up here. +// native members // //========================================================================== -void P_InitPlayerForScript() -{ - PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); - pstruct->Size = sizeof(player_t); - pstruct->Align = alignof(player_t); - PArray *parray = NewArray(pstruct, MAXPLAYERS); - pstruct->Size = 0; // make sure it cannot be instantiated in the script. - PField *playerf = new PField("players", pstruct, VARF_Native | VARF_Static, (intptr_t)&players); - GlobalSymbols.AddSymbol(playerf); +DEFINE_FIELD(APlayerPawn, crouchsprite) +DEFINE_FIELD(APlayerPawn, MaxHealth) +DEFINE_FIELD(APlayerPawn, MugShotMaxHealth) +DEFINE_FIELD(APlayerPawn, RunHealth) +DEFINE_FIELD(APlayerPawn, PlayerFlags) +DEFINE_FIELD(APlayerPawn, InvFirst) +DEFINE_FIELD(APlayerPawn, InvSel) +DEFINE_FIELD(APlayerPawn, JumpZ) +DEFINE_FIELD(APlayerPawn, GruntSpeed) +DEFINE_FIELD(APlayerPawn, FallingScreamMinSpeed) +DEFINE_FIELD(APlayerPawn, FallingScreamMaxSpeed) +DEFINE_FIELD(APlayerPawn, ViewHeight) +DEFINE_FIELD(APlayerPawn, ForwardMove1) +DEFINE_FIELD(APlayerPawn, ForwardMove2) +DEFINE_FIELD(APlayerPawn, SideMove1) +DEFINE_FIELD(APlayerPawn, SideMove2) +DEFINE_FIELD(APlayerPawn, ScoreIcon) +DEFINE_FIELD(APlayerPawn, SpawnMask) +DEFINE_FIELD(APlayerPawn, MorphWeapon) +DEFINE_FIELD(APlayerPawn, AttackZOffset) +DEFINE_FIELD(APlayerPawn, UseRange) +DEFINE_FIELD(APlayerPawn, AirCapacity) +DEFINE_FIELD(APlayerPawn, FlechetteType) +DEFINE_FIELD(APlayerPawn, DamageFade) +DEFINE_FIELD(APlayerPawn, ViewBob) - PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); - PType *TypePlayerPawn = NewPointer(RUNTIME_CLASS(APlayerPawn)); - PType *TypeWeapon = NewPointer(RUNTIME_CLASS(AWeapon)); - PType *TypeClassActor = NewClassPointer(RUNTIME_CLASS(AActor)); - PType *TypeClassPlayerPawn = NewClassPointer(RUNTIME_CLASS(APlayerPawn)); - PType *TypeClassWeapon = NewClassPointer(RUNTIME_CLASS(AWeapon)); - - //ticcmd_t cmd; - //usercmd_t original_cmd; - //userinfo_t userinfo; // [RH] who is this? - //FWeaponSlots weapons; - pstruct->AddNativeField("mo", TypePlayerPawn, myoffsetof(player_t, mo), VARF_ReadOnly); - pstruct->AddNativeField("playerstate", TypeUInt8, myoffsetof(player_t, playerstate)); - pstruct->AddNativeField("original_oldbuttons", TypeUInt32, myoffsetof(player_t, original_oldbuttons)); - pstruct->AddNativeField("cls", TypeClassPlayerPawn, myoffsetof(player_t, cls), VARF_ReadOnly); - pstruct->AddNativeField("DesiredFOV", TypeFloat32, myoffsetof(player_t, DesiredFOV)); - pstruct->AddNativeField("FOV", TypeFloat32, myoffsetof(player_t, FOV), VARF_ReadOnly); - pstruct->AddNativeField("viewz", TypeFloat64, myoffsetof(player_t, viewz)); - pstruct->AddNativeField("viewheight", TypeFloat64, myoffsetof(player_t, viewheight)); - pstruct->AddNativeField("deltaviewheight", TypeFloat64, myoffsetof(player_t, deltaviewheight)); - pstruct->AddNativeField("bob", TypeFloat64, myoffsetof(player_t, bob)); - pstruct->AddNativeField("vel", TypeVector2, myoffsetof(player_t, Vel)); - pstruct->AddNativeField("centering", TypeBool, myoffsetof(player_t, centering)); - pstruct->AddNativeField("turnticks", TypeUInt8, myoffsetof(player_t, turnticks)); - pstruct->AddNativeField("attackdown", TypeBool, myoffsetof(player_t, attackdown)); - pstruct->AddNativeField("usedown", TypeBool, myoffsetof(player_t, usedown)); - pstruct->AddNativeField("oldbuttons", TypeUInt32, myoffsetof(player_t, oldbuttons)); - pstruct->AddNativeField("health", TypeSInt32, myoffsetof(player_t, health)); - pstruct->AddNativeField("inventorytics", TypeSInt32, myoffsetof(player_t, inventorytics)); - pstruct->AddNativeField("CurrentPlayerClass", TypeUInt8, myoffsetof(player_t, CurrentPlayerClass)); - pstruct->AddNativeField("frags", NewArray(TypeSInt32, MAXPLAYERS), myoffsetof(player_t, frags)); - pstruct->AddNativeField("fragcount", TypeSInt32, myoffsetof(player_t, fragcount)); - pstruct->AddNativeField("lastkilltime", TypeSInt32, myoffsetof(player_t, lastkilltime)); - pstruct->AddNativeField("multicount", TypeUInt8, myoffsetof(player_t, multicount)); - pstruct->AddNativeField("spreecount", TypeUInt8, myoffsetof(player_t, spreecount)); - pstruct->AddNativeField("WeaponState", TypeUInt16, myoffsetof(player_t, WeaponState)); - pstruct->AddNativeField("ReadyWeapon", TypeWeapon, myoffsetof(player_t, ReadyWeapon)); - pstruct->AddNativeField("PendingWeapon", TypeWeapon, myoffsetof(player_t, PendingWeapon)); - pstruct->AddNativeField("psprites", NewPointer(RUNTIME_CLASS(DPSprite)), myoffsetof(player_t, psprites)); - pstruct->AddNativeField("cheats", TypeSInt32, myoffsetof(player_t, cheats)); - pstruct->AddNativeField("timefreezer", TypeSInt32, myoffsetof(player_t, timefreezer)); - pstruct->AddNativeField("refire", TypeSInt16, myoffsetof(player_t, refire)); - pstruct->AddNativeField("inconsistent", TypeSInt16, myoffsetof(player_t, inconsistant)); - pstruct->AddNativeField("waiting", TypeSInt32, myoffsetof(player_t, waiting)); - pstruct->AddNativeField("killcount", TypeSInt32, myoffsetof(player_t, killcount)); - pstruct->AddNativeField("itemcount", TypeSInt32, myoffsetof(player_t, itemcount)); - pstruct->AddNativeField("secretcount", TypeSInt32, myoffsetof(player_t, secretcount)); - pstruct->AddNativeField("damagecount", TypeSInt32, myoffsetof(player_t, damagecount)); - pstruct->AddNativeField("bonuscount", TypeSInt32, myoffsetof(player_t, bonuscount)); - pstruct->AddNativeField("hazardcount", TypeSInt32, myoffsetof(player_t, hazardcount)); - pstruct->AddNativeField("hazardinterval", TypeSInt32, myoffsetof(player_t, hazardinterval)); - pstruct->AddNativeField("hazardtype", TypeName, myoffsetof(player_t, hazardtype)); - pstruct->AddNativeField("poisoncount", TypeSInt32, myoffsetof(player_t, poisoncount)); - pstruct->AddNativeField("poisontype", TypeName, myoffsetof(player_t, poisontype)); - pstruct->AddNativeField("poisonpaintype", TypeName, myoffsetof(player_t, poisonpaintype)); - pstruct->AddNativeField("poisoner", TypeActor, myoffsetof(player_t, poisoner)); - pstruct->AddNativeField("attacker", TypeActor, myoffsetof(player_t, attacker)); - pstruct->AddNativeField("extralight", TypeSInt32, myoffsetof(player_t, extralight)); - pstruct->AddNativeField("fixedcolormap", TypeSInt16, myoffsetof(player_t, fixedcolormap)); - pstruct->AddNativeField("fixedlightlevel", TypeSInt16, myoffsetof(player_t, fixedlightlevel)); - pstruct->AddNativeField("morphtics", TypeSInt32, myoffsetof(player_t, morphTics)); - pstruct->AddNativeField("MorphedPlayerClass", TypeClassPlayerPawn, myoffsetof(player_t, MorphedPlayerClass)); - pstruct->AddNativeField("MorphStyle", TypeSInt32, myoffsetof(player_t, MorphStyle)); - pstruct->AddNativeField("MorphExitFlash", TypeClassActor, myoffsetof(player_t, MorphExitFlash)); - pstruct->AddNativeField("PremorphWeapon", TypeClassWeapon, myoffsetof(player_t, PremorphWeapon)); - pstruct->AddNativeField("chickenPeck", TypeSInt32, myoffsetof(player_t, chickenPeck)); - pstruct->AddNativeField("jumpTics", TypeSInt32, myoffsetof(player_t, jumpTics)); - pstruct->AddNativeField("onground", TypeBool, myoffsetof(player_t, onground)); - pstruct->AddNativeField("respawn_time", TypeSInt32, myoffsetof(player_t, respawn_time)); - pstruct->AddNativeField("camera", TypeActor, myoffsetof(player_t, camera)); - pstruct->AddNativeField("air_finished", TypeSInt32, myoffsetof(player_t, air_finished)); - pstruct->AddNativeField("LastDamageType", TypeName, myoffsetof(player_t, LastDamageType)); - pstruct->AddNativeField("MUSINFOactor", TypeActor, myoffsetof(player_t, MUSINFOactor)); - pstruct->AddNativeField("MUSINFOtics", TypeSInt8, myoffsetof(player_t, MUSINFOtics)); - pstruct->AddNativeField("settings_controller", TypeBool, myoffsetof(player_t, settings_controller)); - pstruct->AddNativeField("crouching", TypeSInt8, myoffsetof(player_t, crouching)); - pstruct->AddNativeField("crouchdir", TypeSInt8, myoffsetof(player_t, crouchdir)); - pstruct->AddNativeField("bot", NewPointer(RUNTIME_CLASS(DBot)), myoffsetof(player_t, Bot)); - pstruct->AddNativeField("BlendR", TypeFloat32, myoffsetof(player_t, BlendR)); - pstruct->AddNativeField("BlendG", TypeFloat32, myoffsetof(player_t, BlendG)); - pstruct->AddNativeField("BlendB", TypeFloat32, myoffsetof(player_t, BlendB)); - pstruct->AddNativeField("BlendA", TypeFloat32, myoffsetof(player_t, BlendA)); - pstruct->AddNativeField("LogText", TypeString, myoffsetof(player_t, LogText)); - pstruct->AddNativeField("MinPitch", TypeFloat64, myoffsetof(player_t, MinPitch)); - pstruct->AddNativeField("MaxPitch", TypeFloat64, myoffsetof(player_t, MaxPitch)); - pstruct->AddNativeField("crouchfactor", TypeFloat64, myoffsetof(player_t, crouchfactor)); - pstruct->AddNativeField("crouchoffset", TypeFloat64, myoffsetof(player_t, crouchoffset)); - pstruct->AddNativeField("crouchviewdelta", TypeFloat64, myoffsetof(player_t, crouchviewdelta)); - pstruct->AddNativeField("ConversationNPC", TypeActor, myoffsetof(player_t, ConversationNPC)); - pstruct->AddNativeField("ConversationPC", TypeActor, myoffsetof(player_t, ConversationPC)); - pstruct->AddNativeField("ConversationNPCAngle", TypeFloat64, myoffsetof(player_t, ConversationNPCAngle)); - pstruct->AddNativeField("ConversationFaceTalker", TypeBool, myoffsetof(player_t, ConversationFaceTalker)); -} \ No newline at end of file +DEFINE_FIELD_X(PlayerInfo, player_t, mo) +DEFINE_FIELD_X(PlayerInfo, player_t, playerstate) +DEFINE_FIELD_X(PlayerInfo, player_t, original_oldbuttons) +DEFINE_FIELD_X(PlayerInfo, player_t, cls) +DEFINE_FIELD_X(PlayerInfo, player_t, DesiredFOV) +DEFINE_FIELD_X(PlayerInfo, player_t, FOV) +DEFINE_FIELD_X(PlayerInfo, player_t, viewz) +DEFINE_FIELD_X(PlayerInfo, player_t, viewheight) +DEFINE_FIELD_X(PlayerInfo, player_t, deltaviewheight) +DEFINE_FIELD_X(PlayerInfo, player_t, bob) +DEFINE_FIELD_X(PlayerInfo, player_t, Vel) +DEFINE_FIELD_X(PlayerInfo, player_t, centering) +DEFINE_FIELD_X(PlayerInfo, player_t, turnticks) +DEFINE_FIELD_X(PlayerInfo, player_t, attackdown) +DEFINE_FIELD_X(PlayerInfo, player_t, usedown) +DEFINE_FIELD_X(PlayerInfo, player_t, oldbuttons) +DEFINE_FIELD_X(PlayerInfo, player_t, health) +DEFINE_FIELD_X(PlayerInfo, player_t, inventorytics) +DEFINE_FIELD_X(PlayerInfo, player_t, CurrentPlayerClass) +DEFINE_FIELD_X(PlayerInfo, player_t, frags) +DEFINE_FIELD_X(PlayerInfo, player_t, fragcount) +DEFINE_FIELD_X(PlayerInfo, player_t, lastkilltime) +DEFINE_FIELD_X(PlayerInfo, player_t, multicount) +DEFINE_FIELD_X(PlayerInfo, player_t, spreecount) +DEFINE_FIELD_X(PlayerInfo, player_t, WeaponState) +DEFINE_FIELD_X(PlayerInfo, player_t, ReadyWeapon) +DEFINE_FIELD_X(PlayerInfo, player_t, PendingWeapon) +DEFINE_FIELD_X(PlayerInfo, player_t, psprites) +DEFINE_FIELD_X(PlayerInfo, player_t, cheats) +DEFINE_FIELD_X(PlayerInfo, player_t, timefreezer) +DEFINE_FIELD_X(PlayerInfo, player_t, refire) +DEFINE_FIELD_NAMED_X(PlayerInfo, player_t, inconsistant, inconsistent) +DEFINE_FIELD_X(PlayerInfo, player_t, waiting) +DEFINE_FIELD_X(PlayerInfo, player_t, killcount) +DEFINE_FIELD_X(PlayerInfo, player_t, itemcount) +DEFINE_FIELD_X(PlayerInfo, player_t, secretcount) +DEFINE_FIELD_X(PlayerInfo, player_t, damagecount) +DEFINE_FIELD_X(PlayerInfo, player_t, bonuscount) +DEFINE_FIELD_X(PlayerInfo, player_t, hazardcount) +DEFINE_FIELD_X(PlayerInfo, player_t, hazardinterval) +DEFINE_FIELD_X(PlayerInfo, player_t, hazardtype) +DEFINE_FIELD_X(PlayerInfo, player_t, poisoncount) +DEFINE_FIELD_X(PlayerInfo, player_t, poisontype) +DEFINE_FIELD_X(PlayerInfo, player_t, poisonpaintype) +DEFINE_FIELD_X(PlayerInfo, player_t, poisoner) +DEFINE_FIELD_X(PlayerInfo, player_t, attacker) +DEFINE_FIELD_X(PlayerInfo, player_t, extralight) +DEFINE_FIELD_X(PlayerInfo, player_t, fixedcolormap) +DEFINE_FIELD_X(PlayerInfo, player_t, fixedlightlevel) +DEFINE_FIELD_X(PlayerInfo, player_t, morphTics) +DEFINE_FIELD_X(PlayerInfo, player_t, MorphedPlayerClass) +DEFINE_FIELD_X(PlayerInfo, player_t, MorphStyle) +DEFINE_FIELD_X(PlayerInfo, player_t, MorphExitFlash) +DEFINE_FIELD_X(PlayerInfo, player_t, PremorphWeapon) +DEFINE_FIELD_X(PlayerInfo, player_t, chickenPeck) +DEFINE_FIELD_X(PlayerInfo, player_t, jumpTics) +DEFINE_FIELD_X(PlayerInfo, player_t, onground) +DEFINE_FIELD_X(PlayerInfo, player_t, respawn_time) +DEFINE_FIELD_X(PlayerInfo, player_t, camera) +DEFINE_FIELD_X(PlayerInfo, player_t, air_finished) +DEFINE_FIELD_X(PlayerInfo, player_t, LastDamageType) +DEFINE_FIELD_X(PlayerInfo, player_t, MUSINFOactor) +DEFINE_FIELD_X(PlayerInfo, player_t, MUSINFOtics) +DEFINE_FIELD_X(PlayerInfo, player_t, settings_controller) +DEFINE_FIELD_X(PlayerInfo, player_t, crouching) +DEFINE_FIELD_X(PlayerInfo, player_t, crouchdir) +DEFINE_FIELD_X(PlayerInfo, player_t, Bot) +DEFINE_FIELD_X(PlayerInfo, player_t, BlendR) +DEFINE_FIELD_X(PlayerInfo, player_t, BlendG) +DEFINE_FIELD_X(PlayerInfo, player_t, BlendB) +DEFINE_FIELD_X(PlayerInfo, player_t, BlendA) +DEFINE_FIELD_X(PlayerInfo, player_t, LogText) +DEFINE_FIELD_X(PlayerInfo, player_t, MinPitch) +DEFINE_FIELD_X(PlayerInfo, player_t, MaxPitch) +DEFINE_FIELD_X(PlayerInfo, player_t, crouchfactor) +DEFINE_FIELD_X(PlayerInfo, player_t, crouchoffset) +DEFINE_FIELD_X(PlayerInfo, player_t, crouchviewdelta) +DEFINE_FIELD_X(PlayerInfo, player_t, ConversationNPC) +DEFINE_FIELD_X(PlayerInfo, player_t, ConversationPC) +DEFINE_FIELD_X(PlayerInfo, player_t, ConversationNPCAngle) +DEFINE_FIELD_X(PlayerInfo, player_t, ConversationFaceTalker) +DEFINE_FIELD_X(PlayerInfo, player_t, cmd) +DEFINE_FIELD_X(PlayerInfo, player_t, original_cmd) +DEFINE_FIELD_X(PlayerInfo, player_t, userinfo) +DEFINE_FIELD_X(PlayerInfo, player_t, weapons) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index d50f73bd37..7488c97167 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -63,7 +63,7 @@ static TArray FieldTable; #define DEFINE_DUMMY_FLAG(name, deprec) { DEPF_UNUSED, #name, -1, 0, deprec? VARF_Deprecated:0 } // internal flags. These do not get exposed to actor definitions but scripts need to be able to access them as variables. -FFlagDef InternalActorFlagDefs[]= +static FFlagDef InternalActorFlagDefs[]= { DEFINE_FLAG(MF, INCHASE, AActor, flags), DEFINE_FLAG(MF, UNMORPHED, AActor, flags), @@ -90,11 +90,10 @@ FFlagDef InternalActorFlagDefs[]= DEFINE_FLAG(MF6, INTRYMOVE, AActor, flags6), DEFINE_FLAG(MF7, HANDLENODELAY, AActor, flags7), DEFINE_FLAG(MF7, FLYCHEAT, AActor, flags7), - { 0xffffffff } }; -FFlagDef ActorFlagDefs[]= +static FFlagDef ActorFlagDefs[]= { DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags), DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags), @@ -328,7 +327,6 @@ 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 @@ -387,10 +385,9 @@ static FFlagDef InventoryFlagDefs[] = DEFINE_DEPRECATED_FLAG(PICKUPFLASH), DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP), - { 0xffffffff } }; -FFlagDef WeaponFlagDefs[] = +static FFlagDef WeaponFlagDefs[] = { // Weapon flags DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags), @@ -417,7 +414,6 @@ FFlagDef WeaponFlagDefs[] = DEFINE_DUMMY_FLAG(NOLMS, false), DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false), - { 0xffffffff } }; @@ -428,24 +424,23 @@ static FFlagDef PlayerPawnFlagDefs[] = DEFINE_FLAG(PPF, NOTHRUSTWHENINVUL, APlayerPawn, PlayerFlags), DEFINE_FLAG(PPF, CANSUPERMORPH, APlayerPawn, PlayerFlags), DEFINE_FLAG(PPF, CROUCHABLEMORPH, APlayerPawn, PlayerFlags), - { 0xffffffff } }; static FFlagDef PowerSpeedFlagDefs[] = { // PowerSpeed flags DEFINE_FLAG(PSF, NOTRAIL, APowerSpeed, SpeedFlags), - { 0xffffffff } }; -static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] = +static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; int Use; } FlagLists[] = { - { &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)-1 }, - { &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs)-1 }, - { &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs)-1 }, - { &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs)-1 }, + { &RUNTIME_CLASS_CASTLESS(AActor), ActorFlagDefs, countof(ActorFlagDefs), 3 }, // -1 to account for the terminator + { &RUNTIME_CLASS_CASTLESS(AActor), MoreFlagDefs, countof(MoreFlagDefs), 1 }, + { &RUNTIME_CLASS_CASTLESS(AActor), InternalActorFlagDefs, countof(InternalActorFlagDefs), 2 }, + { &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs), 3 }, + { &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs), 3 }, + { &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs), 3 }, + { &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs), 3 }, }; #define NUM_FLAG_LISTS (countof(FlagLists)) @@ -493,7 +488,7 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bo int max = strict ? 2 : NUM_FLAG_LISTS; for (int i = 0; i < max; ++i) { - if (type->IsDescendantOf (*FlagLists[i].Type)) + if ((FlagLists[i].Use & 1) && type->IsDescendantOf (*FlagLists[i].Type)) { def = FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part1); if (def != NULL) @@ -709,9 +704,35 @@ void InitThingdef() sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); G_InitLevelLocalsForScript(); - P_InitPlayerForScript(); P_InitStateForScript(); + // set up a variable for the global players array. + PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); + pstruct->Size = sizeof(player_t); + pstruct->Align = alignof(player_t); + PArray *parray = NewArray(pstruct, MAXPLAYERS); + PField *playerf = new PField("players", pstruct, VARF_Native | VARF_Static, (intptr_t)&players); + GlobalSymbols.AddSymbol(playerf); + + + // this needs to be done manually until it can be given a proper type. + RUNTIME_CLASS(AActor)->AddNativeField("DecalGenerator", NewPointer(TypeVoid), myoffsetof(AActor, DecalGenerator)); + + // synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them. + for (auto &fl : FlagLists) + { + if (fl.Use & 2) + { + for(int i=0;i 0) // skip the deprecated entries in this list + { + const_cast(*fl.Type)->AddNativeField(FStringf("b%s", fl.Defs[i].name), (fl.Defs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), fl.Defs[i].structoffset, fl.Defs[i].varflags, fl.Defs[i].flagbit); + } + } + } + } + FAutoSegIterator probe(CRegHead, CRegTail); while (*++probe != NULL) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index f2edca9b9c..10ac4bb7b9 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1061,7 +1061,12 @@ struct AFuncDesc #define DEFINE_FIELD_X(cls, icls, name) \ static const FieldDesc VMField_##icls##_##name = { "A" #cls, #name, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), 0 }; \ extern FieldDesc const *const VMField_##icls##_##name##_HookPtr; \ - MSVC_FSEG FieldDesc const *const VMField_##icls##_##name##_HookPtr GCC_FSEG = &VMField_##cls##_##name; + MSVC_FSEG FieldDesc const *const VMField_##icls##_##name##_HookPtr GCC_FSEG = &VMField_##icls##_##name; + +#define DEFINE_FIELD_NAMED_X(cls, icls, name, scriptname) \ + static const FieldDesc VMField_##icls##_##scriptname = { "A" #cls, #scriptname, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), 0 }; \ + extern FieldDesc const *const VMField_##icls##_##scriptname##_HookPtr; \ + MSVC_FSEG FieldDesc const *const VMField_##icls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##icls##_##scriptname; #define DEFINE_FIELD_X_BIT(cls, icls, name, bitval) \ static const FieldDesc VMField_##icls##_##name = { "A" #cls, #name, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), bitval }; \ diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 80057724cd..fc1803f1dc 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -295,8 +295,9 @@ struct_flags(X) ::= NATIVE. { X.Flags = ZCC_Native; } opt_struct_body(X) ::= . { X = NULL; } opt_struct_body(X) ::= struct_body(X). +opt_struct_body(X) ::= error. { X = NULL; } + -struct_body(X) ::= error. { X = NULL; } struct_body(X) ::= struct_member(X). struct_body(X) ::= struct_member(A) struct_body(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 72bfcf7355..ac9a8825c4 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1274,7 +1274,9 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel 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; + int notallowed = forstruct? + ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract | ZCC_Virtual | ZCC_Override | ZCC_Meta | ZCC_Extension : + ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract | ZCC_Virtual | ZCC_Override | ZCC_Extension; if (field->Flags & notallowed) { @@ -1323,13 +1325,15 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel { Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars()); } - else if (thisfieldtype->Size != fd->FieldSize) + else if (thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0) { Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size); } // Q: Should we check alignment, too? A mismatch may be an indicator for bad assumptions. else { + // for bit fields the type must point to the source variable. + if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue); } } @@ -1427,6 +1431,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n case ZCC_FloatAuto: retval = formember ? TypeFloat32 : TypeFloat64; + break; case ZCC_Float64: retval = TypeFloat64; diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index e000da06c5..a2fc3fb560 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -164,6 +164,11 @@ struct ZCC_TreeNode // Appends a sibling to this node's sibling list. void AppendSibling(ZCC_TreeNode *sibling) { + if (this == nullptr) + { + // Some bad syntax can actually get here, so better abort so that the user can see the error which caused this. + I_FatalError("Internal script compiler error. Execution aborted."); + } if (sibling == NULL) { return; diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index b3f48acaea..0f28de3356 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -1,5 +1,7 @@ class Object native { + native bool bDestroyed; + // These really should be global functions... native static int G_SkillPropertyInt(int p); native static double G_SkillPropertyFloat(int p); @@ -35,12 +37,10 @@ class ActorIterator : Object native 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; - */ + native int Amount; } class SpotState : Object native diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index b5b60481aa..68b81dc2b0 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,5 +1,6 @@ // for flag changer functions. const FLAG_NO_CHANGE = -1; +const MAXPLAYERS = 8; enum EStateUseFlags { diff --git a/wadsrc/static/zscript/doom/weaponchaingun.txt b/wadsrc/static/zscript/doom/weaponchaingun.txt index 92b3aec463..3766b9b6e0 100644 --- a/wadsrc/static/zscript/doom/weaponchaingun.txt +++ b/wadsrc/static/zscript/doom/weaponchaingun.txt @@ -70,7 +70,7 @@ extend class StateProvider { // Removed most of the mess that was here in the C++ code because SetSafeFlash already does some thorough validation. State atk = weap.FindState('Fire'); - State cur = player.GetPSprite(PSP_WEAPON).State; + State cur = player.GetPSprite(PSP_WEAPON).CurState; int theflash = atk == cur? 0:1; player.SetSafeFlash(weap, flash, theflash); } diff --git a/wadsrc/static/zscript/shared/botstuff.txt b/wadsrc/static/zscript/shared/botstuff.txt index cf671ea8be..3ae2d18894 100644 --- a/wadsrc/static/zscript/shared/botstuff.txt +++ b/wadsrc/static/zscript/shared/botstuff.txt @@ -23,3 +23,7 @@ class CajunTrace : Actor +NOTELEPORT } } + +struct Bot native +{ +} diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 2a9aabe272..929f826da9 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -102,6 +102,14 @@ class BasicArmor : Armor native class BasicArmorBonus : Armor native { + native double SavePercent; // The default, for when you don't already have armor + native int MaxSaveAmount; + native int MaxAbsorb; + native int MaxFullAbsorb; + native int SaveAmount; + native int BonusCount; + native int BonusMax; + Default { +Inventory.AUTOACTIVATE @@ -438,6 +446,32 @@ class PuzzleItem : Inventory native class Weapon : StateProvider native { + native uint WeaponFlags; + native class AmmoType1, AmmoType2; // Types of ammo used by this weapon + native int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon + native int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon + native int AmmoUse1, AmmoUse2; // How much ammo to use with each shot + native int Kickback; + native float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) + native sound UpSound, ReadySound; // Sounds when coming up and idle + native class SisterWeaponType; // Another weapon to pick up with this one + native class ProjectileType; // Projectile used by primary attack + native class AltProjectileType; // Projectile used by alternate attack + native int SelectionOrder; // Lower-numbered weapons get picked first + native int MinSelAmmo1, MinSelAmmo2; // Ignore in BestWeapon() if inadequate ammo + native double MoveCombatDist; // Used by bots, but do they *really* need it? + native int ReloadCounter; // For A_CheckForReload + native int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double) + native float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs. + native float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction. + native Ammo Ammo1, Ammo2; // In-inventory instance variables + native Weapon SisterWeapon; + native float FOVScale; + native int Crosshair; // 0 to use player's crosshair + native bool GivenAsMorphWeapon; + native bool bAltFire; // Set when this weapon's alternate fire is used. + native readonly bool bDehAmmo; + Default { Inventory.PickupSound "misc/w_pkup"; diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 71cdb84799..ed95354f89 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -1,5 +1,31 @@ class PlayerPawn : Actor native { + + native int crouchsprite; + native int MaxHealth; + native int MugShotMaxHealth; + native int RunHealth; + native int PlayerFlags; + native Inventory InvFirst; // first inventory item displayed on inventory bar + native Inventory InvSel; // selected inventory item + + // [GRB] Player class properties + native double JumpZ; + native double GruntSpeed; + native double FallingScreamMinSpeed, FallingScreamMaxSpeed; + native double ViewHeight; + native double ForwardMove1, ForwardMove2; + native double SideMove1, SideMove2; + native TextureID ScoreIcon; + native int SpawnMask; + native Name MorphWeapon; + native double AttackZOffset; // attack height, relative to player center + native double UseRange; // [NS] Distance at which player can +use + native double AirCapacity; // Multiplier for air supply underwater. + native Class FlechetteType; + native color DamageFade; // [CW] Fades for when you are being damaged. + native double ViewBob; // [SP] ViewBob Multiplier + Default { Health 100; @@ -75,10 +101,118 @@ class PlayerChunk : PlayerPawn native class PSprite : Object native { + native readonly State CurState; + native readonly Actor Caller; + native readonly PSprite Next; + native readonly PlayerInfo Owner; + native SpriteID Sprite; + native int Frame; + native readonly int ID; + native Bool processPending; + native double x; + native double y; + native double oldx; + native double oldy; + native Bool firstTic; + native int Tics; + native bool bAddWeapon; + native bool bAddBob; + native bool bPowDouble; + native bool bCVarFast; + native bool bFlip; } -struct PlayerInfo native // this is what internally is player_t +struct PlayerInfo native // this is what internally is known as player_t { + native readonly PlayerPawn mo; + native uint8 playerstate; + native uint original_oldbuttons; + native readonly Class cls; + native float DesiredFOV; + native readonly float FOV; + native double viewz; + native double viewheight; + native double deltaviewheight; + native double bob; + native vector2 vel; + native bool centering; + native uint8 turnticks; + native bool attackdown; + native bool usedown; + native uint oldbuttons; + native int health; + native int inventorytics; + native uint8 CurrentPlayerClass; + native int frags[MAXPLAYERS]; + native int fragcount; + native int lastkilltime; + native uint8 multicount; + native uint8 spreecount; + native uint16 WeaponState; + native Weapon ReadyWeapon; + native Weapon PendingWeapon; + native PSprite psprites; + native int cheats; + native int timefreezer; + native int16 refire; + native int16 inconsistent; + native bool waiting; + native int killcount; + native int itemcount; + native int secretcount; + native int damagecount; + native int bonuscount; + native int hazardcount; + native int hazardinterval; + native Name hazardtype; + native int poisoncount; + native Name poisontype; + native Name poisonpaintype; + native Actor poisoner; + native Actor attacker; + native int extralight; + native int16 fixedcolormap; + native int16 fixedlightlevel; + native int morphtics; + native ClassMorphedPlayerClass; + native int MorphStyle; + native Class MorphExitFlash; + native Class PremorphWeapon; + native int chickenPeck; + native int jumpTics; + native bool onground; + native int respawn_time; + native Actor camera; + native int air_finished; + native Name LastDamageType; + native Actor MUSINFOactor; + native int8 MUSINFOtics; + native bool settings_controller; + native int8 crouching; + native int8 crouchdir; + native Bot bot; + native float BlendR; + native float BlendG; + native float BlendB; + native float BlendA; + native String LogText; + native double MinPitch; + native double MaxPitch; + native double crouchfactor; + native double crouchoffset; + native double crouchviewdelta; + native Actor ConversationNPC; + native Actor ConversationPC; + native double ConversationNPCAngle; + native bool ConversationFaceTalker; +/* these are not doable yet +ticcmd_t cmd; +usercmd_t original_cmd; +userinfo_t userinfo; // [RH] who is this? +FWeaponSlots weapons; +*/ + + native void SetPsprite(int id, State stat, bool pending = false); native void SetSafeFlash(Weapon weap, State flashstate, int index); native PSprite GetPSprite(int id); From 46757ff8bfbe3716bdc7c8903c7d953c88aeba63 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Nov 2016 00:35:06 +0100 Subject: [PATCH 336/471] - exported the native fields of FState and FLevelLocals as well. --- src/g_level.cpp | 82 +++++++++++++++------------------ src/p_states.cpp | 36 ++++++--------- src/scripting/thingdef_data.cpp | 9 ++-- wadsrc/static/zscript/base.txt | 59 ++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 72 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 8987aed6c2..a715b5d263 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1850,55 +1850,45 @@ 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 = NewNativeStruct("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)); -} +DEFINE_FIELD(FLevelLocals, time) +DEFINE_FIELD(FLevelLocals, maptime) +DEFINE_FIELD(FLevelLocals, totaltime) +DEFINE_FIELD(FLevelLocals, starttime) +DEFINE_FIELD(FLevelLocals, partime) +DEFINE_FIELD(FLevelLocals, sucktime) +DEFINE_FIELD(FLevelLocals, cluster) +DEFINE_FIELD(FLevelLocals, clusterflags) +DEFINE_FIELD(FLevelLocals, levelnum) +DEFINE_FIELD(FLevelLocals, LevelName) +DEFINE_FIELD(FLevelLocals, MapName) +DEFINE_FIELD(FLevelLocals, NextMap) +DEFINE_FIELD(FLevelLocals, NextSecretMap) +DEFINE_FIELD(FLevelLocals, maptype) +DEFINE_FIELD(FLevelLocals, Music) +DEFINE_FIELD(FLevelLocals, musicorder) +DEFINE_FIELD(FLevelLocals, total_secrets) +DEFINE_FIELD(FLevelLocals, found_secrets) +DEFINE_FIELD(FLevelLocals, total_items) +DEFINE_FIELD(FLevelLocals, found_items) +DEFINE_FIELD(FLevelLocals, total_monsters) +DEFINE_FIELD(FLevelLocals, killed_monsters) +DEFINE_FIELD(FLevelLocals, gravity) +DEFINE_FIELD(FLevelLocals, aircontrol) +DEFINE_FIELD(FLevelLocals, airfriction) +DEFINE_FIELD(FLevelLocals, airsupply) +DEFINE_FIELD(FLevelLocals, teamdamage) +DEFINE_FIELD_BIT(FLevelLocals, flags, monsterstelefrag, LEVEL_MONSTERSTELEFRAG) +DEFINE_FIELD_BIT(FLevelLocals, flags, actownspecial, LEVEL_ACTOWNSPECIAL) +DEFINE_FIELD_BIT(FLevelLocals, flags, sndseqtotalctrl, LEVEL_SNDSEQTOTALCTRL) +DEFINE_FIELD_BIT(FLevelLocals, flags2, allmap, LEVEL2_ALLMAP) +DEFINE_FIELD_BIT(FLevelLocals, flags2, missilesactivateimpact, LEVEL2_MISSILESACTIVATEIMPACT) +DEFINE_FIELD_BIT(FLevelLocals, flags2, monsterfallingdamage, LEVEL2_MONSTERFALLINGDAMAGE) +DEFINE_FIELD_BIT(FLevelLocals, flags2, checkswitchrange, LEVEL2_CHECKSWITCHRANGE) +DEFINE_FIELD_BIT(FLevelLocals, flags2, polygrind, LEVEL2_POLYGRIND) //========================================================================== // diff --git a/src/p_states.cpp b/src/p_states.cpp index 6e45db6b0e..b3e9593af6 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -1063,24 +1063,18 @@ CCMD(dumpstates) // //========================================================================== -void P_InitStateForScript() -{ - PNativeStruct *pstruct = dyn_cast(TypeState->PointedType); - assert(pstruct != nullptr); - - pstruct->AddNativeField("NextState", TypeState, myoffsetof(FState, NextState), VARF_ReadOnly); - pstruct->AddNativeField("sprite", TypeSInt32, myoffsetof(FState, sprite), VARF_ReadOnly); - pstruct->AddNativeField("Tics", TypeSInt16, myoffsetof(FState, Tics), VARF_ReadOnly); - pstruct->AddNativeField("TicRange", TypeUInt16, myoffsetof(FState, TicRange), VARF_ReadOnly); - pstruct->AddNativeField("Frame", TypeUInt8, myoffsetof(FState, Frame), VARF_ReadOnly); - pstruct->AddNativeField("UseFlags", TypeUInt8, myoffsetof(FState, UseFlags), VARF_ReadOnly); - pstruct->AddNativeField("Misc1", TypeSInt32, myoffsetof(FState, Misc1), VARF_ReadOnly); - pstruct->AddNativeField("Misc2", TypeSInt32, myoffsetof(FState, Misc2), VARF_ReadOnly); - pstruct->AddNativeField("bSlow", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_SLOW); - pstruct->AddNativeField("bFast", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_FAST); - pstruct->AddNativeField("bFullbright", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_FULLBRIGHT); - pstruct->AddNativeField("bNoDelay", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_NODELAY); - pstruct->AddNativeField("bSameFrame", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_SAMEFRAME); - pstruct->AddNativeField("bCanRaise", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_CANRAISE); - pstruct->AddNativeField("bDehacked", TypeUInt16, myoffsetof(FState, StateFlags), VARF_ReadOnly, STF_DEHACKED); -} \ No newline at end of file +DEFINE_FIELD(FState, NextState) +DEFINE_FIELD(FState, sprite) +DEFINE_FIELD(FState, Tics) +DEFINE_FIELD(FState, TicRange) +DEFINE_FIELD(FState, Frame) +DEFINE_FIELD(FState, UseFlags) +DEFINE_FIELD(FState, Misc1) +DEFINE_FIELD(FState, Misc2) +DEFINE_FIELD_BIT(FState, StateFlags, bSlow) +DEFINE_FIELD_BIT(FState, StateFlags, bFast) +DEFINE_FIELD_BIT(FState, StateFlags, bFullbright) +DEFINE_FIELD_BIT(FState, StateFlags, bNoDelay) +DEFINE_FIELD_BIT(FState, StateFlags, bSameFrame) +DEFINE_FIELD_BIT(FState, StateFlags, bCanRaise) +DEFINE_FIELD_BIT(FState, StateFlags, bDehacked) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 7488c97167..bc6e0ad43a 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -691,9 +691,6 @@ static int fieldcmp(const void * a, const void * b) // Initialization // //========================================================================== -void G_InitLevelLocalsForScript(); -void P_InitPlayerForScript(); -void P_InitStateForScript(); void InitThingdef() { @@ -703,8 +700,10 @@ void InitThingdef() auto sptr = NewPointer(sstruct); sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); - G_InitLevelLocalsForScript(); - P_InitStateForScript(); + // set up a variable for the global level data structure + PStruct *lstruct = NewNativeStruct("LevelLocals", nullptr); + PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level); + GlobalSymbols.AddSymbol(levelf); // set up a variable for the global players array. PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 0f28de3356..15a8c9a3b6 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -49,6 +49,65 @@ class SpotState : Object native native SpecialSpot GetNextInList(class type, int skipcounter); } +struct LevelLocals native +{ + native readonly int time; + native readonly int maptime; + native readonly int totaltime; + native readonly int starttime; + native readonly int partime; + native readonly int sucktime; + native readonly int cluster; + native readonly int clusterflags; + native readonly int levelnum; + native readonly String LevelName; + native readonly String MapName; + native String NextMap; + native String NextSecretMap; + native readonly int maptype; + native readonly String Music; + native readonly int musicorder; + native readonly int total_secrets; + native int found_secrets; + native readonly int total_items; + native int found_items; + native readonly int total_monsters; + native int killed_monsters; + native double gravity; + native double aircontrol; + native double airfriction; + native int airsupply; + native double teamdamage; + native bool monsterstelefrag; + native bool actownspecial; + native bool sndseqtotalctrl; + native bool allmap; + native bool missilesactivateimpact; + native bool monsterfallingdamage; + native bool checkswitchrange; + native bool polygrind; +// level_info_t *info cannot be done yet. +} + +struct State native +{ + State NextState; + int sprite; + int16 Tics; + uint16 TicRange; + uint8 Frame; + uint8 UseFlags; + int Misc1; + int Misc2; + uint16 bSlow; + uint16 bFast; + bool bFullbright; + bool bNoDelay; + bool bSameFrame; + bool bCanRaise; + bool bDehacked; +} + struct Sector native { } From 0c95568d98fe6e23c99361f770a933d17f575b69 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Nov 2016 01:31:48 +0100 Subject: [PATCH 337/471] - exported native fields of several more classes. --- src/g_shared/a_armor.cpp | 18 +++++++++ src/g_shared/a_pickups.cpp | 24 +++++++++++- src/g_shared/a_pickups.h | 2 +- src/scripting/decorate/olddecorations.cpp | 2 + src/scripting/vm/vm.h | 1 + wadsrc/static/zscript/shared/inventory.txt | 45 +++++++++++++++++++++- 6 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 8f1116a9e5..e1dd0986e7 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -15,6 +15,15 @@ IMPLEMENT_CLASS(ABasicArmorPickup, false, false, false, false) IMPLEMENT_CLASS(ABasicArmorBonus, false, false, true, false) IMPLEMENT_CLASS(AHexenArmor, false, false, false, false) + +DEFINE_FIELD(ABasicArmor, AbsorbCount) +DEFINE_FIELD(ABasicArmor, SavePercent) +DEFINE_FIELD(ABasicArmor, MaxAbsorb) +DEFINE_FIELD(ABasicArmor, MaxFullAbsorb) +DEFINE_FIELD(ABasicArmor, BonusCount) +DEFINE_FIELD(ABasicArmor, ArmorType) +DEFINE_FIELD(ABasicArmor, ActualSaveAmount) + //=========================================================================== // // ABasicArmor :: Serialize @@ -193,6 +202,11 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage) } } +DEFINE_FIELD(ABasicArmorPickup, SavePercent) +DEFINE_FIELD(ABasicArmorPickup, MaxAbsorb) +DEFINE_FIELD(ABasicArmorPickup, MaxFullAbsorb) +DEFINE_FIELD(ABasicArmorPickup, SaveAmount) + //=========================================================================== // // ABasicArmorPickup :: Serialize @@ -396,6 +410,10 @@ bool ABasicArmorBonus::Use (bool pickup) return true; } + +DEFINE_FIELD(AHexenArmor, Slots) +DEFINE_FIELD(AHexenArmor, SlotsIncrement) + //=========================================================================== // // AHexenArmor :: Serialize diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index a3abe7cf4c..ce8f53d611 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -88,6 +88,9 @@ void PClassAmmo::DeriveData(PClass *newclass) IMPLEMENT_CLASS(AAmmo, false, false, false, false) +DEFINE_FIELD(AAmmo, BackpackAmount) +DEFINE_FIELD(AAmmo, BackpackMaxAmount) + //=========================================================================== // // AAmmo :: Serialize @@ -483,6 +486,20 @@ IMPLEMENT_POINTERS_START(AInventory) IMPLEMENT_POINTER(Owner) IMPLEMENT_POINTERS_END +DEFINE_FIELD_BIT(AInventory, ItemFlags, bPickupGood, IF_PICKUPGOOD) +DEFINE_FIELD_BIT(AInventory, ItemFlags, bCreateCopyMoved, IF_CREATECOPYMOVED) +DEFINE_FIELD_BIT(AInventory, ItemFlags, bInitEffectFailed, IF_INITEFFECTFAILED) +DEFINE_FIELD(AInventory, Owner) +DEFINE_FIELD(AInventory, Amount) +DEFINE_FIELD(AInventory, MaxAmount) +DEFINE_FIELD(AInventory, InterHubAmount) +DEFINE_FIELD(AInventory, RespawnTics) +DEFINE_FIELD(AInventory, Icon) +DEFINE_FIELD(AInventory, DropTime) +DEFINE_FIELD(AInventory, SpawnPointClass) +DEFINE_FIELD(AInventory, PickupFlash) +DEFINE_FIELD(AInventory, PickupSound) + //=========================================================================== // // AInventory :: Tick @@ -1739,6 +1756,8 @@ void PClassHealth::DeriveData(PClass *newclass) IMPLEMENT_CLASS(AHealth, false, false, false, false) +DEFINE_FIELD(AHealth, PrevHealth) + //=========================================================================== // // AHealth :: PickupMessage @@ -1858,6 +1877,10 @@ void AHealthPickup::Serialize(FSerializer &arc) // Backpack ----------------------------------------------------------------- +IMPLEMENT_CLASS(ABackpackItem, false, false, false, false) + +DEFINE_FIELD(ABackpackItem, bDepleted) + //=========================================================================== // // ABackpackItem :: Serialize @@ -2033,7 +2056,6 @@ void ABackpackItem::DetachFromOwner () // //=========================================================================== -IMPLEMENT_CLASS(ABackpackItem, false, false, false, false) IMPLEMENT_CLASS(AMapRevealer, false, false, false, false) //=========================================================================== diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 6dc2d0bc59..ec34404df2 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -429,8 +429,8 @@ class AHealth : public AInventory { DECLARE_CLASS_WITH_META(AHealth, AInventory, PClassHealth) - int PrevHealth; public: + int PrevHealth; virtual bool TryPickup (AActor *&other); virtual const char *PickupMessage (); }; diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index a2cbc636bf..7540d45f45 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -98,6 +98,8 @@ public: IMPLEMENT_CLASS(AFakeInventory, false, false, false, false) +DEFINE_FIELD(AFakeInventory, Respawnable) + // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 10ac4bb7b9..7b05fae36c 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -4,6 +4,7 @@ #include "zstring.h" #include "autosegs.h" #include "vectors.h" +#include "cmdlib.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 diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 929f826da9..47f753ca16 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -1,5 +1,20 @@ class Inventory : Actor native { + + native Actor Owner; // Who owns this item? NULL if it's still a pickup. + native int Amount; // Amount of item this instance has + native int MaxAmount; // Max amount of item this instance can have + native int InterHubAmount; // Amount of item that can be kept between hubs or levels + native int RespawnTics; // Tics from pickup time to respawn time + native TextureID Icon; // Icon to show on status bar or HUD + native int DropTime; // Countdown after dropping + native Class SpawnPointClass; // For respawning like Heretic's mace + native Class PickupFlash; // actor to spawn as pickup flash + native Sound PickupSound; + native bool bPickupGood; + native bool bCreateCopyMoved; + native bool bInitEffectFailed; + Default { Inventory.Amount 1; @@ -73,6 +88,9 @@ class ScoreItem : Inventory native class Ammo : Inventory native { + native int BackpackAmount; + native int BackpackMaxAmount; + Default { +INVENTORY.KEEPDEPLETED @@ -82,6 +100,7 @@ class Ammo : Inventory native class BackpackItem : Inventory native { + native bool bDepleted; } class Armor : Inventory native @@ -94,6 +113,15 @@ class Armor : Inventory native class BasicArmor : Armor native { + + native int AbsorbCount; + native double SavePercent; + native int MaxAbsorb; + native int MaxFullAbsorb; + native int BonusCount; + native Name ArmorType; + native int ActualSaveAmount; + Default { +Inventory.KEEPDEPLETED @@ -121,6 +149,12 @@ class BasicArmorBonus : Armor native class BasicArmorPickup : Armor native { + + native double SavePercent; + native int MaxAbsorb; + native int MaxFullAbsorb; + native int SaveAmount; + Default { +Inventory.AUTOACTIVATE; @@ -130,6 +164,10 @@ class BasicArmorPickup : Armor native class HexenArmor : Armor native { + + native double Slots[5]; + native double SlotsIncrement[4]; + Default { +Inventory.KEEPDEPLETED @@ -139,7 +177,10 @@ class HexenArmor : Armor native class DehackedPickup : Inventory native {} -class FakeInventory : Inventory native {} +class FakeInventory : Inventory native +{ + native bool Respawnable; +} class CustomInventory : StateProvider native { @@ -151,6 +192,8 @@ class CustomInventory : StateProvider native class Health : Inventory native { + native int PrevHealth; + Default { Inventory.Amount 1; From 7325e3f0f89a0d2431171fd9381d028f38a256e4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Nov 2016 17:34:36 +0100 Subject: [PATCH 338/471] - exported all member fields that make sense. Entirely private ones or classes that are not supposed to be extended were left out. --- src/g_shared/a_artifacts.cpp | 46 +++++++--------------- src/g_shared/a_artifacts.h | 7 ++-- src/g_shared/a_keys.cpp | 2 + src/g_shared/a_pickups.cpp | 2 + src/g_shared/a_puzzleitems.cpp | 2 + src/g_shared/a_weaponpiece.cpp | 3 ++ src/g_shared/a_weapons.cpp | 2 + src/p_states.cpp | 14 +++---- wadsrc/static/zscript/shared/inventory.txt | 40 ++++++++++++++++++- 9 files changed, 75 insertions(+), 43 deletions(-) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 7cf05613ab..66832c21c2 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -56,6 +56,13 @@ void PClassPowerupGiver::ReplaceClassRef(PClass *oldclass, PClass *newclass) } } + +DEFINE_FIELD(APowerupGiver, PowerupType) +DEFINE_FIELD(APowerupGiver, EffectTics) +DEFINE_FIELD(APowerupGiver, BlendColor) +DEFINE_FIELD(APowerupGiver, Mode) +DEFINE_FIELD(APowerupGiver, Strength) + //=========================================================================== // // APowerupGiver :: Use @@ -114,6 +121,11 @@ void APowerupGiver::Serialize(FSerializer &arc) // Powerup ------------------------------------------------------------------- +DEFINE_FIELD(APowerup, EffectTics) +DEFINE_FIELD(APowerup, BlendColor) +DEFINE_FIELD(APowerup, Mode) +DEFINE_FIELD(APowerup, Strength) + //=========================================================================== // // APowerup :: Tick @@ -1184,40 +1196,12 @@ void APowerWeaponLevel2::EndEffect () } } -// Player Speed Trail (used by the Speed Powerup) ---------------------------- - -class APlayerSpeedTrail : public AActor -{ - DECLARE_CLASS (APlayerSpeedTrail, AActor) -public: - void Tick (); -}; - -IMPLEMENT_CLASS(APlayerSpeedTrail, false, false, false, false) - -//=========================================================================== -// -// APlayerSpeedTrail :: Tick -// -//=========================================================================== - -void APlayerSpeedTrail::Tick () -{ - const double fade = .6 / 8; - if (Alpha <= fade) - { - Destroy (); - } - else - { - Alpha -= fade; - } -} - // Speed Powerup ------------------------------------------------------------- IMPLEMENT_CLASS(APowerSpeed, false, false, false, false) +DEFINE_FIELD(APowerSpeed, SpeedFlags) + //=========================================================================== // // APowerSpeed :: Serialize @@ -1280,7 +1264,7 @@ void APowerSpeed::DoEffect () if (Owner->Vel.LengthSquared() <= 12*12) return; - AActor *speedMo = Spawn (Owner->Pos(), NO_REPLACE); + AActor *speedMo = Spawn("PlayerSpeedTrail", Owner->Pos(), NO_REPLACE); if (speedMo) { speedMo->Angles.Yaw = Owner->Angles.Yaw; diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index 85ebc2e81b..163094d328 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -143,6 +143,7 @@ protected: void Tick (); void EndEffect (); +private: bool HitCenterFrame; }; @@ -281,15 +282,15 @@ public: virtual void Serialize(FSerializer &arc); void SetNoCallUndoMorph() { bNoCallUndoMorph = true; } + // Variables FNameNoInit PlayerClass, MorphFlash, UnMorphFlash; int MorphStyle; + player_t *Player; + bool bNoCallUndoMorph; // Because P_UndoPlayerMorph() can call EndEffect recursively protected: void InitEffect (); void EndEffect (); - // Variables - player_t *Player; - bool bNoCallUndoMorph; // Because P_UndoPlayerMorph() can call EndEffect recursively }; #endif //__A_ARTIFACTS_H__ diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index 69fbe48afb..538e26090f 100644 --- a/src/g_shared/a_keys.cpp +++ b/src/g_shared/a_keys.cpp @@ -472,6 +472,8 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote) IMPLEMENT_CLASS(AKey, false, false, false, false) +DEFINE_FIELD(AKey, KeyNumber) + bool AKey::HandlePickup (AInventory *item) { // In single player, you can pick up an infinite number of keys diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index ce8f53d611..c6475cc743 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1801,6 +1801,8 @@ bool AHealth::TryPickup (AActor *&other) IMPLEMENT_CLASS(AHealthPickup, false, false, false, false) +DEFINE_FIELD(AHealthPickup, autousemode) + //=========================================================================== // // AHealthPickup :: CreateCopy diff --git a/src/g_shared/a_puzzleitems.cpp b/src/g_shared/a_puzzleitems.cpp index d243dc73cb..640d5517da 100644 --- a/src/g_shared/a_puzzleitems.cpp +++ b/src/g_shared/a_puzzleitems.cpp @@ -19,6 +19,8 @@ void PClassPuzzleItem::DeriveData(PClass *newclass) IMPLEMENT_CLASS(APuzzleItem, false, false, false, false) +DEFINE_FIELD(APuzzleItem, PuzzleItemNumber) + bool APuzzleItem::HandlePickup (AInventory *item) { // Can't carry more than 1 of each puzzle item in coop netplay diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp index 7aa9591e9b..9edae69069 100644 --- a/src/g_shared/a_weaponpiece.cpp +++ b/src/g_shared/a_weaponpiece.cpp @@ -6,6 +6,9 @@ IMPLEMENT_CLASS(PClassWeaponPiece, false, false, false, false) IMPLEMENT_CLASS(AWeaponHolder, false, false, false, false) +DEFINE_FIELD(AWeaponHolder, PieceMask); +DEFINE_FIELD(AWeaponHolder, PieceWeapon); + void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) { Super::ReplaceClassRef(oldclass, newclass); diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 5f221c5bc9..530f8e3648 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -868,6 +868,8 @@ FState *AWeapon::GetStateForButtonName (FName button) IMPLEMENT_CLASS(AWeaponGiver, false, false, false, false) +DEFINE_FIELD(AWeaponGiver, DropAmmoFactor); + void AWeaponGiver::Serialize(FSerializer &arc) { Super::Serialize(arc); diff --git a/src/p_states.cpp b/src/p_states.cpp index b3e9593af6..f141cb550a 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -1071,10 +1071,10 @@ DEFINE_FIELD(FState, Frame) DEFINE_FIELD(FState, UseFlags) DEFINE_FIELD(FState, Misc1) DEFINE_FIELD(FState, Misc2) -DEFINE_FIELD_BIT(FState, StateFlags, bSlow) -DEFINE_FIELD_BIT(FState, StateFlags, bFast) -DEFINE_FIELD_BIT(FState, StateFlags, bFullbright) -DEFINE_FIELD_BIT(FState, StateFlags, bNoDelay) -DEFINE_FIELD_BIT(FState, StateFlags, bSameFrame) -DEFINE_FIELD_BIT(FState, StateFlags, bCanRaise) -DEFINE_FIELD_BIT(FState, StateFlags, bDehacked) +DEFINE_FIELD_BIT(FState, StateFlags, bSlow, STF_SLOW) +DEFINE_FIELD_BIT(FState, StateFlags, bFast, STF_FAST) +DEFINE_FIELD_BIT(FState, StateFlags, bFullbright, STF_FULLBRIGHT) +DEFINE_FIELD_BIT(FState, StateFlags, bNoDelay, STF_NODELAY) +DEFINE_FIELD_BIT(FState, StateFlags, bSameFrame, STF_SAMEFRAME) +DEFINE_FIELD_BIT(FState, StateFlags, bCanRaise, STF_CANRAISE) +DEFINE_FIELD_BIT(FState, StateFlags, bDehacked, STF_DEHACKED) diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 47f753ca16..048590b397 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -204,6 +204,8 @@ class Health : Inventory native class HealthPickup : Inventory native { + native int autousemode; + Default { Inventory.DefMaxAmount; @@ -213,6 +215,8 @@ class HealthPickup : Inventory native class Key : Inventory native { + native uint8 KeyNumber; + Default { +DONTGIB; // Don't disappear due to a crusher @@ -223,6 +227,13 @@ class Key : Inventory native class PowerupGiver : Inventory native { + + native Class PowerupType; + native int EffectTics; // Non-0 to override the powerup's default tics + native color BlendColor; // Non-0 to override the powerup's default blend + native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility + native double Strength; // Meaning depends on powerup - currently used only by Invisibility + Default { Inventory.DefMaxAmount; @@ -232,7 +243,13 @@ class PowerupGiver : Inventory native } } -class Powerup : Inventory native {} +class Powerup : Inventory native +{ + native int EffectTics; + native color BlendColor; + native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility + native double Strength; // Meaning depends on powerup - currently used only by Invisibility +} class PowerInvulnerable : Powerup native { @@ -337,6 +354,8 @@ class PowerWeaponLevel2 : Powerup native class PowerSpeed : Powerup native { + native int SpeedFlags; + Default { Powerup.Duration -45; @@ -348,7 +367,7 @@ class PowerSpeed : Powerup native // Player Speed Trail (used by the Speed Powerup) ---------------------------- -class PlayerSpeedTrail native +class PlayerSpeedTrail : Actor { Default { @@ -357,6 +376,15 @@ class PlayerSpeedTrail native Alpha 0.6; RenderStyle "Translucent"; } + + override void Tick() + { + Alpha -= .6 / 8; + if (Alpha <= 0) + { + Destroy (); + } + } } class PowerMinotaur : Powerup native @@ -477,6 +505,8 @@ class MapRevealer : Inventory native {} class PuzzleItem : Inventory native { + native int PuzzleItemNumber; + Default { +NOGRAVITY @@ -549,6 +579,9 @@ class Weapon : StateProvider native class WeaponGiver : Weapon native { + + native double DropAmmoFactor; + Default { Weapon.AmmoGive1 -1; @@ -558,6 +591,9 @@ class WeaponGiver : Weapon native class WeaponHolder : Inventory native { + native int PieceMask; + native Class PieceWeapon; + Default { +NOBLOCKMAP From f8c6adb7eb86e53ad537449b205987fe535fdb38 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Nov 2016 18:54:16 +0100 Subject: [PATCH 339/471] - completely redid how A_PainShootSkull checks the legality of the LS spawn. It turned out that the Boom method does not work well with portals and fixing it while keeping it doesn't look feasible - the entire approach was bad from the start. Instead, let's use the same approach as P_XYMovement: Spawn the Lost Soul at the center of the PE, and then use multiple P_TryMoves to get it to its intended location. This will check all blocking lines, just like Boom did, but it will also properly handle z-positioning and portal transitions. --- src/g_doom/a_painelemental.cpp | 126 +++++++++++++++++---------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index f2db5a2402..3fca0896c6 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -62,84 +62,86 @@ void A_PainShootSkull (VMFrameStack *stack, AActor *self, DAngle Angle, PClassAc } // okay, there's room for another one - prestep = 4 + (self->radius + GetDefaultByType(spawntype)->radius) * 1.5; + double otherradius = GetDefaultByType(spawntype)->radius; + prestep = 4 + (self->radius + otherradius) * 1.5; - // NOTE: The following code contains some advance work for line-to-line portals which is currenty inactive. + DVector2 move = Angle.ToVector(prestep); + DVector3 spawnpos = self->PosPlusZ(8.0); + DVector3 destpos = spawnpos + move; - DVector2 dist = Angle.ToVector(prestep); - DVector3 pos = self->Vec3Offset(dist.X, dist.Y, 8., true); - DVector3 src = self->Pos(); + other = Spawn(spawntype, spawnpos, ALLOW_REPLACE); - for (int i = 0; i < 2; i++) + // Now check if the spawn is legal. Unlike Boom's hopeless attempt at fixing it, let's do it the same way + // P_XYMovement solves the line skipping: Spawn the Lost Soul near the PE's center and then use multiple + // smaller steps to get it to its intended position. This will also result in proper clipping, but + // it will avoid all the problems of the Boom method, which checked too many lines and despite some + // adjustments never worked with portals. + + if (other != nullptr) { - // Check whether the Lost Soul is being fired through a 1-sided // phares - // wall or an impassible line, or a "monsters can't cross" line.// | - // If it is, then we don't allow the spawn. // V + double maxmove = other->radius - 1; - FBoundingBox box(MIN(src.X, pos.X), MIN(src.Y, pos.Y), MAX(src.X, pos.X), MAX(src.Y, pos.Y)); - FBlockLinesIterator it(box); - line_t *ld; - bool inportal = false; + if (maxmove <= 0) maxmove = MAXMOVE; - while ((ld = it.Next())) + const double xspeed = fabs(move.X); + const double yspeed = fabs(move.Y); + + int steps = 1; + + if (xspeed > yspeed) { - if (ld->isLinePortal() && i == 0) + if (xspeed > maxmove) { - if (P_PointOnLineSidePrecise(src, ld) == 0 && - P_PointOnLineSidePrecise(pos, ld) == 1) - { - // crossed a portal line from front to back, we need to repeat the check on the other side as well. - inportal = true; - } - } - else if (!(ld->flags & ML_TWOSIDED) || - (ld->flags & (ML_BLOCKING | ML_BLOCKMONSTERS | ML_BLOCKEVERYTHING))) - { - if (box.inRange(ld)) - { - if (P_PointOnLineSidePrecise(src, ld) != P_PointOnLineSidePrecise(pos, ld)) - return; // line blocks trajectory // ^ - } + steps = int(1 + xspeed / maxmove); + } + } + else + { + if (yspeed > maxmove) + { + steps = int(1 + yspeed / maxmove); } } - if (!inportal) break; - // recalculate position and redo the check on the other side of the portal - pos = self->Vec3Offset(dist.X, dist.Y, 8.); - src.X = pos.X - dist.X; - src.Y = pos.Y - dist.Y; + DVector2 stepmove = move / steps; + self->flags &= ~MF_SOLID; // make it solid again + other->flags2 |= MF2_NOTELEPORT; // we do not want the LS to teleport + for (int i = 0; i < steps; i++) + { + DVector2 ptry = other->Pos().XY() + stepmove; + DAngle oldangle = other->Angles.Yaw; + if (!P_TryMove(other, ptry, 0, nullptr)) + { + // kill it immediately + other->ClearCounters(); + P_DamageMobj(other, self, self, TELEFRAG_DAMAGE, NAME_None); + return; + } - } + if (other->Pos().XY() != ptry) + { + // If the new position does not match the desired position, the player + // must have gone through a portal. + // For that we need to adjust the movement vector for the following steps. + DAngle anglediff = deltaangle(oldangle, other->Angles.Yaw); - other = Spawn (spawntype, pos, ALLOW_REPLACE); + if (anglediff != 0) + { + stepmove = stepmove.Rotated(anglediff); + } + } - // Check to see if the new Lost Soul's z value is above the - // ceiling of its new sector, or below the floor. If so, kill it. + } + self->flags |= MF_SOLID; // don't let the LS be stuck in the PE while checking the move - if (other->Top() > other->Sector->HighestCeilingAt(other) || - other->Z() < other->Sector->LowestFloorAt(other)) - { - // kill it immediately - P_DamageMobj (other, self, self, TELEFRAG_DAMAGE, NAME_None);// ^ - return; // | - } // phares + // [RH] Lost souls hate the same things as their pain elementals + other->CopyFriendliness (self, !(flags & PAF_NOTARGET)); - // Check for movements. - - if (!P_CheckPosition (other, other->Pos())) - { - // kill it immediately - P_DamageMobj (other, self, self, TELEFRAG_DAMAGE, NAME_None); - return; - } - - // [RH] Lost souls hate the same things as their pain elementals - other->CopyFriendliness (self, !(flags & PAF_NOTARGET)); - - if (!(flags & PAF_NOSKULLATTACK)) - { - DECLARE_VMFUNC(AActor, A_SkullAttack); - CallAction(stack, A_SkullAttack, other); + if (!(flags & PAF_NOSKULLATTACK)) + { + DECLARE_VMFUNC(AActor, A_SkullAttack); + CallAction(stack, A_SkullAttack, other); + } } } From 1a20a5b9999db0e3e09407624b3713a0ef57f574 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Nov 2016 19:47:09 +0100 Subject: [PATCH 340/471] - scriptified A_PainShootSkull which was the last remaining bit in g_doom, so this directory is gone now. --- src/CMakeLists.txt | 5 - src/g_doom/a_doomglobal.h | 28 ---- src/g_doom/a_doommisc.cpp | 22 --- src/g_doom/a_painelemental.cpp | 160 ------------------- src/p_mobj.cpp | 17 ++ src/scripting/vm/vm.h | 1 + wadsrc/static/zscript/actor.txt | 11 +- wadsrc/static/zscript/doom/painelemental.txt | 134 +++++++++++++++- 8 files changed, 160 insertions(+), 218 deletions(-) delete mode 100644 src/g_doom/a_doomglobal.h delete mode 100644 src/g_doom/a_doommisc.cpp delete mode 100644 src/g_doom/a_painelemental.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 77e756b383..9499cb64f9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -824,7 +824,6 @@ endif() file( GLOB HEADER_FILES ${EXTRA_HEADER_DIRS} fragglescript/*.h - g_doom/*.h g_heretic/*.h g_hexen/*.h g_raven/*.h @@ -858,7 +857,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_doom/a_painelemental.cpp g_heretic/a_dsparil.cpp g_heretic/a_hereticartifacts.cpp g_heretic/a_hereticweaps.cpp @@ -1153,7 +1151,6 @@ set (PCH_SOURCES w_wad.cpp wi_stuff.cpp zstrformat.cpp - g_doom/a_doommisc.cpp g_heretic/a_hereticmisc.cpp g_hexen/a_hexenmisc.cpp g_raven/a_artitele.cpp @@ -1309,7 +1306,6 @@ endif() target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma ) include_directories( . - g_doom g_heretic g_hexen g_raven @@ -1443,7 +1439,6 @@ source_group("External\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/m 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/.+") source_group("Games\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+") source_group("Games\\Raven Shared" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_raven/.+") diff --git a/src/g_doom/a_doomglobal.h b/src/g_doom/a_doomglobal.h deleted file mode 100644 index 73e3d3239a..0000000000 --- a/src/g_doom/a_doomglobal.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __A_DOOMGLOBAL_H__ -#define __A_DOOMGLOBAL_H__ - -#include "info.h" - -class AScriptedMarine : public AActor -{ - DECLARE_CLASS (AScriptedMarine, AActor) -public: - - void Activate (AActor *activator); - void Deactivate (AActor *activator); - void BeginPlay (); - void Tick (); - void SetWeapon (EMarineWeapon); - void SetSprite (PClassActor *source); - - void Serialize(FSerializer &arc); - - int CurrentWeapon; - -protected: - bool GetWeaponStates(int weap, FState *&melee, FState *&missile); - - int SpriteOverride; -}; - -#endif //__A_DOOMGLOBAL_H__ diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp deleted file mode 100644 index 40c8e2f8d0..0000000000 --- a/src/g_doom/a_doommisc.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "p_spec.h" -#include "a_sharedglobal.h" -#include "m_random.h" -#include "gi.h" -#include "doomstat.h" -#include "gstrings.h" -#include "g_level.h" -#include "p_enemy.h" -#include "a_specialspot.h" -#include "templates.h" -#include "m_bbox.h" -#include "portal.h" -#include "d_player.h" -#include "p_maputl.h" -#include "serializer.h" -#include "g_shared/a_pickups.h" - -// Include all the other Doom stuff here to reduce compile time -#include "a_painelemental.cpp" diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp deleted file mode 100644 index 3fca0896c6..0000000000 --- a/src/g_doom/a_painelemental.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_enemy.h" -#include "p_local.h" -#include "a_action.h" -#include "templates.h" -#include "m_bbox.h" -#include "vm.h" -#include "doomstat.h" -*/ - -enum PA_Flags -{ - PAF_NOSKULLATTACK = 1, - PAF_AIMFACING = 2, - PAF_NOTARGET = 4, -}; - -// -// A_PainShootSkull -// Spawn a lost soul and launch it at the target -// -void A_PainShootSkull (VMFrameStack *stack, AActor *self, DAngle Angle, PClassActor *spawntype, int flags = 0, int limit = -1) -{ - AActor *other; - double prestep; - - if (spawntype == NULL) spawntype = PClass::FindActor("LostSoul"); - assert(spawntype != NULL); - if (self->DamageType == NAME_Massacre) return; - - // [RH] check to make sure it's not too close to the ceiling - if (self->Top() + 8 > self->ceilingz) - { - if (self->flags & MF_FLOAT) - { - self->Vel.Z -= 2; - self->flags |= MF_INFLOAT; - self->flags4 |= MF4_VFRICTION; - } - return; - } - - // [RH] make this optional - if (limit == -1 && (i_compatflags & COMPATF_LIMITPAIN)) - limit = 21; - - if (limit) - { - // count total number of skulls currently on the level - // if there are already 21 skulls on the level, don't spit another one - int count = limit; - FThinkerIterator iterator (spawntype); - DThinker *othink; - - while ( (othink = iterator.Next ()) ) - { - if (--count == 0) - return; - } - } - - // okay, there's room for another one - double otherradius = GetDefaultByType(spawntype)->radius; - prestep = 4 + (self->radius + otherradius) * 1.5; - - DVector2 move = Angle.ToVector(prestep); - DVector3 spawnpos = self->PosPlusZ(8.0); - DVector3 destpos = spawnpos + move; - - other = Spawn(spawntype, spawnpos, ALLOW_REPLACE); - - // Now check if the spawn is legal. Unlike Boom's hopeless attempt at fixing it, let's do it the same way - // P_XYMovement solves the line skipping: Spawn the Lost Soul near the PE's center and then use multiple - // smaller steps to get it to its intended position. This will also result in proper clipping, but - // it will avoid all the problems of the Boom method, which checked too many lines and despite some - // adjustments never worked with portals. - - if (other != nullptr) - { - double maxmove = other->radius - 1; - - if (maxmove <= 0) maxmove = MAXMOVE; - - const double xspeed = fabs(move.X); - const double yspeed = fabs(move.Y); - - int steps = 1; - - if (xspeed > yspeed) - { - if (xspeed > maxmove) - { - steps = int(1 + xspeed / maxmove); - } - } - else - { - if (yspeed > maxmove) - { - steps = int(1 + yspeed / maxmove); - } - } - - DVector2 stepmove = move / steps; - self->flags &= ~MF_SOLID; // make it solid again - other->flags2 |= MF2_NOTELEPORT; // we do not want the LS to teleport - for (int i = 0; i < steps; i++) - { - DVector2 ptry = other->Pos().XY() + stepmove; - DAngle oldangle = other->Angles.Yaw; - if (!P_TryMove(other, ptry, 0, nullptr)) - { - // kill it immediately - other->ClearCounters(); - P_DamageMobj(other, self, self, TELEFRAG_DAMAGE, NAME_None); - return; - } - - if (other->Pos().XY() != ptry) - { - // If the new position does not match the desired position, the player - // must have gone through a portal. - // For that we need to adjust the movement vector for the following steps. - DAngle anglediff = deltaangle(oldangle, other->Angles.Yaw); - - if (anglediff != 0) - { - stepmove = stepmove.Rotated(anglediff); - } - } - - } - self->flags |= MF_SOLID; // don't let the LS be stuck in the PE while checking the move - - // [RH] Lost souls hate the same things as their pain elementals - other->CopyFriendliness (self, !(flags & PAF_NOTARGET)); - - if (!(flags & PAF_NOSKULLATTACK)) - { - DECLARE_VMFUNC(AActor, A_SkullAttack); - CallAction(stack, A_SkullAttack, other); - } - } -} - - -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/p_mobj.cpp b/src/p_mobj.cpp index a4dc45df2b..075d34c4e0 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7115,6 +7115,23 @@ DEFINE_ACTION_FUNCTION(AActor, AngleTo) ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees); } +DEFINE_ACTION_FUNCTION(AActor, AngleToVector) +{ + PARAM_PROLOGUE; + PARAM_ANGLE(angle); + PARAM_FLOAT_DEF(length); + ACTION_RETURN_VEC2(angle.ToVector(length)); +} + +DEFINE_ACTION_FUNCTION(AActor, RotateVector) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_ANGLE(angle); + ACTION_RETURN_VEC2(DVector2(x, y).Rotated(angle)); +} + DEFINE_ACTION_FUNCTION(AActor, DistanceBySpeed) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 7b05fae36c..05c43aa1f2 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1097,6 +1097,7 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *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_VEC2(v) do { DVector2 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector2(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) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index da9db687cd..1aa02e5afd 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -4,6 +4,8 @@ class Actor : Thinker native const ONFLOORZ = -2147483648.0; const ONCEILINGZ = 2147483647.0; const FLOATRANDZ = ONCEILINGZ-1; + const TELEFRAG_DAMAGE = 1000000; + // flags are not defined here, the native fields for those get synthesized from the internal tables. @@ -215,6 +217,13 @@ class Actor : Thinker native // Functions + // 'parked' global functions. + native static double deltaangle(double ang1, double ang2); + native static double absangle(double ang1, double ang2); + native static Vector2 AngleToVector(double angle, double length = 1); + native static Vector2 RotateVector(Vector2 vec, double angle); + + bool IsPointerEqual(int ptr_select1, int ptr_select2) { return GetPointer(ptr_select1) == GetPointer(ptr_select2); @@ -231,8 +240,6 @@ class Actor : Thinker native native void AdjustPlayerAngle(FTranslatedLineTarget t); native static readonly GetDefaultByType(class cls); - native static double deltaangle(double ang1, double ang2); - native static double absangle(double ang1, double ang2); native static double GetDefaultSpeed(class type); native void RemoveFromHash(); native string GetTag(string defstr = ""); diff --git a/wadsrc/static/zscript/doom/painelemental.txt b/wadsrc/static/zscript/doom/painelemental.txt index 03a4d82c4c..fe9e0590a0 100644 --- a/wadsrc/static/zscript/doom/painelemental.txt +++ b/wadsrc/static/zscript/doom/painelemental.txt @@ -61,8 +61,139 @@ class PainElemental : Actor extend class Actor { - native void A_PainShootSkull(Class spawntype, double angle, int flags = 0, int limit = -1); + // + // A_PainShootSkull + // Spawn a lost soul and launch it at the target + // + void A_PainShootSkull(Class spawntype, double angle, int flags = 0, int limit = -1) + { + // Don't spawn if we get massacred. + if (DamageType == 'Massacre') return; + if (spawntype == null) spawntype = "LostSoul"; + + // [RH] check to make sure it's not too close to the ceiling + if (pos.z + height + 8 > ceilingz) + { + if (bFloat) + { + Vel.Z -= 2; + bInFloat = true; + bVFriction = true; + } + return; + } + + // [RH] make this optional + if (limit < 0 && compat_limitpain) + limit = 21; + + if (limit > 0) + { + // count total number of skulls currently on the level + // if there are already 21 skulls on the level, don't spit another one + int count = limit; + ThinkerIterator it = ThinkerIterator.Create(spawntype); + Thinker othink; + + while ( (othink = it.Next ()) ) + { + if (--count == 0) + return; + } + } + + // okay, there's room for another one + double otherradius = GetDefaultByType(spawntype).radius; + double prestep = 4 + (radius + otherradius) * 1.5; + + Vector2 move = AngleToVector(angle, prestep); + Vector3 spawnpos = pos + (0,0,8); + Vector3 destpos = spawnpos + move; + + Actor other = Spawn(spawntype, spawnpos, ALLOW_REPLACE); + + // Now check if the spawn is legal. Unlike Boom's hopeless attempt at fixing it, let's do it the same way + // P_XYMovement solves the line skipping: Spawn the Lost Soul near the PE's center and then use multiple + // smaller steps to get it to its intended position. This will also result in proper clipping, but + // it will avoid all the problems of the Boom method, which checked too many lines that weren't even touched + // and despite some adjustments never worked with portals. + + if (other != null) + { + double maxmove = other.radius - 1; + + if (maxmove <= 0) maxmove = 16; + + double xspeed = abs(move.X); + double yspeed = abs(move.Y); + + int steps = 1; + + if (xspeed > yspeed) + { + if (xspeed > maxmove) + { + steps = int(1 + xspeed / maxmove); + } + } + else + { + if (yspeed > maxmove) + { + steps = int(1 + yspeed / maxmove); + } + } + + Vector2 stepmove = move / steps; + bool savedsolid = bSolid; + bool savednoteleport = other.bNoTeleport; + + // make the PE nonsolid for the check and the LS non-teleporting so that P_TryMove doesn't do unwanted things. + bSolid = false; + other.bNoTeleport = true; + for (int i = 0; i < steps; i++) + { + Vector2 ptry = other.pos.xy + stepmove; + double oldangle = other.angle; + if (!other.TryMove(ptry, 0)) + { + // kill it immediately + other.ClearCounters(); + other.DamageMobj(self, self, TELEFRAG_DAMAGE, 'None'); + bSolid = savedsolid; + other.bNoTeleport = savednoteleport; + return; + } + + if (other.pos.xy != ptry) + { + // If the new position does not match the desired position, the player + // must have gone through a portal. + // For that we need to adjust the movement vector for the following steps. + double anglediff = deltaangle(oldangle, other.angle); + + if (anglediff != 0) + { + stepmove = RotateVector(stepmove, anglediff); + } + } + + } + bSolid = savedsolid; + other.bNoTeleport = savednoteleport; + + // [RH] Lost souls hate the same things as their pain elementals + other.CopyFriendliness (self, !(flags & PAF_NOTARGET)); + + if (!(flags & PAF_NOSKULLATTACK)) + { + other.A_SkullAttack(); + } + } + } + + void A_PainAttack(class spawntype = "LostSoul", double addangle = 0, int flags = 0, int limit = -1) { if (target) @@ -71,6 +202,7 @@ extend class Actor A_PainShootSkull(spawntype, angle + addangle, flags, limit); } } + void A_DualPainAttack(class spawntype = "LostSoul") { if (target) From 5e67cf79d34ef753b3f5dc1320ae2e9523794e92 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Nov 2016 21:26:59 +0100 Subject: [PATCH 341/471] - scriptified the Ironlich. --- src/CMakeLists.txt | 1 - src/g_heretic/a_hereticmisc.cpp | 2 - src/g_heretic/a_ironlich.cpp | 213 --------------------- src/p_mobj.cpp | 18 ++ src/scripting/zscript/zcc_compile.cpp | 5 + src/virtual.h | 22 +++ wadsrc/static/zscript/actor.txt | 2 + wadsrc/static/zscript/base.txt | 2 + wadsrc/static/zscript/heretic/ironlich.txt | 173 ++++++++++++++++- 9 files changed, 215 insertions(+), 223 deletions(-) delete mode 100644 src/g_heretic/a_ironlich.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9499cb64f9..cd44a6761d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -860,7 +860,6 @@ set( NOT_COMPILED_SOURCE_FILES g_heretic/a_dsparil.cpp g_heretic/a_hereticartifacts.cpp g_heretic/a_hereticweaps.cpp - g_heretic/a_ironlich.cpp g_hexen/a_blastradius.cpp g_hexen/a_boostarmor.cpp g_hexen/a_clericflame.cpp diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 5aa048977a..18093b752d 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -22,5 +22,3 @@ #include "a_dsparil.cpp" #include "a_hereticartifacts.cpp" #include "a_hereticweaps.cpp" -#include "a_ironlich.cpp" - diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp deleted file mode 100644 index 8068c251bc..0000000000 --- a/src/g_heretic/a_ironlich.cpp +++ /dev/null @@ -1,213 +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 "vm.h" -#include "g_level.h" -*/ - -static FRandom pr_foo ("WhirlwindDamage"); -static FRandom pr_atk ("LichAttack"); -static FRandom pr_seek ("WhirlwindSeek"); - -class AWhirlwind : public AActor -{ - DECLARE_CLASS (AWhirlwind, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(AWhirlwind, false, false, false, false) - -int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - int randVal; - - if (!(target->flags7 & MF7_DONTTHRUST)) - { - target->Angles.Yaw += pr_foo.Random2() * (360 / 4096.); - target->Vel.X += pr_foo.Random2() / 64.; - target->Vel.Y += pr_foo.Random2() / 64.; - } - - if ((level.time & 16) && !(target->flags2 & MF2_BOSS) && !(target->flags7 & MF7_DONTTHRUST)) - { - randVal = pr_foo(); - if (randVal > 160) - { - randVal = 160; - } - target->Vel.Z += randVal / 32.; - if (target->Vel.Z > 12) - { - target->Vel.Z = 12; - } - } - if (!(level.time & 7)) - { - P_DamageMobj (target, NULL, this->target, 3, NAME_Melee); - } - return -1; -} - -//---------------------------------------------------------------------------- -// -// PROC A_LichAttack -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_LichAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - AActor *fire; - AActor *baseFire; - AActor *mo; - AActor *target; - int randAttack; - static const int atkResolve1[] = { 50, 150 }; - static const int atkResolve2[] = { 150, 200 }; - - // Ice ball (close 20% : far 60%) - // Fire column (close 40% : far 20%) - // Whirlwind (close 40% : far 20%) - // Distance threshold = 8 cells - - target = self->target; - if (target == NULL) - { - return 0; - } - A_FaceTarget (self); - if (self->CheckMeleeRange ()) - { - int damage = pr_atk.HitDice (6); - int newdam = P_DamageMobj (target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, target, self); - return 0; - } - int dist = self->Distance2D(target) > 8 * 64; - randAttack = pr_atk (); - if (randAttack < atkResolve1[dist]) - { // Ice ball - P_SpawnMissile (self, target, PClass::FindActor("HeadFX1")); - S_Sound (self, CHAN_BODY, "ironlich/attack2", 1, ATTN_NORM); - } - else if (randAttack < atkResolve2[dist]) - { // Fire column - baseFire = P_SpawnMissile (self, target, PClass::FindActor("HeadFX3")); - if (baseFire != NULL) - { - baseFire->SetState (baseFire->FindState("NoGrow")); - for (i = 0; i < 5; i++) - { - fire = Spawn("HeadFX3", baseFire->Pos(), ALLOW_REPLACE); - if (i == 0) - { - S_Sound (self, CHAN_BODY, "ironlich/attack1", 1, ATTN_NORM); - } - fire->target = baseFire->target; - fire->Angles.Yaw = baseFire->Angles.Yaw; - fire->Vel = baseFire->Vel; - fire->SetDamage(0); - fire->health = (i+1) * 2; - P_CheckMissileSpawn (fire, self->radius); - } - } - } - else - { // Whirlwind - mo = P_SpawnMissile (self, target, RUNTIME_CLASS(AWhirlwind)); - if (mo != NULL) - { - mo->AddZ(-32); - mo->tracer = target; - mo->health = 20*TICRATE; // Duration - S_Sound (self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM); - } - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WhirlwindSeek -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_WhirlwindSeek) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->health -= 3; - if (self->health < 0) - { - self->Vel.Zero(); - self->SetState(self->FindState(NAME_Death)); - self->flags &= ~MF_MISSILE; - return 0; - } - if ((self->threshold -= 3) < 0) - { - self->threshold = 58 + (pr_seek() & 31); - S_Sound(self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM); - } - if (self->tracer && self->tracer->flags&MF_SHADOW) - { - return 0; - } - P_SeekerMissile(self, 10, 30); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_LichIceImpact -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_LichIceImpact) -{ - PARAM_SELF_PROLOGUE(AActor); - - unsigned int i; - AActor *shard; - - for (i = 0; i < 8; i++) - { - shard = Spawn("HeadFX2", self->Pos(), ALLOW_REPLACE); - shard->target = self->target; - shard->Angles.Yaw = i*45.; - shard->VelFromAngle(); - shard->Vel.Z = -.6; - P_CheckMissileSpawn (shard, self->radius); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_LichFireGrow -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_LichFireGrow) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->health--; - self->AddZ(9.); - if (self->health == 0) - { - self->RestoreDamage(); - self->SetState (self->FindState("NoGrow")); - } - return 0; -} - diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 075d34c4e0..a79fc0f16d 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6668,6 +6668,17 @@ int AActor::DoSpecialDamage (AActor *target, int damage, FName damagetype) } } +DEFINE_ACTION_FUNCTION(AActor, DoSpecialDamage) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(target, AActor); + PARAM_INT(damage); + PARAM_NAME(damagetype); + self->VMSuperCall(); + ACTION_RETURN_INT(self->DoSpecialDamage(target, damage, damagetype)); +} + + int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) { FState *death; @@ -7180,6 +7191,13 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) ACTION_RETURN_VEC3(self->Vec3Offset(x, y, z, absolute)); } +DEFINE_ACTION_FUNCTION(AActor, RestoreDamage) +{ + PARAM_SELF_PROLOGUE(AActor); + self->RestoreDamage(); + return 0; +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index ac9a8825c4..3437c848cb 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2326,6 +2326,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool if (varflags & VARF_Virtual) { + if (sym->Variants[0].Implementation == nullptr) + { + Error(f, "Virtual function %s.%s not present.", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()); + return; + } if (varflags & VARF_Final) { sym->Variants[0].Implementation->Final = true; diff --git a/src/virtual.h b/src/virtual.h index f3167407d8..4e0b3f01b7 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -38,6 +38,7 @@ VMEXPORTED_NATIVES_START VMEXPORTED_NATIVES_FUNC(BeginPlay) VMEXPORTED_NATIVES_FUNC(Activate) VMEXPORTED_NATIVES_FUNC(Deactivate) + VMEXPORTED_NATIVES_FUNC(DoSpecialDamage) VMEXPORTED_NATIVES_END @@ -192,6 +193,26 @@ public: stack.Call(VFUNC, params, 2, nullptr, 0, nullptr); } } + int DoSpecialDamage(AActor *target, int damage, FName damagetype) + { + if (this->ObjectFlags & OF_SuperCall) + { + this->ObjectFlags &= ~OF_SuperCall; + return ExportedNatives::Get()->template DoSpecialDamage(this, target, damage, damagetype); + } + else + { + VINDEX(AActor, DoSpecialDamage); + // Without the type cast this picks the 'void *' assignment... + VMValue params[4] = { (DObject*)this, (DObject*)target, damage, damagetype.GetIndex() }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(VFUNC, params, 4, &ret, 1, nullptr); + return retval; + } + } }; @@ -223,6 +244,7 @@ VMEXPORT_NATIVES_START(AActor, DThinker) VMEXPORT_NATIVES_FUNC(BeginPlay) VMEXPORT_NATIVES_FUNC(Activate) VMEXPORT_NATIVES_FUNC(Deactivate) + VMEXPORT_NATIVES_FUNC(DoSpecialDamage) VMEXPORT_NATIVES_END(AActor) /* diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 1aa02e5afd..e7179bd47e 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -237,6 +237,7 @@ class Actor : Thinker native virtual native void BeginPlay(); virtual native void Activate(Actor activator); virtual native void Deactivate(Actor activator); + virtual native int DoSpecialDamage (Actor target, int damage, Name damagetype); native void AdjustPlayerAngle(FTranslatedLineTarget t); native static readonly GetDefaultByType(class cls); @@ -247,6 +248,7 @@ class Actor : Thinker native native void ClearCounters(); native bool GiveBody (int num, int max=0); + native void RestoreDamage(); native void SetDamage(int dmg); native double Distance2D(Actor other); native void SetOrigin(vector3 newpos, bool moving); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 15a8c9a3b6..11d565ae90 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -12,6 +12,8 @@ class Object native class Thinker : Object native { + const TICRATE = 35; + virtual native void Tick(); virtual native void PostBeginPlay(); } diff --git a/wadsrc/static/zscript/heretic/ironlich.txt b/wadsrc/static/zscript/heretic/ironlich.txt index e6ba05e059..8a4dd4c05c 100644 --- a/wadsrc/static/zscript/heretic/ironlich.txt +++ b/wadsrc/static/zscript/heretic/ironlich.txt @@ -27,7 +27,6 @@ class Ironlich : Actor DropItem "ArtiEgg", 51, 0; } - native void A_LichAttack (); States { @@ -54,6 +53,77 @@ class Ironlich : Actor LICH I -1 A_BossDeath; Stop; } + + //---------------------------------------------------------------------------- + // + // PROC A_LichAttack + // + //---------------------------------------------------------------------------- + + void A_LichAttack () + { + static const int atkResolve1[] = { 50, 150 }; + static const int atkResolve2[] = { 150, 200 }; + + // Ice ball (close 20% : far 60%) + // Fire column (close 40% : far 20%) + // Whirlwind (close 40% : far 20%) + // Distance threshold = 8 cells + + if (target == null) + { + return; + } + A_FaceTarget (); + if (CheckMeleeRange ()) + { + int damage = random[LichAttack](1, 8) * 6; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + return; + } + int dist = Distance2D(target) > 8 * 64; + int randAttack = random[LichAttack](); + if (randAttack < atkResolve1[dist]) + { // Ice ball + SpawnMissile (target, "HeadFX1"); + A_PlaySound ("ironlich/attack2", CHAN_BODY); + } + else if (randAttack < atkResolve2[dist]) + { // Fire column + Actor baseFire = SpawnMissile (target, "HeadFX3"); + if (baseFire != null) + { + baseFire.SetStateLabel("NoGrow"); + for (int i = 0; i < 5; i++) + { + Actor fire = Spawn("HeadFX3", baseFire.Pos, ALLOW_REPLACE); + if (i == 0) + { + A_PlaySound ("ironlich/attack1", CHAN_BODY); + } + fire.target = baseFire.target; + fire.angle = baseFire.angle; + fire.Vel = baseFire.Vel; + fire.SetDamage(0); + fire.health = (i+1) * 2; + fire.CheckMissileSpawn (radius); + } + } + } + else + { // Whirlwind + Actor mo = SpawnMissile (target, "Whirlwind"); + if (mo != null) + { + mo.AddZ(-32); + mo.tracer = target; + mo.health = 20*TICRATE; // Duration + A_PlaySound ("ironlich/attack3", CHAN_BODY); + } + } + } + } // Head FX 1 ---------------------------------------------------------------- @@ -74,7 +144,6 @@ class HeadFX1 : Actor RenderStyle "Add"; } - native void A_LichIceImpact(); States { @@ -86,6 +155,25 @@ class HeadFX1 : Actor FX05 EFG 5 BRIGHT; Stop; } + + //---------------------------------------------------------------------------- + // + // PROC A_LichIceImpact + // + //---------------------------------------------------------------------------- + + void A_LichIceImpact() + { + for (int i = 0; i < 8; i++) + { + Actor shard = Spawn("HeadFX2", Pos, ALLOW_REPLACE); + shard.target = target; + shard.angle = i*45.; + shard.VelFromAngle(); + shard.Vel.Z = -.6; + shard.CheckMissileSpawn (radius); + } + } } // Head FX 2 ---------------------------------------------------------------- @@ -135,8 +223,6 @@ class HeadFX3 : Actor RenderStyle "Add"; } - native void A_LichFireGrow (); - States { Spawn: @@ -149,12 +235,29 @@ class HeadFX3 : Actor FX06 DEFG 5 BRIGHT; Stop; } + + //---------------------------------------------------------------------------- + // + // PROC A_LichFireGrow + // + //---------------------------------------------------------------------------- + + void A_LichFireGrow () + { + health--; + AddZ(9.); + if (health == 0) + { + RestoreDamage(); + SetStateLabel("NoGrow"); + } + } } // Whirlwind ---------------------------------------------------------------- -class Whirlwind : Actor native +class Whirlwind : Actor { Default { @@ -174,8 +277,6 @@ class Whirlwind : Actor native Alpha 0.4; } - native void A_WhirlwindSeek(); - States { Spawn: @@ -186,6 +287,64 @@ class Whirlwind : Actor native FX07 GFED 4; Stop; } + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + int randVal; + + if (!target.bDontThrust) + { + target.angle += Random2[WhirlwindDamage]() * (360 / 4096.); + target.Vel.X += Random2[WhirlwindDamage]() / 64.; + target.Vel.Y += Random2[WhirlwindDamage]() / 64.; + } + + if ((level.time & 16) && !target.bBoss && !target.bDontThrust) + { + randVal = min(160, random[WhirlwindSeek]()); + target.Vel.Z += randVal / 32.; + if (target.Vel.Z > 12) + { + target.Vel.Z = 12; + } + } + if (!(level.time & 7)) + { + target.DamageMobj (null, target, 3, 'Melee'); + } + return -1; + } + + //---------------------------------------------------------------------------- + // + // PROC A_WhirlwindSeek + // + //---------------------------------------------------------------------------- + + void A_WhirlwindSeek() + { + + health -= 3; + if (health < 0) + { + Vel = (0,0,0); + SetStateLabel("Death"); + bMissile = false; + return; + } + if ((threshold -= 3) < 0) + { + threshold = 58 + (random[WhirlwindSeek]() & 31); + A_PlaySound("ironlich/attack3", CHAN_BODY); + } + if (tracer && tracer.bShadow) + { + return; + } + A_SeekerMissile(10, 30); + } + } + From 7527141ad4aab0edc87cd41a970b01971e8fc5b5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Nov 2016 22:34:17 +0100 Subject: [PATCH 342/471] - fixed: The morph actors stored their required classes as names, not as class pointers. This prevented any kind of error check on them. Unfortunately, due to backwards compatibility needs, on DECORATE the missing class may not be fatal so a workaround had to be added to clear those bogus pointers later if they are discovered to be broken. For ZScript, though, this will result in a compile error, which was the intention behind this change. --- src/dobjtype.cpp | 1 + src/g_shared/a_artifacts.cpp | 9 ++--- src/g_shared/a_artifacts.h | 7 ++-- src/g_shared/a_morph.cpp | 8 +--- src/g_shared/a_sharedglobal.h | 3 +- src/scripting/thingdef.cpp | 20 +++++++++- src/scripting/thingdef_properties.cpp | 56 ++++++++++++++++----------- 7 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 11640ec94b..52a2698735 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3298,6 +3298,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) // 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) { + existclass->ObjectFlags &= OF_Transient; return existclass; } } diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 66832c21c2..5b03d4a607 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1910,13 +1910,10 @@ void APowerMorph::InitEffect( ) { Super::InitEffect(); - if (Owner != NULL && Owner->player != NULL && PlayerClass != NAME_None) + if (Owner != nullptr && Owner->player != nullptr && PlayerClass != nullptr) { player_t *realplayer = Owner->player; // Remember the identity of the player - PClassActor *morph_flash = PClass::FindActor(MorphFlash); - PClassActor *unmorph_flash = PClass::FindActor(UnMorphFlash); - PClassPlayerPawn *player_class = dyn_cast(PClass::FindClass (PlayerClass)); - if (P_MorphPlayer(realplayer, realplayer, player_class, -1/*INDEFINITELY*/, MorphStyle, morph_flash, unmorph_flash)) + if (P_MorphPlayer(realplayer, realplayer, PlayerClass, -1/*INDEFINITELY*/, MorphStyle, MorphFlash, UnMorphFlash)) { Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet ItemFlags |= IF_CREATECOPYMOVED; // Let the caller know the "real" owner has changed (to the morphed actor) @@ -1960,7 +1957,7 @@ void APowerMorph::EndEffect( ) } // Unmorph if possible - if (!bNoCallUndoMorph) + if (!bInUndoMorph) { int savedMorphTics = Player->morphTics; P_UndoPlayerMorph (Player, Player, 0, !!(Player->MorphStyle & MORPH_UNDOALWAYS)); diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index 163094d328..bd7e86323c 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -280,13 +280,14 @@ class APowerMorph : public APowerup public: virtual void Serialize(FSerializer &arc); - void SetNoCallUndoMorph() { bNoCallUndoMorph = true; } + void SetNoCallUndoMorph() { bInUndoMorph = true; } // Variables - FNameNoInit PlayerClass, MorphFlash, UnMorphFlash; + PClassPlayerPawn *PlayerClass; + PClassActor *MorphFlash, *UnMorphFlash; int MorphStyle; player_t *Player; - bool bNoCallUndoMorph; // Because P_UndoPlayerMorph() can call EndEffect recursively + bool bInUndoMorph; // Because P_UndoPlayerMorph() can call EndEffect recursively protected: void InitEffect (); diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 506f18b2ff..49ea525bbf 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -620,17 +620,13 @@ IMPLEMENT_CLASS(AMorphProjectile, false, false, false, false) int AMorphProjectile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { - PClassActor *morph_flash = PClass::FindActor(MorphFlash); - PClassActor *unmorph_flash = PClass::FindActor(UnMorphFlash); if (target->player) { - PClassPlayerPawn *player_class = dyn_cast(PClass::FindClass(PlayerClass)); - P_MorphPlayer (NULL, target->player, player_class, Duration, MorphStyle, morph_flash, unmorph_flash); + P_MorphPlayer (NULL, target->player, PlayerClass, Duration, MorphStyle, MorphFlash, UnMorphFlash); } else { - PClassActor *monster_class = PClass::FindActor(MonsterClass); - P_MorphMonster (target, monster_class, Duration, MorphStyle, morph_flash, unmorph_flash); + P_MorphMonster (target, MonsterClass, Duration, MorphStyle, MorphFlash, UnMorphFlash); } return -1; } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 65f9d90b63..6911c6688b 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -192,7 +192,8 @@ public: void Serialize(FSerializer &arc); - FNameNoInit PlayerClass, MonsterClass, MorphFlash, UnMorphFlash; + PClassPlayerPawn *PlayerClass; + PClassActor *MonsterClass, *MorphFlash, *UnMorphFlash; int Duration, MorphStyle; }; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 9dcf3a16fb..d6c53dd8de 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -68,6 +68,7 @@ // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void InitThingdef(); +TArray OptionalClassPtrs; // STATIC FUNCTION PROTOTYPES -------------------------------------------- PClassActor *QuestItemClasses[31]; @@ -390,8 +391,21 @@ void LoadActors () { if (ti->Size == TentativeClass) { - Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); - FScriptPosition::ErrorCounter++; + if (ti->ObjectFlags & OF_Transient) + { + Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars()); + FScriptPosition::WarnCounter++; + DObject::StaticPointerSubstitution(ti, nullptr); + for (auto op : OptionalClassPtrs) + { + if (*op == ti) *op = nullptr; + } + } + else + { + Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); + FScriptPosition::ErrorCounter++; + } continue; } @@ -431,4 +445,6 @@ void LoadActors () QuestItemClasses[i] = PClass::FindActor(fmt); } StateSourceLines.Clear(); + OptionalClassPtrs.Clear(); + OptionalClassPtrs.ShrinkToFit(); } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 7faab937bc..8968dc1d6f 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -71,13 +71,14 @@ #include "r_data/colormaps.h" #include "vmbuilder.h" +extern TArray OptionalClassPtrs; //========================================================================== // // Gets a class pointer and performs an error check for correct type // //========================================================================== -static PClassActor *FindClassTentative(const char *name, PClass *ancestor) +static PClassActor *FindClassTentative(const char *name, PClass *ancestor, bool optional = false) { // "" and "none" mean 'no class' if (name == NULL || *name == 0 || !stricmp(name, "none")) @@ -91,23 +92,27 @@ static PClassActor *FindClassTentative(const char *name, PClass *ancestor) { I_Error("%s does not inherit from %s\n", name, ancestor->TypeName.GetChars()); } + if (cls->Size == TentativeClass && optional) + { + cls->ObjectFlags |= OF_Transient; // since this flag has no meaning in class types, let's use it for marking the type optional. + } return static_cast(cls); } -static AAmmo::MetaClass *FindClassTentativeAmmo(const char *name) +static AAmmo::MetaClass *FindClassTentativeAmmo(const char *name, bool optional = false) { - return static_cast(FindClassTentative(name, RUNTIME_CLASS(AAmmo))); + return static_cast(FindClassTentative(name, RUNTIME_CLASS(AAmmo), optional)); } -static AWeapon::MetaClass *FindClassTentativeWeapon(const char *name) +static AWeapon::MetaClass *FindClassTentativeWeapon(const char *name, bool optional = false) { - return static_cast(FindClassTentative(name, RUNTIME_CLASS(AWeapon))); + return static_cast(FindClassTentative(name, RUNTIME_CLASS(AWeapon), optional)); } -static APowerup::MetaClass *FindClassTentativePowerup(const char *name) +static APowerup::MetaClass *FindClassTentativePowerup(const char *name, bool optional = false) { - return static_cast(FindClassTentative(name, RUNTIME_CLASS(APowerup))); + return static_cast(FindClassTentative(name, RUNTIME_CLASS(APowerup), optional)); } -static APlayerPawn::MetaClass *FindClassTentativePlayerPawn(const char *name) +static APlayerPawn::MetaClass *FindClassTentativePlayerPawn(const char *name, bool optional = false) { - return static_cast(FindClassTentative(name, RUNTIME_CLASS(APlayerPawn))); + return static_cast(FindClassTentative(name, RUNTIME_CLASS(APlayerPawn), optional)); } //========================================================================== @@ -2984,21 +2989,23 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, viewbob, F, PlayerPawn) } //========================================================================== -// +// (non-fatal with non-existent types only in DECORATE) //========================================================================== DEFINE_CLASS_PROPERTY(playerclass, S, MorphProjectile) { PROP_STRING_PARM(str, 0); - defaults->PlayerClass = FName(str); + defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate); + if (bag.fromDecorate) OptionalClassPtrs.Push((PClassActor**)&defaults->PlayerClass); } //========================================================================== -// +// (non-fatal with non-existent types only in DECORATE) //========================================================================== DEFINE_CLASS_PROPERTY(monsterclass, S, MorphProjectile) { PROP_STRING_PARM(str, 0); - defaults->MonsterClass = FName(str); + defaults->MonsterClass = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); + if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MonsterClass); } //========================================================================== @@ -3020,12 +3027,13 @@ DEFINE_CLASS_PROPERTY(morphstyle, M, MorphProjectile) } //========================================================================== -// +// (non-fatal with non-existent types only in DECORATE) //========================================================================== DEFINE_CLASS_PROPERTY(morphflash, S, MorphProjectile) { PROP_STRING_PARM(str, 0); - defaults->MorphFlash = FName(str); + defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); + if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MorphFlash); } //========================================================================== @@ -3034,16 +3042,18 @@ DEFINE_CLASS_PROPERTY(morphflash, S, MorphProjectile) DEFINE_CLASS_PROPERTY(unmorphflash, S, MorphProjectile) { PROP_STRING_PARM(str, 0); - defaults->UnMorphFlash = FName(str); + defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); + if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->UnMorphFlash); } //========================================================================== -// +// (non-fatal with non-existent types only in DECORATE) //========================================================================== DEFINE_CLASS_PROPERTY(playerclass, S, PowerMorph) { PROP_STRING_PARM(str, 0); - defaults->PlayerClass = FName(str); + defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate); + if (bag.fromDecorate) OptionalClassPtrs.Push((PClassActor**)&defaults->PlayerClass); } //========================================================================== @@ -3056,21 +3066,23 @@ DEFINE_CLASS_PROPERTY(morphstyle, M, PowerMorph) } //========================================================================== -// +// (non-fatal with non-existent types only in DECORATE) //========================================================================== DEFINE_CLASS_PROPERTY(morphflash, S, PowerMorph) { PROP_STRING_PARM(str, 0); - defaults->MorphFlash = FName(str); + defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); + if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MorphFlash); } //========================================================================== -// +// (non-fatal with non-existent types only in DECORATE) //========================================================================== DEFINE_CLASS_PROPERTY(unmorphflash, S, PowerMorph) { PROP_STRING_PARM(str, 0); - defaults->UnMorphFlash = FName(str); + defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); + if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->UnMorphFlash); } From 8a7671ad8b0e5cbd5b7fe93d7e4c240c1050bbc1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Nov 2016 23:28:03 +0100 Subject: [PATCH 343/471] - exported all member fields from the morph items. - renamed APowerMorph::Player to avoid accidental confusion with AActor::player, which in scripting is the same due to case insensitvity. - renamed save key for above variable. --- src/g_shared/a_artifacts.cpp | 29 ++++++++++++++-------- src/g_shared/a_artifacts.h | 2 +- src/g_shared/a_morph.cpp | 12 +++++++++ wadsrc/static/zscript/shared/inventory.txt | 6 +++++ wadsrc/static/zscript/shared/morph.txt | 9 +++++++ 5 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 5b03d4a607..bf24c8eb85 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1884,6 +1884,13 @@ void APowerDoubleFiringSpeed::EndEffect( ) IMPLEMENT_CLASS(APowerMorph, false, false, false, false) +DEFINE_FIELD(APowerMorph, PlayerClass) +DEFINE_FIELD(APowerMorph, MorphFlash) +DEFINE_FIELD(APowerMorph, UnMorphFlash) +DEFINE_FIELD(APowerMorph, MorphStyle) +DEFINE_FIELD(APowerMorph, MorphedPlayer) +DEFINE_FIELD(APowerMorph, bInUndoMorph) + //=========================================================================== // // APowerMorph :: Serialize @@ -1897,7 +1904,7 @@ void APowerMorph::Serialize(FSerializer &arc) ("morphstyle", MorphStyle) ("morphflash", MorphFlash) ("unmorphflash", UnMorphFlash) - ("player", Player); + ("morphedplayer", MorphedPlayer); } //=========================================================================== @@ -1917,7 +1924,7 @@ void APowerMorph::InitEffect( ) { Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet ItemFlags |= IF_CREATECOPYMOVED; // Let the caller know the "real" owner has changed (to the morphed actor) - Player = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field) + MorphedPlayer = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field) } else // morph failed - give the caller an opportunity to fail the pickup completely { @@ -1939,19 +1946,19 @@ void APowerMorph::EndEffect( ) // Abort if owner already destroyed if (Owner == NULL) { - assert(Player == NULL); + assert(MorphedPlayer == NULL); return; } // Abort if owner already unmorphed - if (Player == NULL) + if (MorphedPlayer == NULL) { return; } // Abort if owner is dead; their Die() method will // take care of any required unmorphing on death. - if (Player->health <= 0) + if (MorphedPlayer->health <= 0) { return; } @@ -1959,26 +1966,26 @@ void APowerMorph::EndEffect( ) // Unmorph if possible if (!bInUndoMorph) { - int savedMorphTics = Player->morphTics; - P_UndoPlayerMorph (Player, Player, 0, !!(Player->MorphStyle & MORPH_UNDOALWAYS)); + int savedMorphTics = MorphedPlayer->morphTics; + P_UndoPlayerMorph (MorphedPlayer, MorphedPlayer, 0, !!(MorphedPlayer->MorphStyle & MORPH_UNDOALWAYS)); // Abort if unmorph failed; in that case, // set the usual retry timer and return. - if (Player != NULL && Player->morphTics) + if (MorphedPlayer != NULL && MorphedPlayer->morphTics) { // Transfer retry timeout // to the powerup's timer. - EffectTics = Player->morphTics; + EffectTics = MorphedPlayer->morphTics; // Reload negative morph tics; // use actual value; it may // be in use for animation. - Player->morphTics = savedMorphTics; + MorphedPlayer->morphTics = savedMorphTics; // Try again some time later return; } } // Unmorph suceeded - Player = NULL; + MorphedPlayer = NULL; } // Infinite Ammo Powerup ----------------------------------------------------- diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index bd7e86323c..d9629c1653 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -286,7 +286,7 @@ public: PClassPlayerPawn *PlayerClass; PClassActor *MorphFlash, *UnMorphFlash; int MorphStyle; - player_t *Player; + player_t *MorphedPlayer; bool bInUndoMorph; // Because P_UndoPlayerMorph() can call EndEffect recursively protected: diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 49ea525bbf..84de5a0d6e 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -618,6 +618,13 @@ void InitAllPowerupEffects(AInventory *item) IMPLEMENT_CLASS(AMorphProjectile, false, false, false, false) +DEFINE_FIELD(AMorphProjectile, PlayerClass) +DEFINE_FIELD(AMorphProjectile, MonsterClass) +DEFINE_FIELD(AMorphProjectile, MorphFlash) +DEFINE_FIELD(AMorphProjectile, UnMorphFlash) +DEFINE_FIELD(AMorphProjectile, Duration) +DEFINE_FIELD(AMorphProjectile, MorphStyle) + int AMorphProjectile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { if (target->player) @@ -652,6 +659,11 @@ IMPLEMENT_POINTERS_START(AMorphedMonster) IMPLEMENT_POINTER(UnmorphedMe) IMPLEMENT_POINTERS_END +DEFINE_FIELD(AMorphedMonster, UnmorphedMe) +DEFINE_FIELD(AMorphedMonster, UnmorphTime) +DEFINE_FIELD(AMorphedMonster, MorphStyle) +DEFINE_FIELD(AMorphedMonster, MorphExitFlash) + void AMorphedMonster::Serialize(FSerializer &arc) { Super::Serialize (arc); diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 048590b397..12e521d53f 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -487,6 +487,12 @@ class PowerDoubleFiringSpeed : Powerup native {} class PowerMorph : Powerup native { + native Class PlayerClass; + native Class MorphFlash, UnMorphFlash; + native int MorphStyle; + native PlayerInfo MorphedPlayer; + native bool bInUndoMorph; + Default { Powerup.Duration -40; diff --git a/wadsrc/static/zscript/shared/morph.txt b/wadsrc/static/zscript/shared/morph.txt index ff58d897b1..c5c2cbe0a7 100644 --- a/wadsrc/static/zscript/shared/morph.txt +++ b/wadsrc/static/zscript/shared/morph.txt @@ -1,5 +1,10 @@ class MorphProjectile : Actor native { + + native Class PlayerClass; + native Class MonsterClass, MorphFlash, UnMorphFlash; + native int Duration, MorphStyle; + Default { Damage 1; @@ -11,6 +16,10 @@ class MorphProjectile : Actor native class MorphedMonster : Actor native { + native Actor UnmorphedMe; + native int UnmorphTime, MorphStyle; + native Class MorphExitFlash; + Default { Monster; From cd919e72e16012dcbb35b1dd1decf50cc670d53e Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Wed, 23 Nov 2016 21:50:21 +0100 Subject: [PATCH 344/471] - Don't null-check the ZCC_TreeNode 'this' pointer. Compilers are allowed to simplify the 'this == nullptr' code block because it makes no sense in 'well-defined C++ code'. --- src/scripting/zscript/zcc-parse.lemon | 38 +++++++++++++-------------- src/scripting/zscript/zcc_parser.cpp | 31 ++++++++++++++++++++++ src/scripting/zscript/zcc_parser.h | 30 ++------------------- 3 files changed, 52 insertions(+), 47 deletions(-) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index fc1803f1dc..379d1516ef 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -22,7 +22,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) // If a is non-null, appends b to a. Otherwise, sets a to b. #define SAFE_APPEND(a,b) \ - if (a == NULL) a = b; else a->AppendSibling(b); + if (a == NULL) a = b; else AppendTreeNodeSibling(a, b); #define UNARY_EXPR(X,T) NEW_AST_NODE(ExprUnary, expr1, X); expr1->Operation = T; expr1->Operand = X; expr1->Type = NULL #define BINARY_EXPR(X,Y,T) NEW_AST_NODE(ExprBinary, expr2, X); expr2->Operation = T; expr2->Type = NULL; expr2->Left = X; expr2->Right = Y @@ -221,14 +221,14 @@ dottable_id(X) ::= dottable_id(A) DOT IDENTIFIER(B). { NEW_AST_NODE(Identifier,id2,A); id2->Id = B.Name(); - A->AppendSibling(id2); + AppendTreeNodeSibling(A, 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); + AppendTreeNodeSibling(A, id2); X = A; /*X-overwrites-A*/ } @@ -239,7 +239,7 @@ dottable_id(X) ::= dottable_id(A) DOT COLOR. { NEW_AST_NODE(Identifier,id2,A); id2->Id = NAME_Color; - A->AppendSibling(id2); + AppendTreeNodeSibling(A, id2); X = A; /*X-overwrites-A*/ } @@ -299,7 +299,7 @@ opt_struct_body(X) ::= error. { X = NULL; } struct_body(X) ::= struct_member(X). -struct_body(X) ::= struct_member(A) struct_body(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); } +struct_body(X) ::= struct_member(A) struct_body(B). { X = A; /*X-overwrites-A*/ AppendTreeNodeSibling(X, B); } struct_member(X) ::= declarator(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ } @@ -375,11 +375,11 @@ enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRAC } // Add a new terminating node, to indicate that the ConstantDefs for this enum are done. NEW_AST_NODE(EnumTerminator,term,U); - C->AppendSibling(term); + AppendTreeNodeSibling(C, term); } if (C != NULL) { - def->AppendSibling(C); + AppendTreeNodeSibling(def, C); } X = def; } @@ -389,7 +389,7 @@ enum_type(X) ::= COLON int_type(A). { X = A; /*X-overwrites-A*/ } enum_list(X) ::= error. { X = NULL; } enum_list(X) ::= enumerator(X). -enum_list(X) ::= enum_list(A) COMMA enumerator(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); } +enum_list(X) ::= enum_list(A) COMMA enumerator(B). { X = A; /*X-overwrites-A*/ AppendTreeNodeSibling(X, B); } opt_enum_list(X) ::= . { X = NULL; } opt_enum_list(X) ::= enum_list(X) opt_comma. @@ -450,7 +450,7 @@ 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); + AppendTreeNodeSibling(X, id); } @@ -545,7 +545,7 @@ state_opts(X) ::= state_opts(A) FAST. { A.Fast = true; X = A; /*X-overwri state_opts(X) ::= state_opts(A) SLOW. { A.Slow = true; X = A; /*X-overwrites-A*/ } 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) OFFSET LPAREN expr(B) COMMA expr(C) RPAREN. { A.Offset = B; AppendTreeNodeSibling(B, C); X = A; /*X-overwrites-A*/ } state_opts(X) ::= state_opts(A) LIGHT LPAREN light_list(B) RPAREN. { X = A; /*X-overwrites-A*/ X.Lights = B; } %type light_list {ZCC_ExprConstant *} @@ -565,7 +565,7 @@ light_list(X) ::= light_list(A) COMMA STRCONST(B). strconst->Operation = PEX_ConstValue; strconst->Type = TypeString; strconst->StringVal = B.String; - A->AppendSibling(strconst); + AppendTreeNodeSibling(A, strconst); X = A; /*X-overwrites-A*/ } @@ -783,7 +783,7 @@ type_or_array(X) ::= type(X). type_or_array(X) ::= type(A) array_size(B). { X = A; /*X-overwrites-A*/ X->ArraySize = B; } type_list(X) ::= type_or_array(X). /* A comma-separated list of types */ -type_list(X) ::= type_list(A) COMMA type_or_array(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); } +type_list(X) ::= type_list(A) COMMA type_or_array(B). { X = A; /*X-overwrites-A*/ AppendTreeNodeSibling(X, B); } type_list_or_void(X) ::= VOID. { X = NULL; } type_list_or_void(X) ::= type_list(X). @@ -805,7 +805,7 @@ array_size_expr(X) ::= LBRACKET(L) opt_expr(A) RBRACKET. array_size(X) ::= array_size_expr(X). array_size(X) ::= array_size(A) array_size_expr(B). { - A->AppendSibling(B); + AppendTreeNodeSibling(A, B); X = A; /*X-overwrites-A*/ } @@ -911,7 +911,7 @@ variable_name(X) ::= IDENTIFIER(A) array_size(B). variable_list(X) ::= variable_name(X). variable_list(X) ::= variable_list(A) COMMA variable_name(B). { - A->AppendSibling(B); + AppendTreeNodeSibling(A, B); X = A; /*X-overwrites-A*/ } @@ -984,11 +984,11 @@ func_params(X) ::= func_param_list(A) COMMA ELLIPSIS. parm->Flags = 0; parm->Default = nullptr; X = A; /*X-overwrites-A*/ - X->AppendSibling(parm); + AppendTreeNodeSibling(X, 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); } +func_param_list(X) ::= func_param_list(A) COMMA func_param(B). { X = A; /*X-overwrites-A*/ AppendTreeNodeSibling(X, B); } func_param(X) ::= func_param_flags(A) type(B) IDENTIFIER(C). { @@ -1422,7 +1422,7 @@ expr_list(X) ::= expr(X). expr_list(X) ::= expr_list(A) COMMA expr(B). { X = A; /*X-overwrites-A*/ - X->AppendSibling(B); + AppendTreeNodeSibling(X, B); } /*----- Function argument lists -----*/ @@ -1453,7 +1453,7 @@ func_expr_list(X) ::= func_expr_list(A) COMMA(T) func_expr_item(B). B = nil_b; } X = A; /*X-overwrites-A*/ - X->AppendSibling(B); + AppendTreeNodeSibling(X, B); } func_expr_item(X) ::= . @@ -1877,6 +1877,6 @@ var_init(X) ::= IDENTIFIER EQ LBRACE error RBRACE. 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); + AppendTreeNodeSibling(A, B); X = A; /*X-overwrites-A*/ } diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 37fd8ff0c3..401a15c251 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -466,3 +466,34 @@ ZCC_TreeNode *ZCCParseState::InitNode(size_t size, EZCCTreeNodeType type) node->SourceLump = sc->LumpNum; return node; } + +// Appends a sibling to this node's sibling list. +void AppendTreeNodeSibling(ZCC_TreeNode *thisnode, ZCC_TreeNode *sibling) +{ + if (thisnode == nullptr) + { + // Some bad syntax can actually get here, so better abort so that the user can see the error which caused this. + I_FatalError("Internal script compiler error. Execution aborted."); + } + if (sibling == nullptr) + { + return; + } + + ZCC_TreeNode *&SiblingPrev = thisnode->SiblingPrev; + ZCC_TreeNode *&SiblingNext = thisnode->SiblingNext; + + // Check integrity of our sibling list. + assert(SiblingPrev->SiblingNext == thisnode); + assert(SiblingNext->SiblingPrev == thisnode); + + // Check integrity of new sibling list. + assert(sibling->SiblingPrev->SiblingNext == sibling); + assert(sibling->SiblingNext->SiblingPrev == sibling); + + ZCC_TreeNode *siblingend = sibling->SiblingPrev; + SiblingPrev->SiblingNext = sibling; + sibling->SiblingPrev = SiblingPrev; + SiblingPrev = siblingend; + siblingend->SiblingNext = thisnode; +} diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index a2fc3fb560..7a763b2c18 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -161,34 +161,6 @@ struct ZCC_TreeNode // one of the structures below. EZCCTreeNodeType NodeType; - // Appends a sibling to this node's sibling list. - void AppendSibling(ZCC_TreeNode *sibling) - { - if (this == nullptr) - { - // Some bad syntax can actually get here, so better abort so that the user can see the error which caused this. - I_FatalError("Internal script compiler error. Execution aborted."); - } - if (sibling == NULL) - { - return; - } - - // Check integrity of our sibling list. - assert(SiblingPrev->SiblingNext == this); - assert(SiblingNext->SiblingPrev == this); - - // Check integrity of new sibling list. - assert(sibling->SiblingPrev->SiblingNext == sibling); - assert(sibling->SiblingNext->SiblingPrev == sibling); - - ZCC_TreeNode *siblingend = sibling->SiblingPrev; - SiblingPrev->SiblingNext = sibling; - sibling->SiblingPrev = SiblingPrev; - SiblingPrev = siblingend; - siblingend->SiblingNext = this; - } - operator FScriptPosition() { return FScriptPosition(*SourceName, SourceLoc); @@ -196,6 +168,8 @@ struct ZCC_TreeNode }; +void AppendTreeNodeSibling(ZCC_TreeNode *thisnode, ZCC_TreeNode *sibling); + struct ZCC_Identifier : ZCC_TreeNode { ENamedName Id; From 3e890d182b62a8ad42f83e745c58276312ad6a16 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 24 Nov 2016 01:23:35 +0100 Subject: [PATCH 345/471] - scriptified D'Sparil. - added retrieval of defaults from an actor pointer. --- src/CMakeLists.txt | 1 - src/g_heretic/a_dsparil.cpp | 327 ------------------ src/g_heretic/a_hereticmisc.cpp | 1 - src/g_heretic/a_hereticweaps.cpp | 45 +-- src/g_shared/a_specialspot.cpp | 12 + src/p_map.cpp | 5 + src/p_mobj.cpp | 6 + src/p_pspr.cpp | 13 - src/p_teleport.cpp | 12 + src/scripting/codegeneration/codegen.cpp | 16 + wadsrc/static/zscript/actor.txt | 13 +- wadsrc/static/zscript/base.txt | 2 + wadsrc/static/zscript/heretic/dsparil.txt | 272 ++++++++++++++- .../static/zscript/heretic/hereticweaps.txt | 30 +- 14 files changed, 349 insertions(+), 406 deletions(-) delete mode 100644 src/g_heretic/a_dsparil.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd44a6761d..d4edae81e9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -857,7 +857,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_heretic/a_dsparil.cpp g_heretic/a_hereticartifacts.cpp g_heretic/a_hereticweaps.cpp g_hexen/a_blastradius.cpp diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp deleted file mode 100644 index 5ab4067d39..0000000000 --- a/src/g_heretic/a_dsparil.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "p_enemy.h" -#include "a_action.h" -#include "s_sound.h" -#include "m_random.h" -#include "a_sharedglobal.h" -#include "gstrings.h" -#include "a_specialspot.h" -#include "vm.h" -#include "g_level.h" -*/ - -static FRandom pr_s2fx1 ("S2FX1"); -static FRandom pr_scrc1atk ("Srcr1Attack"); -static FRandom pr_dst ("D'SparilTele"); -static FRandom pr_s2d ("Srcr2Decide"); -static FRandom pr_s2a ("Srcr2Attack"); -static FRandom pr_bluespark ("BlueSpark"); - -//---------------------------------------------------------------------------- -// -// PROC A_Sor1Pain -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_Sor1Pain) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->special1 = 20; // Number of steps to walk fast - CALL_ACTION(A_Pain, self); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_Sor1Chase -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_Sor1Chase) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->special1) - { - self->special1--; - self->tics -= 3; - } - A_Chase(stack, self); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_Srcr1Attack -// -// Sorcerer demon attack. -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - DAngle angle; - - if (!self->target) - { - return 0; - } - S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM); - if (self->CheckMeleeRange ()) - { - int damage = pr_scrc1atk.HitDice (8); - 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("SorcererFX1"); - if (self->health > (self->SpawnHealth()/3)*2) - { // Spit one fireball - P_SpawnMissileZ (self, self->Z() + 48, self->target, fx ); - } - else - { // Spit three fireballs - mo = P_SpawnMissileZ (self, self->Z() + 48, self->target, fx); - if (mo != NULL) - { - angle = mo->Angles.Yaw; - P_SpawnMissileAngleZ(self, self->Z() + 48, fx, angle - 3, mo->Vel.Z); - P_SpawnMissileAngleZ(self, self->Z() + 48, fx, angle + 3, mo->Vel.Z); - } - if (self->health < self->SpawnHealth()/3) - { // Maybe attack again - if (self->special1) - { // Just attacked, so don't attack again - self->special1 = 0; - } - else - { // Set state to attack again - self->special1 = 1; - self->SetState (self->FindState("Missile2")); - } - } - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_SorcererRise -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_SorcererRise) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - self->flags &= ~MF_SOLID; - mo = Spawn("Sorcerer2", self->Pos(), ALLOW_REPLACE); - mo->Translation = self->Translation; - mo->SetState (mo->FindState("Rise")); - mo->Angles.Yaw = self->Angles.Yaw; - mo->CopyFriendliness (self, true); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC P_DSparilTeleport -// -//---------------------------------------------------------------------------- - -void P_DSparilTeleport (AActor *actor) -{ - DVector3 prev; - AActor *mo; - AActor *spot; - - DSpotState *state = DSpotState::GetSpotState(); - if (state == NULL) return; - - spot = state->GetSpotWithMinMaxDistance(PClass::FindActor("BossSpot"), actor->X(), actor->Y(), 128, 0); - if (spot == NULL) return; - - prev = actor->Pos(); - if (P_TeleportMove (actor, spot->Pos(), false)) - { - mo = Spawn("Sorcerer2Telefade", prev, ALLOW_REPLACE); - if (mo) mo->Translation = actor->Translation; - S_Sound (mo, CHAN_BODY, "misc/teleport", 1, ATTN_NORM); - actor->SetState (actor->FindState("Teleport")); - S_Sound (actor, CHAN_BODY, "misc/teleport", 1, ATTN_NORM); - actor->SetZ(actor->floorz); - actor->Angles.Yaw = spot->Angles.Yaw; - actor->Vel.Zero(); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_Srcr2Decide -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Decide) -{ - PARAM_SELF_PROLOGUE(AActor); - - static const int chance[] = - { - 192, 120, 120, 120, 64, 64, 32, 16, 0 - }; - - unsigned int chanceindex = self->health / ((self->SpawnHealth()/8 == 0) ? 1 : self->SpawnHealth()/8); - if (chanceindex >= countof(chance)) - { - chanceindex = countof(chance) - 1; - } - - if (pr_s2d() < chance[chanceindex]) - { - P_DSparilTeleport (self); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_Srcr2Attack -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Attack) -{ - PARAM_SELF_PROLOGUE(AActor); - - int chance; - - if (!self->target) - { - return 0; - } - S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NONE); - if (self->CheckMeleeRange()) - { - int damage = pr_s2a.HitDice (20); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; - } - chance = self->health < self->SpawnHealth()/2 ? 96 : 48; - if (pr_s2a() < chance) - { // Wizard spawners - - PClassActor *fx = PClass::FindActor("Sorcerer2FX2"); - if (fx) - { - P_SpawnMissileAngle(self, fx, self->Angles.Yaw - 45, 0.5); - P_SpawnMissileAngle(self, fx, self->Angles.Yaw + 45, 0.5); - } - } - else - { // Blue bolt - P_SpawnMissile (self, self->target, PClass::FindActor("Sorcerer2FX1")); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_BlueSpark -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_BlueSpark) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - AActor *mo; - - for (i = 0; i < 2; i++) - { - mo = Spawn("Sorcerer2FXSpark", self->Pos(), ALLOW_REPLACE); - mo->Vel.X = pr_bluespark.Random2() / 128.; - mo->Vel.Y = pr_bluespark.Random2() / 128.; - mo->Vel.Z = 1. + pr_bluespark() / 256.; - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_GenWizard -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_GenWizard) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - mo = Spawn("Wizard", self->Pos(), ALLOW_REPLACE); - if (mo != NULL) - { - mo->AddZ(-mo->GetDefault()->Height / 2, false); - if (!P_TestMobjLocation (mo)) - { // Didn't fit - mo->ClearCounters(); - mo->Destroy (); - } - else - { // [RH] Make the new wizards inherit D'Sparil's target - mo->CopyFriendliness (self->target, true); - - self->Vel.Zero(); - self->SetState (self->FindState(NAME_Death)); - self->flags &= ~MF_MISSILE; - mo->master = self->target; - P_SpawnTeleportFog(self, self->Pos(), false, true); - } - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_Sor2DthInit -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_Sor2DthInit) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->special1 = 7; // Animation loop counter - P_Massacre (); // Kill monsters early - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_Sor2DthLoop -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_Sor2DthLoop) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (--self->special1) - { // Need to loop - self->SetState (self->FindState("DeathLoop")); - } - return 0; -} - diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 18093b752d..5929c1d865 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -19,6 +19,5 @@ #include "serializer.h" // Include all the other Heretic stuff here to reduce compile time -#include "a_dsparil.cpp" #include "a_hereticartifacts.cpp" #include "a_hereticweaps.cpp" diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 4d3a0b0e82..dc34fd2068 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -27,7 +27,6 @@ static FRandom pr_bfx1 ("BlasterFX1"); static FRandom pr_ripd ("RipperD"); static FRandom pr_fb1 ("FireBlasterPL1"); static FRandom pr_bfx1t ("BlasterFX1Tick"); -static FRandom pr_hrfx2 ("HornRodFX2"); static FRandom pr_rp ("RainPillar"); static FRandom pr_fsr1 ("FireSkullRodPL1"); static FRandom pr_storm ("SkullRodStorm"); @@ -819,27 +818,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnRippers) // --- Skull rod ------------------------------------------------------------ -// Horn Rod FX 2 ------------------------------------------------------------ - -class AHornRodFX2 : public AActor -{ - DECLARE_CLASS (AHornRodFX2, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(AHornRodFX2, false, false, false, false) - -int AHornRodFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->IsKindOf (PClass::FindClass("Sorcerer2")) && pr_hrfx2() < 96) - { // D'Sparil teleports away - P_DSparilTeleport (target); - return -1; - } - return damage; -} - // Rain pillar 1 ------------------------------------------------------------ class ARainPillar : public AActor @@ -940,7 +918,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL2) if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } - P_SpawnPlayerMissile (self, 0,0,0, RUNTIME_CLASS(AHornRodFX2), self->Angles.Yaw, &t, &MissileActor); + P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("HornRodFX2"), self->Angles.Yaw, &t, &MissileActor); // Use MissileActor instead of the return value from // P_SpawnPlayerMissile because we need to give info to the mobj // even if it exploded immediately. @@ -1170,25 +1148,6 @@ void APhoenixRodPowered::EndPowerup () P_SetPsprite(Owner->player, PSP_WEAPON, SisterWeapon->GetReadyState()); } -class APhoenixFX1 : public AActor -{ - DECLARE_CLASS (APhoenixFX1, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(APhoenixFX1, false, false, false, false) - -int APhoenixFX1::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->IsKindOf (PClass::FindClass("Sorcerer2")) && pr_hrfx2() < 96) - { // D'Sparil teleports away - P_DSparilTeleport (target); - return -1; - } - return damage; -} - // Phoenix FX 2 ------------------------------------------------------------- class APhoenixFX2 : public AActor @@ -1232,7 +1191,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL1) if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } - P_SpawnPlayerMissile (self, RUNTIME_CLASS(APhoenixFX1)); + P_SpawnPlayerMissile (self, PClass::FindActor("PhoenixFX1")); self->Thrust(self->Angles.Yaw + 180, 4); return 0; } diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index e96f5a9036..935333a5ce 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -344,6 +344,18 @@ ASpecialSpot *DSpotState::GetSpotWithMinMaxDistance(PClassActor *type, double x, return NULL; } +DEFINE_ACTION_FUNCTION(DSpotState, GetSpotWithMinMaxDistance) +{ + PARAM_SELF_PROLOGUE(DSpotState); + PARAM_CLASS(type, AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(mindist); + PARAM_FLOAT(maxdist); + ACTION_RETURN_OBJECT(self->GetSpotWithMinMaxDistance(type, x, y, mindist, maxdist)); +} + + //---------------------------------------------------------------------------- // // diff --git a/src/p_map.cpp b/src/p_map.cpp index db0a129c6d..af5ab100af 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1777,6 +1777,11 @@ bool P_TestMobjLocation(AActor *mobj) return false; } +DEFINE_ACTION_FUNCTION(AActor, TestMobjLocation) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(P_TestMobjLocation(self)); +} //============================================================================= // diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a79fc0f16d..8784dc0753 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6781,6 +6781,12 @@ int AActor::SpawnHealth() const } } +DEFINE_ACTION_FUNCTION(AActor, SpawnHealth) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(self->SpawnHealth()); +} + FState *AActor::GetRaiseState() { if (!(flags & MF_CORPSE)) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 0e39e259e0..ca305d677b 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1449,19 +1449,6 @@ DEFINE_ACTION_FUNCTION(AActor, AimTarget) ACTION_RETURN_OBJECT(P_AimTarget(self)); } - -DEFINE_ACTION_FUNCTION(AActor, A_Light) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(light); - - if (self->player != NULL) - { - self->player->extralight = clamp(light, -20, 20); - } - return 0; -} - //------------------------------------------------------------------------ // // PROC P_SetupPsprites diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index 01595ff659..80bfd4f7fb 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -96,6 +96,18 @@ void P_SpawnTeleportFog(AActor *mobj, const DVector3 &pos, bool beforeTele, bool mo->target = mobj; } +DEFINE_ACTION_FUNCTION(AActor, SpawnTeleportFog) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_BOOL(before); + PARAM_BOOL(settarget); + P_SpawnTeleportFog(self, DVector3(x, y, z), before, settarget); + return 0; +} + // // TELEPORTATION // diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 1cc16214ce..ba4eab9e3b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5593,6 +5593,22 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classct PSymbol *sym; PSymbolTable *symtbl; bool isclass = objtype->IsKindOf(RUNTIME_CLASS(PClass)); + + if (Identifier == NAME_Default) + { + if (!objtype->IsKindOf(RUNTIME_CLASS(PClassActor))) + { + ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type."); + delete this; + return nullptr; + } + + FxExpression * x = new FxClassDefaults(object, ScriptPosition); + object = nullptr; + delete this; + return x->Resolve(ctx); + } + if ((sym = objtype->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr) { if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index e7179bd47e..f4489f575c 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -249,6 +249,7 @@ class Actor : Thinker native native bool GiveBody (int num, int max=0); native void RestoreDamage(); + native int SpawnHealth(); native void SetDamage(int dmg); native double Distance2D(Actor other); native void SetOrigin(vector3 newpos, bool moving); @@ -259,17 +260,19 @@ class Actor : Thinker native native Actor AimTarget(); native bool CheckMissileSpawn(double maxdist); native bool CheckPosition(Vector2 pos, bool actorsonly = false); + native bool TestMobjLocation(); 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, double angle, double vz, double speed, Actor owner = null, bool checkspawn = true); native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); + native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); - native void A_Light(int extralight); - void A_Light0() { A_Light(0); } - void A_Light1() { A_Light(1); } - void A_Light2() { A_Light(2); } - void A_LightInverse() { A_Light(0x80000000); } + void A_Light(int extralight) { if (player) player.extralight = clamp(extralight, -20, 20); } + void A_Light0() { if (player) player.extralight = 0; } + void A_Light1() { if (player) player.extralight = 1; } + void A_Light2() { if (player) player.extralight = 2; } + void A_LightInverse() { if (player) player.extralight = 0x80000000; } native Actor OldSpawnMissile(Actor dest, class type, Actor owner = null); native Actor SpawnPuff(class pufftype, vector3 pos, double hitdir, double particledir, int updown, int flags = 0, Actor vict = null); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 11d565ae90..a63020bbf5 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -49,6 +49,8 @@ class SpotState : Object native { native static SpotState GetSpotState(); native SpecialSpot GetNextInList(class type, int skipcounter); + native SpecialSpot GetSpotWithMinMaxDistance(Class type, double x, double y, double mindist, double maxdist); + } struct LevelLocals native diff --git a/wadsrc/static/zscript/heretic/dsparil.txt b/wadsrc/static/zscript/heretic/dsparil.txt index 8cd60c8bb4..e2cfca558d 100644 --- a/wadsrc/static/zscript/heretic/dsparil.txt +++ b/wadsrc/static/zscript/heretic/dsparil.txt @@ -38,10 +38,6 @@ class Sorcerer1 : Actor HitObituary "$OB_DSPARIL1HIT"; } - native void A_Sor1Pain (); - native void A_Sor1Chase (); - native void A_Srcr1Attack (); - native void A_SorcererRise (); States { @@ -79,6 +75,104 @@ class Sorcerer1 : Actor SRCR L 12; SRCR P -1 A_SorcererRise; } + + + //---------------------------------------------------------------------------- + // + // PROC A_Sor1Pain + // + //---------------------------------------------------------------------------- + + void A_Sor1Pain () + { + special1 = 20; // Number of steps to walk fast + A_Pain(); + } + + //---------------------------------------------------------------------------- + // + // PROC A_Sor1Chase + // + //---------------------------------------------------------------------------- + + void A_Sor1Chase () + { + if (special1) + { + special1--; + tics -= 3; + } + A_Chase(); + } + + //---------------------------------------------------------------------------- + // + // PROC A_Srcr1Attack + // + // Sorcerer demon attack. + // + //---------------------------------------------------------------------------- + + void A_Srcr1Attack () + { + if (!target) + { + return; + } + A_PlaySound (AttackSound, CHAN_BODY); + if (CheckMeleeRange ()) + { + int damage = random[Srcr1Attack](1,8) * 8; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + return; + } + + if (health > (SpawnHealth()/3)*2) + { // Spit one fireball + SpawnMissileZ (pos.z + 48, target, "SorcererFX1"); + } + else + { // Spit three fireballs + Actor mo = SpawnMissileZ (pos.z + 48, target, "SorcererFX1"); + if (mo != null) + { + double ang = mo.angle; + SpawnMissileAngleZ(pos.z + 48, "SorcererFX1", ang - 3, mo.Vel.Z); + SpawnMissileAngleZ(pos.z + 48, "SorcererFX1", ang + 3, mo.Vel.Z); + } + if (health < SpawnHealth()/3) + { // Maybe attack again + if (special1) + { // Just attacked, so don't attack again + special1 = 0; + } + else + { // Set state to attack again + special1 = 1; + SetStateLabel("Missile2"); + } + } + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_SorcererRise + // + //---------------------------------------------------------------------------- + + void A_SorcererRise () + { + bSolid = false; + Actor mo = Spawn("Sorcerer2", Pos, ALLOW_REPLACE); + mo.Translation = Translation; + mo.SetStateLabel("Rise"); + mo.angle = angle; + mo.CopyFriendliness (self, true); + } + + } @@ -142,10 +236,6 @@ class Sorcerer2 : Actor HitObituary "$OB_DSPARIL2HIT"; } - native void A_Srcr2Decide (); - native void A_Srcr2Attack (); - native void A_Sor2DthInit (); - native void A_Sor2DthLoop (); States { @@ -189,6 +279,118 @@ class Sorcerer2 : Actor SDTH O -1 A_BossDeath; Stop; } + + //---------------------------------------------------------------------------- + // + // PROC P_DSparilTeleport + // + //---------------------------------------------------------------------------- + + void DSparilTeleport () + { + SpotState state = SpotState.GetSpotState(); + if (state == null) return; + + Actor spot = state.GetSpotWithMinMaxDistance("BossSpot", pos.x, pos.y, 128, 0); + if (spot == null) return; + + Vector3 prev = Pos; + if (TeleportMove (spot.Pos, false)) + { + Actor mo = Spawn("Sorcerer2Telefade", prev, ALLOW_REPLACE); + if (mo) + { + mo.Translation = Translation; + mo.A_PlaySound("misc/teleport", CHAN_BODY); + } + SetStateLabel ("Teleport"); + A_PlaySound ("misc/teleport", CHAN_BODY); + SetZ(floorz); + angle = spot.angle; + vel = (0,0,0); + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_Srcr2Decide + // + //---------------------------------------------------------------------------- + + void A_Srcr2Decide () + { + static const int chance[] = + { + 192, 120, 120, 120, 64, 64, 32, 16, 0 + }; + + int health8 = max(1, SpawnHealth() / 8); + int chanceindex = min(8, health / health8); + + if (random[Srcr2Decide]() < chance[chanceindex]) + { + DSparilTeleport (); + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_Srcr2Attack + // + //---------------------------------------------------------------------------- + + void A_Srcr2Attack () + { + if (!target) + { + return; + } + A_PlaySound (AttackSound, CHAN_BODY); + if (CheckMeleeRange()) + { + int damage = random[Srcr2Atk](1, 8) * 20; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + return; + } + int chance = health < SpawnHealth()/2 ? 96 : 48; + if (random[Srcr2Atk]() < chance) + { // Wizard spawners + + SpawnMissileAngle("Sorcerer2FX2", Angle - 45, 0.5); + SpawnMissileAngle("Sorcerer2FX2", Angle + 45, 0.5); + } + else + { // Blue bolt + SpawnMissile (target, "Sorcerer2FX1"); + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_Sor2DthInit + // + //---------------------------------------------------------------------------- + + void A_Sor2DthInit () + { + special1 = 7; // Animation loop counter + Thing_Destroy(0); // Kill monsters early + } + + //---------------------------------------------------------------------------- + // + // PROC A_Sor2DthLoop + // + //---------------------------------------------------------------------------- + + void A_Sor2DthLoop () + { + if (--special1) + { // Need to loop + SetStateLabel("DeathLoop"); + } + } } @@ -210,8 +412,6 @@ class Sorcerer2FX1 : Actor RenderStyle "Add"; } - native void A_BlueSpark (); - States { Spawn: @@ -222,6 +422,23 @@ class Sorcerer2FX1 : Actor FX16 HIJKL 5 BRIGHT; Stop; } + + //---------------------------------------------------------------------------- + // + // PROC A_BlueSpark + // + //---------------------------------------------------------------------------- + + void A_BlueSpark () + { + for (int i = 0; i < 2; i++) + { + Actor mo = Spawn("Sorcerer2FXSpark", pos, ALLOW_REPLACE); + mo.Vel.X = Random2[BlueSpark]() / 128.; + mo.Vel.Y = Random2[BlueSpark]() / 128.; + mo.Vel.Z = 1. + Random[BlueSpark]() / 256.; + } + } } // Sorcerer 2 FX Spark ------------------------------------------------------ @@ -244,7 +461,7 @@ class Sorcerer2FXSpark : Actor Spawn: FX16 DEF 12 BRIGHT; Stop; - } + } } // Sorcerer 2 FX 2 ---------------------------------------------------------- @@ -263,8 +480,6 @@ class Sorcerer2FX2 : Actor RenderStyle "Add"; } - native void A_GenWizard (); - States { Spawn: @@ -277,7 +492,38 @@ class Sorcerer2FX2 : Actor Stop; } + +//---------------------------------------------------------------------------- +// +// PROC A_GenWizard +// +//---------------------------------------------------------------------------- + + void A_GenWizard () + { + Actor mo = Spawn("Wizard", pos, ALLOW_REPLACE); + if (mo != null) + { + mo.AddZ(-mo.Default.Height / 2, false); + if (!mo.TestMobjLocation ()) + { // Didn't fit + mo.ClearCounters(); + mo.Destroy (); + } + else + { // [RH] Make the new wizards inherit D'Sparil's target + mo.CopyFriendliness (self.target, true); + + Vel = (0,0,0); + SetStateLabel('Death'); + bMissile = false; + mo.master = target; + SpawnTeleportFog(pos, false, true); + } + } + } } + // Sorcerer 2 Telefade ------------------------------------------------------ class Sorcerer2Telefade : Actor diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index 4c254500b9..e309ba0956 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -1037,7 +1037,7 @@ class HornRodFX1 : Actor // Horn Rod FX 2 ------------------------------------------------------------ -class HornRodFX2 : Actor native +class HornRodFX2 : Actor { Default { @@ -1059,7 +1059,7 @@ class HornRodFX2 : Actor native States { - Spawn: + Spawn: FX00 C 3 BRIGHT; FX00 D 3 BRIGHT A_SeekerMissile(10, 30); FX00 E 3 BRIGHT; @@ -1074,6 +1074,18 @@ class HornRodFX2 : Actor native FX00 G 1 A_SkullRodStorm; Wait; } + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + Sorcerer2 s2 = Sorcerer2(target); + if (s2 != null && random[HornRodFX2]() < 96) + { // D'Sparil teleports away + s2.DSparilTeleport (); + return -1; + } + return damage; + } + } // Rain pillar 1 ------------------------------------------------------------ @@ -1195,7 +1207,7 @@ class PhoenixRodPowered : PhoenixRod native // Phoenix FX 1 ------------------------------------------------------------- -class PhoenixFX1 : Actor native +class PhoenixFX1 : Actor { Default { @@ -1225,6 +1237,18 @@ class PhoenixFX1 : Actor native FX08 DEFGH 4 BRIGHT; Stop; } + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + Sorcerer2 s2 = Sorcerer2(target); + if (s2 != null && random[HornRodFX2]() < 96) + { // D'Sparil teleports away + s2.DSparilTeleport (); + return -1; + } + return damage; + } + } // Phoenix puff ------------------------------------------------------------- From 2ece9b6172950b82371f2ac22139c7fc00160c81 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 24 Nov 2016 10:39:16 +0100 Subject: [PATCH 346/471] - scriptified Heretic's staff and wand. --- src/g_heretic/a_hereticweaps.cpp | 184 ++---------- src/sc_man_tokens.h | 1 + wadsrc/static/zscript.txt | 2 + .../static/zscript/heretic/hereticweaps.txt | 270 ------------------ wadsrc/static/zscript/heretic/weaponstaff.txt | 147 ++++++++++ wadsrc/static/zscript/heretic/weaponwand.txt | 217 ++++++++++++++ 6 files changed, 393 insertions(+), 428 deletions(-) create mode 100644 wadsrc/static/zscript/heretic/weaponstaff.txt create mode 100644 wadsrc/static/zscript/heretic/weaponwand.txt diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index dc34fd2068..196bd32407 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -15,10 +15,6 @@ #include "doomstat.h" */ -static FRandom pr_sap ("StaffAtkPL1"); -static FRandom pr_sap2 ("StaffAtkPL2"); -static FRandom pr_fgw ("FireWandPL1"); -static FRandom pr_fgw2 ("FireWandPL2"); static FRandom pr_boltspark ("BoltSpark"); static FRandom pr_macerespawn ("MaceRespawn"); static FRandom pr_maceatk ("FireMacePL1"); @@ -50,134 +46,6 @@ void P_DSparilTeleport (AActor *actor); extern bool P_AutoUseChaosDevice (player_t *player); -// --- Staff ---------------------------------------------------------------- - -//---------------------------------------------------------------------------- -// -// PROC A_StaffAttackPL1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_StaffAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - DAngle slope; - player_t *player; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - - PARAM_INT (damage); - PARAM_CLASS (puff, AActor); - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - if (puff == NULL) - { - puff = PClass::FindActor(NAME_BulletPuff); // just to be sure - } - angle = self->Angles.Yaw + pr_sap.Random2() * (5.625 / 256); - slope = P_AimLineAttack (self, angle, MELEERANGE); - P_LineAttack (self, angle, MELEERANGE, slope, damage, NAME_Melee, puff, true, &t); - if (t.linetarget) - { - //S_StartSound(player->mo, sfx_stfhit); - // turn to face target - self->Angles.Yaw = t.angleFromSource; - } - return 0; -} - - -//---------------------------------------------------------------------------- -// -// PROC A_FireGoldWandPL1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo(weapon->bAltFire)) - return 0; - } - DAngle pitch = P_BulletSlope(self); - damage = 7 + (pr_fgw() & 7); - angle = self->Angles.Yaw; - if (player->refire) - { - angle += pr_fgw.Random2() * (5.625 / 256); - } - P_LineAttack(self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "GoldWandPuff1"); - S_Sound(self, CHAN_WEAPON, "weapons/wandhit", 1, ATTN_NORM); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireGoldWandPL2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - int i; - DAngle angle; - int damage; - double vz; - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - DAngle pitch = P_BulletSlope(self); - - vz = -GetDefaultByName("GoldWandFX2")->Speed * pitch.TanClamped(); - P_SpawnMissileAngle(self, PClass::FindActor("GoldWandFX2"), self->Angles.Yaw - (45. / 8), vz); - P_SpawnMissileAngle(self, PClass::FindActor("GoldWandFX2"), self->Angles.Yaw + (45. / 8), vz); - angle = self->Angles.Yaw - (45. / 8); - for(i = 0; i < 5; i++) - { - damage = 1+(pr_fgw2()&7); - P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "GoldWandPuff2"); - angle += ((45. / 8) * 2) / 4; - } - S_Sound (self, CHAN_WEAPON, "weapons/wandhit", 1, ATTN_NORM); - return 0; -} - //---------------------------------------------------------------------------- // // PROC A_FireCrossbowPL1 @@ -323,20 +191,20 @@ DEFINE_ACTION_FUNCTION(AActor, A_GauntletAttack) S_Sound (self, CHAN_AUTO, "weapons/gauntletshit", 1, ATTN_NORM); } // turn to face target - DAngle angle = t.angleFromSource; - DAngle anglediff = deltaangle(self->Angles.Yaw, angle); + DAngle ang = t.angleFromSource; + DAngle anglediff = deltaangle(self->Angles.Yaw, ang); if (anglediff < 0.0) { if (anglediff < -4.5) - self->Angles.Yaw = angle + 90.0 / 21; + self->Angles.Yaw = ang + 90.0 / 21; else self->Angles.Yaw -= 4.5; } else { if (anglediff > 4.5) - self->Angles.Yaw = angle - 90.0 / 21; + self->Angles.Yaw = ang - 90.0 / 21; else self->Angles.Yaw += 4.5; } @@ -477,9 +345,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_MacePL1Check) // [RH] Avoid some precision loss by scaling the velocity directly #if 0 // This is the original code, for reference. - a.ngle_t angle = self->angle>>ANGLETOF.INESHIFT; - self->velx = F.ixedMul(7*F.RACUNIT, f.inecosine[angle]); - self->vely = F.ixedMul(7*F.RACUNIT, f.inesine[angle]); + a.ngle_t ang = self->ang>>ANGLETOF.INESHIFT; + self->velx = F.ixedMul(7*F.RACUNIT, f.inecosine[ang]); + self->vely = F.ixedMul(7*F.RACUNIT, f.inesine[ang]); #else double velscale = 7 / self->Vel.XY().Length(); self->Vel.X *= velscale; @@ -621,7 +489,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact) int i; AActor *target; - DAngle angle = 0.; + DAngle ang = 0.; bool newAngle; FTranslatedLineTarget t; @@ -648,29 +516,29 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact) } else { // Seek - angle = self->AngleTo(target); + ang = self->AngleTo(target); newAngle = true; } } else { // Find new target - angle = 0.; + ang = 0.; for (i = 0; i < 16; i++) { - P_AimLineAttack (self, angle, 640., &t, 0., ALF_NOFRIENDS|ALF_PORTALRESTRICT, NULL, self->target); + P_AimLineAttack (self, ang, 640., &t, 0., ALF_NOFRIENDS|ALF_PORTALRESTRICT, NULL, self->target); if (t.linetarget && self->target != t.linetarget) { self->tracer = t.linetarget; - angle = t.angleFromSource; + ang = t.angleFromSource; newAngle = true; break; } - angle += 22.5; + ang += 22.5; } } if (newAngle) { - self->Angles.Yaw = angle; + self->Angles.Yaw = ang; self->VelFromAngle(); } self->SetState (self->SpawnState); @@ -762,7 +630,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1) { PARAM_ACTION_PROLOGUE(AActor); - DAngle angle; + DAngle ang; int damage; player_t *player; @@ -779,12 +647,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1) } DAngle pitch = P_BulletSlope(self); damage = pr_fb1.HitDice (4); - angle = self->Angles.Yaw; + ang = self->Angles.Yaw; if (player->refire) { - angle += pr_fb1.Random2() * (5.625 / 256); + ang += pr_fb1.Random2() * (5.625 / 256); } - P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "BlasterPuff"); + P_LineAttack (self, ang, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "BlasterPuff"); S_Sound (self, CHAN_WEAPON, "weapons/blastershoot", 1, ATTN_NORM); return 0; } @@ -800,15 +668,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnRippers) PARAM_SELF_PROLOGUE(AActor); unsigned int i; - DAngle angle; + DAngle ang; AActor *ripper; for(i = 0; i < 8; i++) { ripper = Spawn (self->Pos(), ALLOW_REPLACE); - angle = i*45.; + ang = i*45.; ripper->target = self->target; - ripper->Angles.Yaw = angle; + ripper->Angles.Yaw = ang; ripper->VelFromAngle(); P_CheckMissileSpawn (ripper, self->radius); } @@ -1207,17 +1075,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff) PARAM_SELF_PROLOGUE(AActor); AActor *puff; - DAngle angle; + DAngle ang; //[RH] Heretic never sets the target for seeking //P_SeekerMissile (self, 5, 10); puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE); - angle = self->Angles.Yaw + 90; - puff->Vel = DVector3(angle.ToVector(1.3), 0); + ang = self->Angles.Yaw + 90; + puff->Vel = DVector3(ang.ToVector(1.3), 0); puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE); - angle = self->Angles.Yaw - 90; - puff->Vel = DVector3(angle.ToVector(1.3), 0); + ang = self->Angles.Yaw - 90; + puff->Vel = DVector3(ang.ToVector(1.3), 0); return 0; } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 8ea05d7e40..dfa6c044c6 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -49,6 +49,7 @@ xx(TK_Until, "'until'") xx(TK_While, "'while'") xx(TK_Bool, "'bool'") xx(TK_Float, "'float'") +xx(TK_Float32, "'float32'") xx(TK_Double, "'double'") xx(TK_Char, "'char'") xx(TK_Byte, "'byte'") diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index fdf057b58c..1e73cc0dd8 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -95,6 +95,8 @@ zscript/heretic/wizard.txt zscript/heretic/ironlich.txt zscript/heretic/dsparil.txt zscript/heretic/chicken.txt +zscript/heretic/weaponstaff.txt +zscript/heretic/weaponwand.txt zscript/hexen/baseweapons.txt zscript/hexen/korax.txt diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index e309ba0956..00985b2baa 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -8,276 +8,6 @@ class HereticWeapon : Weapon } -// 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 diff --git a/wadsrc/static/zscript/heretic/weaponstaff.txt b/wadsrc/static/zscript/heretic/weaponstaff.txt new file mode 100644 index 0000000000..6349bd61bb --- /dev/null +++ b/wadsrc/static/zscript/heretic/weaponstaff.txt @@ -0,0 +1,147 @@ +// Staff -------------------------------------------------------------------- + +class Staff : HereticWeapon +{ + Default + { + Weapon.SelectionOrder 3800; + +THRUGHOST + +WEAPON.WIMPY_WEAPON + +WEAPON.MELEEWEAPON + Weapon.sisterweapon "StaffPowered"; + Obituary "$OB_MPSTAFF"; + Tag "$TAG_STAFF"; + } + + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_StaffAttackPL1 + // + //---------------------------------------------------------------------------- + + action void A_StaffAttack (int damage, class puff) + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + double ang = angle + Random2[StaffAtk]() * (5.625 / 256); + double slope = AimLineAttack (ang, MELEERANGE); + LineAttack (ang, MELEERANGE, slope, damage, 'Melee', puff, true, t); + if (t.linetarget) + { + //S_StartSound(player.mo, sfx_stfhit); + // turn to face target + angle = t.angleFromSource; + } + } +} + +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; + } +} + + + diff --git a/wadsrc/static/zscript/heretic/weaponwand.txt b/wadsrc/static/zscript/heretic/weaponwand.txt new file mode 100644 index 0000000000..bd1475adb6 --- /dev/null +++ b/wadsrc/static/zscript/heretic/weaponwand.txt @@ -0,0 +1,217 @@ +// 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"; + } + + 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; + } + + + //---------------------------------------------------------------------------- + // + // PROC A_FireGoldWandPL1 + // + //---------------------------------------------------------------------------- + + action void A_FireGoldWandPL1 () + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + double pitch = BulletSlope(); + int damage = 7 + random[FireGoldWand]() & 7; + double ang = angle; + if (player.refire) + { + ang += Random2[FireGoldWand]() * (5.625 / 256); + } + LineAttack(ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', "GoldWandPuff1"); + A_PlaySound("weapons/wandhit", CHAN_WEAPON); + } + +} + +class GoldWandPowered : GoldWand +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoGive 0; + Weapon.SisterWeapon "GoldWand"; + Obituary "$OB_MPPGOLDWAND"; + Tag "$TAG_GOLDWANDP"; + } + + States + { + Fire: + GWND B 3; + GWND C 4 A_FireGoldWandPL2; + GWND D 3; + GWND D 0 A_ReFire; + Goto Ready; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FireGoldWandPL2 + // + //---------------------------------------------------------------------------- + + action void A_FireGoldWandPL2 () + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + double pitch = BulletSlope(); + + double vz = -GetDefaultByType("GoldWandFX2").Speed * clamp(tan(pitch), -5, 5); + SpawnMissileAngle("GoldWandFX2", angle - (45. / 8), vz); + SpawnMissileAngle("GoldWandFX2", angle + (45. / 8), vz); + double ang = angle - (45. / 8); + for(int i = 0; i < 5; i++) + { + int damage = random[FireGoldWand](1, 8); + LineAttack (ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', "GoldWandPuff2"); + ang += ((45. / 8) * 2) / 4; + } + A_PlaySound("weapons/wandhit", CHAN_WEAPON); + } + + +} + + +// 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; + } +} + From 677d7579d41991d48ed2c2774c5278aeb1a5db71 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 24 Nov 2016 11:29:51 +0100 Subject: [PATCH 347/471] - scriptified Heretic's crossbow and gauntlets. --- src/g_heretic/a_hereticweaps.cpp | 167 ----------- wadsrc/static/zscript.txt | 2 + .../static/zscript/heretic/hereticweaps.txt | 279 ------------------ .../static/zscript/heretic/weaponcrossbow.txt | 208 +++++++++++++ .../zscript/heretic/weapongauntlets.txt | 210 +++++++++++++ 5 files changed, 420 insertions(+), 446 deletions(-) create mode 100644 wadsrc/static/zscript/heretic/weaponcrossbow.txt create mode 100644 wadsrc/static/zscript/heretic/weapongauntlets.txt diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 196bd32407..b584be0ea0 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -18,7 +18,6 @@ static FRandom pr_boltspark ("BoltSpark"); static FRandom pr_macerespawn ("MaceRespawn"); static FRandom pr_maceatk ("FireMacePL1"); -static FRandom pr_gatk ("GauntletAttack"); static FRandom pr_bfx1 ("BlasterFX1"); static FRandom pr_ripd ("RipperD"); static FRandom pr_fb1 ("FireBlasterPL1"); @@ -46,172 +45,6 @@ void P_DSparilTeleport (AActor *actor); extern bool P_AutoUseChaosDevice (player_t *player); -//---------------------------------------------------------------------------- -// -// PROC A_FireCrossbowPL1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX1")); - P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX3"), self->Angles.Yaw - 4.5); - P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX3"), self->Angles.Yaw + 4.5); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireCrossbowPL2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX2")); - P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX2"), self->Angles.Yaw - 4.5); - P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX2"), self->Angles.Yaw + 4.5); - P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX3"), self->Angles.Yaw - 9.); - P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX3"), self->Angles.Yaw + 9.); - return 0; -} - -//--------------------------------------------------------------------------- -// -// PROC A_GauntletAttack -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_GauntletAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle Angle; - int damage; - DAngle slope; - int randVal; - double dist; - player_t *player; - PClassActor *pufftype; - FTranslatedLineTarget t; - int actualdamage = 0; - - if (nullptr == (player = self->player)) - { - return 0; - } - - PARAM_INT(power); - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != nullptr) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - - player->GetPSprite(PSP_WEAPON)->x = ((pr_gatk() & 3) - 2); - player->GetPSprite(PSP_WEAPON)->y = WEAPONTOP + (pr_gatk() & 3); - } - Angle = self->Angles.Yaw; - if (power) - { - damage = pr_gatk.HitDice (2); - dist = 4*MELEERANGE; - Angle += pr_gatk.Random2() * (2.8125 / 256); - pufftype = PClass::FindActor("GauntletPuff2"); - } - else - { - damage = pr_gatk.HitDice (2); - dist = SAWRANGE; - Angle += pr_gatk.Random2() * (5.625 / 256); - pufftype = PClass::FindActor("GauntletPuff1"); - } - slope = P_AimLineAttack (self, Angle, dist); - P_LineAttack (self, Angle, dist, slope, damage, NAME_Melee, pufftype, false, &t, &actualdamage); - if (!t.linetarget) - { - if (pr_gatk() > 64) - { - player->extralight = !player->extralight; - } - S_Sound (self, CHAN_AUTO, "weapons/gauntletson", 1, ATTN_NORM); - return 0; - } - randVal = pr_gatk(); - if (randVal < 64) - { - player->extralight = 0; - } - else if (randVal < 160) - { - player->extralight = 1; - } - else - { - player->extralight = 2; - } - if (power) - { - if (!(t.linetarget->flags5 & MF5_DONTDRAIN)) P_GiveBody (self, actualdamage>>1); - S_Sound (self, CHAN_AUTO, "weapons/gauntletspowhit", 1, ATTN_NORM); - } - else - { - S_Sound (self, CHAN_AUTO, "weapons/gauntletshit", 1, ATTN_NORM); - } - // turn to face target - DAngle ang = t.angleFromSource; - DAngle anglediff = deltaangle(self->Angles.Yaw, ang); - - if (anglediff < 0.0) - { - if (anglediff < -4.5) - self->Angles.Yaw = ang + 90.0 / 21; - else - self->Angles.Yaw -= 4.5; - } - else - { - if (anglediff > 4.5) - self->Angles.Yaw = ang - 90.0 / 21; - else - self->Angles.Yaw += 4.5; - } - self->flags |= MF_JUSTATTACKED; - return 0; -} - // --- Mace ----------------------------------------------------------------- #define MAGIC_JUNK 1234 diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 1e73cc0dd8..d2853ddb98 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -97,6 +97,8 @@ zscript/heretic/dsparil.txt zscript/heretic/chicken.txt zscript/heretic/weaponstaff.txt zscript/heretic/weaponwand.txt +zscript/heretic/weaponcrossbow.txt +zscript/heretic/weapongauntlets.txt zscript/hexen/baseweapons.txt zscript/hexen/korax.txt diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index 00985b2baa..a6faf958f2 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -8,285 +8,6 @@ class HereticWeapon : Weapon } -// 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 ---------------------------------------------------------- diff --git a/wadsrc/static/zscript/heretic/weaponcrossbow.txt b/wadsrc/static/zscript/heretic/weaponcrossbow.txt new file mode 100644 index 0000000000..bd5e9517ac --- /dev/null +++ b/wadsrc/static/zscript/heretic/weaponcrossbow.txt @@ -0,0 +1,208 @@ +// 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"; + } + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FireCrossbowPL1 + // + //---------------------------------------------------------------------------- + + action void A_FireCrossbowPL1 () + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + SpawnPlayerMissile ("CrossbowFX1"); + SpawnPlayerMissile ("CrossbowFX3", angle - 4.5); + SpawnPlayerMissile ("CrossbowFX3", angle + 4.5); + } +} + + +class CrossbowPowered : Crossbow +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoGive 0; + Weapon.SisterWeapon "Crossbow"; + Tag "$TAG_CROSSBOWP"; + } + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FireCrossbowPL2 + // + //---------------------------------------------------------------------------- + + action void A_FireCrossbowPL2() + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + SpawnPlayerMissile ("CrossbowFX2"); + SpawnPlayerMissile ("CrossbowFX2", angle - 4.5); + SpawnPlayerMissile ("CrossbowFX2", angle + 4.5); + SpawnPlayerMissile ("CrossbowFX3", angle - 9.); + SpawnPlayerMissile ("CrossbowFX3", angle + 9.); + } +} + + +// 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; + } +} + diff --git a/wadsrc/static/zscript/heretic/weapongauntlets.txt b/wadsrc/static/zscript/heretic/weapongauntlets.txt new file mode 100644 index 0000000000..d06efe4655 --- /dev/null +++ b/wadsrc/static/zscript/heretic/weapongauntlets.txt @@ -0,0 +1,210 @@ +// 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"; + } + + 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; + } + + //--------------------------------------------------------------------------- + // + // PROC A_GauntletAttack + // + //--------------------------------------------------------------------------- + + action void A_GauntletAttack (int power) + { + int damage; + double dist; + Class pufftype; + FTranslatedLineTarget t; + int actualdamage = 0; + Actor puff; + + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + + player.GetPSprite(PSP_WEAPON).x = ((random[GauntletAtk]() & 3) - 2); + player.GetPSprite(PSP_WEAPON).y = WEAPONTOP + (random[GauntletAtk]() & 3); + } + double ang = angle; + if (power) + { + damage = random[GauntletAtk](1, 8) * 2; + dist = 4*MELEERANGE; + ang += random2[GauntletAtk]() * (2.8125 / 256); + pufftype = "GauntletPuff2"; + } + else + { + damage = random[GauntletAtk](1, 8) * 2; + dist = SAWRANGE; + ang += random2[GauntletAtk]() * (5.625 / 256); + pufftype = "GauntletPuff1"; + } + double slope = AimLineAttack (ang, dist); + [puff, actualdamage] = LineAttack (ang, dist, slope, damage, 'Melee', pufftype, false, t); + if (!t.linetarget) + { + if (random[GauntletAtk]() > 64) + { + player.extralight = !player.extralight; + } + A_PlaySound ("weapons/gauntletson", CHAN_AUTO); + return; + } + int randVal = random[GauntletAtk](); + if (randVal < 64) + { + player.extralight = 0; + } + else if (randVal < 160) + { + player.extralight = 1; + } + else + { + player.extralight = 2; + } + if (power) + { + if (!t.linetarget.bDontDrain) GiveBody (actualdamage >> 1); + A_PlaySound ("weapons/gauntletspowhit", CHAN_AUTO); + } + else + { + A_PlaySound ("weapons/gauntletshit", CHAN_AUTO); + } + // turn to face target + ang = t.angleFromSource; + double anglediff = deltaangle(angle, ang); + + if (anglediff < 0.0) + { + if (anglediff < -4.5) + angle = ang + 90.0 / 21; + else + angle -= 4.5; + } + else + { + if (anglediff > 4.5) + angle = ang - 90.0 / 21; + else + angle += 4.5; + } + bJustAttacked = true; + } +} + + +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; + } +} + From 3a059cbfd6ca0884b778506b50a2728bf39a039c Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Thu, 24 Nov 2016 10:47:45 +0100 Subject: [PATCH 348/471] - Backported A_FireRailgun 'puffType' param from Zandronum. Zandronum added this so that it could restore the original Skulltag piercing armor capability with a specific puff, like it's done with the other zdoom railgun action functions. --- wadsrc/static/zscript/doom/doomweapons.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/wadsrc/static/zscript/doom/doomweapons.txt b/wadsrc/static/zscript/doom/doomweapons.txt index 731740ac64..f3a40c22a2 100644 --- a/wadsrc/static/zscript/doom/doomweapons.txt +++ b/wadsrc/static/zscript/doom/doomweapons.txt @@ -19,8 +19,9 @@ extend class StateProvider // // [RH] A_FireRailgun + // [TP] This now takes a puff type to retain Skulltag's railgun's ability to pierce armor. // - action void A_FireRailgun(int offset_xy = 0) + action void A_FireRailgun(class puffType = "BulletPuff", int offset_xy = 0) { if (player == null) { @@ -42,17 +43,17 @@ extend class StateProvider } int damage = deathmatch ? 100 : 150; - A_RailAttack(damage, offset_xy, false); // note that this function handles ammo depletion itself for Dehacked compatibility purposes. + A_RailAttack(damage, offset_xy, false, pufftype: puffType); // note that this function handles ammo depletion itself for Dehacked compatibility purposes. } action void A_FireRailgunLeft() { - A_FireRailgun(-10); + A_FireRailgun(offset_xy: -10); } action void A_FireRailgunRight() { - A_FireRailgun(10); + A_FireRailgun(offset_xy: 10); } action void A_RailWait() @@ -60,4 +61,4 @@ extend class StateProvider // only here to satisfy old Dehacked patches. } -} \ No newline at end of file +} From 3f5bf88d69ff85eeea5b719c0ace3feaa0836776 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 24 Nov 2016 13:45:43 +0100 Subject: [PATCH 349/471] - scriptified Heretic's mace. - fixed: FxAssignSelf did not the correct number of registers for vector operations. - fixed a few asserts in vector2 instructions. - turned the virtual AActor::HitFloor method into a flag MF7_SMASHABLE. The only use of this function was to kill Hexen's pottery when they hit the floor, and this looks like something that can be exposed to modders less clumsily. --- src/actor.h | 4 +- src/g_heretic/a_hereticweaps.cpp | 343 ------------- src/g_hexen/a_hexenspecialdecs.cpp | 15 - src/g_raven/a_artitele.cpp | 18 - src/namedef.h | 1 + src/p_mobj.cpp | 30 +- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/thingdef_data.cpp | 1 + src/scripting/vm/vmexec.h | 8 +- src/virtual.h | 22 + wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 3 + .../static/zscript/heretic/hereticweaps.txt | 204 -------- wadsrc/static/zscript/heretic/weaponmace.txt | 468 ++++++++++++++++++ .../static/zscript/hexen/hexenspecialdecs.txt | 4 +- 15 files changed, 529 insertions(+), 595 deletions(-) create mode 100644 wadsrc/static/zscript/heretic/weaponmace.txt diff --git a/src/actor.h b/src/actor.h index 83873adc50..bbe7381a24 100644 --- a/src/actor.h +++ b/src/actor.h @@ -385,6 +385,7 @@ enum ActorFlag7 MF7_USEKILLSCRIPTS = 0x00800000, // [JM] Use "KILL" Script on death if not forced by GameInfo. MF7_NOKILLSCRIPTS = 0x01000000, // [JM] No "KILL" Script on death whatsoever, even if forced by GameInfo. MF7_SPRITEANGLE = 0x02000000, // [MC] Utilize the SpriteAngle property and lock the rotation to the degrees specified. + MF7_SMASHABLE = 0x04000000, // dies if hitting the floor. }; // --- mobj.renderflags --- @@ -636,9 +637,6 @@ public: // Made a metadata property so no longer virtual void Howl (); - // Actor just hit the floor - virtual void HitFloor (); - // plays bouncing sound void PlayBounceSound(bool onfloor); diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index b584be0ea0..cc964ecc05 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -45,349 +45,6 @@ void P_DSparilTeleport (AActor *actor); extern bool P_AutoUseChaosDevice (player_t *player); -// --- Mace ----------------------------------------------------------------- - -#define MAGIC_JUNK 1234 - -// Mace FX4 ----------------------------------------------------------------- - -class AMaceFX4 : public AActor -{ - DECLARE_CLASS (AMaceFX4, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(AMaceFX4, false, false, false, false) - -int AMaceFX4::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if ((target->flags2 & MF2_BOSS) || (target->flags3 & MF3_DONTSQUASH) || target->IsTeammate (this->target)) - { // Don't allow cheap boss kills and don't instagib teammates - return damage; - } - else if (target->player) - { // Player specific checks - if (target->player->mo->flags2 & MF2_INVULNERABLE) - { // Can't hurt invulnerable players - return -1; - } - if (P_AutoUseChaosDevice (target->player)) - { // Player was saved using chaos device - return -1; - } - } - return TELEFRAG_DAMAGE; // Something's gonna die -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireMacePL1B -// -//---------------------------------------------------------------------------- - -void FireMacePL1B (AActor *actor) -{ - AActor *ball; - player_t *player; - - if (NULL == (player = actor->player)) - { - return; - } - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return; - } - ball = Spawn("MaceFX2", actor->PosPlusZ(28 - actor->Floorclip), ALLOW_REPLACE); - ball->Vel.Z = 2 - player->mo->Angles.Pitch.TanClamped(); - ball->target = actor; - ball->Angles.Yaw = actor->Angles.Yaw; - ball->AddZ(ball->Vel.Z); - ball->VelFromAngle(); - ball->Vel += actor->Vel.XY()/2; - S_Sound (ball, CHAN_BODY, "weapons/maceshoot", 1, ATTN_NORM); - P_CheckMissileSpawn (ball, actor->radius); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireMacePL1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *ball; - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - - if (pr_maceatk() < 28) - { - FireMacePL1B(self); - return 0; - } - AWeapon *weapon = player->ReadyWeapon; - if (weapon != nullptr) - { - if (!weapon->DepleteAmmo(weapon->bAltFire)) - return 0; - - player->GetPSprite(PSP_WEAPON)->x = ((pr_maceatk() & 3) - 2); - player->GetPSprite(PSP_WEAPON)->y = WEAPONTOP + (pr_maceatk() & 3); - } - ball = P_SpawnPlayerMissile(self, PClass::FindActor("MaceFX1"), self->Angles.Yaw + (((pr_maceatk() & 7) - 4) * (360. / 256))); - if (ball) - { - ball->special1 = 16; // tics till dropoff - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MacePL1Check -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MacePL1Check) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->special1 == 0) - { - return 0; - } - self->special1 -= 4; - if (self->special1 > 0) - { - return 0; - } - self->special1 = 0; - self->flags &= ~MF_NOGRAVITY; - self->Gravity = 1. / 8;; - // [RH] Avoid some precision loss by scaling the velocity directly -#if 0 - // This is the original code, for reference. - a.ngle_t ang = self->ang>>ANGLETOF.INESHIFT; - self->velx = F.ixedMul(7*F.RACUNIT, f.inecosine[ang]); - self->vely = F.ixedMul(7*F.RACUNIT, f.inesine[ang]); -#else - double velscale = 7 / self->Vel.XY().Length(); - self->Vel.X *= velscale; - self->Vel.Y *= velscale; -#endif - self->Vel.Z *= 0.5; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MaceBallImpact -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact) -{ - PARAM_SELF_PROLOGUE(AActor); - - if ((self->health != MAGIC_JUNK) && (self->flags & MF_INBOUNCE)) - { // Bounce - self->health = MAGIC_JUNK; - self->Vel.Z *= 0.75; - self->BounceFlags = BOUNCE_None; - self->SetState (self->SpawnState); - S_Sound (self, CHAN_BODY, "weapons/macebounce", 1, ATTN_NORM); - } - else - { // Explode - self->Vel.Zero(); - self->flags |= MF_NOGRAVITY; - self->Gravity = 1; - S_Sound (self, CHAN_BODY, "weapons/macehit", 1, ATTN_NORM); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MaceBallImpact2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact2) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *tiny; - - if ((self->Z() <= self->floorz) && P_HitFloor (self)) - { // Landed in some sort of liquid - self->Destroy (); - return 0; - } - if (self->flags & MF_INBOUNCE) - { - if (self->Vel.Z < 2) - { - goto boom; - } - - // Bounce - self->Vel.Z *= 0.75; - self->SetState (self->SpawnState); - - tiny = Spawn("MaceFX3", self->Pos(), ALLOW_REPLACE); - tiny->target = self->target; - tiny->Angles.Yaw = self->Angles.Yaw + 90.; - tiny->VelFromAngle(self->Vel.Z - 1.); - tiny->Vel += { self->Vel.X * .5, self->Vel.Y * .5, self->Vel.Z }; - P_CheckMissileSpawn (tiny, self->radius); - - tiny = Spawn("MaceFX3", self->Pos(), ALLOW_REPLACE); - tiny->target = self->target; - tiny->Angles.Yaw = self->Angles.Yaw - 90.; - tiny->VelFromAngle(self->Vel.Z - 1.); - tiny->Vel += { self->Vel.X * .5, self->Vel.Y * .5, self->Vel.Z }; - P_CheckMissileSpawn (tiny, self->radius); - } - else - { // Explode -boom: - self->Vel.Zero(); - self->flags |= MF_NOGRAVITY; - self->BounceFlags = BOUNCE_None; - self->Gravity = 1; - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireMacePL2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *mo; - player_t *player; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - mo = P_SpawnPlayerMissile (self, 0,0,0, RUNTIME_CLASS(AMaceFX4), self->Angles.Yaw, &t); - if (mo) - { - mo->Vel += self->Vel.XY(); - mo->Vel.Z = 2 - player->mo->Angles.Pitch.TanClamped(); - if (t.linetarget && !t.unlinked) - { - mo->tracer = t.linetarget; - } - } - S_Sound (self, CHAN_WEAPON, "weapons/maceshoot", 1, ATTN_NORM); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_DeathBallImpact -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - AActor *target; - DAngle ang = 0.; - bool newAngle; - FTranslatedLineTarget t; - - if ((self->Z() <= self->floorz) && P_HitFloor (self)) - { // Landed in some sort of liquid - self->Destroy (); - return 0; - } - if (self->flags & MF_INBOUNCE) - { - if (self->Vel.Z < 2) - { - goto boom; - } - - // Bounce - newAngle = false; - target = self->tracer; - if (target) - { - if (!(target->flags&MF_SHOOTABLE)) - { // Target died - self->tracer = NULL; - } - else - { // Seek - ang = self->AngleTo(target); - newAngle = true; - } - } - else - { // Find new target - ang = 0.; - for (i = 0; i < 16; i++) - { - P_AimLineAttack (self, ang, 640., &t, 0., ALF_NOFRIENDS|ALF_PORTALRESTRICT, NULL, self->target); - if (t.linetarget && self->target != t.linetarget) - { - self->tracer = t.linetarget; - ang = t.angleFromSource; - newAngle = true; - break; - } - ang += 22.5; - } - } - if (newAngle) - { - self->Angles.Yaw = ang; - self->VelFromAngle(); - } - self->SetState (self->SpawnState); - S_Sound (self, CHAN_BODY, "weapons/macestop", 1, ATTN_NORM); - } - else - { // Explode -boom: - self->Vel.Zero(); - self->flags |= MF_NOGRAVITY; - self->Gravity = 1; - S_Sound (self, CHAN_BODY, "weapons/maceexplode", 1, ATTN_NORM); - } - return 0; -} - // Blaster FX 1 ------------------------------------------------------------- diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index 6d441ba57c..0dcdc2c5f4 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -32,21 +32,6 @@ void A_PotteryExplode (AActor *); void A_PotteryChooseBit (AActor *); void A_PotteryCheck (AActor *); -class APottery1 : public AActor -{ - DECLARE_CLASS (APottery1, AActor) -public: - void HitFloor (); -}; - -IMPLEMENT_CLASS(APottery1, false, false, false, false) - -void APottery1::HitFloor () -{ - Super::HitFloor (); - P_DamageMobj (this, NULL, NULL, 25, NAME_None); -} - //============================================================================ // // A_PotteryExplode diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp index 35387df450..b333c9a13e 100644 --- a/src/g_raven/a_artitele.cpp +++ b/src/g_raven/a_artitele.cpp @@ -61,21 +61,3 @@ bool AArtiTeleport::Use (bool pickup) return true; } -//--------------------------------------------------------------------------- -// -// FUNC P_AutoUseChaosDevice -// -//--------------------------------------------------------------------------- - -bool P_AutoUseChaosDevice (player_t *player) -{ - AInventory *arti = player->mo->FindInventory(PClass::FindActor("ArtiTeleport")); - - if (arti != NULL) - { - player->mo->UseInventory (arti); - player->health = player->mo->health = (player->health+1)/2; - return true; - } - return false; -} diff --git a/src/namedef.h b/src/namedef.h index 545bf02604..639c762ebd 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -209,6 +209,7 @@ xx(XDeath) xx(Burn) //xx(Ice) // already defined above xx(Disintegrate) +xx(Smash) // Weapon animator names. xx(Select) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 8784dc0753..46ecbd3faf 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -948,6 +948,14 @@ bool AActor::UseInventory (AInventory *item) return true; } +DEFINE_ACTION_FUNCTION(AActor, UseInventory) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(item, AInventory); + self->VMSuperCall(); + ACTION_RETURN_BOOL(self->UseInventory(item)); +} + //=========================================================================== // // AActor :: DropInventory @@ -2741,7 +2749,10 @@ void P_ZMovement (AActor *mo, double oldfloorz) return; } // Let the actor do something special for hitting the floor - mo->HitFloor (); + if (mo->flags7 & MF7_SMASHABLE) + { + P_DamageMobj(mo, nullptr, nullptr, mo->health, NAME_Smash); + } if (mo->player) { if (mo->player->jumpTics < 0 || mo->Vel.Z < minvel) @@ -3230,10 +3241,6 @@ void AActor::Howl () } } -void AActor::HitFloor () -{ -} - bool AActor::Slam (AActor *thing) { flags &= ~MF_SKULLFLY; @@ -5945,6 +5952,12 @@ bool P_HitFloor (AActor *thing) return P_HitWater (thing, m->m_sector, pos); } +DEFINE_ACTION_FUNCTION(AActor, HitFloor) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(P_HitFloor(self)); +} + //--------------------------------------------------------------------------- // // P_CheckSplash @@ -6543,6 +6556,13 @@ bool AActor::IsTeammate (AActor *other) return false; } +DEFINE_ACTION_FUNCTION(AActor, isTeammate) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_BOOL(self->IsTeammate(other)); +} + //========================================================================== // // AActor :: GetSpecies diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index ba4eab9e3b..4bf6f076eb 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2323,7 +2323,7 @@ ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it if (!pointer.Target) { - ExpEmit out(build, ValueType->GetRegType()); + ExpEmit out(build, ValueType->GetRegType(), ValueType->GetRegCount()); if (Assignment->IsBitWrite != -1) { build->Emit(OP_LBIT, out.RegNum, pointer.RegNum, 1 << Assignment->IsBitWrite); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index bc6e0ad43a..3d7a9d3e11 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -294,6 +294,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF7, USEKILLSCRIPTS, AActor, flags7), DEFINE_FLAG(MF7, NOKILLSCRIPTS, AActor, flags7), DEFINE_FLAG(MF7, SPRITEANGLE, AActor, flags7), + DEFINE_FLAG(MF7, SMASHABLE, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 2e77716808..6f25318d61 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -217,7 +217,7 @@ begin: reg.atag[a] = ATAG_GENERIC; NEXTOP; OP(LV2): - ASSERTF(a+2); ASSERTA(B); ASSERTKD(C); + ASSERTF(a+1); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); { auto v = (double *)ptr; @@ -226,7 +226,7 @@ begin: } NEXTOP; OP(LV2_R): - ASSERTF(a+2); ASSERTA(B); ASSERTD(C); + ASSERTF(a+1); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); { auto v = (double *)ptr; @@ -331,7 +331,7 @@ begin: *(void **)ptr = reg.a[B]; NEXTOP; OP(SV2): - ASSERTA(a); ASSERTF(B+2); ASSERTKD(C); + ASSERTA(a); ASSERTF(B+1); ASSERTKD(C); GETADDR(PA,KC,X_WRITE_NIL); { auto v = (double *)ptr; @@ -340,7 +340,7 @@ begin: } NEXTOP; OP(SV2_R): - ASSERTA(a); ASSERTF(B+2); ASSERTD(C); + ASSERTA(a); ASSERTF(B+1); ASSERTD(C); GETADDR(PA,RC,X_WRITE_NIL); { auto v = (double *)ptr; diff --git a/src/virtual.h b/src/virtual.h index 4e0b3f01b7..26fc694ea1 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -39,6 +39,7 @@ VMEXPORTED_NATIVES_START VMEXPORTED_NATIVES_FUNC(Activate) VMEXPORTED_NATIVES_FUNC(Deactivate) VMEXPORTED_NATIVES_FUNC(DoSpecialDamage) + VMEXPORTED_NATIVES_FUNC(UseInventory) VMEXPORTED_NATIVES_END @@ -213,6 +214,26 @@ public: return retval; } } + bool UseInventory(AInventory *item) + { + if (this->ObjectFlags & OF_SuperCall) + { + this->ObjectFlags &= ~OF_SuperCall; + return ExportedNatives::Get()->template UseInventory(this, item); + } + else + { + VINDEX(AActor, UseInventory); + // Without the type cast this picks the 'void *' assignment... + VMValue params[2] = { (DObject*)this, (DObject*)item }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(VFUNC, params, 2, &ret, 1, nullptr); + return !!retval; + } + } }; @@ -245,6 +266,7 @@ VMEXPORT_NATIVES_START(AActor, DThinker) VMEXPORT_NATIVES_FUNC(Activate) VMEXPORT_NATIVES_FUNC(Deactivate) VMEXPORT_NATIVES_FUNC(DoSpecialDamage) + VMEXPORT_NATIVES_FUNC(UseInventory) VMEXPORT_NATIVES_END(AActor) /* diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index d2853ddb98..074bb89681 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -99,6 +99,7 @@ zscript/heretic/weaponstaff.txt zscript/heretic/weaponwand.txt zscript/heretic/weaponcrossbow.txt zscript/heretic/weapongauntlets.txt +zscript/heretic/weaponmace.txt zscript/hexen/baseweapons.txt zscript/hexen/korax.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index f4489f575c..0f0acc3077 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -238,6 +238,7 @@ class Actor : Thinker native virtual native void Activate(Actor activator); virtual native void Deactivate(Actor activator); virtual native int DoSpecialDamage (Actor target, int damage, Name damagetype); + virtual native bool UseInventory(Inventory item); native void AdjustPlayerAngle(FTranslatedLineTarget t); native static readonly GetDefaultByType(class cls); @@ -247,6 +248,8 @@ class Actor : Thinker native native double GetBobOffset(double frac = 0); native void ClearCounters(); native bool GiveBody (int num, int max=0); + native bool HitFloor(); + native bool isTeammate(Actor other); native void RestoreDamage(); native int SpawnHealth(); diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index a6faf958f2..07f993efe1 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -7,210 +7,6 @@ class HereticWeapon : Weapon } } - - -// 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 diff --git a/wadsrc/static/zscript/heretic/weaponmace.txt b/wadsrc/static/zscript/heretic/weaponmace.txt new file mode 100644 index 0000000000..fd11e685fd --- /dev/null +++ b/wadsrc/static/zscript/heretic/weaponmace.txt @@ -0,0 +1,468 @@ +// 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"; + } + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FireMacePL1 + // + //---------------------------------------------------------------------------- + + action void A_FireMacePL1() + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + + if (random[MaceAtk]() < 28) + { + Actor ball = Spawn("MaceFX2", Pos + (0, 0, 28 - Floorclip), ALLOW_REPLACE); + ball.Vel.Z = 2 - clamp(tan(pitch), -5, 5); + ball.target = self; + ball.angle = self.angle; + ball.AddZ(ball.Vel.Z); + ball.VelFromAngle(); + ball.Vel += Vel.xy / 2; + ball.A_PlaySound ("weapons/maceshoot", CHAN_BODY); + ball.CheckMissileSpawn (radius); + } + else + { + player.GetPSprite(PSP_WEAPON).x = ((random[MaceAtk]() & 3) - 2); + player.GetPSprite(PSP_WEAPON).y = WEAPONTOP + (random[MaceAtk]() & 3); + Actor ball = SpawnPlayerMissile("MaceFX1", angle + (((random[MaceAtk]() & 7) - 4) * (360. / 256))); + if (ball) + { + ball.special1 = 16; // tics till dropoff + } + } + } +} + +class MacePowered : Mace +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoUse 5; + Weapon.AmmoGive 0; + Weapon.SisterWeapon "Mace"; + Tag "$TAG_MACEP"; + } + + States + { + Fire: + Hold: + MACE B 4; + MACE D 4 A_FireMacePL2; + MACE B 4; + MACE A 8 A_ReFire; + Goto Ready; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FireMacePL2 + // + //---------------------------------------------------------------------------- + + action void A_FireMacePL2() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + Actor mo = SpawnPlayerMissile ("MaceFX4", angle, pLineTarget:t); + if (mo) + { + mo.Vel.xy += Vel.xy; + mo.Vel.Z = 2 - clamp(tan(pitch), -5, 5); + if (t.linetarget && !t.unlinked) + { + mo.tracer = t.linetarget; + } + } + A_PlaySound ("weapons/maceshoot", CHAN_WEAPON); + } +} + +// Mace FX1 ----------------------------------------------------------------- + +class MaceFX1 : Actor +{ + const MAGIC_JUNK = 1234; + + Default + { + Radius 8; + Height 6; + Speed 20; + Damage 2; + Projectile; + +THRUGHOST + BounceType "HereticCompat"; + SeeSound "weapons/maceshoot"; + Obituary "$OB_MPMACE"; + } + + States + { + Spawn: + FX02 AB 4 A_MacePL1Check; + Loop; + Death: + FX02 F 4 BRIGHT A_MaceBallImpact; + FX02 GHIJ 4 BRIGHT; + Stop; + } + + //---------------------------------------------------------------------------- + // + // PROC A_MacePL1Check + // + //---------------------------------------------------------------------------- + + void A_MacePL1Check() + { + if (special1 == 0) return; + special1 -= 4; + if (special1 > 0) return; + special1 = 0; + bNoGravity = false; + Gravity = 1. / 8; + // [RH] Avoid some precision loss by scaling the velocity directly + double velscale = 7 / Vel.XY.Length(); + Vel.XY *= velscale; + Vel.Z *= 0.5; + } + + //---------------------------------------------------------------------------- + // + // PROC A_MaceBallImpact + // + //---------------------------------------------------------------------------- + + void A_MaceBallImpact() + { + if ((health != MAGIC_JUNK) && bInFloat) + { // Bounce + health = MAGIC_JUNK; + Vel.Z *= 0.75; + bBounceOnFloors = bBounceOnCeilings = false; + SetState (SpawnState); + A_PlaySound ("weapons/macebounce", CHAN_BODY); + } + else + { // Explode + Vel = (0,0,0); + bNoGravity = true; + Gravity = 1; + A_PlaySound ("weapons/macehit", CHAN_BODY); + } + } +} + +// Mace FX2 ----------------------------------------------------------------- + +class MaceFX2 : MaceFX1 +{ + Default + { + Speed 10; + Damage 6; + Gravity 0.125; + -NOGRAVITY + SeeSound ""; + } + + States + { + Spawn: + FX02 CD 4; + Loop; + Death: + FX02 F 4 A_MaceBallImpact2; + goto Super::Death+1; + } + + //---------------------------------------------------------------------------- + // + // PROC A_MaceBallImpact2 + // + //---------------------------------------------------------------------------- + + void A_MaceBallImpact2() + { + if ((pos.Z <= floorz) && HitFloor ()) + { // Landed in some sort of liquid + Destroy (); + return; + } + if (bInFloat) + { + if (Vel.Z >= 2) + { + // Bounce + Vel.Z *= 0.75; + SetState (SpawnState); + + Actor tiny = Spawn("MaceFX3", Pos, ALLOW_REPLACE); + tiny.target = target; + tiny.angle = angle + 90.; + tiny.VelFromAngle(Vel.Z - 1.); + tiny.Vel += (Vel.XY * .5, Vel.Z); + tiny.CheckMissileSpawn (radius); + + tiny = Spawn("MaceFX3", Pos, ALLOW_REPLACE); + tiny.target = target; + tiny.angle = angle - 90.; + tiny.VelFromAngle(Vel.Z - 1.); + tiny.Vel += (Vel.XY * .5, Vel.Z); + tiny.CheckMissileSpawn (radius); + return; + } + } + Vel = (0,0,0); + bNoGravity = true; + bBounceOnFloors = bBounceOnCeilings = false; + Gravity = 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 +{ + Default + { + Radius 8; + Height 6; + Speed 7; + Damage 18; + Gravity 0.125; + Projectile; + -NOGRAVITY + +TELESTOMP + +THRUGHOST + -NOTELEPORT + BounceType "HereticCompat"; + SeeSound ""; + Obituary "$OB_MPPMACE"; + } + + States + { + Spawn: + FX02 E 99; + Loop; + Death: + FX02 C 4 A_DeathBallImpact; + FX02 GHIJ 4 BRIGHT; + Stop; + } + + //--------------------------------------------------------------------------- + // + // FUNC P_AutoUseChaosDevice + // + //--------------------------------------------------------------------------- + + private bool AutoUseChaosDevice (PlayerInfo player) + { + Inventory arti = player.mo.FindInventory("ArtiTeleport"); + + if (arti != null) + { + player.mo.UseInventory (arti); + player.health = player.mo.health = (player.health+1)/2; + return true; + } + return false; + } + + //---------------------------------------------------------------------------- + // + // PROC DoSpecialDamage + // + //---------------------------------------------------------------------------- + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if (target.bBoss || target.bDontSquash || target.IsTeammate (self.target)) + { // Don't allow cheap boss kills and don't instagib teammates + return damage; + } + else if (target.player) + { // Player specific checks + if (target.player.mo.bInvulnerable) + { // Can't hurt invulnerable players + return -1; + } + if (AutoUseChaosDevice (target.player)) + { // Player was saved using chaos device + return -1; + } + } + return TELEFRAG_DAMAGE; // Something's gonna die + } + + //---------------------------------------------------------------------------- + // + // PROC A_DeathBallImpact + // + //---------------------------------------------------------------------------- + + void A_DeathBallImpact() + { + FTranslatedLineTarget t; + + if ((pos.Z <= floorz) && HitFloor ()) + { // Landed in some sort of liquid + Destroy (); + return; + } + if (bInFloat) + { + if (Vel.Z >= 2) + { + // Bounce + bool newAngle = false; + double ang = 0; + if (tracer) + { + if (!tracer.bShootable) + { // Target died + tracer = null; + } + else + { // Seek + ang = AngleTo(tracer); + newAngle = true; + } + } + else + { // Find new target + ang = 0.; + for (int i = 0; i < 16; i++) + { + AimLineAttack (ang, 640., t, 0., ALF_NOFRIENDS|ALF_PORTALRESTRICT, null, target); + if (t.linetarget && target != t.linetarget) + { + tracer = t.linetarget; + ang = t.angleFromSource; + newAngle = true; + break; + } + ang += 22.5; + } + } + if (newAngle) + { + angle = ang; + VelFromAngle(); + } + SetState (SpawnState); + A_PlaySound ("weapons/macestop", CHAN_BODY); + return; + } + } + Vel = (0,0,0); + bNoGravity = true; + Gravity = 1; + A_PlaySound ("weapons/maceexplode", CHAN_BODY); + } +} + + +// Mace spawn spot ---------------------------------------------------------- + +class MaceSpawner : SpecialSpot +{ + Default + { + +NOSECTOR + +NOBLOCKMAP + } + + States + { + Spawn: + TNT1 A 1; + TNT1 A -1 A_SpawnSingleItem("Mace", 64, 64, 0); + Stop; + } +} diff --git a/wadsrc/static/zscript/hexen/hexenspecialdecs.txt b/wadsrc/static/zscript/hexen/hexenspecialdecs.txt index 30ae0fff14..558ef8395c 100644 --- a/wadsrc/static/zscript/hexen/hexenspecialdecs.txt +++ b/wadsrc/static/zscript/hexen/hexenspecialdecs.txt @@ -83,14 +83,14 @@ class TreeDestructible : Actor // Pottery1 ------------------------------------------------------------------ -class Pottery1 : Actor native +class Pottery1 : Actor { Default { Health 15; Speed 10; Height 32; - +SOLID +SHOOTABLE +NOBLOOD +DROPOFF + +SOLID +SHOOTABLE +NOBLOOD +DROPOFF +SMASHABLE +SLIDESONWALLS +PUSHABLE +TELESTOMP +CANPASS +NOICEDEATH } From 9ae272d753009808265fc66a15ebce3ed92de737 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 24 Nov 2016 20:02:44 +0100 Subject: [PATCH 350/471] - scriptified Heretic's blaster. - scriptified all Effect functions of Fastprojectile's children - implemented access to class meta data. - added a VM instruction to retrieve the class metadata, to eliminate the overhead of the function call that would otherwise be needed. - made GetClass() a builtin so that it can use the new instruction Important note about this commit: Scriptifying CFlameMissile::Effect revealed a problem with the virtual function interface: In order to work, this needs to be explicitly enabled for each single native class that may be used as a base for a scripted class. Needless to say, this will end up way too much work, as there are over 100 native classes, excluding those which will be scriptified. But in order to fix the problem this partially broken state needs to be committed first. --- src/dobject.cpp | 6 - src/g_heretic/a_hereticweaps.cpp | 127 --------- src/g_hexen/a_clericflame.cpp | 34 +-- src/g_shared/a_fastprojectile.cpp | 41 +-- src/g_shared/a_sharedglobal.h | 1 - src/info.cpp | 2 - src/info.h | 1 - src/namedef.h | 1 + src/p_mobj.cpp | 22 ++ src/scripting/codegeneration/codegen.cpp | 119 +++++--- src/scripting/codegeneration/codegen.h | 20 ++ src/scripting/vm/vmexec.cpp | 1 + src/scripting/vm/vmexec.h | 6 + src/scripting/vm/vmops.h | 1 + src/scripting/zscript/zcc_compile.cpp | 11 +- wadsrc/static/zscript.txt | 2 + wadsrc/static/zscript/actor.txt | 23 ++ wadsrc/static/zscript/base.txt | 1 - .../static/zscript/heretic/hereticweaps.txt | 173 ------------ .../static/zscript/heretic/weaponblaster.txt | 259 ++++++++++++++++++ wadsrc/static/zscript/hexen/clericflame.txt | 26 +- .../static/zscript/shared/fastprojectile.txt | 41 +++ wadsrc/static/zscript/shared/sharedmisc.txt | 11 - 23 files changed, 499 insertions(+), 430 deletions(-) create mode 100644 wadsrc/static/zscript/heretic/weaponblaster.txt create mode 100644 wadsrc/static/zscript/shared/fastprojectile.txt diff --git a/src/dobject.cpp b/src/dobject.cpp index e3e37432b8..849f6a477e 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -363,12 +363,6 @@ DEFINE_ACTION_FUNCTION(DObject, Destroy) return 0; } -DEFINE_ACTION_FUNCTION(DObject, GetClass) -{ - PARAM_SELF_PROLOGUE(DObject); - ACTION_RETURN_OBJECT(self->GetClass()); -} - //========================================================================== // // diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index cc964ecc05..3b2711e246 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -46,133 +46,6 @@ void P_DSparilTeleport (AActor *actor); extern bool P_AutoUseChaosDevice (player_t *player); -// Blaster FX 1 ------------------------------------------------------------- - -//---------------------------------------------------------------------------- -// -// Thinker for the ultra-fast blaster PL2 ripper-spawning missile. -// -//---------------------------------------------------------------------------- - -class ABlasterFX1 : public AFastProjectile -{ - DECLARE_CLASS(ABlasterFX1, AFastProjectile) -public: - void Effect (); - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -int ABlasterFX1::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->IsKindOf (PClass::FindClass ("Ironlich"))) - { // Less damage to Ironlich bosses - damage = pr_bfx1() & 1; - if (!damage) - { - return -1; - } - } - return damage; -} - -void ABlasterFX1::Effect () -{ - if (pr_bfx1t() < 64) - { - Spawn("BlasterSmoke", PosAtZ(MAX(Z() - 8., floorz)), ALLOW_REPLACE); - } -} - -IMPLEMENT_CLASS(ABlasterFX1, false, false, false, false) - -// Ripper ------------------------------------------------------------------- - - -class ARipper : public AActor -{ - DECLARE_CLASS (ARipper, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(ARipper, false, false, false, false) - -int ARipper::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->IsKindOf (PClass::FindClass ("Ironlich"))) - { // Less damage to Ironlich bosses - damage = pr_ripd() & 1; - if (!damage) - { - return -1; - } - } - return damage; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireBlasterPL1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle ang; - int damage; - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - DAngle pitch = P_BulletSlope(self); - damage = pr_fb1.HitDice (4); - ang = self->Angles.Yaw; - if (player->refire) - { - ang += pr_fb1.Random2() * (5.625 / 256); - } - P_LineAttack (self, ang, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "BlasterPuff"); - S_Sound (self, CHAN_WEAPON, "weapons/blastershoot", 1, ATTN_NORM); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_SpawnRippers -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_SpawnRippers) -{ - PARAM_SELF_PROLOGUE(AActor); - - unsigned int i; - DAngle ang; - AActor *ripper; - - for(i = 0; i < 8; i++) - { - ripper = Spawn (self->Pos(), ALLOW_REPLACE); - ang = i*45.; - ripper->target = self->target; - ripper->Angles.Yaw = ang; - ripper->VelFromAngle(); - P_CheckMissileSpawn (ripper, self->radius); - } - return 0; -} - // --- Skull rod ------------------------------------------------------------ diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp index 2c66cb42d1..d4f86ecd5b 100644 --- a/src/g_hexen/a_clericflame.cpp +++ b/src/g_hexen/a_clericflame.cpp @@ -25,38 +25,6 @@ void A_CFlameMissile (AActor *); // Flame Missile ------------------------------------------------------------ -class ACFlameMissile : public AFastProjectile -{ - DECLARE_CLASS (ACFlameMissile, AFastProjectile) -public: - void BeginPlay (); - void Effect (); -}; - -IMPLEMENT_CLASS(ACFlameMissile, false, false, false, false) - -void ACFlameMissile::BeginPlay () -{ - special1 = 2; -} - -void ACFlameMissile::Effect () -{ - if (!--special1) - { - special1 = 4; - double newz = Z() - 12; - if (newz < floorz) - { - newz = floorz; - } - AActor *mo = Spawn ("CFlameFloor", PosAtZ(newz), ALLOW_REPLACE); - if (mo) - { - mo->Angles.Yaw = Angles.Yaw; - } - } -} //============================================================================ // @@ -80,7 +48,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlameAttack) if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } - P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACFlameMissile)); + P_SpawnPlayerMissile (self, PClass::FindActor("CFlameMissile")); S_Sound (self, CHAN_WEAPON, "ClericFlameFire", 1, ATTN_NORM); return 0; } diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index ffca8a8fad..1ded466a9e 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -6,6 +6,7 @@ #include "p_lnspec.h" #include "b_bot.h" #include "p_checkposition.h" +#include "virtual.h" IMPLEMENT_CLASS(AFastProjectile, false, false, false, false) @@ -132,7 +133,13 @@ void AFastProjectile::Tick () if (!frac.isZero() && ripcount <= 0) { ripcount = count >> 3; - Effect(); + + // call the scripted 'Effect' method. + VINDEX(AFastProjectile, Effect); + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); } } } @@ -153,35 +160,3 @@ void AFastProjectile::Tick () } -void AFastProjectile::Effect() -{ - FName name = GetClass()->MissileName; - if (name != NAME_None) - { - double hitz = Z()-8; - - if (hitz < floorz) - { - hitz = floorz; - } - // Do not clip this offset to the floor. - hitz += GetClass()->MissileHeight; - - PClassActor *trail = PClass::FindActor(name); - if (trail != NULL) - { - AActor *act = Spawn (trail, PosAtZ(hitz), ALLOW_REPLACE); - if (act != nullptr) - { - if ((flags5 & MF5_GETOWNER) && (target != nullptr)) - act->target = target; - else - act->target = this; - - act->Angles.Pitch = Angles.Pitch; - act->Angles.Yaw = Angles.Yaw; - } - } - } -} - diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 6911c6688b..bb85a023c2 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -228,7 +228,6 @@ class AFastProjectile : public AActor DECLARE_CLASS(AFastProjectile, AActor) public: void Tick (); - virtual void Effect(); }; diff --git a/src/info.cpp b/src/info.cpp index 8ef594d1bf..fec5af63e0 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -230,7 +230,6 @@ PClassActor::PClassActor() BurnHeight = -1; GibHealth = INT_MIN; WoundHealth = 6; - PoisonDamage = 0; FastSpeed = -1.; RDFactor = 1.; CameraHeight = INT_MIN; @@ -291,7 +290,6 @@ void PClassActor::DeriveData(PClass *newclass) newa->BloodColor = BloodColor; newa->GibHealth = GibHealth; newa->WoundHealth = WoundHealth; - newa->PoisonDamage = PoisonDamage; newa->FastSpeed = FastSpeed; newa->RDFactor = RDFactor; newa->CameraHeight = CameraHeight; diff --git a/src/info.h b/src/info.h index a41a6def8d..bb21524a52 100644 --- a/src/info.h +++ b/src/info.h @@ -296,7 +296,6 @@ public: PalEntry BloodColor; // Colorized blood int GibHealth; // Negative health below which this monster dies an extreme death int WoundHealth; // Health needed to enter wound state - int PoisonDamage; // Amount of poison damage double FastSpeed; // speed in fast mode double RDFactor; // Radius damage factor double CameraHeight; // Height of camera when used as such diff --git a/src/namedef.h b/src/namedef.h index 639c762ebd..b7365b2b21 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -285,6 +285,7 @@ xx(FRandom) xx(Random2) xx(RandomPick) xx(FRandomPick) +xx(GetClass) xx(Exp) xx(Log10) xx(Ceil) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 46ecbd3faf..3c8d1173b9 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -310,6 +310,28 @@ DEFINE_FIELD(AActor, ConversationRoot) DEFINE_FIELD(AActor, Conversation) DEFINE_FIELD(AActor, DecalGenerator) +DEFINE_FIELD(PClassActor, Obituary) +DEFINE_FIELD(PClassActor, HitObituary) +DEFINE_FIELD(PClassActor, DeathHeight) +DEFINE_FIELD(PClassActor, BurnHeight) +DEFINE_FIELD(PClassActor, BloodColor) +DEFINE_FIELD(PClassActor, GibHealth) +DEFINE_FIELD(PClassActor, WoundHealth) +DEFINE_FIELD(PClassActor, FastSpeed) +DEFINE_FIELD(PClassActor, RDFactor) +DEFINE_FIELD(PClassActor, CameraHeight) +DEFINE_FIELD(PClassActor, HowlSound) +DEFINE_FIELD(PClassActor, BloodType) +DEFINE_FIELD(PClassActor, BloodType2) +DEFINE_FIELD(PClassActor, BloodType3) +DEFINE_FIELD(PClassActor, DontHurtShooter) +DEFINE_FIELD(PClassActor, ExplosionRadius) +DEFINE_FIELD(PClassActor, ExplosionDamage) +DEFINE_FIELD(PClassActor, MeleeDamage) +DEFINE_FIELD(PClassActor, MeleeSound) +DEFINE_FIELD(PClassActor, MissileName) +DEFINE_FIELD(PClassActor, MissileHeight) + //========================================================================== // // AActor :: Serialize diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4bf6f076eb..b7e20f7fc3 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5637,12 +5637,6 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classct 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); @@ -5918,40 +5912,14 @@ FxExpression *FxClassDefaults::Resolve(FCompileContext& ctx) // //========================================================================== -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; + ExpEmit ob = obj->Emit(build); + ob.Free(build); + ExpEmit meta(build, REGT_POINTER); + build->Emit(OP_META, meta.RegNum, ob.RegNum); + build->Emit(OP_LO, meta.RegNum, meta.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults))); + return meta; } @@ -6272,6 +6240,11 @@ FxStructMember::~FxStructMember() bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable) { + // Cannot take the address of metadata variables. + if (membervar->Flags & VARF_Static) + { + return false; + } AddressRequested = true; if (writable != nullptr) *writable = (AddressWritable && !ctx.CheckReadOnly(membervar->Flags) && (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast(classx->ValueType)->IsConst)); @@ -6411,6 +6384,14 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) obj = newobj; } + if (membervar->Flags & VARF_Static) + { + obj.Free(build); + ExpEmit meta(build, REGT_POINTER); + build->Emit(OP_META, meta.RegNum, obj.RegNum); + obj = meta; + } + if (AddressRequested) { if (membervar->Offset == 0) @@ -6953,6 +6934,13 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } break; + case NAME_GetClass: + if (CheckArgSize(NAME_GetClass, ArgList, 0, 0, ScriptPosition)) + { + func = new FxGetClass(new FxSelf(ScriptPosition)); + } + break; + case NAME_Random: // allow calling Random without arguments to default to (0, 255) if (ArgList.Size() == 0) @@ -7132,6 +7120,12 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) // handle builtins: Vectors got 2: Length and Unit. if (MethodName == NAME_Length || MethodName == NAME_Unit) { + if (ArgList.Size() > 0) + { + ScriptPosition.Message(MSG_ERROR, "too many parameters in call to %s", MethodName.GetChars()); + delete this; + return nullptr; + } auto x = new FxVectorBuiltin(Self, MethodName); Self = nullptr; delete this; @@ -7144,6 +7138,17 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) auto ptype = static_cast(Self->ValueType)->PointedType; if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) { + if (ptype->IsKindOf(RUNTIME_CLASS(PClass)) && MethodName == NAME_GetClass) + { + if (ArgList.Size() > 0) + { + ScriptPosition.Message(MSG_ERROR, "too many parameters in call to %s", MethodName.GetChars()); + delete this; + return nullptr; + } + auto x = new FxGetClass(Self); + return x->Resolve(ctx); + } cls = static_cast(ptype); } else @@ -7976,6 +7981,44 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build) return to; } +//========================================================================== +// +// +//========================================================================== + +FxGetClass::FxGetClass(FxExpression *self) + :FxExpression(EFX_GetClass, self->ScriptPosition) +{ + Self = self; +} + +FxGetClass::~FxGetClass() +{ + SAFE_DELETE(Self); +} + +FxExpression *FxGetClass::Resolve(FCompileContext &ctx) +{ + SAFE_RESOLVE(Self, ctx); + if (!Self->IsObject()) + { + ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object"); + delete this; + return nullptr; + } + ValueType = NewClassPointer(static_cast(static_cast(Self->ValueType)->PointedType)); + return this; +} + +ExpEmit FxGetClass::Emit(VMFunctionBuilder *build) +{ + ExpEmit op = Self->Emit(build); + op.Free(build); + ExpEmit to(build, REGT_POINTER); + build->Emit(OP_META, to.RegNum, op.RegNum); + return to; +} + //========================================================================== // // FxSequence :: Resolve diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index f004e469a3..d7547a198e 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -286,6 +286,7 @@ enum EFxType EFX_StaticArrayVariable, EFX_CVar, EFX_NamedNode, + EFX_GetClass, EFX_COUNT }; @@ -320,6 +321,7 @@ public: 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); } + bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); } virtual ExpEmit Emit(VMFunctionBuilder *build); @@ -1520,6 +1522,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxFlopFunctionCall +// +//========================================================================== + +class FxGetClass : public FxExpression +{ + FxExpression *Self; + +public: + + FxGetClass(FxExpression *self); + ~FxGetClass(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxVMFunctionCall diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 24beb7f9c6..750c384e0d 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -75,6 +75,7 @@ #define ASSERTF(x) assert((unsigned)(x) < f->NumRegF) #define ASSERTA(x) assert((unsigned)(x) < f->NumRegA) #define ASSERTS(x) assert((unsigned)(x) < f->NumRegS) +#define ASSERTO(x) assert((unsigned)(x) < f->NumRegA && reg.atag[x] == ATAG_OBJECT) #define ASSERTKD(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstD) #define ASSERTKF(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstF) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 6f25318d61..4df76a73e7 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -110,6 +110,12 @@ begin: reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts. NEXTOP; + OP(META): + ASSERTA(a); ASSERTO(B); + reg.a[a] = ((DObject*)reg.a[B])->GetClass(); // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... + reg.atag[a] = ATAG_OBJECT; + NEXTOP; + OP(LB): ASSERTD(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index cf2a757469..b36f93881c 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -23,6 +23,7 @@ xx(LKF_R, lk, RFRII8, NOP, 0, 0), // load float constant indexed xx(LKS_R, lk, RSRII8, NOP, 0, 0), // load string constant indexed xx(LKP_R, lk, RPRII8, NOP, 0, 0), // load pointer constant indexed xx(LFP, lf, LFP, NOP, 0, 0), // load frame pointer +xx(META, meta, RPRP, NOP, 0, 0), // load a class's meta class address // Load from memory. rA = *(rB + rkC) xx(LB, lb, RIRPKI, LB_R, 4, REGT_INT), // load byte diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 3437c848cb..a4a2cc4533 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1298,8 +1298,12 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel if (field->Flags & ZCC_Meta) { - varflags |= VARF_ReadOnly; // metadata implies readonly - // todo: this needs to go into the metaclass and needs some handling + varflags |= VARF_Static|VARF_ReadOnly; // metadata implies readonly + if (!(field->Flags & ZCC_Native)) + { + // Non-native meta data is not implemented yet and requires some groundwork in the class copy code. + Error(field, "Metadata member %s must be native", FName(field->Names->Name).GetChars()); + } } if (field->Type->ArraySize != nullptr) @@ -1320,7 +1324,8 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel if (varflags & VARF_Native) { - fd = FindField(type, FName(name->Name).GetChars()); + auto querytype = (varflags & VARF_Static) ? type->GetClass() : type; + fd = FindField(querytype, FName(name->Name).GetChars()); if (fd == nullptr) { Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars()); diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 074bb89681..3507e45a8b 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -31,6 +31,7 @@ zscript/shared/setcolor.txt zscript/shared/sectoraction.txt zscript/shared/ice.txt zscript/shared/dog.txt +zscript/shared/fastprojectile.txt zscript/doom/doomplayer.txt zscript/doom/possessed.txt @@ -100,6 +101,7 @@ zscript/heretic/weaponwand.txt zscript/heretic/weaponcrossbow.txt zscript/heretic/weapongauntlets.txt zscript/heretic/weaponmace.txt +zscript/heretic/weaponblaster.txt zscript/hexen/baseweapons.txt zscript/hexen/korax.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0f0acc3077..3eb855007e 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -145,6 +145,29 @@ class Actor : Thinker native native readonly State SeeState; native State MeleeState; native State MissileState; + + native meta String Obituary; // Player was killed by this actor + native meta String HitObituary; // Player was killed by this actor in melee + native meta double DeathHeight; // Height on normal death + native meta double BurnHeight; // Height on burning death + native meta color BloodColor; // Colorized blood + native meta int GibHealth; // Negative health below which this monster dies an extreme death + native meta int WoundHealth; // Health needed to enter wound state + native meta double FastSpeed; // speed in fast mode + native meta double RDFactor; // Radius damage factor + native meta double CameraHeight; // Height of camera when used as such + native meta Sound HowlSound; // Sound being played when electrocuted or poisoned + native meta Name BloodType; // Blood replacement type + native meta Name BloodType2; // Bloopsplatter replacement type + native meta Name BloodType3; // AxeBlood replacement type + native meta bool DontHurtShooter; + native meta int ExplosionRadius; + native meta int ExplosionDamage; + native meta int MeleeDamage; + native meta Sound MeleeSound; + native meta Name MissileName; + native meta double MissileHeight; + // need some definition work first //FRenderStyle RenderStyle; diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index a63020bbf5..c899bbd373 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -7,7 +7,6 @@ class Object native native static double G_SkillPropertyFloat(int p); virtual native void Destroy(); - native class GetClass(); } class Thinker : Object native diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index 07f993efe1..c3c641b4ea 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -7,179 +7,6 @@ class HereticWeapon : Weapon } } -// 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 --------------------------------------------------------- diff --git a/wadsrc/static/zscript/heretic/weaponblaster.txt b/wadsrc/static/zscript/heretic/weaponblaster.txt new file mode 100644 index 0000000000..8f4756b5b6 --- /dev/null +++ b/wadsrc/static/zscript/heretic/weaponblaster.txt @@ -0,0 +1,259 @@ +// 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"; + } + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FireBlasterPL1 + // + //---------------------------------------------------------------------------- + + action void A_FireBlasterPL1() + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + + double pitch = BulletSlope(); + int damage = random[FireBlaster](1, 8) * 4; + double ang = angle; + if (player.refire) + { + ang += Random2[FireBlaster]() * (5.625 / 256); + } + LineAttack (ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', "BlasterPuff"); + A_PlaySound ("weapons/blastershoot", CHAN_WEAPON); + } +} + +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 +{ + Default + { + Radius 12; + Height 8; + Speed 184; + Damage 2; + SeeSound "weapons/blastershoot"; + DeathSound "weapons/blasterhit"; + +SPAWNSOUNDSOURCE + Obituary "$OB_MPPBLASTER"; + } + + States + { + Spawn: + ACLO E 200; + Loop; + Death: + FX18 A 3 BRIGHT A_SpawnRippers; + FX18 B 3 BRIGHT; + FX18 CDEFG 4 BRIGHT; + Stop; + } + + //---------------------------------------------------------------------------- + // + // + // + //---------------------------------------------------------------------------- + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if (target is "Ironlich") + { // Less damage to Ironlich bosses + damage = random[BlasterFX]() & 1; + if (!damage) + { + return -1; + } + } + return damage; + } + + override void Effect () + { + if (random[BlasterFX]() < 64) + { + Spawn("BlasterSmoke", (pos.xy, max(pos.z - 8, floorz)), ALLOW_REPLACE); + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_SpawnRippers + // + //---------------------------------------------------------------------------- + + void A_SpawnRippers() + { + for(int i = 0; i < 8; i++) + { + Actor ripper = Spawn("Ripper", pos, ALLOW_REPLACE); + ripper.target = target; + ripper.angle = i*45; + ripper.VelFromAngle(); + ripper.CheckMissileSpawn (radius); + } + } +} + +// 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 +{ + 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; + } + + int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if (target is "Ironlich") + { // Less damage to Ironlich bosses + damage = random[Ripper]() & 1; + if (!damage) + { + return -1; + } + } + return damage; + } + +} + +// 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; + } +} + diff --git a/wadsrc/static/zscript/hexen/clericflame.txt b/wadsrc/static/zscript/hexen/clericflame.txt index 13fca8ad10..37e4149f92 100644 --- a/wadsrc/static/zscript/hexen/clericflame.txt +++ b/wadsrc/static/zscript/hexen/clericflame.txt @@ -170,7 +170,7 @@ class CircleFlame : Actor // Flame Missile ------------------------------------------------------------ -class CFlameMissile : FastProjectile native +class CFlameMissile : FastProjectile { Default { @@ -208,4 +208,28 @@ class CFlameMissile : FastProjectile native CFFX M 3 Bright; Stop; } + + override void BeginPlay () + { + special1 = 2; + } + + override void Effect () + { + if (!--special1) + { + special1 = 4; + double newz = pos.z - 12; + if (newz < floorz) + { + newz = floorz; + } + Actor mo = Spawn ("CFlameFloor", (pos.xy, newz), ALLOW_REPLACE); + if (mo) + { + mo.angle = angle; + } + } + } + } diff --git a/wadsrc/static/zscript/shared/fastprojectile.txt b/wadsrc/static/zscript/shared/fastprojectile.txt new file mode 100644 index 0000000000..b1d5090738 --- /dev/null +++ b/wadsrc/static/zscript/shared/fastprojectile.txt @@ -0,0 +1,41 @@ +// Fast projectiles -------------------------------------------------------- + +class FastProjectile : Actor native +{ + Default + { + Projectile; + MissileHeight 0; + } + + + virtual void Effect() + { + class trail = MissileName; + if (trail != null) + { + double hitz = pos.z - 8; + + if (hitz < floorz) + { + hitz = floorz; + } + // Do not clip this offset to the floor. + hitz += MissileHeight; + + Actor act = Spawn (trail, (pos.xy, hitz), ALLOW_REPLACE); + if (act != null) + { + if (bGetOwner && target != null) + act.target = target; + else + act.target = self; + + act.angle = angle; + act.pitch = pitch; + } + } + } + +} + diff --git a/wadsrc/static/zscript/shared/sharedmisc.txt b/wadsrc/static/zscript/shared/sharedmisc.txt index bebf285492..5989702fdf 100644 --- a/wadsrc/static/zscript/shared/sharedmisc.txt +++ b/wadsrc/static/zscript/shared/sharedmisc.txt @@ -179,17 +179,6 @@ class RandomSpawner : Actor native } } -// Fast projectiles -------------------------------------------------------- - -class FastProjectile : Actor native -{ - Default - { - Projectile; - MissileHeight 0; - } -} - // Sector flag setter ------------------------------------------------------ class SectorFlagSetter : Actor native From 66d28a24b88471162be0a7201fe2693fe9ab771b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 24 Nov 2016 21:36:02 +0100 Subject: [PATCH 351/471] - disabled the scripted virtual function module after finding out that it only works if each single class that may serve as a parent for scripting is explicitly declared. Needless to say, this is simply too volatile and would require constant active maintenance, not to mention a huge amount of work up front to get going. It also hid a nasty problem with the Destroy method. Due to the way the garbage collector works, Destroy cannot be exposed to scripts as-is. It may be called from scripts but it may not be overridden from scripts because the garbage collector can call this function after all data needed for calling a scripted override has already been destroyed because if that data is also being collected there is no guarantee that proper order of destruction is observed. So for now Destroy is just a normal native method to scripted classes --- src/actor.h | 9 +- src/b_bot.cpp | 2 +- src/c_dispatch.cpp | 4 +- src/d_dehacked.cpp | 2 +- src/d_dehacked.h | 2 +- src/d_player.h | 2 +- src/decallib.cpp | 10 +- src/dobject.cpp | 3 +- src/dobject.h | 16 +- src/dobjgc.cpp | 2 +- src/dobjtype.cpp | 83 ++++--- src/dobjtype.h | 1 - src/dsectoreffect.cpp | 8 +- src/dsectoreffect.h | 4 +- src/dthinker.cpp | 173 +++++++++++++- src/dthinker.h | 4 +- src/fragglescript/t_func.cpp | 4 +- src/fragglescript/t_prepro.cpp | 2 +- src/fragglescript/t_script.cpp | 6 +- src/fragglescript/t_script.h | 6 +- src/fragglescript/t_variable.cpp | 2 +- src/g_heretic/a_hereticartifacts.cpp | 4 +- src/g_heretic/a_hereticweaps.cpp | 10 +- src/g_hexen/a_boostarmor.cpp | 2 +- src/g_hexen/a_clericholy.cpp | 4 +- src/g_hexen/a_clericstaff.cpp | 2 +- src/g_hexen/a_fighteraxe.cpp | 2 +- src/g_hexen/a_fighterplayer.cpp | 6 +- src/g_hexen/a_fighterquietus.cpp | 2 +- src/g_hexen/a_flechette.cpp | 14 +- src/g_hexen/a_healingradius.cpp | 2 +- src/g_hexen/a_heresiarch.cpp | 10 +- src/g_hexen/a_hexenspecialdecs.cpp | 4 +- src/g_hexen/a_magecone.cpp | 2 +- src/g_hexen/a_magelightning.cpp | 4 +- src/g_hexen/a_magestaff.cpp | 4 +- src/g_hexen/a_spike.cpp | 2 +- src/g_hexen/a_summon.cpp | 2 +- src/g_hexen/a_teleportother.cpp | 4 +- src/g_level.cpp | 2 +- src/g_raven/a_artitele.cpp | 2 +- src/g_raven/a_minotaur.cpp | 4 +- src/g_shared/a_action.cpp | 8 +- src/g_shared/a_armor.cpp | 10 +- src/g_shared/a_artifacts.cpp | 52 ++--- src/g_shared/a_artifacts.h | 2 +- src/g_shared/a_bridge.cpp | 6 +- src/g_shared/a_camera.cpp | 4 +- src/g_shared/a_debris.cpp | 2 +- src/g_shared/a_decals.cpp | 6 +- src/g_shared/a_fastprojectile.cpp | 14 +- src/g_shared/a_flashfader.cpp | 2 +- src/g_shared/a_fountain.cpp | 4 +- src/g_shared/a_hatetarget.cpp | 2 +- src/g_shared/a_keys.cpp | 2 +- src/g_shared/a_lightning.cpp | 2 +- src/g_shared/a_mapmarker.cpp | 2 +- src/g_shared/a_morph.cpp | 4 +- src/g_shared/a_movingcamera.cpp | 14 +- src/g_shared/a_pickups.cpp | 26 +-- src/g_shared/a_pickups.h | 4 +- src/g_shared/a_puzzleitems.cpp | 4 +- src/g_shared/a_quake.cpp | 2 +- src/g_shared/a_randomspawner.cpp | 2 +- src/g_shared/a_secrettrigger.cpp | 2 +- src/g_shared/a_sectoraction.cpp | 24 +- src/g_shared/a_setcolor.cpp | 4 +- src/g_shared/a_sharedglobal.h | 10 +- src/g_shared/a_skies.cpp | 14 +- src/g_shared/a_soundenvironment.cpp | 4 +- src/g_shared/a_soundsequence.cpp | 6 +- src/g_shared/a_spark.cpp | 2 +- src/g_shared/a_specialspot.cpp | 4 +- src/g_shared/a_specialspot.h | 4 +- src/g_shared/a_waterzone.cpp | 2 +- src/g_shared/a_weaponpiece.cpp | 6 +- src/g_shared/a_weapons.cpp | 6 +- src/g_shared/hudmessages.cpp | 8 +- src/g_shared/sbar.h | 2 +- src/g_shared/sbarinfo.cpp | 2 +- src/g_shared/shared_sbar.cpp | 2 +- src/g_strife/a_coin.cpp | 2 +- src/g_strife/a_loremaster.cpp | 2 +- src/g_strife/a_programmer.cpp | 2 +- src/g_strife/a_rebels.cpp | 2 +- src/g_strife/a_spectral.cpp | 2 +- src/g_strife/a_strifeitems.cpp | 28 +-- src/g_strife/a_strifestuff.cpp | 6 +- src/g_strife/a_strifeweapons.cpp | 6 +- src/g_strife/strife_sbar.cpp | 2 +- src/info.cpp | 2 +- src/intermission/intermission.cpp | 12 +- src/intermission/intermission.h | 4 +- src/m_argv.cpp | 2 +- src/m_cheat.cpp | 2 +- src/menu/colorpickermenu.cpp | 4 +- src/menu/joystickmenu.cpp | 2 +- src/menu/listmenu.cpp | 2 +- src/menu/loadsavemenu.cpp | 12 +- src/menu/menu.cpp | 2 +- src/menu/menuinput.cpp | 2 +- src/menu/messagebox.cpp | 13 +- src/menu/optionmenu.cpp | 6 +- src/menu/optionmenuitems.h | 2 +- src/menu/playermenu.cpp | 2 +- src/menu/readthis.cpp | 2 +- src/menu/videomenu.cpp | 2 +- src/p_acs.cpp | 6 +- src/p_buildmap.cpp | 2 +- src/p_ceiling.cpp | 2 +- src/p_conversation.cpp | 3 +- src/p_doors.cpp | 4 +- src/p_floor.cpp | 15 +- src/p_interaction.cpp | 2 +- src/p_lights.cpp | 16 +- src/p_lnspec.cpp | 4 +- src/p_map.cpp | 4 +- src/p_mobj.cpp | 117 +++++++++- src/p_pillar.cpp | 2 +- src/p_plats.cpp | 2 +- src/p_pspr.cpp | 2 +- src/p_pspr.h | 2 +- src/p_pusher.cpp | 2 +- src/p_scroll.cpp | 4 +- src/p_spec.cpp | 4 +- src/p_spec.h | 5 +- src/p_switch.cpp | 2 +- src/p_teleport.cpp | 2 +- src/p_user.cpp | 40 ++-- src/po_man.cpp | 10 +- src/po_man.h | 2 +- src/posix/sdl/sdlvideo.cpp | 2 +- src/r_data/r_interpolate.cpp | 18 +- src/r_data/r_interpolate.h | 2 +- src/r_defs.h | 2 +- src/s_advsound.cpp | 6 +- src/s_sndseq.cpp | 14 +- src/s_sndseq.h | 2 +- src/scripting/decorate/olddecorations.cpp | 2 +- src/scripting/vm/vm.h | 2 +- src/scripting/vm/vmframe.cpp | 8 +- src/scripting/zscript/zcc_compile.cpp | 36 --- src/v_video.cpp | 8 +- src/virtual.h | 272 +--------------------- src/win32/fb_d3d9.cpp | 2 +- src/win32/fb_ddraw.cpp | 2 +- src/win32/win32video.cpp | 2 +- wadsrc/static/zscript/base.txt | 2 +- wadsrc/static/zscript/hexen/firedemon.txt | 16 +- 149 files changed, 727 insertions(+), 759 deletions(-) diff --git a/src/actor.h b/src/actor.h index bbe7381a24..36fcc5de4d 100644 --- a/src/actor.h +++ b/src/actor.h @@ -584,7 +584,7 @@ public: AActor () throw(); AActor (const AActor &other) throw(); AActor &operator= (const AActor &other); - void Destroy (); + void Destroy () override; ~AActor (); void Serialize(FSerializer &arc); @@ -612,6 +612,7 @@ public: bool CheckNoDelay(); virtual void BeginPlay(); // Called immediately after the actor is created + void CallBeginPlay(); virtual void PostBeginPlay(); // Called immediately before the actor's first tick void LevelSpawned(); // Called after BeginPlay if this actor was spawned by the world virtual void HandleSpawnFlags(); // Translates SpawnFlags into in-game flags. @@ -620,6 +621,8 @@ public: virtual void Activate (AActor *activator); virtual void Deactivate (AActor *activator); + void CallActivate(AActor *activator); + void CallDeactivate(AActor *activator); virtual void Tick (); @@ -629,6 +632,7 @@ public: // Perform some special damage action. Returns the amount of damage to do. // Returning -1 signals the damage routine to exit immediately virtual int DoSpecialDamage (AActor *target, int damage, FName damagetype); + int CallDoSpecialDamage(AActor *target, int damage, FName damagetype); // Like DoSpecialDamage, but called on the actor receiving the damage. virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); @@ -684,7 +688,8 @@ public: virtual bool TakeInventory (PClassActor *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false); // Uses an item and removes it from the inventory. - virtual bool UseInventory (AInventory *item); + virtual bool DoUseInventory (AInventory *item); + bool UseInventory(AInventory *item); // Tosses an item out of the inventory. virtual AInventory *DropInventory (AInventory *item); diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 93d71092d7..3f4d0c592b 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -15,7 +15,7 @@ #include "serializer.h" #include "d_player.h" -IMPLEMENT_CLASS(DBot, false, true, false, false) +IMPLEMENT_CLASS(DBot, false, true) IMPLEMENT_POINTERS_START(DBot) IMPLEMENT_POINTER(dest) diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 71aeea0faa..d112634d6a 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -187,7 +187,7 @@ static const char *KeyConfCommands[] = // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(DWaitingCommand, false, false, false, false) +IMPLEMENT_CLASS(DWaitingCommand, false, false) void DWaitingCommand::Serialize(FSerializer &arc) { @@ -225,7 +225,7 @@ void DWaitingCommand::Tick () } } -IMPLEMENT_CLASS(DStoredCommand, false, false, false, false) +IMPLEMENT_CLASS(DStoredCommand, false, false) DStoredCommand::DStoredCommand () { diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 2e8c56f05c..40e8e57028 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -221,7 +221,7 @@ DehInfo deh = // from the original actor's defaults. The original actor is then changed to // spawn the new class. -IMPLEMENT_CLASS(ADehackedPickup, false, true, false, false) +IMPLEMENT_CLASS(ADehackedPickup, false, true) IMPLEMENT_POINTERS_START(ADehackedPickup) IMPLEMENT_POINTER(RealPickup) diff --git a/src/d_dehacked.h b/src/d_dehacked.h index 564a6d499b..a622707a3a 100644 --- a/src/d_dehacked.h +++ b/src/d_dehacked.h @@ -41,7 +41,7 @@ class ADehackedPickup : public AInventory DECLARE_CLASS (ADehackedPickup, AInventory) HAS_OBJECT_POINTERS public: - void Destroy (); + void Destroy() override; const char *PickupMessage (); bool ShouldRespawn (); bool ShouldStay (); diff --git a/src/d_player.h b/src/d_player.h index d1678b6199..af06e97301 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -109,7 +109,7 @@ public: virtual void Tick(); virtual void AddInventory (AInventory *item); virtual void RemoveInventory (AInventory *item); - virtual bool UseInventory (AInventory *item); + virtual bool DoUseInventory (AInventory *item); virtual void MarkPrecacheSounds () const; virtual void PlayIdle (); diff --git a/src/decallib.cpp b/src/decallib.cpp index 970bd7458c..9fe2966eb4 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -119,7 +119,7 @@ protected: DDecalThinker () : DThinker (STAT_DECALTHINKER) {} }; -IMPLEMENT_CLASS(DDecalThinker, false, true, false, false) +IMPLEMENT_CLASS(DDecalThinker, false, true) IMPLEMENT_POINTERS_START(DDecalThinker) IMPLEMENT_POINTER(TheDecal) @@ -1153,7 +1153,7 @@ FDecalAnimator::~FDecalAnimator () { } -IMPLEMENT_CLASS(DDecalFader, false, false, false, false) +IMPLEMENT_CLASS(DDecalFader, false, false) void DDecalFader::Serialize(FSerializer &arc) { @@ -1202,7 +1202,7 @@ DThinker *FDecalFaderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const return fader; } -IMPLEMENT_CLASS(DDecalStretcher, false, false, false, false) +IMPLEMENT_CLASS(DDecalStretcher, false, false) void DDecalStretcher::Serialize(FSerializer &arc) { @@ -1290,7 +1290,7 @@ void DDecalStretcher::Tick () } } -IMPLEMENT_CLASS(DDecalSlider, false, false, false, false) +IMPLEMENT_CLASS(DDecalSlider, false, false) void DDecalSlider::Serialize(FSerializer &arc) { @@ -1370,7 +1370,7 @@ FDecalAnimator *FDecalLib::FindAnimator (const char *name) return NULL; } -IMPLEMENT_CLASS(DDecalColorer, false, false, false, false) +IMPLEMENT_CLASS(DDecalColorer, false, false) void DDecalColorer::Serialize(FSerializer &arc) { diff --git a/src/dobject.cpp b/src/dobject.cpp index 849f6a477e..b05ae69acf 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -61,7 +61,7 @@ ClassReg DObject::RegistrationInfo = nullptr, // MyClass "DObject", // Name nullptr, // ParentType - &DVMObject::RegistrationInfo, // VMExport + nullptr, nullptr, // Pointers &DObject::InPlaceConstructor, // ConstructNative nullptr, @@ -358,7 +358,6 @@ void DObject::Destroy () DEFINE_ACTION_FUNCTION(DObject, Destroy) { PARAM_SELF_PROLOGUE(DObject); - self->VMSuperCall(); self->Destroy(); return 0; } diff --git a/src/dobject.h b/src/dobject.h index f728713e08..cb1074c0c4 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -110,7 +110,7 @@ struct ClassReg PClass *MyClass; const char *Name; ClassReg *ParentType; - ClassReg *VMExport; + ClassReg *_VMExport; const size_t *Pointers; void (*ConstructNative)(void *); void(*InitNatives)(); @@ -157,23 +157,23 @@ protected: \ # define _DECLARE_TI(cls) ClassReg * const cls::RegistrationInfoPtr __attribute__((section(SECTION_CREG))) = &cls::RegistrationInfo; #endif -#define _IMP_PCLASS(cls, ptrs, create, initn, vmexport) \ +#define _IMP_PCLASS(cls, ptrs, create) \ ClassReg cls::RegistrationInfo = {\ nullptr, \ #cls, \ &cls::Super::RegistrationInfo, \ - vmexport, \ + nullptr, \ ptrs, \ create, \ - initn, \ + nullptr, \ sizeof(cls), \ cls::MetaClassNum }; \ _DECLARE_TI(cls) \ PClass *cls::StaticType() const { return RegistrationInfo.MyClass; } -#define IMPLEMENT_CLASS(cls, isabstract, ptrs, fields, vmexport) \ +#define IMPLEMENT_CLASS(cls, isabstract, ptrs) \ _X_CONSTRUCTOR_##isabstract(cls) \ - _IMP_PCLASS(cls, _X_POINTERS_##ptrs(cls), _X_ABSTRACT_##isabstract(cls), _X_FIELDS_##fields(cls), _X_VMEXPORT_##vmexport(cls)) + _IMP_PCLASS(cls, _X_POINTERS_##ptrs(cls), _X_ABSTRACT_##isabstract(cls)) // 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. @@ -190,7 +190,7 @@ protected: \ #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_true(cls) nullptr #define _X_VMEXPORT_false(cls) nullptr enum EObjectFlags @@ -481,7 +481,7 @@ public: // that don't call their base class. void CheckIfSerialized () const; - virtual void Destroy (); + virtual void Destroy(); // If you need to replace one object with another and want to // change any pointers from the old object to the new object, diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index 40ef7b7845..827516172e 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -125,7 +125,7 @@ public: int SideNum; }; -IMPLEMENT_CLASS(DSectorMarker, false, false, false, false) +IMPLEMENT_CLASS(DSectorMarker, false, false) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 52a2698735..079890f863 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -97,8 +97,8 @@ static const size_t TheEnd = ~(size_t)0; // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(PErrorType, false, false, false, false) -IMPLEMENT_CLASS(PVoidType, false, false, false, false) +IMPLEMENT_CLASS(PErrorType, false, false) +IMPLEMENT_CLASS(PVoidType, false, false) void DumpTypeTable() { @@ -145,7 +145,7 @@ void DumpTypeTable() /* PClassType *************************************************************/ -IMPLEMENT_CLASS(PClassType, false, false, false, false) +IMPLEMENT_CLASS(PClassType, false, false) //========================================================================== // @@ -173,7 +173,7 @@ void PClassType::DeriveData(PClass *newclass) /* PClassClass ************************************************************/ -IMPLEMENT_CLASS(PClassClass, false, false, false, false) +IMPLEMENT_CLASS(PClassClass, false, false) //========================================================================== // @@ -191,7 +191,7 @@ PClassClass::PClassClass() /* PType ******************************************************************/ -IMPLEMENT_CLASS(PType, true, true, false, false) +IMPLEMENT_CLASS(PType, true, true) IMPLEMENT_POINTERS_START(PType) IMPLEMENT_POINTER(HashNext) @@ -647,7 +647,7 @@ void PType::StaticInit() /* PBasicType *************************************************************/ -IMPLEMENT_CLASS(PBasicType, true, false, false, false) +IMPLEMENT_CLASS(PBasicType, true, false) //========================================================================== // @@ -673,11 +673,11 @@ PBasicType::PBasicType(unsigned int size, unsigned int align) /* PCompoundType **********************************************************/ -IMPLEMENT_CLASS(PCompoundType, true, false, false, false) +IMPLEMENT_CLASS(PCompoundType, true, false) /* PNamedType *************************************************************/ -IMPLEMENT_CLASS(PNamedType, true, true, false, false) +IMPLEMENT_CLASS(PNamedType, true, true) IMPLEMENT_POINTERS_START(PNamedType) IMPLEMENT_POINTER(Outer) @@ -725,7 +725,7 @@ FString PNamedType::QualifiedName() const /* PInt *******************************************************************/ -IMPLEMENT_CLASS(PInt, false, false, false, false) +IMPLEMENT_CLASS(PInt, false, false) //========================================================================== // @@ -964,7 +964,7 @@ double PInt::GetValueFloat(void *addr) const /* PBool ******************************************************************/ -IMPLEMENT_CLASS(PBool, false, false, false, false) +IMPLEMENT_CLASS(PBool, false, false) //========================================================================== // @@ -985,7 +985,7 @@ PBool::PBool() /* PFloat *****************************************************************/ -IMPLEMENT_CLASS(PFloat, false, false, false, false) +IMPLEMENT_CLASS(PFloat, false, false) //========================================================================== // @@ -1235,7 +1235,7 @@ void PFloat::SetOps() /* PString ****************************************************************/ -IMPLEMENT_CLASS(PString, false, false, false, false) +IMPLEMENT_CLASS(PString, false, false) //========================================================================== // @@ -1332,7 +1332,7 @@ void PString::DestroyValue(void *addr) const /* PName ******************************************************************/ -IMPLEMENT_CLASS(PName, false, false, false, false) +IMPLEMENT_CLASS(PName, false, false) //========================================================================== // @@ -1382,7 +1382,7 @@ bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PSpriteID ******************************************************************/ -IMPLEMENT_CLASS(PSpriteID, false, false, false, false) +IMPLEMENT_CLASS(PSpriteID, false, false) //========================================================================== // @@ -1424,7 +1424,7 @@ bool PSpriteID::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PTextureID ******************************************************************/ -IMPLEMENT_CLASS(PTextureID, false, false, false, false) +IMPLEMENT_CLASS(PTextureID, false, false) //========================================================================== // @@ -1467,7 +1467,7 @@ bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PSound *****************************************************************/ -IMPLEMENT_CLASS(PSound, false, false, false, false) +IMPLEMENT_CLASS(PSound, false, false) //========================================================================== // @@ -1517,7 +1517,7 @@ bool PSound::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PColor *****************************************************************/ -IMPLEMENT_CLASS(PColor, false, false, false, false) +IMPLEMENT_CLASS(PColor, false, false) //========================================================================== // @@ -1534,7 +1534,7 @@ PColor::PColor() /* PStateLabel *****************************************************************/ -IMPLEMENT_CLASS(PStateLabel, false, false, false, false) +IMPLEMENT_CLASS(PStateLabel, false, false) //========================================================================== // @@ -1550,7 +1550,7 @@ PStateLabel::PStateLabel() /* PPointer ***************************************************************/ -IMPLEMENT_CLASS(PPointer, false, true, false, false) +IMPLEMENT_CLASS(PPointer, false, true) IMPLEMENT_POINTERS_START(PPointer) IMPLEMENT_POINTER(PointedType) @@ -1695,7 +1695,7 @@ PPointer *NewPointer(PType *type, bool isconst) /* PStatePointer **********************************************************/ -IMPLEMENT_CLASS(PStatePointer, false, false, false, false) +IMPLEMENT_CLASS(PStatePointer, false, false) //========================================================================== // @@ -1738,7 +1738,7 @@ bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons /* PClassPointer **********************************************************/ -IMPLEMENT_CLASS(PClassPointer, false, true, false, false) +IMPLEMENT_CLASS(PClassPointer,false, true) IMPLEMENT_POINTERS_START(PClassPointer) IMPLEMENT_POINTER(ClassRestriction) @@ -1819,7 +1819,7 @@ PClassPointer *NewClassPointer(PClass *restrict) /* PEnum ******************************************************************/ -IMPLEMENT_CLASS(PEnum, false, true, false, false) +IMPLEMENT_CLASS(PEnum, false, true) IMPLEMENT_POINTERS_START(PEnum) IMPLEMENT_POINTER(ValueType) @@ -1872,7 +1872,7 @@ PEnum *NewEnum(FName name, PTypeBase *outer) /* PArray *****************************************************************/ -IMPLEMENT_CLASS(PArray, false, true, false, false) +IMPLEMENT_CLASS(PArray, false, true) IMPLEMENT_POINTERS_START(PArray) IMPLEMENT_POINTER(ElementType) @@ -2035,7 +2035,7 @@ PArray *NewArray(PType *type, unsigned int count) /* PDynArray **************************************************************/ -IMPLEMENT_CLASS(PDynArray, false, true, false, false) +IMPLEMENT_CLASS(PDynArray, false, true) IMPLEMENT_POINTERS_START(PDynArray) IMPLEMENT_POINTER(ElementType) @@ -2118,7 +2118,7 @@ PDynArray *NewDynArray(PType *type) /* PMap *******************************************************************/ -IMPLEMENT_CLASS(PMap, false, true, false, false) +IMPLEMENT_CLASS(PMap, false, true) IMPLEMENT_POINTERS_START(PMap) IMPLEMENT_POINTER(KeyType) @@ -2202,7 +2202,7 @@ PMap *NewMap(PType *keytype, PType *valuetype) /* PStruct ****************************************************************/ -IMPLEMENT_CLASS(PStruct, false, false, false, false) +IMPLEMENT_CLASS(PStruct, false, false) //========================================================================== // @@ -2440,7 +2440,7 @@ PStruct *NewStruct(FName name, PTypeBase *outer) /* PNativeStruct ****************************************************************/ -IMPLEMENT_CLASS(PNativeStruct, false, false, false, false) +IMPLEMENT_CLASS(PNativeStruct, false, false) //========================================================================== // @@ -2478,7 +2478,7 @@ PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer) /* PField *****************************************************************/ -IMPLEMENT_CLASS(PField, false, false, false, false) +IMPLEMENT_CLASS(PField, false, false) //========================================================================== // @@ -2523,7 +2523,7 @@ PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue /* PPrototype *************************************************************/ -IMPLEMENT_CLASS(PPrototype, false, false, false, false) +IMPLEMENT_CLASS(PPrototype, false, false) //========================================================================== // @@ -2609,7 +2609,7 @@ PPrototype *NewPrototype(const TArray &rettypes, const TArray /* PFunction **************************************************************/ -IMPLEMENT_CLASS(PFunction, false, false, false, false) +IMPLEMENT_CLASS(PFunction, false, false) //========================================================================== // @@ -2672,7 +2672,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TArra /* PClass *****************************************************************/ -IMPLEMENT_CLASS(PClass, false, true, false, false) +IMPLEMENT_CLASS(PClass, false, true) IMPLEMENT_POINTERS_START(PClass) IMPLEMENT_POINTER(ParentClass) @@ -2907,7 +2907,6 @@ void PClass::StaticShutdown () { auto cr = ((ClassReg *)*probe); cr->MyClass = nullptr; - if (cr->VMExport != nullptr) cr->VMExport->MyClass = nullptr; } } @@ -3034,10 +3033,6 @@ PClass *ClassReg::RegisterClass() { cls->ParentClass = ParentType->RegisterClass(); } - if (VMExport != nullptr) - { - cls->VMExported = VMExport->RegisterClass(); - } return cls; } @@ -3717,19 +3712,19 @@ CCMD(typetable) // Symbol tables ------------------------------------------------------------ -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_CLASS(PTypeBase, true, false); +IMPLEMENT_CLASS(PSymbol, true, false); +IMPLEMENT_CLASS(PSymbolConst, false, false); +IMPLEMENT_CLASS(PSymbolConstNumeric, false, false); +IMPLEMENT_CLASS(PSymbolConstString, false, false); +IMPLEMENT_CLASS(PSymbolTreeNode, false, false) +IMPLEMENT_CLASS(PSymbolType, false, true) IMPLEMENT_POINTERS_START(PSymbolType) IMPLEMENT_POINTER(Type) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(PSymbolVMFunction, false, true, false, false) +IMPLEMENT_CLASS(PSymbolVMFunction, false, true) IMPLEMENT_POINTERS_START(PSymbolVMFunction) IMPLEMENT_POINTER(Function) diff --git a/src/dobjtype.h b/src/dobjtype.h index 76d6e75858..b952a3c232 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -809,7 +809,6 @@ public: // 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; diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 700a407fd7..3c33d1634c 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -31,7 +31,7 @@ #include "serializer.h" #include "doomstat.h" -IMPLEMENT_CLASS(DSectorEffect, false, false, false, false) +IMPLEMENT_CLASS(DSectorEffect, false, false) DSectorEffect::DSectorEffect () : DThinker(STAT_SECTOREFFECT) @@ -71,7 +71,7 @@ void DSectorEffect::Serialize(FSerializer &arc) arc("sector", m_Sector); } -IMPLEMENT_CLASS(DMover, false, true, false, false) +IMPLEMENT_CLASS(DMover, false, true) IMPLEMENT_POINTERS_START(DMover) IMPLEMENT_POINTER(interpolation) @@ -108,7 +108,7 @@ void DMover::StopInterpolation(bool force) } } -IMPLEMENT_CLASS(DMovingFloor, false, false, false, false) +IMPLEMENT_CLASS(DMovingFloor, false, false) DMovingFloor::DMovingFloor () { @@ -121,7 +121,7 @@ DMovingFloor::DMovingFloor (sector_t *sector) interpolation = sector->SetInterpolation(sector_t::FloorMove, true); } -IMPLEMENT_CLASS(DMovingCeiling, false, false, false, false) +IMPLEMENT_CLASS(DMovingCeiling, false, false) DMovingCeiling::DMovingCeiling () { diff --git a/src/dsectoreffect.h b/src/dsectoreffect.h index 0a5e9bd568..e9327ce702 100644 --- a/src/dsectoreffect.h +++ b/src/dsectoreffect.h @@ -12,7 +12,7 @@ public: void Serialize(FSerializer &arc); - void Destroy(); + void Destroy() override; sector_t *GetSector() const { return m_Sector; } @@ -35,7 +35,7 @@ protected: DMover (); void Serialize(FSerializer &arc); - void Destroy(); + void Destroy() override; }; class DMovingFloor : public DMover diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 9478393c0e..d214b28e99 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -48,7 +48,7 @@ extern cycle_t BotSupportCycles; extern cycle_t ActionCycles; extern int BotWTG; -IMPLEMENT_CLASS(DThinker, false, false, false, true) +IMPLEMENT_CLASS(DThinker, false, false) DThinker *NextToThink; @@ -56,6 +56,12 @@ FThinkerList DThinker::Thinkers[MAX_STATNUM+2]; FThinkerList DThinker::FreshThinkers[MAX_STATNUM+1]; bool DThinker::bSerialOverride = false; +//========================================================================== +// +// +// +//========================================================================== + void FThinkerList::AddTail(DThinker *thinker) { assert(thinker->PrevThinker == NULL && thinker->NextThinker == NULL); @@ -80,6 +86,12 @@ void FThinkerList::AddTail(DThinker *thinker) GC::WriteBarrier(Sentinel, thinker); } +//========================================================================== +// +// +// +//========================================================================== + DThinker *FThinkerList::GetHead() const { if (Sentinel == NULL || Sentinel->NextThinker == Sentinel) @@ -90,6 +102,12 @@ DThinker *FThinkerList::GetHead() const return Sentinel->NextThinker; } +//========================================================================== +// +// +// +//========================================================================== + DThinker *FThinkerList::GetTail() const { if (Sentinel == NULL || Sentinel->PrevThinker == Sentinel) @@ -99,11 +117,23 @@ DThinker *FThinkerList::GetTail() const return Sentinel->PrevThinker; } +//========================================================================== +// +// +// +//========================================================================== + bool FThinkerList::IsEmpty() const { return Sentinel == NULL || Sentinel->NextThinker == NULL; } +//========================================================================== +// +// +// +//========================================================================== + void DThinker::SaveList(FSerializer &arc, DThinker *node) { if (node != NULL) @@ -234,6 +264,12 @@ void DThinker::Destroy () Super::Destroy(); } +//========================================================================== +// +// +// +//========================================================================== + void DThinker::Remove() { if (this == NextToThink) @@ -254,6 +290,12 @@ void DThinker::Remove() PrevThinker = NULL; } +//========================================================================== +// +// +// +//========================================================================== + void DThinker::PostBeginPlay () { } @@ -261,15 +303,41 @@ void DThinker::PostBeginPlay () DEFINE_ACTION_FUNCTION(DThinker, PostBeginPlay) { PARAM_SELF_PROLOGUE(DThinker); - self->VMSuperCall(); self->PostBeginPlay(); return 0; } +void DThinker::CallPostBeginPlay() +{ + IFVIRTUAL(DThinker, PostBeginPlay) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } + else + { + PostBeginPlay(); + } +} + +//========================================================================== +// +// +// +//========================================================================== + void DThinker::PostSerialize() { } +//========================================================================== +// +// +// +//========================================================================== + DThinker *DThinker::FirstThinker (int statnum) { DThinker *node; @@ -290,6 +358,12 @@ DThinker *DThinker::FirstThinker (int statnum) return node; } +//========================================================================== +// +// +// +//========================================================================== + void DThinker::ChangeStatNum (int statnum) { FThinkerList *list; @@ -313,7 +387,12 @@ void DThinker::ChangeStatNum (int statnum) list->AddTail(this); } +//========================================================================== +// // Mark the first thinker of each list +// +//========================================================================== + void DThinker::MarkRoots() { for (int i = 0; i <= MAX_STATNUM; ++i) @@ -324,7 +403,12 @@ void DThinker::MarkRoots() GC::Mark(Thinkers[MAX_STATNUM+1].Sentinel); } +//========================================================================== +// // Destroy every thinker +// +//========================================================================== + void DThinker::DestroyAllThinkers () { int i; @@ -341,6 +425,12 @@ void DThinker::DestroyAllThinkers () GC::FullGC(); } +//========================================================================== +// +// +// +//========================================================================== + void DThinker::DestroyThinkersInList (FThinkerList &list) { if (list.Sentinel != NULL) @@ -355,6 +445,12 @@ void DThinker::DestroyThinkersInList (FThinkerList &list) } } +//========================================================================== +// +// +// +//========================================================================== + void DThinker::RunThinkers () { int i, count; @@ -385,6 +481,12 @@ void DThinker::RunThinkers () ThinkCycles.Unclock(); } +//========================================================================== +// +// +// +//========================================================================== + int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest) { int count = 0; @@ -407,7 +509,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest) node->Remove(); dest->AddTail(node); } - node->PostBeginPlay(); + node->CallPostBeginPlay(); } else if (dest != NULL) { @@ -416,7 +518,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest) if (!(node->ObjectFlags & OF_EuthanizeMe)) { // Only tick thinkers not scheduled for destruction - node->Tick(); + node->CallTick(); node->ObjectFlags &= ~OF_JustSpawned; GC::CheckGC(); } @@ -425,6 +527,12 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest) return count; } +//========================================================================== +// +// +// +//========================================================================== + void DThinker::Tick () { } @@ -432,11 +540,28 @@ void DThinker::Tick () DEFINE_ACTION_FUNCTION(DThinker, Tick) { PARAM_SELF_PROLOGUE(DThinker); - self->VMSuperCall(); self->Tick(); return 0; } +void DThinker::CallTick() +{ + IFVIRTUAL(DThinker, Tick) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } + else Tick(); +} + +//========================================================================== +// +// +// +//========================================================================== + size_t DThinker::PropagateMark() { // Do not choke on partially initialized objects (as happens when loading a savegame fails) @@ -450,6 +575,12 @@ size_t DThinker::PropagateMark() return Super::PropagateMark(); } +//========================================================================== +// +// +// +//========================================================================== + FThinkerIterator::FThinkerIterator (const PClass *type, int statnum) { if ((unsigned)statnum > MAX_STATNUM) @@ -467,6 +598,12 @@ FThinkerIterator::FThinkerIterator (const PClass *type, int statnum) m_SearchingFresh = false; } +//========================================================================== +// +// +// +//========================================================================== + FThinkerIterator::FThinkerIterator (const PClass *type, int statnum, DThinker *prev) { if ((unsigned)statnum > MAX_STATNUM) @@ -491,12 +628,24 @@ FThinkerIterator::FThinkerIterator (const PClass *type, int statnum, DThinker *p } } +//========================================================================== +// +// +// +//========================================================================== + void FThinkerIterator::Reinit () { m_CurrThinker = DThinker::Thinkers[m_Stat].GetHead(); m_SearchingFresh = false; } +//========================================================================== +// +// +// +//========================================================================== + DThinker *FThinkerIterator::Next (bool exact) { if (m_ParentType == NULL) @@ -542,8 +691,13 @@ DThinker *FThinkerIterator::Next (bool exact) 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) @@ -555,7 +709,7 @@ public: } }; -IMPLEMENT_CLASS(DThinkerIterator, false, false, false, false); +IMPLEMENT_CLASS(DThinkerIterator, false, false); DEFINE_ACTION_FUNCTION(DThinkerIterator, Create) { PARAM_PROLOGUE; @@ -577,8 +731,11 @@ DEFINE_ACTION_FUNCTION(DThinkerIterator, Reinit) return 0; } - - +//========================================================================== +// +// +// +//========================================================================== ADD_STAT (think) { diff --git a/src/dthinker.h b/src/dthinker.h index 95985c2fb4..3d580c3c20 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -66,10 +66,12 @@ class DThinker : public DObject DECLARE_CLASS (DThinker, DObject) public: DThinker (int statnum = STAT_DEFAULT) throw(); - void Destroy (); + void Destroy () override; virtual ~DThinker (); virtual void Tick (); + void CallTick(); virtual void PostBeginPlay (); // Called just before the first tick + void CallPostBeginPlay(); virtual void PostSerialize(); size_t PropagateMark(); diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index ddc1a4bd42..7266daf40a 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -1785,7 +1785,7 @@ public: void Destroy() { Super::Destroy(); m_Sector->lightingdata=NULL; } }; -IMPLEMENT_CLASS(DLightLevel, false, false, false, false) +IMPLEMENT_CLASS(DLightLevel, false, false) void DLightLevel::Serialize(FSerializer &arc) { @@ -2975,7 +2975,7 @@ void FParser::SF_ObjAwaken(void) if(mo) { - mo->Activate(Script->trigger); + mo->CallActivate(Script->trigger); } } diff --git a/src/fragglescript/t_prepro.cpp b/src/fragglescript/t_prepro.cpp index 2129df54f7..4128e6661d 100644 --- a/src/fragglescript/t_prepro.cpp +++ b/src/fragglescript/t_prepro.cpp @@ -71,7 +71,7 @@ // //========================================================================== -IMPLEMENT_CLASS(DFsSection, false, true, false, false) +IMPLEMENT_CLASS(DFsSection, false, true) IMPLEMENT_POINTERS_START(DFsSection) IMPLEMENT_POINTER(next) diff --git a/src/fragglescript/t_script.cpp b/src/fragglescript/t_script.cpp index a401226236..b852607b3c 100644 --- a/src/fragglescript/t_script.cpp +++ b/src/fragglescript/t_script.cpp @@ -99,7 +99,7 @@ AActor *trigger_obj; // //========================================================================== -IMPLEMENT_CLASS(DFsScript, false, true, false, false) +IMPLEMENT_CLASS(DFsScript, false, true) IMPLEMENT_POINTERS_START(DFsScript) IMPLEMENT_POINTER(parent) @@ -269,7 +269,7 @@ void DFsScript::ParseScript(char *position) // //========================================================================== -IMPLEMENT_CLASS(DRunningScript, false, true, false, false) +IMPLEMENT_CLASS(DRunningScript, false, true) IMPLEMENT_POINTERS_START(DRunningScript) IMPLEMENT_POINTER(prev) @@ -380,7 +380,7 @@ void DRunningScript::Serialize(FSerializer &arc) // //========================================================================== -IMPLEMENT_CLASS(DFraggleThinker, false, true, false, false) +IMPLEMENT_CLASS(DFraggleThinker, false, true) IMPLEMENT_POINTERS_START(DFraggleThinker) IMPLEMENT_POINTER(RunningScripts) diff --git a/src/fragglescript/t_script.h b/src/fragglescript/t_script.h index 3734e16b8a..50829e0008 100644 --- a/src/fragglescript/t_script.h +++ b/src/fragglescript/t_script.h @@ -337,7 +337,7 @@ public: DFsScript(); ~DFsScript(); - void Destroy(); + void Destroy() override; void Serialize(FSerializer &ar); DFsVariable *NewVariable(const char *name, int vtype); @@ -652,7 +652,7 @@ class DRunningScript : public DObject public: DRunningScript(AActor *trigger=NULL, DFsScript *owner = NULL, int index = 0) ; - void Destroy(); + void Destroy() override; void Serialize(FSerializer &arc); TObjPtr script; @@ -687,7 +687,7 @@ public: bool nocheckposition; DFraggleThinker(); - void Destroy(); + void Destroy() override; void Serialize(FSerializer & arc); diff --git a/src/fragglescript/t_variable.cpp b/src/fragglescript/t_variable.cpp index 23d24b78a7..9bdddda34d 100644 --- a/src/fragglescript/t_variable.cpp +++ b/src/fragglescript/t_variable.cpp @@ -179,7 +179,7 @@ AActor* actorvalue(const svalue_t &svalue) // //========================================================================== -IMPLEMENT_CLASS(DFsVariable, false, true, false, false) +IMPLEMENT_CLASS(DFsVariable, false, true) IMPLEMENT_POINTERS_START(DFsVariable) IMPLEMENT_POINTER(next) diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index f2ad18b2fa..2fb45c1242 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -17,7 +17,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiTomeOfPower, false, false, false, false) +IMPLEMENT_CLASS(AArtiTomeOfPower, false, false) bool AArtiTomeOfPower::Use (bool pickup) { @@ -51,7 +51,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiTimeBomb, false, false, false, false) +IMPLEMENT_CLASS(AArtiTimeBomb, false, false) bool AArtiTimeBomb::Use (bool pickup) { diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 3b2711e246..4e2d62f1d1 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -58,7 +58,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(ARainPillar, false, false, false, false) +IMPLEMENT_CLASS(ARainPillar, false, false) int ARainPillar::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -80,7 +80,7 @@ public: TObjPtr Rain1, Rain2; }; -IMPLEMENT_CLASS(ARainTracker, false, false, false, false) +IMPLEMENT_CLASS(ARainTracker, false, false) void ARainTracker::Serialize(FSerializer &arc) { @@ -367,8 +367,8 @@ public: void EndPowerup (); }; -IMPLEMENT_CLASS(APhoenixRod, false, false, false, false) -IMPLEMENT_CLASS(APhoenixRodPowered, false, false, false, false) +IMPLEMENT_CLASS(APhoenixRod, false, false) +IMPLEMENT_CLASS(APhoenixRodPowered, false, false) void APhoenixRodPowered::EndPowerup () { @@ -388,7 +388,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(APhoenixFX2, false, false, false, false) +IMPLEMENT_CLASS(APhoenixFX2, false, false) int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) { diff --git a/src/g_hexen/a_boostarmor.cpp b/src/g_hexen/a_boostarmor.cpp index 1323af8a53..b910f63e78 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, false, false, false, false) +IMPLEMENT_CLASS(AArtiBoostArmor, false, false) bool AArtiBoostArmor::Use (bool pickup) { diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index 362434b023..52ff4179df 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -58,11 +58,11 @@ public: BYTE CHolyCount; }; -IMPLEMENT_CLASS(ACWeapWraithverge, false, false, false, false) +IMPLEMENT_CLASS(ACWeapWraithverge, false, false) // Holy Spirit -------------------------------------------------------------- -IMPLEMENT_CLASS(AHolySpirit, false, false, false, false) +IMPLEMENT_CLASS(AHolySpirit, false, false) bool AHolySpirit::Slam(AActor *thing) { diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index a838357d63..ef7beaffa0 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -25,7 +25,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(ACStaffMissile, false, false, false, false) +IMPLEMENT_CLASS(ACStaffMissile, false, false) int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetype) { diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index 1dc02d599e..fde3a9c18a 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -31,7 +31,7 @@ public: FState *GetAtkState (bool hold); }; -IMPLEMENT_CLASS(AFWeapAxe, false, false, false, false) +IMPLEMENT_CLASS(AFWeapAxe, false, false) FState *AFWeapAxe::GetUpState () { diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index afdbe8a90f..4f1d1fd3b6 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -11,9 +11,9 @@ #include "vm.h" */ -IMPLEMENT_CLASS(AFighterWeapon, false, false, false, false) -IMPLEMENT_CLASS(AClericWeapon, false, false, false, false) -IMPLEMENT_CLASS(AMageWeapon, false, false, false, false) +IMPLEMENT_CLASS(AFighterWeapon, false, false) +IMPLEMENT_CLASS(AClericWeapon, false, false) +IMPLEMENT_CLASS(AMageWeapon, false, false) static FRandom pr_fpatk ("FPunchAttack"); diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp index adba8d2354..458d1415bf 100644 --- a/src/g_hexen/a_fighterquietus.cpp +++ b/src/g_hexen/a_fighterquietus.cpp @@ -59,7 +59,7 @@ public: int DoSpecialDamage(AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AFSwordMissile, false, false, false, false) +IMPLEMENT_CLASS(AFSwordMissile, false, false) int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype) { diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index 3358428874..77917c4022 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -24,7 +24,7 @@ DECLARE_ACTION(A_CheckThrowBomb) // Poison Bag Artifact (Flechette) ------------------------------------------ -IMPLEMENT_CLASS(AArtiPoisonBag, false, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBag, false, false) // Poison Bag 1 (The Cleric's) ---------------------------------------------- @@ -35,7 +35,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBag1, false, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBag1, false, false) bool AArtiPoisonBag1::Use (bool pickup) { @@ -60,7 +60,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBag2, false, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBag2, false, false) bool AArtiPoisonBag2::Use (bool pickup) { @@ -85,7 +85,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBag3, false, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBag3, false, false) bool AArtiPoisonBag3::Use (bool pickup) { @@ -136,7 +136,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBagGiver, false, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBagGiver, false, false) bool AArtiPoisonBagGiver::Use (bool pickup) { @@ -167,7 +167,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiPoisonBagShooter, false, false, false, false) +IMPLEMENT_CLASS(AArtiPoisonBagShooter, false, false) bool AArtiPoisonBagShooter::Use (bool pickup) { @@ -296,7 +296,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(APoisonCloud, false, false, false, false) +IMPLEMENT_CLASS(APoisonCloud, false, false) void APoisonCloud::BeginPlay () { diff --git a/src/g_hexen/a_healingradius.cpp b/src/g_hexen/a_healingradius.cpp index 25efbc3ca4..bf18a7e0ef 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, false, false, false, false) +IMPLEMENT_CLASS(AArtiHealingRadius, false, false) bool AArtiHealingRadius::Use (bool pickup) { diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index 32ad9ab696..a53d9926de 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -72,7 +72,7 @@ public: void Die (AActor *source, AActor *inflictor, int dmgflags); }; -IMPLEMENT_CLASS(AHeresiarch, false, false, false, false) +IMPLEMENT_CLASS(AHeresiarch, false, false) void AHeresiarch::Serialize(FSerializer &arc) { @@ -122,7 +122,7 @@ public: } }; -IMPLEMENT_CLASS(ASorcBall, false, false, false, false) +IMPLEMENT_CLASS(ASorcBall, false, false) // First ball (purple) - fires projectiles ---------------------------------- @@ -140,7 +140,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS(ASorcBall1, false, false, false, false) +IMPLEMENT_CLASS(ASorcBall1, false, false) // Second ball (blue) - generates the shield -------------------------------- @@ -156,7 +156,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS(ASorcBall2, false, false, false, false) +IMPLEMENT_CLASS(ASorcBall2, false, false) // Third ball (green) - summons Bishops ------------------------------------- @@ -172,7 +172,7 @@ public: virtual void CastSorcererSpell (); }; -IMPLEMENT_CLASS(ASorcBall3, false, false, false, false) +IMPLEMENT_CLASS(ASorcBall3, false, false) // Sorcerer spell 1 (The burning, bouncing head thing) ---------------------- diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index 0dcdc2c5f4..1745e6efc4 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -121,7 +121,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS(AZCorpseLynchedNoHeart, false, false, false, false) +IMPLEMENT_CLASS(AZCorpseLynchedNoHeart, false, false) void AZCorpseLynchedNoHeart::PostBeginPlay () { @@ -329,7 +329,7 @@ public: void Activate (AActor *activator); }; -IMPLEMENT_CLASS(AZBell, false, false, false, false) +IMPLEMENT_CLASS(AZBell, false, false) void AZBell::Activate (AActor *activator) { diff --git a/src/g_hexen/a_magecone.cpp b/src/g_hexen/a_magecone.cpp index da53a829c0..102f681555 100644 --- a/src/g_hexen/a_magecone.cpp +++ b/src/g_hexen/a_magecone.cpp @@ -32,7 +32,7 @@ public: int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AFrostMissile, false, false, false, false) +IMPLEMENT_CLASS(AFrostMissile, false, false) int AFrostMissile::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 2a744db75d..d5fcef880b 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -34,7 +34,7 @@ public: int SpecialMissileHit (AActor *victim); }; -IMPLEMENT_CLASS(ALightning, false, false, false, false) +IMPLEMENT_CLASS(ALightning, false, false) int ALightning::SpecialMissileHit (AActor *thing) { @@ -87,7 +87,7 @@ public: int SpecialMissileHit (AActor *thing); }; -IMPLEMENT_CLASS(ALightningZap, false, false, false, false) +IMPLEMENT_CLASS(ALightningZap, false, false) int ALightningZap::SpecialMissileHit (AActor *thing) { diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index 0b78bd279d..78d9edec04 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -56,7 +56,7 @@ public: BYTE MStaffCount; }; -IMPLEMENT_CLASS(AMWeapBloodscourge, false, false, false, false) +IMPLEMENT_CLASS(AMWeapBloodscourge, false, false) // Mage Staff FX2 (Bloodscourge) -------------------------------------------- @@ -68,7 +68,7 @@ public: bool SpecialBlastHandling (AActor *source, double strength); }; -IMPLEMENT_CLASS(AMageStaffFX2, false, false, false, false) +IMPLEMENT_CLASS(AMageStaffFX2, false, false) int AMageStaffFX2::SpecialMissileHit (AActor *victim) { diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp index be28e38dfd..cd0d2e8914 100644 --- a/src/g_hexen/a_spike.cpp +++ b/src/g_hexen/a_spike.cpp @@ -26,7 +26,7 @@ public: void Deactivate (AActor *activator); }; -IMPLEMENT_CLASS(AThrustFloor, false, false, false, false) +IMPLEMENT_CLASS(AThrustFloor, false, false) void AThrustFloor::Activate (AActor *activator) { diff --git a/src/g_hexen/a_summon.cpp b/src/g_hexen/a_summon.cpp index 7c0746c915..58e50eeafc 100644 --- a/src/g_hexen/a_summon.cpp +++ b/src/g_hexen/a_summon.cpp @@ -21,7 +21,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiDarkServant, false, false, false, false) +IMPLEMENT_CLASS(AArtiDarkServant, false, false) //============================================================================ // diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp index 4eeba53f99..0e7dd018d7 100644 --- a/src/g_hexen/a_teleportother.cpp +++ b/src/g_hexen/a_teleportother.cpp @@ -34,7 +34,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AArtiTeleportOther, false, false, false, false) +IMPLEMENT_CLASS(AArtiTeleportOther, false, false) // Teleport Other FX -------------------------------------------------------- @@ -45,7 +45,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(ATelOtherFX1, false, false, false, false) +IMPLEMENT_CLASS(ATelOtherFX1, false, false) static void TeloSpawn (AActor *source, const char *type) { diff --git a/src/g_level.cpp b/src/g_level.cpp index a715b5d263..904b38b8a3 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -903,7 +903,7 @@ public: void Tick (); }; -IMPLEMENT_CLASS(DAutosaver, false, false, false, false) +IMPLEMENT_CLASS(DAutosaver, false, false) void DAutosaver::Tick () { diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp index b333c9a13e..76c0bc402f 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, false, false, false, false) +IMPLEMENT_CLASS(AArtiTeleport, false, false) bool AArtiTeleport::Use (bool pickup) { diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index dd4e4a8b81..cd0ab2669b 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -31,7 +31,7 @@ void P_MinotaurSlam (AActor *source, AActor *target); DECLARE_ACTION(A_MinotaurLook) -IMPLEMENT_CLASS(AMinotaur, false, false, false, false) +IMPLEMENT_CLASS(AMinotaur, false, false) void AMinotaur::Tick () { @@ -72,7 +72,7 @@ int AMinotaur::DoSpecialDamage (AActor *target, int damage, FName damagetype) // Minotaur Friend ---------------------------------------------------------- -IMPLEMENT_CLASS(AMinotaurFriend, false, false, false, false) +IMPLEMENT_CLASS(AMinotaurFriend, false, false) void AMinotaurFriend::BeginPlay () { diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index a371e4ad51..3938a9743f 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -28,7 +28,7 @@ public: void Deactivate (AActor *activator); }; -IMPLEMENT_CLASS(ASwitchableDecoration, false, false, false, false) +IMPLEMENT_CLASS(ASwitchableDecoration, false, false) void ASwitchableDecoration::Activate (AActor *activator) { @@ -49,7 +49,7 @@ public: void Deactivate (AActor *activator) {} }; -IMPLEMENT_CLASS(ASwitchingDecoration, false, false, false, false) +IMPLEMENT_CLASS(ASwitchingDecoration, false, false) //---------------------------------------------------------------------------- // @@ -295,7 +295,7 @@ class DCorpsePointer : public DThinker HAS_OBJECT_POINTERS public: DCorpsePointer (AActor *ptr); - void Destroy (); + void Destroy() override; void Serialize(FSerializer &arc); TObjPtr Corpse; DWORD Count; // Only the first corpse pointer's count is valid. @@ -303,7 +303,7 @@ private: DCorpsePointer () {} }; -IMPLEMENT_CLASS(DCorpsePointer, false, true, false, false) +IMPLEMENT_CLASS(DCorpsePointer, false, true) IMPLEMENT_POINTERS_START(DCorpsePointer) IMPLEMENT_POINTER(Corpse) diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index e1dd0986e7..6be1472bfc 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -9,11 +9,11 @@ #include "serializer.h" #include "cmdlib.h" -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, true, false) -IMPLEMENT_CLASS(AHexenArmor, false, false, false, false) +IMPLEMENT_CLASS(AArmor, false, false) +IMPLEMENT_CLASS(ABasicArmor, false, false) +IMPLEMENT_CLASS(ABasicArmorPickup, false, false) +IMPLEMENT_CLASS(ABasicArmorBonus, false, false) +IMPLEMENT_CLASS(AHexenArmor, false, false) DEFINE_FIELD(ABasicArmor, AbsorbCount) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index bf24c8eb85..73b71e2ffb 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, false, false, false, false) +IMPLEMENT_CLASS(APowerup, false, false) // Powerup-Giver ------------------------------------------------------------- -IMPLEMENT_CLASS(PClassPowerupGiver, false, false, false, false) +IMPLEMENT_CLASS(PClassPowerupGiver, false, false) void PClassPowerupGiver::ReplaceClassRef(PClass *oldclass, PClass *newclass) { @@ -388,7 +388,7 @@ bool APowerup::GetNoTeleportFreeze () // Invulnerability Powerup --------------------------------------------------- -IMPLEMENT_CLASS(APowerInvulnerable, false, false, false, false) +IMPLEMENT_CLASS(APowerInvulnerable, false, false) //=========================================================================== // @@ -525,7 +525,7 @@ int APowerInvulnerable::AlterWeaponSprite (visstyle_t *vis) // Strength (aka Berserk) Powerup -------------------------------------------- -IMPLEMENT_CLASS(APowerStrength, false, false, false, false) +IMPLEMENT_CLASS(APowerStrength, false, false) //=========================================================================== // @@ -590,7 +590,7 @@ PalEntry APowerStrength::GetBlend () // Invisibility Powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerInvisibility, false, false, false, false) +IMPLEMENT_CLASS(APowerInvisibility, false, false) // Invisibility flag combos #define INVISIBILITY_FLAGS1 (MF_SHADOW) @@ -795,7 +795,7 @@ bool APowerInvisibility::HandlePickup (AInventory *item) // Ironfeet Powerup ---------------------------------------------------------- -IMPLEMENT_CLASS(APowerIronFeet, false, false, false, false) +IMPLEMENT_CLASS(APowerIronFeet, false, false) //=========================================================================== // @@ -832,7 +832,7 @@ void APowerIronFeet::DoEffect () // Strife Environment Suit Powerup ------------------------------------------- -IMPLEMENT_CLASS(APowerMask, false, false, false, false) +IMPLEMENT_CLASS(APowerMask, false, false) //=========================================================================== // @@ -869,7 +869,7 @@ void APowerMask::DoEffect () // Light-Amp Powerup --------------------------------------------------------- -IMPLEMENT_CLASS(APowerLightAmp, false, false, false, false) +IMPLEMENT_CLASS(APowerLightAmp, false, false) //=========================================================================== // @@ -911,7 +911,7 @@ void APowerLightAmp::EndEffect () // Torch Powerup ------------------------------------------------------------- -IMPLEMENT_CLASS(APowerTorch, false, false, false, false) +IMPLEMENT_CLASS(APowerTorch, false, false) //=========================================================================== // @@ -974,7 +974,7 @@ void APowerTorch::DoEffect () // Flight (aka Wings of Wrath) powerup --------------------------------------- -IMPLEMENT_CLASS(APowerFlight, false, false, false, false) +IMPLEMENT_CLASS(APowerFlight, false, false) //=========================================================================== // @@ -1114,7 +1114,7 @@ bool APowerFlight::DrawPowerup (int x, int y) // Weapon Level 2 (aka Tome of Power) Powerup -------------------------------- -IMPLEMENT_CLASS(APowerWeaponLevel2, false, false, false, false) +IMPLEMENT_CLASS(APowerWeaponLevel2, false, false) //=========================================================================== // @@ -1198,7 +1198,7 @@ void APowerWeaponLevel2::EndEffect () // Speed Powerup ------------------------------------------------------------- -IMPLEMENT_CLASS(APowerSpeed, false, false, false, false) +IMPLEMENT_CLASS(APowerSpeed, false, false) DEFINE_FIELD(APowerSpeed, SpeedFlags) @@ -1287,11 +1287,11 @@ void APowerSpeed::DoEffect () // Minotaur (aka Dark Servant) powerup --------------------------------------- -IMPLEMENT_CLASS(APowerMinotaur, false, false, false, false) +IMPLEMENT_CLASS(APowerMinotaur, false, false) // Targeter powerup --------------------------------------------------------- -IMPLEMENT_CLASS(APowerTargeter, false, false, false, false) +IMPLEMENT_CLASS(APowerTargeter, false, false) void APowerTargeter::Travelled () { @@ -1406,7 +1406,7 @@ void APowerTargeter::PositionAccuracy () // Frightener Powerup -------------------------------- -IMPLEMENT_CLASS(APowerFrightener, false, false, false, false) +IMPLEMENT_CLASS(APowerFrightener, false, false) //=========================================================================== // @@ -1442,7 +1442,7 @@ void APowerFrightener::EndEffect () // Buddha Powerup -------------------------------- -IMPLEMENT_CLASS(APowerBuddha, false, false, false, false) +IMPLEMENT_CLASS(APowerBuddha, false, false) //=========================================================================== // @@ -1478,11 +1478,11 @@ void APowerBuddha::EndEffect () // Scanner powerup ---------------------------------------------------------- -IMPLEMENT_CLASS(APowerScanner, false, false, false, false) +IMPLEMENT_CLASS(APowerScanner, false, false) // Time freezer powerup ----------------------------------------------------- -IMPLEMENT_CLASS( APowerTimeFreezer, false, false, false, false) +IMPLEMENT_CLASS( APowerTimeFreezer, false, false) //=========================================================================== // @@ -1609,7 +1609,7 @@ void APowerTimeFreezer::EndEffect() // Damage powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerDamage, false, false, false, false) +IMPLEMENT_CLASS(APowerDamage, false, false) //=========================================================================== // @@ -1666,7 +1666,7 @@ void APowerDamage::ModifyDamage(int damage, FName damageType, int &newdamage, bo // Quarter damage powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerProtection, false, false, false, false) +IMPLEMENT_CLASS(APowerProtection, false, false) #define PROTECTION_FLAGS3 (MF3_NORADIUSDMG | MF3_DONTMORPH | MF3_DONTSQUASH | MF3_DONTBLAST | MF3_NOTELEOTHER) #define PROTECTION_FLAGS5 (MF5_NOPAIN | MF5_DONTRIP) @@ -1744,7 +1744,7 @@ void APowerProtection::ModifyDamage(int damage, FName damageType, int &newdamage // Drain rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerDrain, false, false, false, false) +IMPLEMENT_CLASS(APowerDrain, false, false) //=========================================================================== // @@ -1784,7 +1784,7 @@ void APowerDrain::EndEffect( ) // Regeneration rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerRegeneration, false, false, false, false) +IMPLEMENT_CLASS(APowerRegeneration, false, false) //=========================================================================== // @@ -1806,7 +1806,7 @@ void APowerRegeneration::DoEffect() // High jump rune ------------------------------------------------------- -IMPLEMENT_CLASS(APowerHighJump, false, false, false, false) +IMPLEMENT_CLASS(APowerHighJump, false, false) //=========================================================================== // @@ -1844,7 +1844,7 @@ void APowerHighJump::EndEffect( ) // Double firing speed rune --------------------------------------------- -IMPLEMENT_CLASS(APowerDoubleFiringSpeed, false, false, false, false) +IMPLEMENT_CLASS(APowerDoubleFiringSpeed, false, false) //=========================================================================== // @@ -1882,7 +1882,7 @@ void APowerDoubleFiringSpeed::EndEffect( ) // Morph powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerMorph, false, false, false, false) +IMPLEMENT_CLASS(APowerMorph, false, false) DEFINE_FIELD(APowerMorph, PlayerClass) DEFINE_FIELD(APowerMorph, MorphFlash) @@ -1990,7 +1990,7 @@ void APowerMorph::EndEffect( ) // Infinite Ammo Powerup ----------------------------------------------------- -IMPLEMENT_CLASS(APowerInfiniteAmmo, false, false, false, false) +IMPLEMENT_CLASS(APowerInfiniteAmmo, false, false) //=========================================================================== // diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index d9629c1653..95de950867 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -12,7 +12,7 @@ class APowerup : public AInventory DECLARE_CLASS (APowerup, AInventory) public: virtual void Tick (); - virtual void Destroy (); + virtual void Destroy () override; virtual bool HandlePickup (AInventory *item); virtual AInventory *CreateCopy (AActor *other); virtual AInventory *CreateTossable (); diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index c4b452f770..556767f373 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -37,10 +37,10 @@ class ACustomBridge : public AActor DECLARE_CLASS (ACustomBridge, AActor) public: void BeginPlay (); - void Destroy(); + void Destroy() override; }; -IMPLEMENT_CLASS(ACustomBridge, false, false, false, false) +IMPLEMENT_CLASS(ACustomBridge, false, false) void ACustomBridge::BeginPlay () { @@ -155,7 +155,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(AInvisibleBridge, false, false, false, false) +IMPLEMENT_CLASS(AInvisibleBridge, false, false) void AInvisibleBridge::BeginPlay () { diff --git a/src/g_shared/a_camera.cpp b/src/g_shared/a_camera.cpp index ae34c3cbc3..a0bc40ce33 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, false, false, false, false) +IMPLEMENT_CLASS(ASecurityCamera, false, false) void ASecurityCamera::Serialize(FSerializer &arc) { @@ -124,7 +124,7 @@ protected: DAngle MaxPitchChange; }; -IMPLEMENT_CLASS(AAimingCamera, false, false, false, false) +IMPLEMENT_CLASS(AAimingCamera, false, false) void AAimingCamera::Serialize(FSerializer &arc) { diff --git a/src/g_shared/a_debris.cpp b/src/g_shared/a_debris.cpp index d3d69d7f6b..0932088c2d 100644 --- a/src/g_shared/a_debris.cpp +++ b/src/g_shared/a_debris.cpp @@ -23,5 +23,5 @@ public: } }; -IMPLEMENT_CLASS(AGlassShard, false, false, false, false) +IMPLEMENT_CLASS(AGlassShard, false, false) diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index 06563f9954..bfbe6d13d2 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -58,14 +58,14 @@ static int ImpactCount; CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE) -IMPLEMENT_CLASS(DBaseDecal, false, true, false, false) +IMPLEMENT_CLASS(DBaseDecal, false, true) IMPLEMENT_POINTERS_START(DBaseDecal) IMPLEMENT_POINTER(WallPrev) IMPLEMENT_POINTER(WallNext) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(DImpactDecal, false, false, false, false) +IMPLEMENT_CLASS(DImpactDecal, false, false) DBaseDecal::DBaseDecal () : DThinker(STAT_DECAL), @@ -746,7 +746,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(ADecal, false, false, false, false) +IMPLEMENT_CLASS(ADecal, false, false) void ADecal::BeginPlay () { diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index 1ded466a9e..c68fa800c1 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -8,7 +8,7 @@ #include "p_checkposition.h" #include "virtual.h" -IMPLEMENT_CLASS(AFastProjectile, false, false, false, false) +IMPLEMENT_CLASS(AFastProjectile, false, false) //---------------------------------------------------------------------------- @@ -135,11 +135,13 @@ void AFastProjectile::Tick () ripcount = count >> 3; // call the scripted 'Effect' method. - VINDEX(AFastProjectile, Effect); - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); + IFVIRTUAL(AFastProjectile, Effect) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } } } } diff --git a/src/g_shared/a_flashfader.cpp b/src/g_shared/a_flashfader.cpp index 8602f7a864..3e0b939e0f 100644 --- a/src/g_shared/a_flashfader.cpp +++ b/src/g_shared/a_flashfader.cpp @@ -3,7 +3,7 @@ #include "d_player.h" #include "serializer.h" -IMPLEMENT_CLASS(DFlashFader, false, true, false, false) +IMPLEMENT_CLASS(DFlashFader, false, true) IMPLEMENT_POINTERS_START(DFlashFader) IMPLEMENT_POINTER(ForWho) diff --git a/src/g_shared/a_fountain.cpp b/src/g_shared/a_fountain.cpp index e89745fc79..7d7e2e412f 100644 --- a/src/g_shared/a_fountain.cpp +++ b/src/g_shared/a_fountain.cpp @@ -46,13 +46,13 @@ public: void Deactivate (AActor *activator); }; -IMPLEMENT_CLASS(AParticleFountain, false, false, false, false) +IMPLEMENT_CLASS(AParticleFountain, false, false) void AParticleFountain::PostBeginPlay () { Super::PostBeginPlay (); if (!(SpawnFlags & MTF_DORMANT)) - Activate (NULL); + CallActivate (NULL); } void AParticleFountain::Activate (AActor *activator) diff --git a/src/g_shared/a_hatetarget.cpp b/src/g_shared/a_hatetarget.cpp index 7d25bdb31d..8d5b0fa725 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, false, false, false, false) +IMPLEMENT_CLASS(AHateTarget, false, false) void AHateTarget::BeginPlay() { diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index 538e26090f..51962c1b08 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, false, false, false, false) +IMPLEMENT_CLASS(AKey, false, false) DEFINE_FIELD(AKey, KeyNumber) diff --git a/src/g_shared/a_lightning.cpp b/src/g_shared/a_lightning.cpp index f00560fc80..3f44f2fddd 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, false, false, false, false) +IMPLEMENT_CLASS(DLightningThinker, false, false) DLightningThinker::DLightningThinker () : DThinker (STAT_LIGHTNING) diff --git a/src/g_shared/a_mapmarker.cpp b/src/g_shared/a_mapmarker.cpp index d874042c5f..524bfca44f 100644 --- a/src/g_shared/a_mapmarker.cpp +++ b/src/g_shared/a_mapmarker.cpp @@ -51,7 +51,7 @@ // //-------------------------------------------------------------------------- -IMPLEMENT_CLASS(AMapMarker, false, false, false, false) +IMPLEMENT_CLASS(AMapMarker, false, false) void AMapMarker::BeginPlay () { diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 84de5a0d6e..5514ae4137 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, false, false, false, false) +IMPLEMENT_CLASS(AMorphProjectile, false, false) DEFINE_FIELD(AMorphProjectile, PlayerClass) DEFINE_FIELD(AMorphProjectile, MonsterClass) @@ -653,7 +653,7 @@ void AMorphProjectile::Serialize(FSerializer &arc) // Morphed Monster (you must subclass this to do something useful) --------- -IMPLEMENT_CLASS(AMorphedMonster, false, true, false, false) +IMPLEMENT_CLASS(AMorphedMonster, false, true) IMPLEMENT_POINTERS_START(AMorphedMonster) IMPLEMENT_POINTER(UnmorphedMe) diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index 030f5d3683..a1ffe5dc60 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -66,7 +66,7 @@ public: TObjPtr Next; }; -IMPLEMENT_CLASS(AInterpolationPoint, false, true, false, false) +IMPLEMENT_CLASS(AInterpolationPoint, false, true) IMPLEMENT_POINTERS_START(AInterpolationPoint) IMPLEMENT_POINTER(Next) @@ -135,7 +135,7 @@ public: void Tick () {} // Does absolutely nothing itself }; -IMPLEMENT_CLASS(AInterpolationSpecial, false, false, false, false) +IMPLEMENT_CLASS(AInterpolationSpecial, false, false) /* == PathFollower: something that follows a camera path @@ -178,7 +178,7 @@ protected: int HoldTime; }; -IMPLEMENT_CLASS(APathFollower, false, true, false, false) +IMPLEMENT_CLASS(APathFollower, false, true) IMPLEMENT_POINTERS_START(APathFollower) IMPLEMENT_POINTER(PrevNode) @@ -342,9 +342,9 @@ void APathFollower::Tick () if (CurrNode != NULL) NewNode (); if (CurrNode == NULL || CurrNode->Next == NULL) - Deactivate (this); + CallDeactivate (this); if ((args[2] & 1) == 0 && CurrNode->Next->Next == NULL) - Deactivate (this); + CallDeactivate (this); } } } @@ -480,7 +480,7 @@ protected: bool Interpolate (); }; -IMPLEMENT_CLASS(AActorMover, false, false, false, false) +IMPLEMENT_CLASS(AActorMover, false, false) void AActorMover::BeginPlay() { @@ -596,7 +596,7 @@ protected: TObjPtr Activator; }; -IMPLEMENT_CLASS(AMovingCamera, false, true, false, false) +IMPLEMENT_CLASS(AMovingCamera, false, true) IMPLEMENT_POINTERS_START(AMovingCamera) IMPLEMENT_POINTER(Activator) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index c6475cc743..16a63a2ff4 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -23,7 +23,7 @@ static FRandom pr_restore ("RestorePos"); -IMPLEMENT_CLASS(PClassInventory, false, false, false, false) +IMPLEMENT_CLASS(PClassInventory, false, false) PClassInventory::PClassInventory() { @@ -70,7 +70,7 @@ void PClassInventory::Finalize(FStateDefinitions &statedef) ((AActor*)Defaults)->flags |= MF_SPECIAL; } -IMPLEMENT_CLASS(PClassAmmo, false, false, false, false) +IMPLEMENT_CLASS(PClassAmmo, false, false) PClassAmmo::PClassAmmo() { @@ -86,7 +86,7 @@ void PClassAmmo::DeriveData(PClass *newclass) newc->DropAmount = DropAmount; } -IMPLEMENT_CLASS(AAmmo, false, false, false, false) +IMPLEMENT_CLASS(AAmmo, false, false) DEFINE_FIELD(AAmmo, BackpackAmount) DEFINE_FIELD(AAmmo, BackpackMaxAmount) @@ -480,7 +480,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) int AInventory::StaticLastMessageTic; const char *AInventory::StaticLastMessage; -IMPLEMENT_CLASS(AInventory, false, true, false, false) +IMPLEMENT_CLASS(AInventory, false, true) IMPLEMENT_POINTERS_START(AInventory) IMPLEMENT_POINTER(Owner) @@ -1378,7 +1378,7 @@ bool AInventory::DrawPowerup (int x, int y) /* AArtifact implementation */ /***************************************************************************/ -IMPLEMENT_CLASS(APowerupGiver, false, false, false, false) +IMPLEMENT_CLASS(APowerupGiver, false, false) //=========================================================================== // @@ -1679,8 +1679,8 @@ void AInventory::DetachFromOwner () { } -IMPLEMENT_CLASS(AStateProvider, false, false, false, false) -IMPLEMENT_CLASS(ACustomInventory, false, false, false, false) +IMPLEMENT_CLASS(AStateProvider, false, false) +IMPLEMENT_CLASS(ACustomInventory, false, false) //=========================================================================== // @@ -1725,7 +1725,7 @@ bool ACustomInventory::TryPickup (AActor *&toucher) return useok; } -IMPLEMENT_CLASS(PClassHealth, false, false, false, false) +IMPLEMENT_CLASS(PClassHealth, false, false) //=========================================================================== // @@ -1754,7 +1754,7 @@ void PClassHealth::DeriveData(PClass *newclass) newc->LowHealthMessage = LowHealthMessage; } -IMPLEMENT_CLASS(AHealth, false, false, false, false) +IMPLEMENT_CLASS(AHealth, false, false) DEFINE_FIELD(AHealth, PrevHealth) @@ -1799,7 +1799,7 @@ bool AHealth::TryPickup (AActor *&other) return false; } -IMPLEMENT_CLASS(AHealthPickup, false, false, false, false) +IMPLEMENT_CLASS(AHealthPickup, false, false) DEFINE_FIELD(AHealthPickup, autousemode) @@ -1879,7 +1879,7 @@ void AHealthPickup::Serialize(FSerializer &arc) // Backpack ----------------------------------------------------------------- -IMPLEMENT_CLASS(ABackpackItem, false, false, false, false) +IMPLEMENT_CLASS(ABackpackItem, false, false) DEFINE_FIELD(ABackpackItem, bDepleted) @@ -2058,7 +2058,7 @@ void ABackpackItem::DetachFromOwner () // //=========================================================================== -IMPLEMENT_CLASS(AMapRevealer, false, false, false, false) +IMPLEMENT_CLASS(AMapRevealer, false, false) //=========================================================================== // @@ -2083,7 +2083,7 @@ bool AMapRevealer::TryPickup (AActor *&toucher) // //=========================================================================== -IMPLEMENT_CLASS(AScoreItem, false, false, false, false) +IMPLEMENT_CLASS(AScoreItem, false, false) //=========================================================================== // diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index ec34404df2..bf4af5a635 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -159,7 +159,7 @@ public: virtual void MarkPrecacheSounds() const; virtual void BeginPlay (); - virtual void Destroy (); + virtual void Destroy () override; virtual void DepleteOrDestroy (); virtual void Tick (); virtual bool ShouldRespawn (); @@ -331,7 +331,7 @@ public: virtual bool TryPickupRestricted (AActor *&toucher); virtual bool PickupForAmmo (AWeapon *ownedWeapon); virtual bool Use (bool pickup); - virtual void Destroy(); + virtual void Destroy() override; virtual FState *GetUpState (); virtual FState *GetDownState (); diff --git a/src/g_shared/a_puzzleitems.cpp b/src/g_shared/a_puzzleitems.cpp index 640d5517da..0d63bb00c3 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, false, false, false, false) +IMPLEMENT_CLASS(PClassPuzzleItem, false, false) void PClassPuzzleItem::DeriveData(PClass *newclass) { @@ -17,7 +17,7 @@ void PClassPuzzleItem::DeriveData(PClass *newclass) static_cast(newclass)->PuzzFailMessage = PuzzFailMessage; } -IMPLEMENT_CLASS(APuzzleItem, false, false, false, false) +IMPLEMENT_CLASS(APuzzleItem, false, false) DEFINE_FIELD(APuzzleItem, PuzzleItemNumber) diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 80a53ee080..96a932d4f4 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -14,7 +14,7 @@ static FRandom pr_quake ("Quake"); -IMPLEMENT_CLASS(DEarthquake, false, true, false, false) +IMPLEMENT_CLASS(DEarthquake, false, true) IMPLEMENT_POINTERS_START(DEarthquake) IMPLEMENT_POINTER(m_Spot) diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index 40fdd0745f..0cecfd1154 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -230,4 +230,4 @@ class ARandomSpawner : public AActor }; -IMPLEMENT_CLASS(ARandomSpawner, false, false, false, false) +IMPLEMENT_CLASS(ARandomSpawner, false, false) diff --git a/src/g_shared/a_secrettrigger.cpp b/src/g_shared/a_secrettrigger.cpp index 372cef07d8..509ec47e92 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, false, false, false, false) +IMPLEMENT_CLASS(ASecretTrigger, false, false) void ASecretTrigger::PostBeginPlay () { diff --git a/src/g_shared/a_sectoraction.cpp b/src/g_shared/a_sectoraction.cpp index 61a69b1b39..2d70375510 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, false, false, false, false) +IMPLEMENT_CLASS(ASectorAction, false, false) ASectorAction::ASectorAction (bool activatedByUse) : ActivatedByUse (activatedByUse) {} @@ -142,7 +142,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEnter, false, false, false, false) +IMPLEMENT_CLASS(ASecActEnter, false, false) bool ASecActEnter::DoTriggerAction (AActor *triggerer, int activationType) @@ -160,7 +160,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActExit, false, false, false, false) +IMPLEMENT_CLASS(ASecActExit, false, false) bool ASecActExit::DoTriggerAction (AActor *triggerer, int activationType) @@ -181,7 +181,7 @@ 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, false, false, false, false) +IMPLEMENT_CLASS(ASecActHitFloor, false, false) bool ASecActHitFloor::DoTriggerAction (AActor *triggerer, int activationType) @@ -199,7 +199,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActHitCeil, false, false, false, false) +IMPLEMENT_CLASS(ASecActHitCeil, false, false) bool ASecActHitCeil::DoTriggerAction (AActor *triggerer, int activationType) @@ -218,7 +218,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActUse, false, false, false, false) +IMPLEMENT_CLASS(ASecActUse, false, false) bool ASecActUse::DoTriggerAction (AActor *triggerer, int activationType) @@ -237,7 +237,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActUseWall, false, false, false, false) +IMPLEMENT_CLASS(ASecActUseWall, false, false) bool ASecActUseWall::DoTriggerAction (AActor *triggerer, int activationType) @@ -255,7 +255,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEyesDive, false, false, false, false) +IMPLEMENT_CLASS(ASecActEyesDive, false, false) bool ASecActEyesDive::DoTriggerAction (AActor *triggerer, int activationType) @@ -273,7 +273,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEyesSurface, false, false, false, false) +IMPLEMENT_CLASS(ASecActEyesSurface, false, false) bool ASecActEyesSurface::DoTriggerAction (AActor *triggerer, int activationType) @@ -291,7 +291,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEyesBelowC, false, false, false, false) +IMPLEMENT_CLASS(ASecActEyesBelowC, false, false) bool ASecActEyesBelowC::DoTriggerAction (AActor *triggerer, int activationType) @@ -309,7 +309,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActEyesAboveC, false, false, false, false) +IMPLEMENT_CLASS(ASecActEyesAboveC, false, false) bool ASecActEyesAboveC::DoTriggerAction (AActor *triggerer, int activationType) @@ -327,7 +327,7 @@ public: bool DoTriggerAction (AActor *triggerer, int activationType); }; -IMPLEMENT_CLASS(ASecActHitFakeFloor, false, false, false, false) +IMPLEMENT_CLASS(ASecActHitFakeFloor, 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 585b9fcf61..e8a11b850b 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, false, false, false, false) +IMPLEMENT_CLASS(AColorSetter, false, false) class AFadeSetter : public AActor { @@ -30,4 +30,4 @@ class AFadeSetter : public AActor }; -IMPLEMENT_CLASS(AFadeSetter, false, false, false, false) +IMPLEMENT_CLASS(AFadeSetter, false, false) diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index bb85a023c2..a690107c90 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -24,7 +24,7 @@ public: DBaseDecal (const DBaseDecal *basis); void Serialize(FSerializer &arc); - void Destroy (); + void Destroy() override; FTextureID StickToWall(side_t *wall, double x, double y, F3DFloor * ffloor); double GetRealZ (const side_t *wall) const; void SetShade (DWORD rgb); @@ -66,7 +66,7 @@ public: static DImpactDecal *StaticCreate(const FDecalTemplate *tpl, const DVector3 &pos, side_t *wall, F3DFloor * ffloor, PalEntry color = 0); void BeginPlay (); - void Destroy (); + void Destroy() override; protected: DBaseDecal *CloneSelf(const FDecalTemplate *tpl, double x, double y, double z, side_t *wall, F3DFloor * ffloor) const; @@ -88,7 +88,7 @@ class ASkyViewpoint : public AActor DECLARE_CLASS (ASkyViewpoint, AActor) public: void BeginPlay (); - void Destroy (); + void Destroy() override; }; // For an EE compatible linedef based definition. @@ -116,7 +116,7 @@ public: DFlashFader (float r1, float g1, float b1, float a1, float r2, float g2, float b2, float a2, float time, AActor *who); - void Destroy (); + void Destroy() override; void Serialize(FSerializer &arc); void Tick (); AActor *WhoFor() { return ForWho; } @@ -206,7 +206,7 @@ public: void Serialize(FSerializer &arc); void Die (AActor *source, AActor *inflictor, int dmgflags); - void Destroy (); + void Destroy() override; TObjPtr UnmorphedMe; int UnmorphTime, MorphStyle; diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 148a452e0c..d42324936b 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, false, false, false, false) +IMPLEMENT_CLASS(ASkyViewpoint, 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, false, false, false, false) +IMPLEMENT_CLASS(ASkyCamCompat, false, false) void ASkyCamCompat::BeginPlay() { @@ -98,7 +98,7 @@ public: void PostBeginPlay (); }; -IMPLEMENT_CLASS(ASkyPicker, false, false, false, false) +IMPLEMENT_CLASS(ASkyPicker, false, false) void ASkyPicker::PostBeginPlay () { @@ -142,7 +142,7 @@ void ASkyPicker::PostBeginPlay () // arg0 = opacity of plane; 0 = invisible, 255 = fully opaque -IMPLEMENT_CLASS(AStackPoint, false, false, false, false) +IMPLEMENT_CLASS(AStackPoint, false, false) void AStackPoint::BeginPlay () { @@ -157,10 +157,10 @@ class ASectorSilencer : public AActor DECLARE_CLASS (ASectorSilencer, AActor) public: void BeginPlay (); - void Destroy (); + void Destroy() override; }; -IMPLEMENT_CLASS(ASectorSilencer, false, false, false, false) +IMPLEMENT_CLASS(ASectorSilencer, false, false) void ASectorSilencer::BeginPlay () { @@ -184,7 +184,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(ASectorFlagSetter, false, false, false, false) +IMPLEMENT_CLASS(ASectorFlagSetter, false, false) void ASectorFlagSetter::BeginPlay () { diff --git a/src/g_shared/a_soundenvironment.cpp b/src/g_shared/a_soundenvironment.cpp index 8e5cb133b5..25088ae448 100644 --- a/src/g_shared/a_soundenvironment.cpp +++ b/src/g_shared/a_soundenvironment.cpp @@ -46,14 +46,14 @@ public: void Activate (AActor *deactivator); }; -IMPLEMENT_CLASS(ASoundEnvironment, false, false, false, false) +IMPLEMENT_CLASS(ASoundEnvironment, false, false) void ASoundEnvironment::PostBeginPlay () { Super::PostBeginPlay (); if (!(flags2 & MF2_DORMANT)) { - Activate (this); + CallActivate (this); } } diff --git a/src/g_shared/a_soundsequence.cpp b/src/g_shared/a_soundsequence.cpp index 25380a4c73..304017fbad 100644 --- a/src/g_shared/a_soundsequence.cpp +++ b/src/g_shared/a_soundsequence.cpp @@ -80,7 +80,7 @@ public: TObjPtr Sequence; }; -IMPLEMENT_CLASS(ASoundSequenceSlot, false, true, false, false) +IMPLEMENT_CLASS(ASoundSequenceSlot, false, true) IMPLEMENT_POINTERS_START(ASoundSequenceSlot) IMPLEMENT_POINTER(Sequence) @@ -104,14 +104,14 @@ class ASoundSequence : public AActor { DECLARE_CLASS (ASoundSequence, AActor) public: - void Destroy (); + void Destroy() override; void PostBeginPlay (); void Activate (AActor *activator); void Deactivate (AActor *activator); void MarkPrecacheSounds () const; }; -IMPLEMENT_CLASS(ASoundSequence, false, false, false, false) +IMPLEMENT_CLASS(ASoundSequence, false, false) //========================================================================== // diff --git a/src/g_shared/a_spark.cpp b/src/g_shared/a_spark.cpp index 654ad710b1..f13c7178f7 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, false, false, false, false) +IMPLEMENT_CLASS(ASpark, false, false) void ASpark::Activate (AActor *activator) { diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 935333a5ce..026185d07a 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -44,8 +44,8 @@ static FRandom pr_spot ("SpecialSpot"); static FRandom pr_spawnmace ("SpawnMace"); -IMPLEMENT_CLASS(DSpotState, false, false, false, false) -IMPLEMENT_CLASS(ASpecialSpot, false, false, false, false) +IMPLEMENT_CLASS(DSpotState, false, false) +IMPLEMENT_CLASS(ASpecialSpot, false, false) TObjPtr DSpotState::SpotState; //---------------------------------------------------------------------------- diff --git a/src/g_shared/a_specialspot.h b/src/g_shared/a_specialspot.h index 8fe38608aa..57a643bdd8 100644 --- a/src/g_shared/a_specialspot.h +++ b/src/g_shared/a_specialspot.h @@ -11,7 +11,7 @@ class ASpecialSpot : public AActor public: void BeginPlay(); - void Destroy(); + void Destroy() override; }; @@ -28,7 +28,7 @@ public: DSpotState (); - void Destroy (); + void Destroy() override; void Tick (); static DSpotState *GetSpotState(bool create = true); FSpotList *FindSpotList(PClassActor *type); diff --git a/src/g_shared/a_waterzone.cpp b/src/g_shared/a_waterzone.cpp index 556d08d7a6..2245b22bd3 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, false, false, false, false) +IMPLEMENT_CLASS(AWaterZone, false, false) void AWaterZone::PostBeginPlay () { diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp index 9edae69069..52c9a9e388 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, false, false, false, false) -IMPLEMENT_CLASS(AWeaponHolder, false, false, false, false) +IMPLEMENT_CLASS(PClassWeaponPiece, false, false) +IMPLEMENT_CLASS(AWeaponHolder, false, false) DEFINE_FIELD(AWeaponHolder, PieceMask); DEFINE_FIELD(AWeaponHolder, PieceWeapon); @@ -27,7 +27,7 @@ void AWeaponHolder::Serialize(FSerializer &arc) ("pieceweapon", PieceWeapon); } -IMPLEMENT_CLASS(AWeaponPiece, false, true, false, false) +IMPLEMENT_CLASS(AWeaponPiece, false, true) IMPLEMENT_POINTERS_START(AWeaponPiece) IMPLEMENT_POINTER(FullWeapon) diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 530f8e3648..b94a4770ca 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -23,7 +23,7 @@ extern FFlagDef WeaponFlagDefs[]; -IMPLEMENT_CLASS(AWeapon, false, true, true, false) +IMPLEMENT_CLASS(AWeapon, false, true) IMPLEMENT_POINTERS_START(AWeapon) IMPLEMENT_POINTER(Ammo1) @@ -80,7 +80,7 @@ TMap Weapons_hton; static int ntoh_cmp(const void *a, const void *b); -IMPLEMENT_CLASS(PClassWeapon, false, false, false, false) +IMPLEMENT_CLASS(PClassWeapon, false, false) //=========================================================================== // @@ -866,7 +866,7 @@ FState *AWeapon::GetStateForButtonName (FName button) /* Weapon giver ***********************************************************/ -IMPLEMENT_CLASS(AWeaponGiver, false, false, false, false) +IMPLEMENT_CLASS(AWeaponGiver, false, false) DEFINE_FIELD(AWeaponGiver, DropAmmoFactor); diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index e9370ae793..0db6d4743a 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -44,15 +44,15 @@ EXTERN_CVAR(Int, con_scaletext) int active_con_scaletext(); -IMPLEMENT_CLASS(DHUDMessage, false, true, false, false) +IMPLEMENT_CLASS(DHUDMessage, false, true) 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) +IMPLEMENT_CLASS(DHUDMessageFadeOut, false, false) +IMPLEMENT_CLASS(DHUDMessageFadeInOut, false, false) +IMPLEMENT_CLASS(DHUDMessageTypeOnFadeOut, false, false) /************************************************************************* * Basic HUD message. Appears and disappears without any special effects * diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index 6d5b107394..7b7a2849ae 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -341,7 +341,7 @@ public: }; DBaseStatusBar (int reltop, int hres=320, int vres=200); - void Destroy (); + void Destroy() override; void SetScaled (bool scale, bool force=false); diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 3041013119..a005c1adae 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -1531,7 +1531,7 @@ private: SBarInfoMainBlock *lastPopup; }; -IMPLEMENT_CLASS(DSBarInfo, false, true, false, false) +IMPLEMENT_CLASS(DSBarInfo, false, true) IMPLEMENT_POINTERS_START(DSBarInfo) IMPLEMENT_POINTER(ammo1) diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 80d221cfc5..c288a05c86 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -62,7 +62,7 @@ #define XHAIRPICKUPSIZE (2+XHAIRSHRINKSIZE) #define POWERUPICONSIZE 32 -IMPLEMENT_CLASS(DBaseStatusBar, false, true, false, false) +IMPLEMENT_CLASS(DBaseStatusBar, false, true) IMPLEMENT_POINTERS_START(DBaseStatusBar) IMPLEMENT_POINTER(Messages[0]) diff --git a/src/g_strife/a_coin.cpp b/src/g_strife/a_coin.cpp index 87c4619d3c..53cc59f506 100644 --- a/src/g_strife/a_coin.cpp +++ b/src/g_strife/a_coin.cpp @@ -6,7 +6,7 @@ // Coin --------------------------------------------------------------------- -IMPLEMENT_CLASS(ACoin, false, false, false, false) +IMPLEMENT_CLASS(ACoin, false, false) const char *ACoin::PickupMessage () { diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp index 0f1bef7cca..747ba326af 100644 --- a/src/g_strife/a_loremaster.cpp +++ b/src/g_strife/a_loremaster.cpp @@ -17,7 +17,7 @@ public: int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; -IMPLEMENT_CLASS(ALoreShot, false, false, false, false) +IMPLEMENT_CLASS(ALoreShot, false, false) int ALoreShot::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp index c00e7fb011..07f6a6c4ca 100644 --- a/src/g_strife/a_programmer.cpp +++ b/src/g_strife/a_programmer.cpp @@ -23,7 +23,7 @@ public: PalEntry GetBlend (); }; -IMPLEMENT_CLASS(AProgLevelEnder, false, false, false, false) +IMPLEMENT_CLASS(AProgLevelEnder, false, false) //============================================================================ // diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index 7f21886bf2..d3d68153f3 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -47,7 +47,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(ATeleporterBeacon, false, false, false, false) +IMPLEMENT_CLASS(ATeleporterBeacon, false, false) bool ATeleporterBeacon::Use (bool pickup) { diff --git a/src/g_strife/a_spectral.cpp b/src/g_strife/a_spectral.cpp index c7012accff..4bd24bac7d 100644 --- a/src/g_strife/a_spectral.cpp +++ b/src/g_strife/a_spectral.cpp @@ -16,7 +16,7 @@ public: void Touch (AActor *toucher); }; -IMPLEMENT_CLASS(ASpectralMonster, false, false, false, false) +IMPLEMENT_CLASS(ASpectralMonster, false, false) void ASpectralMonster::Touch (AActor *toucher) { diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index c1b9d75d61..0586583ff5 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -19,7 +19,7 @@ */ // Degnin Ore --------------------------------------------------------------- -IMPLEMENT_CLASS(ADegninOre, false, false, false, false) +IMPLEMENT_CLASS(ADegninOre, false, false) DEFINE_ACTION_FUNCTION(AActor, A_RemoveForceField) { @@ -75,7 +75,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS(AHealthTraining, false, false, false, false) +IMPLEMENT_CLASS(AHealthTraining, false, false) bool AHealthTraining::TryPickup (AActor *&toucher) { @@ -105,7 +105,7 @@ public: bool Use (bool pickup); }; -IMPLEMENT_CLASS(AScanner, false, false, false, false) +IMPLEMENT_CLASS(AScanner, false, false) bool AScanner::Use (bool pickup) { @@ -130,7 +130,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS(APrisonPass, false, false, false, false) +IMPLEMENT_CLASS(APrisonPass, false, false) bool APrisonPass::TryPickup (AActor *&toucher) { @@ -163,7 +163,7 @@ bool APrisonPass::SpecialDropAction (AActor *dropper) // actions and cannot be held. ---------------------------------------------- //--------------------------------------------------------------------------- -IMPLEMENT_CLASS(ADummyStrifeItem, false, false, false, false) +IMPLEMENT_CLASS(ADummyStrifeItem, false, false) // Sound the alarm! --------------------------------------------------------- @@ -175,7 +175,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS(ARaiseAlarm, false, false, false, false) +IMPLEMENT_CLASS(ARaiseAlarm, false, false) bool ARaiseAlarm::TryPickup (AActor *&toucher) { @@ -209,7 +209,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS(AOpenDoor222, false, false, false, false) +IMPLEMENT_CLASS(AOpenDoor222, false, false) bool AOpenDoor222::TryPickup (AActor *&toucher) { @@ -228,7 +228,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS(ACloseDoor222, false, false, false, false) +IMPLEMENT_CLASS(ACloseDoor222, false, false) bool ACloseDoor222::TryPickup (AActor *&toucher) { @@ -262,7 +262,7 @@ public: bool SpecialDropAction (AActor *dropper); }; -IMPLEMENT_CLASS(AOpenDoor224, false, false, false, false) +IMPLEMENT_CLASS(AOpenDoor224, false, false) bool AOpenDoor224::TryPickup (AActor *&toucher) { @@ -287,7 +287,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS(AAmmoFillup, false, false, false, false) +IMPLEMENT_CLASS(AAmmoFillup, false, false) bool AAmmoFillup::TryPickup (AActor *&toucher) { @@ -325,7 +325,7 @@ public: bool TryPickup (AActor *&toucher); }; -IMPLEMENT_CLASS(AHealthFillup, false, false, false, false) +IMPLEMENT_CLASS(AHealthFillup, false, false) bool AHealthFillup::TryPickup (AActor *&toucher) { @@ -342,7 +342,7 @@ bool AHealthFillup::TryPickup (AActor *&toucher) // Upgrade Stamina ---------------------------------------------------------- -IMPLEMENT_CLASS(AUpgradeStamina, false, false, false, false) +IMPLEMENT_CLASS(AUpgradeStamina, false, false) bool AUpgradeStamina::TryPickup (AActor *&toucher) { @@ -360,7 +360,7 @@ bool AUpgradeStamina::TryPickup (AActor *&toucher) // Upgrade Accuracy --------------------------------------------------------- -IMPLEMENT_CLASS(AUpgradeAccuracy, false, false, false, false) +IMPLEMENT_CLASS(AUpgradeAccuracy, false, false) bool AUpgradeAccuracy::TryPickup (AActor *&toucher) { @@ -373,7 +373,7 @@ bool AUpgradeAccuracy::TryPickup (AActor *&toucher) // Start a slideshow -------------------------------------------------------- -IMPLEMENT_CLASS(ASlideshowStarter, false, false, false, false) +IMPLEMENT_CLASS(ASlideshowStarter, false, false) bool ASlideshowStarter::TryPickup (AActor *&toucher) { diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 1580f127f4..7cccdd3f36 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -72,7 +72,7 @@ public: int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); }; -IMPLEMENT_CLASS(AForceFieldGuard, false, false, false, false) +IMPLEMENT_CLASS(AForceFieldGuard, false, false) int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) { @@ -197,7 +197,7 @@ public: void Die (AActor *source, AActor *inflictor, int dmgflags); }; -IMPLEMENT_CLASS(APowerCoupling, false, false, false, false) +IMPLEMENT_CLASS(APowerCoupling, false, false) void APowerCoupling::Die (AActor *source, AActor *inflictor, int dmgflags) { @@ -239,7 +239,7 @@ public: } }; -IMPLEMENT_CLASS(AMeat, false, false, false, false) +IMPLEMENT_CLASS(AMeat, false, false) //========================================================================== // diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 56eb06597c..0268682f33 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -184,7 +184,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(APoisonBolt, false, false, false, false) +IMPLEMENT_CLASS(APoisonBolt, false, false) int APoisonBolt::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -607,7 +607,7 @@ public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); }; -IMPLEMENT_CLASS(APhosphorousFire, false, false, false, false) +IMPLEMENT_CLASS(APhosphorousFire, false, false) int APhosphorousFire::DoSpecialDamage (AActor *target, int damage, FName damagetype) { @@ -734,7 +734,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireGrenade) // The Almighty Sigil! ------------------------------------------------------ -IMPLEMENT_CLASS(ASigil, false, false, false, false) +IMPLEMENT_CLASS(ASigil, false, false) //============================================================================ // diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 73e31e6765..39f92d0762 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -851,7 +851,7 @@ private: double ItemFlash; }; -IMPLEMENT_CLASS(DStrifeStatusBar, false, false, false, false); +IMPLEMENT_CLASS(DStrifeStatusBar, false, false); DBaseStatusBar *CreateStrifeStatusBar () { diff --git a/src/info.cpp b/src/info.cpp index fec5af63e0..8a2842ff45 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -151,7 +151,7 @@ int GetSpriteIndex(const char * spritename, bool add) return (lastindex = (int)sprites.Push (temp)); } -IMPLEMENT_CLASS(PClassActor, false, true, false, false) +IMPLEMENT_CLASS(PClassActor, false, true) IMPLEMENT_POINTERS_START(PClassActor) IMPLEMENT_POINTER(DropItems) diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index be8f58e19f..2aacd215b3 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -54,12 +54,12 @@ FIntermissionDescriptorList IntermissionDescriptors; -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_CLASS(DIntermissionScreen, false, false) +IMPLEMENT_CLASS(DIntermissionScreenFader, false, false) +IMPLEMENT_CLASS(DIntermissionScreenText, false, false) +IMPLEMENT_CLASS(DIntermissionScreenCast, false, false) +IMPLEMENT_CLASS(DIntermissionScreenScroller, false, false) +IMPLEMENT_CLASS(DIntermissionController, false, true) IMPLEMENT_POINTERS_START(DIntermissionController) IMPLEMENT_POINTER(mScreen) diff --git a/src/intermission/intermission.h b/src/intermission/intermission.h index 45779f895a..25b369a3ae 100644 --- a/src/intermission/intermission.h +++ b/src/intermission/intermission.h @@ -176,7 +176,7 @@ public: virtual int Responder (event_t *ev); virtual int Ticker (); virtual void Drawer (); - void Destroy(); + void Destroy() override; FTextureID GetBackground(bool *fill) { *fill = mFlatfill; @@ -301,7 +301,7 @@ public: bool Responder (event_t *ev); void Ticker (); void Drawer (); - void Destroy(); + void Destroy() override; friend void F_AdvanceIntermission(); }; diff --git a/src/m_argv.cpp b/src/m_argv.cpp index 7d82ed834c..3958859860 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, false, false, false, false) +IMPLEMENT_CLASS(DArgs, false, false) //=========================================================================== // diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index c53192ee7b..7ba40f957e 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -1033,7 +1033,7 @@ public: } }; -IMPLEMENT_CLASS(DSuicider, false, true, false, false) +IMPLEMENT_CLASS(DSuicider, false, true) IMPLEMENT_POINTERS_START(DSuicider) IMPLEMENT_POINTER(Pawn) diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp index 639c6bbef3..e1ee3566d8 100644 --- a/src/menu/colorpickermenu.cpp +++ b/src/menu/colorpickermenu.cpp @@ -95,7 +95,7 @@ public: desc->CalcIndent(); } - void Destroy() + void Destroy() override { if (mStartItem >= 0) { @@ -331,7 +331,7 @@ public: } }; -IMPLEMENT_CLASS(DColorPickerMenu, true, false, false, false) +IMPLEMENT_CLASS(DColorPickerMenu, true, false) CCMD(undocolorpic) { diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index cca13ad44c..f715dce4ae 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, false, false, false, false) +IMPLEMENT_CLASS(DJoystickConfigMenu, false, false) //============================================================================= // diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index 7fdd0c5bcf..455ea6c4bd 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, false, false, false, false) +IMPLEMENT_CLASS(DListMenu, false, false) //============================================================================= // diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 6d543228c4..73183ca220 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -103,7 +103,7 @@ protected: char savegamestring[SAVESTRINGSIZE]; DLoadSaveMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL); - void Destroy(); + void Destroy() override; int RemoveSaveSlot (int index); void UnloadSaveData (); @@ -119,7 +119,7 @@ public: }; -IMPLEMENT_CLASS(DLoadSaveMenu, false, false, false, false) +IMPLEMENT_CLASS(DLoadSaveMenu, false, false) TArray DLoadSaveMenu::SaveGames; int DLoadSaveMenu::LastSaved = -1; @@ -466,6 +466,7 @@ void DLoadSaveMenu::Destroy() if (currentSavePic != nullptr) delete currentSavePic; currentSavePic = nullptr; ClearSaveStuff (); + Super::Destroy(); } //============================================================================= @@ -927,14 +928,14 @@ class DSaveMenu : public DLoadSaveMenu public: DSaveMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL); - void Destroy(); + void Destroy() override; void DoSave (FSaveGameNode *node); bool Responder (event_t *ev); bool MenuEvent (int mkey, bool fromcontroller); }; -IMPLEMENT_CLASS(DSaveMenu, false, false, false, false) +IMPLEMENT_CLASS(DSaveMenu, false, false) //============================================================================= @@ -975,6 +976,7 @@ void DSaveMenu::Destroy() if (Selected == 0) Selected = -1; else Selected--; } + Super::Destroy(); } //============================================================================= @@ -1102,7 +1104,7 @@ public: bool MenuEvent (int mkey, bool fromcontroller); }; -IMPLEMENT_CLASS(DLoadMenu, false, false, false, false) +IMPLEMENT_CLASS(DLoadMenu, false, false) //============================================================================= diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 6648c32b4f..0c6019a5fb 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -91,7 +91,7 @@ static bool MenuEnabled = true; // //============================================================================ -IMPLEMENT_CLASS(DMenu, false, true, false, false) +IMPLEMENT_CLASS(DMenu, false, true) IMPLEMENT_POINTERS_START(DMenu) IMPLEMENT_POINTER(mParentMenu) diff --git a/src/menu/menuinput.cpp b/src/menu/menuinput.cpp index c33e9fed28..cca4756f5b 100644 --- a/src/menu/menuinput.cpp +++ b/src/menu/menuinput.cpp @@ -44,7 +44,7 @@ // [TP] New #includes #include "v_text.h" -IMPLEMENT_CLASS(DTextEnterMenu, true, false, false, false) +IMPLEMENT_CLASS(DTextEnterMenu, true, false) #define INPUTGRID_WIDTH 13 #define INPUTGRID_HEIGHT 5 diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index de8fa10272..c406fc7011 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -63,7 +63,7 @@ class DMessageBoxMenu : public DMenu public: DMessageBoxMenu(DMenu *parent = NULL, const char *message = NULL, int messagemode = 0, bool playsound = false, FName action = NAME_None); - void Destroy(); + void Destroy() override; void Init(DMenu *parent, const char *message, int messagemode, bool playsound = false); void Drawer(); bool Responder(event_t *ev); @@ -73,7 +73,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DMessageBoxMenu, false, false, false, false) +IMPLEMENT_CLASS(DMessageBoxMenu, false, false) //============================================================================= // @@ -128,6 +128,7 @@ void DMessageBoxMenu::Destroy() { if (mMessage != NULL) V_FreeBrokenLines(mMessage); mMessage = NULL; + Super::Destroy(); } //============================================================================= @@ -365,7 +366,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuitMenu, false, false, false, false) +IMPLEMENT_CLASS(DQuitMenu, false, false) //============================================================================= // @@ -458,7 +459,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DEndGameMenu, false, false, false, false) +IMPLEMENT_CLASS(DEndGameMenu, false, false) //============================================================================= // @@ -536,7 +537,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuickSaveMenu, false, false, false, false) +IMPLEMENT_CLASS(DQuickSaveMenu, false, false) //============================================================================= // @@ -632,7 +633,7 @@ public: virtual void HandleResult(bool res); }; -IMPLEMENT_CLASS(DQuickLoadMenu, false, false, false, false) +IMPLEMENT_CLASS(DQuickLoadMenu, false, false) //============================================================================= // diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index 1631c3d4b6..f9a29b6f53 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -64,7 +64,7 @@ void M_DrawConText (int color, int x, int y, const char *str) TAG_DONE); } -IMPLEMENT_CLASS(DOptionMenu, false, false, false, false) +IMPLEMENT_CLASS(DOptionMenu, false, false) //============================================================================= // @@ -578,7 +578,7 @@ public: } }; -IMPLEMENT_CLASS(DGameplayMenu, false, false, false, false) +IMPLEMENT_CLASS(DGameplayMenu, false, false) class DCompatibilityMenu : public DOptionMenu { @@ -600,4 +600,4 @@ public: } }; -IMPLEMENT_CLASS(DCompatibilityMenu, false, false, false, false) +IMPLEMENT_CLASS(DCompatibilityMenu, false, false) diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index e83f4ada41..c3cb7297a4 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -399,7 +399,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DEnterKey, true, false, false, false) +IMPLEMENT_CLASS(DEnterKey, true, false) #endif //============================================================================= diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index e32c7dd618..9f5196367a 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -526,7 +526,7 @@ public: void Drawer (); }; -IMPLEMENT_CLASS(DPlayerMenu, false, false, false, false) +IMPLEMENT_CLASS(DPlayerMenu, false, false) //============================================================================= // diff --git a/src/menu/readthis.cpp b/src/menu/readthis.cpp index 0dfc47e736..b8a3837ee0 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, false, false, false, false) +IMPLEMENT_CLASS(DReadThisMenu, false, false) //============================================================================= // diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 37f59149e6..d8edee8f1e 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -183,7 +183,7 @@ public: } }; -IMPLEMENT_CLASS(DVideoModeMenu, false, false, false, false) +IMPLEMENT_CLASS(DVideoModeMenu, false, false) //============================================================================= diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 96e20d0227..a5b8b977d4 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1368,7 +1368,7 @@ private: DPlaneWatcher() {} }; -IMPLEMENT_CLASS(DPlaneWatcher, false, true, false, false) +IMPLEMENT_CLASS(DPlaneWatcher, false, true) IMPLEMENT_POINTERS_START(DPlaneWatcher) IMPLEMENT_POINTER(Activator) @@ -2859,7 +2859,7 @@ void FBehavior::StaticStopMyScripts (AActor *actor) //---- The ACS Interpreter ----// -IMPLEMENT_CLASS(DACSThinker, false, true, false, false) +IMPLEMENT_CLASS(DACSThinker, false, true) IMPLEMENT_POINTERS_START(DACSThinker) IMPLEMENT_POINTER(LastScript) @@ -2990,7 +2990,7 @@ void DACSThinker::StopScriptsFor (AActor *actor) } } -IMPLEMENT_CLASS(DLevelScript, false, true, false, false) +IMPLEMENT_CLASS(DLevelScript, false, true) IMPLEMENT_POINTERS_START(DLevelScript) IMPLEMENT_POINTER(next) diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index b3526c60d5..4d1909da5d 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -865,7 +865,7 @@ public: void BeginPlay (); }; -IMPLEMENT_CLASS(ACustomSprite, false, false, false, false) +IMPLEMENT_CLASS(ACustomSprite, false, false) void ACustomSprite::BeginPlay () { diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index d22dd6371d..a38a17f9ca 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -38,7 +38,7 @@ // //============================================================================ -IMPLEMENT_CLASS(DCeiling, false, false, false, false) +IMPLEMENT_CLASS(DCeiling, false, false) DCeiling::DCeiling () { diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 15e3e42c44..404b2f2bc0 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -834,6 +834,7 @@ public: V_FreeBrokenLines(mDialogueLines); mDialogueLines = NULL; I_SetMusicVolume (1.f); + Super::Destroy(); } bool DimAllowed() @@ -1103,7 +1104,7 @@ public: }; -IMPLEMENT_CLASS(DConversationMenu, true, false, false, false) +IMPLEMENT_CLASS(DConversationMenu, true, 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 542308fa6f..aa59e5463f 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -45,7 +45,7 @@ // //============================================================================ -IMPLEMENT_CLASS(DDoor, false, false, false, false) +IMPLEMENT_CLASS(DDoor, false, false) DDoor::DDoor () { @@ -513,7 +513,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing, // //============================================================================ -IMPLEMENT_CLASS(DAnimatedDoor, false, false, false, false) +IMPLEMENT_CLASS(DAnimatedDoor, false, false) DAnimatedDoor::DAnimatedDoor () { diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 7b5ff5cc93..0431fa808b 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -64,7 +64,7 @@ static void StartFloorSound (sector_t *sec) // //========================================================================== -IMPLEMENT_CLASS(DFloor, false, false, false, false) +IMPLEMENT_CLASS(DFloor, false, false) DFloor::DFloor () { @@ -815,7 +815,7 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed) // //========================================================================== -IMPLEMENT_CLASS(DElevator, false, true, false, false) +IMPLEMENT_CLASS(DElevator, false, true) IMPLEMENT_POINTERS_START(DElevator) IMPLEMENT_POINTER(m_Interp_Floor) @@ -1105,9 +1105,9 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag) // //========================================================================== -IMPLEMENT_CLASS(DWaggleBase, false, false, false, false) -IMPLEMENT_CLASS(DFloorWaggle, false, false, false, false) -IMPLEMENT_CLASS(DCeilingWaggle, false, false, false, false) +IMPLEMENT_CLASS(DWaggleBase, false, false) +IMPLEMENT_CLASS(DFloorWaggle, false, false) +IMPLEMENT_CLASS(DCeilingWaggle, false, false) DWaggleBase::DWaggleBase () { @@ -1141,11 +1141,6 @@ DWaggleBase::DWaggleBase (sector_t *sec) { } -void DWaggleBase::Destroy() -{ - Super::Destroy(); -} - //========================================================================== // // diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 48d13bebff..aece79edc4 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1071,7 +1071,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, } } - damage = inflictor->DoSpecialDamage(target, damage, mod); + damage = inflictor->CallDoSpecialDamage(target, damage, mod); if (damage < 0) { return -1; diff --git a/src/p_lights.cpp b/src/p_lights.cpp index c44a22d4b1..910c52a648 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -173,7 +173,7 @@ private: // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DLighting, false, false, false, false) +IMPLEMENT_CLASS(DLighting, false, false) DLighting::DLighting () { @@ -191,7 +191,7 @@ DLighting::DLighting (sector_t *sector) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DFireFlicker, false, false, false, false) +IMPLEMENT_CLASS(DFireFlicker, false, false) DFireFlicker::DFireFlicker () { @@ -258,7 +258,7 @@ DFireFlicker::DFireFlicker (sector_t *sector, int upper, int lower) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DFlicker, false, false, false, false) +IMPLEMENT_CLASS(DFlicker, false, false) DFlicker::DFlicker () { @@ -334,7 +334,7 @@ void EV_StartLightFlickering (int tag, int upper, int lower) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DLightFlash, false, false, false, false) +IMPLEMENT_CLASS(DLightFlash, false, false) DLightFlash::DLightFlash () { @@ -409,7 +409,7 @@ DLightFlash::DLightFlash (sector_t *sector, int min, int max) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DStrobe, false, false, false, false) +IMPLEMENT_CLASS(DStrobe, false, false) DStrobe::DStrobe () { @@ -667,7 +667,7 @@ void EV_LightChange (int tag, int value) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DGlow, false, false, false, false) +IMPLEMENT_CLASS(DGlow, false, false) DGlow::DGlow () { @@ -736,7 +736,7 @@ DGlow::DGlow (sector_t *sector) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DGlow2, false, false, false, false) +IMPLEMENT_CLASS(DGlow2, false, false) DGlow2::DGlow2 () { @@ -869,7 +869,7 @@ void EV_StartLightFading (int tag, int value, int tics) // //----------------------------------------------------------------------------- -IMPLEMENT_CLASS(DPhased, false, false, false, false) +IMPLEMENT_CLASS(DPhased, false, false) DPhased::DPhased () { diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index c8c7db74d0..e41912e239 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1368,7 +1368,7 @@ void DoActivateThing(AActor * thing, AActor * activator) if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching thing->activationtype |= THINGSPEC_Deactivate; } - thing->Activate (activator); + thing->CallActivate (activator); } void DoDeactivateThing(AActor * thing, AActor * activator) @@ -1379,7 +1379,7 @@ void DoDeactivateThing(AActor * thing, AActor * activator) if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching thing->activationtype |= THINGSPEC_Activate; } - thing->Deactivate (activator); + thing->CallDeactivate (activator); } FUNC(LS_Thing_Activate) diff --git a/src/p_map.cpp b/src/p_map.cpp index af5ab100af..f1fa55cf91 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -6758,7 +6758,7 @@ bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death) thing->activationtype &= ~THINGSPEC_Activate; // Clear flag if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching thing->activationtype |= THINGSPEC_Deactivate; - thing->Activate(trigger); + thing->CallActivate(trigger); res = true; } // If not, can it be deactivated? @@ -6767,7 +6767,7 @@ bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death) thing->activationtype &= ~THINGSPEC_Deactivate; // Clear flag if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching thing->activationtype |= THINGSPEC_Activate; - thing->Deactivate(trigger); + thing->CallDeactivate(trigger); res = true; } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3c8d1173b9..cde2eb0b46 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -131,7 +131,7 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(AActor, false, true, false, true) +IMPLEMENT_CLASS(AActor, false, true) IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(target) @@ -943,7 +943,7 @@ AInventory *AActor::FirstInv () // //============================================================================ -bool AActor::UseInventory (AInventory *item) +bool AActor::DoUseInventory (AInventory *item) { // No using items if you're dead. if (health <= 0) @@ -975,7 +975,23 @@ DEFINE_ACTION_FUNCTION(AActor, UseInventory) PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(item, AInventory); self->VMSuperCall(); - ACTION_RETURN_BOOL(self->UseInventory(item)); + ACTION_RETURN_BOOL(self->DoUseInventory(item)); +} + +bool AActor::UseInventory(AInventory *item) +{ + IFVIRTUAL(AActor, UseInventory) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[2] = { (DObject*)this, (DObject*)item }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + return !!retval; + } + else return DoUseInventory(item); } //=========================================================================== @@ -4475,7 +4491,7 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a actor->UpdateWaterLevel (false); if (!SpawningMapThing) { - actor->BeginPlay (); + actor->CallBeginPlay (); if (actor->ObjectFlags & OF_EuthanizeMe) { return NULL; @@ -4551,7 +4567,7 @@ void AActor::HandleSpawnFlags () } if (SpawnFlags & MTF_DORMANT) { - Deactivate (NULL); + CallDeactivate (NULL); } if (SpawnFlags & MTF_STANDSTILL) { @@ -4595,18 +4611,29 @@ void AActor::BeginPlay () if (flags2 & MF2_DORMANT) { flags2 &= ~MF2_DORMANT; - Deactivate (NULL); + CallDeactivate (NULL); } } DEFINE_ACTION_FUNCTION(AActor, BeginPlay) { PARAM_SELF_PROLOGUE(AActor); - self->VMSuperCall(); self->BeginPlay(); return 0; } +void AActor::CallBeginPlay() +{ + IFVIRTUAL(AActor, BeginPlay) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } + else BeginPlay(); +} + void AActor::PostBeginPlay () { @@ -4643,6 +4670,12 @@ bool AActor::isSlow() return !!G_SkillProperty(SKILLP_SlowMonsters); } +//=========================================================================== +// +// Activate +// +//=========================================================================== + void AActor::Activate (AActor *activator) { if ((flags3 & MF3_ISMONSTER) && (health > 0 || (flags & MF_ICECORPSE))) @@ -4672,6 +4705,25 @@ DEFINE_ACTION_FUNCTION(AActor, Activate) return 0; } +void AActor::CallActivate(AActor *activator) +{ + IFVIRTUAL(AActor, Activate) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[2] = { (DObject*)this, (DObject*)activator }; + VMFrameStack stack; + stack.Call(func, params, 2, nullptr, 0, nullptr); + } + else Activate(activator); +} + + +//=========================================================================== +// +// Deactivate +// +//=========================================================================== + void AActor::Deactivate (AActor *activator) { if ((flags3 & MF3_ISMONSTER) && (health > 0 || (flags & MF_ICECORPSE))) @@ -4701,10 +4753,23 @@ DEFINE_ACTION_FUNCTION(AActor, Deactivate) return 0; } +void AActor::CallDeactivate(AActor *activator) +{ + IFVIRTUAL(AActor, Deactivate) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[2] = { (DObject*)this, (DObject*)activator }; + VMFrameStack stack; + stack.Call(func, params, 2, nullptr, 0, nullptr); + } + else Deactivate(activator); +} +//=========================================================================== // -// P_RemoveMobj +// Destroy // +//=========================================================================== void AActor::Destroy () { @@ -5415,7 +5480,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) if (mthing->fillcolor) mobj->fillcolor = mthing->fillcolor; - mobj->BeginPlay (); + mobj->CallBeginPlay (); if (!(mobj->ObjectFlags & OF_EuthanizeMe)) { mobj->LevelSpawned (); @@ -6687,6 +6752,14 @@ bool AActor::IsHostile (AActor *other) return true; } +//========================================================================== +// +// AActor :: DoSpecialDamage +// +// override this for special damage effects. +// +//========================================================================== + int AActor::DoSpecialDamage (AActor *target, int damage, FName damagetype) { if (target->player && target->player->mo == target && damage < 1000 && @@ -6720,6 +6793,28 @@ DEFINE_ACTION_FUNCTION(AActor, DoSpecialDamage) ACTION_RETURN_INT(self->DoSpecialDamage(target, damage, damagetype)); } +int AActor::CallDoSpecialDamage(AActor *target, int damage, FName damagetype) +{ + IFVIRTUAL(AActor, DoSpecialDamage) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[4] = { (DObject*)this, (DObject*)target, damage, damagetype.GetIndex() }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 4, &ret, 1, nullptr); + return retval; + } + else return DoSpecialDamage(target, damage, damagetype); + +} + +//========================================================================== +// +// AActor :: TakeSpecialDamage +// +//========================================================================== int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) { @@ -7032,7 +7127,7 @@ public: } }; -IMPLEMENT_CLASS(DActorIterator, false, false, false, false); +IMPLEMENT_CLASS(DActorIterator, false, false); DEFINE_ACTION_FUNCTION(DActorIterator, Create) { PARAM_PROLOGUE; @@ -7252,7 +7347,7 @@ DEFINE_ACTION_FUNCTION(AActor, RestoreDamage) // //---------------------------------------------------------------------------- -IMPLEMENT_CLASS(DDropItem, false, true, true, false) +IMPLEMENT_CLASS(DDropItem, false, true) IMPLEMENT_POINTERS_START(DDropItem) IMPLEMENT_POINTER(Next) diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index 27eb13ec5b..b0ea0e4a3a 100644 --- a/src/p_pillar.cpp +++ b/src/p_pillar.cpp @@ -40,7 +40,7 @@ #include "serializer.h" #include "r_data/r_interpolate.h" -IMPLEMENT_CLASS(DPillar, false, true, false, false) +IMPLEMENT_CLASS(DPillar, false, true) IMPLEMENT_POINTERS_START(DPillar) IMPLEMENT_POINTER(m_Interp_Floor) diff --git a/src/p_plats.cpp b/src/p_plats.cpp index 9924a0f9ce..43e8eefb49 100644 --- a/src/p_plats.cpp +++ b/src/p_plats.cpp @@ -35,7 +35,7 @@ static FRandom pr_doplat ("DoPlat"); -IMPLEMENT_CLASS(DPlat, false, false, false, false) +IMPLEMENT_CLASS(DPlat, false, false) DPlat::DPlat () { diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index ca305d677b..eddeb3430d 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -99,7 +99,7 @@ static const FGenericButtons ButtonChecks[] = // //------------------------------------------------------------------------ -IMPLEMENT_CLASS(DPSprite, false, true, false, false) +IMPLEMENT_CLASS(DPSprite, false, true) IMPLEMENT_POINTERS_START(DPSprite) IMPLEMENT_POINTER(Caller) diff --git a/src/p_pspr.h b/src/p_pspr.h index 7039b2cc82..d6eb2a82d7 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -86,7 +86,7 @@ private: void Serialize(FSerializer &arc); void Tick(); - void Destroy(); + void Destroy() override; public: // must be public to be able to generate the field export tables. Grrr... TObjPtr Caller; diff --git a/src/p_pusher.cpp b/src/p_pusher.cpp index f2f982a7fa..1cf0041203 100644 --- a/src/p_pusher.cpp +++ b/src/p_pusher.cpp @@ -74,7 +74,7 @@ protected: friend bool PIT_PushThing (AActor *thing); }; -IMPLEMENT_CLASS(DPusher, false, true, false, false) +IMPLEMENT_CLASS(DPusher, false, true) IMPLEMENT_POINTERS_START(DPusher) IMPLEMENT_POINTER(m_Source) diff --git a/src/p_scroll.cpp b/src/p_scroll.cpp index f44eac25a9..25789d9448 100644 --- a/src/p_scroll.cpp +++ b/src/p_scroll.cpp @@ -44,7 +44,7 @@ public: DScroller (EScroll type, double dx, double dy, int control, int affectee, int accel, EScrollPos scrollpos = EScrollPos::scw_all); DScroller (double dx, double dy, const line_t *l, int control, int accel, EScrollPos scrollpos = EScrollPos::scw_all); - void Destroy(); + void Destroy() override; void Serialize(FSerializer &arc); void Tick (); @@ -73,7 +73,7 @@ private: } }; -IMPLEMENT_CLASS(DScroller, false, true, false, false) +IMPLEMENT_CLASS(DScroller, false, true) IMPLEMENT_POINTERS_START(DScroller) IMPLEMENT_POINTER(m_Interpolations[0]) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index e687d5724f..c9a8294b59 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -660,7 +660,7 @@ protected: short LastLight; }; -IMPLEMENT_CLASS(DLightTransfer, false, false, false, false) +IMPLEMENT_CLASS(DLightTransfer, false, false) void DLightTransfer::Serialize(FSerializer &arc) { @@ -750,7 +750,7 @@ protected: BYTE Flags; }; -IMPLEMENT_CLASS(DWallLightTransfer, false, false, false, false) +IMPLEMENT_CLASS(DWallLightTransfer, false, false) void DWallLightTransfer::Serialize(FSerializer &arc) { diff --git a/src/p_spec.h b/src/p_spec.h index 41d47c7216..8a0729d6a1 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -243,7 +243,7 @@ public: void Serialize(FSerializer &arc); void Tick (); - void Destroy(); + void Destroy() override; protected: EPillar m_Type; @@ -572,7 +572,7 @@ public: DElevator (sector_t *sec); - void Destroy(); + void Destroy() override; void Serialize(FSerializer &arc); void Tick (); @@ -617,7 +617,6 @@ protected: int offset, int timer, bool ceiling); void DoWaggle (bool ceiling); - void Destroy(); DWaggleBase (); }; diff --git a/src/p_switch.cpp b/src/p_switch.cpp index 2d5423f084..ae7cf21432 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, false, false, false, false) +IMPLEMENT_CLASS(DActiveButton, false, false) DActiveButton::DActiveButton () { diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index 80bfd4f7fb..14055202a2 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, false, false, false, false) +IMPLEMENT_CLASS(ATeleportFog, false, false) void ATeleportFog::PostBeginPlay () { diff --git a/src/p_user.cpp b/src/p_user.cpp index 2917db6685..03df6a0ca2 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -508,7 +508,7 @@ int player_t::GetSpawnClass() // //=========================================================================== -IMPLEMENT_CLASS(PClassPlayerPawn, false, false, false, false) +IMPLEMENT_CLASS(PClassPlayerPawn, false, false) PClassPlayerPawn::PClassPlayerPawn() { @@ -622,14 +622,14 @@ void player_t::SendPitchLimits() const // //=========================================================================== -IMPLEMENT_CLASS(APlayerPawn, false, true, false, true) +IMPLEMENT_CLASS(APlayerPawn, false, true) IMPLEMENT_POINTERS_START(APlayerPawn) IMPLEMENT_POINTER(InvFirst) IMPLEMENT_POINTER(InvSel) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(APlayerChunk, false, false, false, false) +IMPLEMENT_CLASS(APlayerChunk, false, false) void APlayerPawn::Serialize(FSerializer &arc) { @@ -882,7 +882,7 @@ void APlayerPawn::RemoveInventory (AInventory *item) // //=========================================================================== -bool APlayerPawn::UseInventory (AInventory *item) +bool APlayerPawn::DoUseInventory (AInventory *item) { const PClass *itemtype = item->GetClass(); @@ -896,7 +896,7 @@ bool APlayerPawn::UseInventory (AInventory *item) return false; } - if (!Super::UseInventory (item)) + if (!Super::DoUseInventory (item)) { // Heretic and Hexen advance the inventory cursor if the use failed. // Should this behavior be retained? @@ -1280,18 +1280,22 @@ void APlayerPawn::PlayRunning () void APlayerPawn::PlayAttacking () { - VINDEX(APlayerPawn, PlayAttacking); - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); + IFVIRTUAL(APlayerPawn, PlayAttacking) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } } void APlayerPawn::PlayAttacking2 () { - VINDEX(APlayerPawn, PlayAttacking2); - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); + IFVIRTUAL(APlayerPawn, PlayAttacking2) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } } void APlayerPawn::ThrowPoisonBag () @@ -1381,10 +1385,12 @@ void APlayerPawn::GiveDefaultInventory () void APlayerPawn::MorphPlayerThink () { - VINDEX(APlayerPawn, MorphPlayerThink); - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); + IFVIRTUAL(APlayerPawn, MorphPlayerThink) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } } void APlayerPawn::ActivateMorphWeapon () diff --git a/src/po_man.cpp b/src/po_man.cpp index 4e304daa8b..fafa227eee 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -172,7 +172,7 @@ static FPolyNode *FreePolyNodes; // //========================================================================== -IMPLEMENT_CLASS(DPolyAction, false, true, false, false) +IMPLEMENT_CLASS(DPolyAction, false, true) IMPLEMENT_POINTERS_START(DPolyAction) IMPLEMENT_POINTER(m_Interpolation) @@ -240,7 +240,7 @@ void DPolyAction::StopInterpolation () // //========================================================================== -IMPLEMENT_CLASS(DRotatePoly, false, false, false, false) +IMPLEMENT_CLASS(DRotatePoly, false, false) DRotatePoly::DRotatePoly () { @@ -257,7 +257,7 @@ DRotatePoly::DRotatePoly (int polyNum) // //========================================================================== -IMPLEMENT_CLASS(DMovePoly, false, false, false, false) +IMPLEMENT_CLASS(DMovePoly, false, false) DMovePoly::DMovePoly () { @@ -284,7 +284,7 @@ DMovePoly::DMovePoly (int polyNum) // //========================================================================== -IMPLEMENT_CLASS(DMovePolyTo, false, false, false, false) +IMPLEMENT_CLASS(DMovePolyTo, false, false) DMovePolyTo::DMovePolyTo() { @@ -309,7 +309,7 @@ DMovePolyTo::DMovePolyTo(int polyNum) // //========================================================================== -IMPLEMENT_CLASS(DPolyDoor, false, false, false, false) +IMPLEMENT_CLASS(DPolyDoor, false, false) DPolyDoor::DPolyDoor () { diff --git a/src/po_man.h b/src/po_man.h index ec6a3901b9..4d78fa1796 100644 --- a/src/po_man.h +++ b/src/po_man.h @@ -12,7 +12,7 @@ class DPolyAction : public DThinker public: DPolyAction(int polyNum); void Serialize(FSerializer &arc); - void Destroy(); + void Destroy() override; void Stop(); double GetSpeed() const { return m_Speed; } diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index a1e6056ca7..4a68330260 100644 --- a/src/posix/sdl/sdlvideo.cpp +++ b/src/posix/sdl/sdlvideo.cpp @@ -79,7 +79,7 @@ private: SDLFB () {} }; -IMPLEMENT_CLASS(SDLFB, false, false, false, false) +IMPLEMENT_CLASS(SDLFB, false, false) struct MiniModeInfo { diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp index c98adb47b7..a202345a32 100644 --- a/src/r_data/r_interpolate.cpp +++ b/src/r_data/r_interpolate.cpp @@ -62,7 +62,7 @@ public: DSectorPlaneInterpolation() {} DSectorPlaneInterpolation(sector_t *sector, bool plane, bool attach); - void Destroy(); + void Destroy() override; void UpdateInterpolation(); void Restore(); void Interpolate(double smoothratio); @@ -91,7 +91,7 @@ public: DSectorScrollInterpolation() {} DSectorScrollInterpolation(sector_t *sector, bool plane); - void Destroy(); + void Destroy() override; void UpdateInterpolation(); void Restore(); void Interpolate(double smoothratio); @@ -119,7 +119,7 @@ public: DWallScrollInterpolation() {} DWallScrollInterpolation(side_t *side, int part); - void Destroy(); + void Destroy() override; void UpdateInterpolation(); void Restore(); void Interpolate(double smoothratio); @@ -146,7 +146,7 @@ public: DPolyobjInterpolation() {} DPolyobjInterpolation(FPolyObj *poly); - void Destroy(); + void Destroy() override; void UpdateInterpolation(); void Restore(); void Interpolate(double smoothratio); @@ -161,17 +161,17 @@ public: // //========================================================================== -IMPLEMENT_CLASS(DInterpolation, true, true, false, false) +IMPLEMENT_CLASS(DInterpolation, true, true) 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) +IMPLEMENT_CLASS(DSectorPlaneInterpolation, false, false) +IMPLEMENT_CLASS(DSectorScrollInterpolation, false, false) +IMPLEMENT_CLASS(DWallScrollInterpolation, false, false) +IMPLEMENT_CLASS(DPolyobjInterpolation, false, false) //========================================================================== // diff --git a/src/r_data/r_interpolate.h b/src/r_data/r_interpolate.h index 092cbe5eec..44ff9bed06 100644 --- a/src/r_data/r_interpolate.h +++ b/src/r_data/r_interpolate.h @@ -27,7 +27,7 @@ public: int AddRef(); int DelRef(bool force = false); - virtual void Destroy(); + void Destroy() override; virtual void UpdateInterpolation() = 0; virtual void Restore() = 0; virtual void Interpolate(double smoothratio) = 0; diff --git a/src/r_defs.h b/src/r_defs.h index a21d236168..2d16d28f9d 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -253,7 +253,7 @@ class ASectorAction : public AActor DECLARE_CLASS (ASectorAction, AActor) public: ASectorAction (bool activatedByUse = false); - void Destroy (); + void Destroy () override; void BeginPlay (); void Activate (AActor *source); void Deactivate (AActor *source); diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index c68df5f3c8..083e0eeef5 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -2213,7 +2213,7 @@ private: int NextCheck; }; -IMPLEMENT_CLASS(AAmbientSound, false, false, false, false) +IMPLEMENT_CLASS(AAmbientSound, false, false) //========================================================================== // @@ -2346,7 +2346,7 @@ void AAmbientSound::SetTicker (struct FAmbientSound *ambient) void AAmbientSound::BeginPlay () { Super::BeginPlay (); - Activate (NULL); + CallActivate (NULL); } //========================================================================== @@ -2470,7 +2470,7 @@ public: virtual void PostBeginPlay(); }; -IMPLEMENT_CLASS(AMusicChanger, false, false, false, false) +IMPLEMENT_CLASS(AMusicChanger, false, false) bool AMusicChanger::DoTriggerAction (AActor *triggerer, int activationType) { diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index 1bed35ed5b..28786ef8f0 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -105,7 +105,7 @@ class DSeqActorNode : public DSeqNode HAS_OBJECT_POINTERS public: DSeqActorNode(AActor *actor, int sequence, int modenum); - void Destroy(); + void Destroy() override; void Serialize(FSerializer &arc); void MakeSound(int loop, FSoundID id) { @@ -133,7 +133,7 @@ class DSeqPolyNode : public DSeqNode DECLARE_CLASS(DSeqPolyNode, DSeqNode) public: DSeqPolyNode(FPolyObj *poly, int sequence, int modenum); - void Destroy(); + void Destroy() override; void Serialize(FSerializer &arc); void MakeSound(int loop, FSoundID id) { @@ -161,7 +161,7 @@ class DSeqSectorNode : public DSeqNode DECLARE_CLASS(DSeqSectorNode, DSeqNode) public: DSeqSectorNode(sector_t *sec, int chan, int sequence, int modenum); - void Destroy(); + void Destroy() override; void Serialize(FSerializer &arc); void MakeSound(int loop, FSoundID id) { @@ -285,7 +285,7 @@ void DSeqNode::SerializeSequences (FSerializer &arc) arc("sndseqlisthead", SequenceListHead); } -IMPLEMENT_CLASS(DSeqNode, false, true, false, false) +IMPLEMENT_CLASS(DSeqNode, false, true) IMPLEMENT_POINTERS_START(DSeqNode) IMPLEMENT_POINTER(m_ChildSeqNode) @@ -429,7 +429,7 @@ FName DSeqNode::GetSequenceName () const return Sequences[m_Sequence]->SeqName; } -IMPLEMENT_CLASS(DSeqActorNode, false, true, false, false) +IMPLEMENT_CLASS(DSeqActorNode, false, true) IMPLEMENT_POINTERS_START(DSeqActorNode) IMPLEMENT_POINTER(m_Actor) @@ -441,7 +441,7 @@ void DSeqActorNode::Serialize(FSerializer &arc) arc("actor", m_Actor); } -IMPLEMENT_CLASS(DSeqPolyNode, false, false, false, false) +IMPLEMENT_CLASS(DSeqPolyNode, false, false) void DSeqPolyNode::Serialize(FSerializer &arc) { @@ -449,7 +449,7 @@ void DSeqPolyNode::Serialize(FSerializer &arc) arc("poly", m_Poly); } -IMPLEMENT_CLASS(DSeqSectorNode, false, false, false, false) +IMPLEMENT_CLASS(DSeqSectorNode, false, false) void DSeqSectorNode::Serialize(FSerializer &arc) { diff --git a/src/s_sndseq.h b/src/s_sndseq.h index 74ded5af47..13444f8628 100644 --- a/src/s_sndseq.h +++ b/src/s_sndseq.h @@ -22,7 +22,7 @@ class DSeqNode : public DObject public: void Serialize(FSerializer &arc); void StopAndDestroy (); - void Destroy (); + void Destroy() override; void Tick (); void ChangeData (int seqOffset, int delayTics, float volume, FSoundID currentSoundID); void AddChoice (int seqnum, seqtype_t type); diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 7540d45f45..8321a8f899 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -96,7 +96,7 @@ public: } }; -IMPLEMENT_CLASS(AFakeInventory, false, false, false, false) +IMPLEMENT_CLASS(AFakeInventory, false, false) DEFINE_FIELD(AFakeInventory, Respawnable) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 05c43aa1f2..c7082ff763 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -667,7 +667,7 @@ public: 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; + unsigned VirtualIndex = ~0u; FName Name; TArray DefaultArgs; FString PrintableName; // so that the VM can print meaningful info if something in this function goes wrong. diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index f35c3718d5..0ec6ec15b6 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -34,15 +34,15 @@ #include #include "dobject.h" -IMPLEMENT_CLASS(VMException, false, false, false, false) -IMPLEMENT_CLASS(VMFunction, true, true, false, false) +IMPLEMENT_CLASS(VMException, false, false) +IMPLEMENT_CLASS(VMFunction, true, true) IMPLEMENT_POINTERS_START(VMFunction) IMPLEMENT_POINTER(Proto) IMPLEMENT_POINTERS_END -IMPLEMENT_CLASS(VMScriptFunction, false, false, false, false) -IMPLEMENT_CLASS(VMNativeFunction, false, false, false, false) +IMPLEMENT_CLASS(VMScriptFunction, false, false) +IMPLEMENT_CLASS(VMNativeFunction, false, false) VMScriptFunction::VMScriptFunction(FName name) { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index a4a2cc4533..98ebc17d93 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -51,8 +51,6 @@ #include "codegeneration/codegen.h" #include "vmbuilder.h" -#define DEFAULTS_VMEXPORT ((BYTE *)(void *)1) - //========================================================================== // // ZCCCompiler :: ProcessClass @@ -505,26 +503,6 @@ void ZCCCompiler::CreateClassTypes() } 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 { @@ -1980,15 +1958,6 @@ void ZCCCompiler::InitDefaults() // 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); @@ -2400,11 +2369,6 @@ void ZCCCompiler::InitFunctions() // 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) diff --git a/src/v_video.cpp b/src/v_video.cpp index b18a6e727e..7192c5d033 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -69,8 +69,8 @@ int active_con_scale(); FRenderer *Renderer; -IMPLEMENT_CLASS(DCanvas, true, false, false, false) -IMPLEMENT_CLASS(DFrameBuffer, true, false, false, false) +IMPLEMENT_CLASS(DCanvas, true, false) +IMPLEMENT_CLASS(DFrameBuffer, true, false) #if defined(_DEBUG) && defined(_M_IX86) && !defined(__MINGW32__) #define DBGBREAK { __asm int 3 } @@ -106,11 +106,11 @@ public: float Gamma; }; -IMPLEMENT_CLASS(DDummyFrameBuffer, true, false, false, false) +IMPLEMENT_CLASS(DDummyFrameBuffer, true, false) // SimpleCanvas is not really abstract, but this macro does not // try to generate a CreateNew() function. -IMPLEMENT_CLASS(DSimpleCanvas, true, false, false, false) +IMPLEMENT_CLASS(DSimpleCanvas, true, false) class FPaletteTester : public FTexture { diff --git a/src/virtual.h b/src/virtual.h index 26fc694ea1..8485dec078 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -1,275 +1,21 @@ - - - -// 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_FUNC(BeginPlay) - VMEXPORTED_NATIVES_FUNC(Activate) - VMEXPORTED_NATIVES_FUNC(Deactivate) - VMEXPORTED_NATIVES_FUNC(DoSpecialDamage) - VMEXPORTED_NATIVES_FUNC(UseInventory) -VMEXPORTED_NATIVES_END - - -inline int GetVirtualIndex(PClass *cls, const char *funcname) +inline unsigned GetVirtualIndex(PClass *cls, const char *funcname) { // 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(cls->Symbols.FindSymbol(funcname, false)); assert(sym != nullptr); auto VIndex = sym->Variants[0].Implementation->VirtualIndex; - assert(VIndex >= 0); return VIndex; } -#define VINDEX(cls, funcname) \ - static int VIndex = -1; \ - if (VIndex < 0) { \ +#define IFVIRTUAL(cls, funcname) \ + static unsigned VIndex = ~0u; \ + if (VIndex == ~0u) { \ VIndex = GetVirtualIndex(RUNTIME_CLASS(cls), #funcname); \ - if (VIndex < 0) I_Error("Unable to find virtual function %s in " #cls, #funcname); \ - } + assert(VIndex != ~0u); \ + } \ + auto clss = GetClass(); \ + VMFunction *func = clss->Virtuals.Size() > VIndex? clss->Virtuals[VIndex] : nullptr; \ + if (func != nullptr) -#define VFUNC this->GetClass()->Virtuals[VIndex] -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 - { - VINDEX(DObject, Destroy); - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); - } - } - void Tick() - { - if (this->ObjectFlags & OF_SuperCall) - { - this->ObjectFlags &= ~OF_SuperCall; - ExportedNatives::Get()->template Tick(this); - } - else - { - VINDEX(DThinker, Tick); - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); - } - } - - void PostBeginPlay() - { - if (this->ObjectFlags & OF_SuperCall) - { - this->ObjectFlags &= ~OF_SuperCall; - ExportedNatives::Get()->template PostBeginPlay(this); - } - else - { - VINDEX(DThinker, PostBeginPlay); - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); - } - } - - void BeginPlay() - { - if (this->ObjectFlags & OF_SuperCall) - { - this->ObjectFlags &= ~OF_SuperCall; - ExportedNatives::Get()->template BeginPlay(this); - } - else - { - VINDEX(AActor, BeginPlay); - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(VFUNC, params, 1, nullptr, 0, nullptr); - } - } - - void Activate(AActor *activator) - { - if (this->ObjectFlags & OF_SuperCall) - { - this->ObjectFlags &= ~OF_SuperCall; - ExportedNatives::Get()->template Activate(this, activator); - } - else - { - VINDEX(AActor, Activate); - // Without the type cast this picks the 'void *' assignment... - VMValue params[2] = { (DObject*)this, (DObject*)activator }; - VMFrameStack stack; - stack.Call(VFUNC, params, 2, nullptr, 0, nullptr); - } - } - - void Deactivate(AActor *activator) - { - if (this->ObjectFlags & OF_SuperCall) - { - this->ObjectFlags &= ~OF_SuperCall; - ExportedNatives::Get()->template Deactivate(this, activator); - } - else - { - VINDEX(AActor, Deactivate); - // Without the type cast this picks the 'void *' assignment... - VMValue params[2] = { (DObject*)this, (DObject*)activator }; - VMFrameStack stack; - stack.Call(VFUNC, params, 2, nullptr, 0, nullptr); - } - } - int DoSpecialDamage(AActor *target, int damage, FName damagetype) - { - if (this->ObjectFlags & OF_SuperCall) - { - this->ObjectFlags &= ~OF_SuperCall; - return ExportedNatives::Get()->template DoSpecialDamage(this, target, damage, damagetype); - } - else - { - VINDEX(AActor, DoSpecialDamage); - // Without the type cast this picks the 'void *' assignment... - VMValue params[4] = { (DObject*)this, (DObject*)target, damage, damagetype.GetIndex() }; - VMReturn ret; - VMFrameStack stack; - int retval; - ret.IntAt(&retval); - stack.Call(VFUNC, params, 4, &ret, 1, nullptr); - return retval; - } - } - bool UseInventory(AInventory *item) - { - if (this->ObjectFlags & OF_SuperCall) - { - this->ObjectFlags &= ~OF_SuperCall; - return ExportedNatives::Get()->template UseInventory(this, item); - } - else - { - VINDEX(AActor, UseInventory); - // Without the type cast this picks the 'void *' assignment... - VMValue params[2] = { (DObject*)this, (DObject*)item }; - VMReturn ret; - VMFrameStack stack; - int retval; - ret.IntAt(&retval); - stack.Call(VFUNC, params, 2, &ret, 1, nullptr); - return !!retval; - } - } - -}; - -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_FUNC(BeginPlay) - VMEXPORT_NATIVES_FUNC(Activate) - VMEXPORT_NATIVES_FUNC(Deactivate) - VMEXPORT_NATIVES_FUNC(DoSpecialDamage) - VMEXPORT_NATIVES_FUNC(UseInventory) -VMEXPORT_NATIVES_END(AActor) - -/* -VMEXPORT_NATIVES_START(AActor, DThinker) -VMEXPORT_NATIVES_END(AActor) -*/ diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 6d162bbec0..0e8dd3dec9 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -91,7 +91,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_CLASS(D3DFB, false, false, false, false) +IMPLEMENT_CLASS(D3DFB, false, false) struct D3DFB::PackedTexture { diff --git a/src/win32/fb_ddraw.cpp b/src/win32/fb_ddraw.cpp index bd5a4db230..85f0c47685 100644 --- a/src/win32/fb_ddraw.cpp +++ b/src/win32/fb_ddraw.cpp @@ -61,7 +61,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_CLASS(DDrawFB, false, false, false, false) +IMPLEMENT_CLASS(DDrawFB, false, false) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/win32/win32video.cpp b/src/win32/win32video.cpp index df96f7f413..0d91ed1d04 100644 --- a/src/win32/win32video.cpp +++ b/src/win32/win32video.cpp @@ -80,7 +80,7 @@ // TYPES ------------------------------------------------------------------- -IMPLEMENT_CLASS(BaseWinFB, true, false, false, false) +IMPLEMENT_CLASS(BaseWinFB, true, false) typedef IDirect3D9 *(WINAPI *DIRECT3DCREATE9FUNC)(UINT SDKVersion); typedef HRESULT (WINAPI *DIRECTDRAWCREATEFUNC)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index c899bbd373..3eebceeb55 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -6,7 +6,7 @@ class Object native native static int G_SkillPropertyInt(int p); native static double G_SkillPropertyFloat(int p); - virtual native void Destroy(); + /*virtual*/ native void Destroy(); } class Thinker : Object native diff --git a/wadsrc/static/zscript/hexen/firedemon.txt b/wadsrc/static/zscript/hexen/firedemon.txt index b425ecb118..9ca12529f5 100644 --- a/wadsrc/static/zscript/hexen/firedemon.txt +++ b/wadsrc/static/zscript/hexen/firedemon.txt @@ -4,7 +4,7 @@ class FireDemon : Actor { const FIREDEMON_ATTACK_RANGE = 64*8.; - int strafecount; + int fdstrafecount; Default { @@ -77,7 +77,7 @@ class FireDemon : Actor // Fire Demon AI // // special1 index into floatbob - // strafecount whether strafing or not + // fdstrafecount whether strafing or not //============================================================================ //============================================================================ @@ -125,7 +125,7 @@ class FireDemon : Actor } // Initialize fire demon - strafecount = 0; + fdstrafecount = 0; bJustAttacked = false; } @@ -188,13 +188,13 @@ class FireDemon : Actor } // Strafe - if (strafecount > 0) + if (fdstrafecount > 0) { - strafecount--; + fdstrafecount--; } else { - strafecount = 0; + fdstrafecount = 0; Vel.X = Vel.Y = 0; dist = Distance2D(target); if (dist < FIREDEMON_ATTACK_RANGE) @@ -207,7 +207,7 @@ class FireDemon : Actor else ang -= 90; Thrust(8, ang); - strafecount = 3; // strafe time + fdstrafecount = 3; // strafe time } } } @@ -215,7 +215,7 @@ class FireDemon : Actor FaceMovementDirection (); // Normal movement - if (!strafecount) + if (!fdstrafecount) { if (--movecount<0 || !MonsterMove ()) { From c25774e311e7d73e10710d501de901a74c5a9960 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Thu, 24 Nov 2016 20:43:37 +0100 Subject: [PATCH 352/471] - Fixed the Super Shotgun refire mismatch. --- wadsrc/static/zscript/doom/weaponssg.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/doom/weaponssg.txt b/wadsrc/static/zscript/doom/weaponssg.txt index 75ac9f09e7..6c06fe6ec4 100644 --- a/wadsrc/static/zscript/doom/weaponssg.txt +++ b/wadsrc/static/zscript/doom/weaponssg.txt @@ -111,6 +111,7 @@ extend class StateProvider action void A_CloseShotgun2() { - A_PlaySound("weapons/sshotc", CHAN_WEAPON); + A_PlaySound("weapons/sshotc", CHAN_WEAPON); + A_Refire(); } } From 11ac0c622b15f4a6c97c8a59dcba0611702d57da Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 01:33:04 +0100 Subject: [PATCH 353/471] - fixed: The BFG needs to get its default ammo usage from the DehInfo struct. - fixed: State's fields need to be declared native. --- src/d_dehacked.cpp | 6 ++++ src/scripting/thingdef_data.cpp | 5 +++ wadsrc/static/zscript/base.txt | 41 +++++++++++++++--------- wadsrc/static/zscript/doom/weaponbfg.txt | 2 +- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 40e8e57028..679c8c1adf 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -214,6 +214,12 @@ DehInfo deh = 40, // BFG cells per shot }; +DEFINE_FIELD_X(DehInfo, DehInfo, MaxSoulsphere) +DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionStyle) +DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionAlpha) +DEFINE_FIELD_X(DehInfo, DehInfo, NoAutofreeze) +DEFINE_FIELD_X(DehInfo, DehInfo, BFGCells) + // Doom identified pickup items by their sprites. ZDoom prefers to use their // class type to identify them instead. To support the traditional Doom // behavior, for every thing touched by dehacked that has the MF_PICKUP flag, diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 3d7a9d3e11..3f7f27e437 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -706,6 +706,11 @@ void InitThingdef() PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level); GlobalSymbols.AddSymbol(levelf); + // set up a variable for the DEH data + PStruct *dstruct = NewNativeStruct("DehInfo", nullptr); + PField *dehi = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh); + GlobalSymbols.AddSymbol(dehi); + // set up a variable for the global players array. PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); pstruct->Size = sizeof(player_t); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 3eebceeb55..160c1c5145 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -92,23 +92,34 @@ struct LevelLocals native // level_info_t *info cannot be done yet. } +// a few values of this need to be readable by the play code. +// Most are handled at load time and are omitted here. +struct DehInfo native +{ + native int MaxSoulsphere; + native uint8 ExplosionStyle; + native double ExplosionAlpha; + native int NoAutofreeze; + native int BFGCells; +} + struct State native { - State NextState; - int sprite; - int16 Tics; - uint16 TicRange; - uint8 Frame; - uint8 UseFlags; - int Misc1; - int Misc2; - uint16 bSlow; - uint16 bFast; - bool bFullbright; - bool bNoDelay; - bool bSameFrame; - bool bCanRaise; - bool bDehacked; + native State NextState; + native int sprite; + native int16 Tics; + native uint16 TicRange; + native uint8 Frame; + native uint8 UseFlags; + native int Misc1; + native int Misc2; + native uint16 bSlow; + native uint16 bFast; + native bool bFullbright; + native bool bNoDelay; + native bool bSameFrame; + native bool bCanRaise; + native bool bDehacked; } struct Sector native diff --git a/wadsrc/static/zscript/doom/weaponbfg.txt b/wadsrc/static/zscript/doom/weaponbfg.txt index 1b96bfc29d..e83c5d8f6c 100644 --- a/wadsrc/static/zscript/doom/weaponbfg.txt +++ b/wadsrc/static/zscript/doom/weaponbfg.txt @@ -77,7 +77,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, 1)) + if (!weap.DepleteAmmo (weap.bAltFire, true, deh.MaxSoulsphere/*BFGCells*/)) return; } From b5f55cacba49348ff1850a7794942846cc0d5053 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 09:56:06 +0100 Subject: [PATCH 354/471] - removed test code. --- wadsrc/static/zscript/doom/weaponbfg.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/doom/weaponbfg.txt b/wadsrc/static/zscript/doom/weaponbfg.txt index e83c5d8f6c..9bf0084b34 100644 --- a/wadsrc/static/zscript/doom/weaponbfg.txt +++ b/wadsrc/static/zscript/doom/weaponbfg.txt @@ -77,7 +77,7 @@ extend class StateProvider Weapon weap = player.ReadyWeapon; if (weap != null && invoker == weap && stateinfo != null && stateinfo.mStateType == STATE_Psprite) { - if (!weap.DepleteAmmo (weap.bAltFire, true, deh.MaxSoulsphere/*BFGCells*/)) + if (!weap.DepleteAmmo (weap.bAltFire, true, deh.BFGCells)) return; } From 82e5e2daa949c66f46e577c9ffa7c1e1bf99aa62 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 12:31:13 +0100 Subject: [PATCH 355/471] - fixed a variable mixup in Dehacked weapon initialization. This ultimately failed to set the weapon's AmmoUse field and made the weapon fail to detect it's out of ammo. --- src/d_dehacked.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 679c8c1adf..624116e06f 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3085,10 +3085,10 @@ void FinishDehPatch () StateVisited[state] = true; for(unsigned j = 0; AmmoPerAttacks[j].func != NAME_None; j++) { - if (AmmoPerAttacks[i].ptr == nullptr) + if (AmmoPerAttacks[j].ptr == nullptr) { - auto p = dyn_cast(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(AmmoPerAttacks[i].func, true)); - if (p != nullptr) AmmoPerAttacks[i].ptr = p->Variants[0].Implementation; + auto p = dyn_cast(RUNTIME_CLASS(AStateProvider)->Symbols.FindSymbol(AmmoPerAttacks[j].func, true)); + if (p != nullptr) AmmoPerAttacks[j].ptr = p->Variants[0].Implementation; } if (state->ActionFunc == AmmoPerAttacks[j].ptr) { From c2f7ed7f1c2266b72d35f8ef0684096225f35dbc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 12:45:17 +0100 Subject: [PATCH 356/471] - fixed: BuiltinNameToClass should treat NAME_None as 'nothing'. It's names that get here, after all, so the name for 'nothing' should actually mean 'nothing' here. --- src/scripting/codegeneration/codegen.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index b7e20f7fc3..a34e12f7db 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -9150,15 +9150,19 @@ int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray &def 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)) + if (clsname != NAME_None) { - Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); - cls = nullptr; + 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'\n", clsname.GetChars(), desttype->TypeName.GetChars()); + cls = nullptr; + } + ret->SetPointer(const_cast(cls), ATAG_OBJECT); } - ret->SetPointer(const_cast(cls), ATAG_OBJECT); + else ret->SetPointer(nullptr, ATAG_OBJECT); return 1; } From 8dba322775eeedf2a8a22eda5437a002f96fae0b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 16:05:03 +0100 Subject: [PATCH 357/471] - scriptified Heretic's Skull Rod. - Took the opportunity and fixed the logic for the Skull Rod's rain spawner. The old code which was part of the 3D floor submission was unable to work with portals at all. The new approach no longer tries to hide the dead projectile in the ceiling, it leaves it where it is and changes a few flags, so that its z-position can be used as reference to get the actual ceiling. This works for line portals, but for sector portals still requires some changes to sector_t::NextHighestCeilingAt to work, but at least this can be made to work unlike the old code. - added names for the player-related translations to A_SetTranslation. - fixed: Failure to resolve a function argument was checked for, too late. - made the parameter for A_SetTranslation a name instead of a string, because it is more efficient. We do not need full strings here. --- src/actor.h | 2 +- src/g_heretic/a_hereticweaps.cpp | 299 ------------ src/namedef.h | 19 + src/p_actionfunctions.cpp | 2 +- src/p_mobj.cpp | 19 +- src/p_sectors.cpp | 30 +- src/r_data/r_translate.cpp | 37 +- src/r_data/r_translate.h | 2 +- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/thingdef_data.cpp | 9 +- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actor.txt | 6 +- wadsrc/static/zscript/base.txt | 8 +- wadsrc/static/zscript/constants.txt | 30 +- .../static/zscript/heretic/hereticweaps.txt | 200 --------- .../static/zscript/heretic/weaponskullrod.txt | 425 ++++++++++++++++++ 16 files changed, 570 insertions(+), 521 deletions(-) create mode 100644 wadsrc/static/zscript/heretic/weaponskullrod.txt diff --git a/src/actor.h b/src/actor.h index 36fcc5de4d..bdb5241d16 100644 --- a/src/actor.h +++ b/src/actor.h @@ -759,7 +759,7 @@ public: virtual FName GetSpecies(); // set translation - void SetTranslation(const char *trname); + void SetTranslation(FName trname); double GetBobOffset(double ticfrac = 0) const { diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 4e2d62f1d1..7ec0364130 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -46,305 +46,6 @@ void P_DSparilTeleport (AActor *actor); extern bool P_AutoUseChaosDevice (player_t *player); -// --- Skull rod ------------------------------------------------------------ - - -// Rain pillar 1 ------------------------------------------------------------ - -class ARainPillar : public AActor -{ - DECLARE_CLASS (ARainPillar, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(ARainPillar, false, false) - -int ARainPillar::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->flags2 & MF2_BOSS) - { // Decrease damage for bosses - damage = (pr_rp() & 7) + 1; - } - return damage; -} - -// Rain tracker "inventory" item -------------------------------------------- - -class ARainTracker : public AInventory -{ - DECLARE_CLASS (ARainTracker, AInventory) -public: - - void Serialize(FSerializer &arc); - TObjPtr Rain1, Rain2; -}; - -IMPLEMENT_CLASS(ARainTracker, false, false) - -void ARainTracker::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - arc("rain1", Rain1) - ("rain2", Rain2); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireSkullRodPL1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *mo; - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - mo = P_SpawnPlayerMissile (self, PClass::FindActor("HornRodFX1")); - // Randomize the first frame - if (mo && pr_fsr1() > 128) - { - mo->SetState (mo->state->GetNextState()); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireSkullRodPL2 -// -// The special2 field holds the player number that shot the rain missile. -// The special1 field holds the id of the rain sound. -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - AActor *MissileActor; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("HornRodFX2"), self->Angles.Yaw, &t, &MissileActor); - // Use MissileActor instead of the return value from - // P_SpawnPlayerMissile because we need to give info to the mobj - // even if it exploded immediately. - if (MissileActor != NULL) - { - MissileActor->special2 = (int)(player - players); - if (t.linetarget && !t.unlinked) - { - MissileActor->tracer = t.linetarget; - } - S_Sound (MissileActor, CHAN_WEAPON, "weapons/hornrodpowshoot", 1, ATTN_NORM); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_AddPlayerRain -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_AddPlayerRain) -{ - PARAM_SELF_PROLOGUE(AActor); - - ARainTracker *tracker; - - if (self->target == NULL || self->target->health <= 0) - { // Shooter is dead or nonexistant - return 0; - } - - tracker = self->target->FindInventory (); - - // They player is only allowed two rainstorms at a time. Shooting more - // than that will cause the oldest one to terminate. - if (tracker != NULL) - { - if (tracker->Rain1 && tracker->Rain2) - { // Terminate an active rain - if (tracker->Rain1->health < tracker->Rain2->health) - { - if (tracker->Rain1->health > 16) - { - tracker->Rain1->health = 16; - } - tracker->Rain1 = NULL; - } - else - { - if (tracker->Rain2->health > 16) - { - tracker->Rain2->health = 16; - } - tracker->Rain2 = NULL; - } - } - } - else - { - tracker = static_cast (self->target->GiveInventoryType (RUNTIME_CLASS(ARainTracker))); - } - // Add rain mobj to list - if (tracker->Rain1) - { - tracker->Rain2 = self; - } - else - { - tracker->Rain1 = self; - } - self->special1 = S_FindSound ("misc/rain"); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_SkullRodStorm -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_SkullRodStorm) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - ARainTracker *tracker; - - if (self->health-- == 0) - { - S_StopSound (self, CHAN_BODY); - if (self->target == NULL) - { // Player left the game - self->Destroy (); - return 0; - } - tracker = self->target->FindInventory (); - if (tracker != NULL) - { - if (tracker->Rain1 == self) - { - tracker->Rain1 = NULL; - } - else if (tracker->Rain2 == self) - { - tracker->Rain2 = NULL; - } - } - self->Destroy (); - return 0; - } - if (pr_storm() < 25) - { // Fudge rain frequency - return 0; - } - double xo = ((pr_storm() & 127) - 64); - double yo = ((pr_storm() & 127) - 64); - DVector3 pos = self->Vec2OffsetZ(xo, yo, ONCEILINGZ); - mo = Spawn (pos, ALLOW_REPLACE); - // We used bouncecount to store the 3D floor index in A_HideInCeiling - if (!mo) return 0; - if (mo->Sector->PortalGroup != self->Sector->PortalGroup) - { - // spawning this through a portal will never work right so abort right away. - mo->Destroy(); - return 0; - } - if (self->bouncecount >= 0 && (unsigned)self->bouncecount < self->Sector->e->XFloor.ffloors.Size()) - pos.Z = self->Sector->e->XFloor.ffloors[self->bouncecount]->bottom.plane->ZatPoint(mo); - else - pos.Z = self->Sector->ceilingplane.ZatPoint(mo); - int moceiling = P_Find3DFloor(NULL, pos, false, false, pos.Z); - if (moceiling >= 0) mo->SetZ(pos.Z - mo->Height); - mo->Translation = multiplayer ? TRANSLATION(TRANSLATION_RainPillar,self->special2) : 0; - mo->target = self->target; - mo->Vel.X = MinVel; // Force collision detection - mo->Vel.Z = -mo->Speed; - mo->special2 = self->special2; // Transfer player number - P_CheckMissileSpawn (mo, self->radius); - if (self->special1 != -1 && !S_IsActorPlayingSomething (self, CHAN_BODY, -1)) - { - S_Sound (self, CHAN_BODY|CHAN_LOOP, self->special1, 1, ATTN_NORM); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_RainImpact -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_RainImpact) -{ - PARAM_SELF_PROLOGUE(AActor); - if (self->Z() > self->floorz) - { - self->SetState (self->FindState("NotFloor")); - } - else if (pr_impact() < 40) - { - P_HitFloor (self); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_HideInCeiling -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_HideInCeiling) -{ - PARAM_SELF_PROLOGUE(AActor); - - // We use bouncecount to store the 3D floor index - double foo; - for (int i = self->Sector->e->XFloor.ffloors.Size() - 1; i >= 0; i--) - { - F3DFloor * rover = self->Sector->e->XFloor.ffloors[i]; - if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; - - if ((foo = rover->bottom.plane->ZatPoint(self)) >= self->Top()) - { - self->SetZ(foo + 4, false); - self->bouncecount = i; - return 0; - } - } - self->bouncecount = -1; - self->SetZ(self->ceilingz + 4, false); - return 0; -} - // --- Phoenix Rod ---------------------------------------------------------- class APhoenixRod : public AWeapon diff --git a/src/namedef.h b/src/namedef.h index b7365b2b21..779c2e1329 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -764,3 +764,22 @@ xx(a) xx(r) xx(g) xx(b) + +// Special translation names +xx(RainPillar1) +xx(RainPillar2) +xx(RainPillar3) +xx(RainPillar4) +xx(RainPillar5) +xx(RainPillar6) +xx(RainPillar7) +xx(RainPillar8) + +xx(Player1) +xx(Player2) +xx(Player3) +xx(Player4) +xx(Player5) +xx(Player6) +xx(Player7) +xx(Player8) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 24c98f86c0..95bcb3e25e 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -6802,7 +6802,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetVisibleRotation) DEFINE_ACTION_FUNCTION(AActor, A_SetTranslation) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STRING(trname); + PARAM_NAME(trname); self->SetTranslation(trname); return 0; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index cde2eb0b46..f956d8911a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1089,6 +1089,14 @@ AInventory *AActor::GiveInventoryType (PClassActor *type) return item; } +DEFINE_ACTION_FUNCTION(AActor, GiveInventoryType) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(type, AInventory); + ACTION_RETURN_OBJECT(self->GiveInventoryType(type)); +} + + //============================================================================ // // AActor :: GiveAmmo @@ -7098,9 +7106,10 @@ int AActor::ApplyDamageFactor(FName damagetype, int damage) const } -void AActor::SetTranslation(const char *trname) +void AActor::SetTranslation(FName trname) { - if (*trname == 0) + // There is no constant for the empty name... + if (trname.GetChars()[0] == 0) { // an empty string resets to the default Translation = GetDefault()->Translation; @@ -7341,6 +7350,12 @@ DEFINE_ACTION_FUNCTION(AActor, RestoreDamage) return 0; } +DEFINE_ACTION_FUNCTION(AActor, PlayerNumber) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(self->player ? int(self->player - players) : 0); +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 5ed4cd1442..e93d718cd6 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -960,7 +960,7 @@ double sector_t::NextHighestCeilingAt(double x, double y, double bottomz, double } } if ((flags & FFCF_NOPORTALS) || sec->PortalBlocksMovement(ceiling) || planeheight >= sec->GetPortalPlaneZ(ceiling)) - { // Use sector's floor + { // Use sector's ceiling if (resultffloor) *resultffloor = NULL; if (resultsec) *resultsec = sec; return realceil; @@ -976,6 +976,34 @@ double sector_t::NextHighestCeilingAt(double x, double y, double bottomz, double } } +DEFINE_ACTION_FUNCTION(_Sector, NextHighestCeilingAt) +{ + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(bottomz); + PARAM_FLOAT(topz); + PARAM_INT_DEF(flags); + sector_t *resultsec; + F3DFloor *resultff; + double resultheight = self->NextHighestCeilingAt(x, y, bottomz, topz, flags, &resultsec, &resultff); + + if (numret > 2) + { + ret[2].SetPointer(resultff, ATAG_GENERIC); + numret = 3; + } + if (numret > 1) + { + ret[1].SetPointer(resultsec, ATAG_GENERIC); + } + if (numret > 0) + { + ret[0].SetFloat(resultheight); + } + return numret; +} + double sector_t::NextLowestFloorAt(double x, double y, double z, int flags, double steph, sector_t **resultsec, F3DFloor **resultffloor) { sector_t *sec = this; diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 983baea58c..3689d1c0f3 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -1196,20 +1196,37 @@ void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayer //---------------------------------------------------------------------------- static TMap customTranslationMap; -int R_FindCustomTranslation(const char *name) +int R_FindCustomTranslation(FName name) { - if (name == nullptr) - { - return -1; - } - // Ice is a special case which will remain in its original slot. - if (!stricmp(name, "Ice")) + switch (name) { + case NAME_Ice: + // Ice is a special case which will remain in its original slot. return TRANSLATION(TRANSLATION_Standard, 7); - } - else if (!stricmp(name, "None")) - { + + case NAME_None: return 0; + + case NAME_RainPillar1: + case NAME_RainPillar2: + case NAME_RainPillar3: + case NAME_RainPillar4: + case NAME_RainPillar5: + case NAME_RainPillar6: + case NAME_RainPillar7: + case NAME_RainPillar8: + return TRANSLATION(TRANSLATION_RainPillar, name.GetIndex() - NAME_RainPillar1); + + case NAME_Player1: + case NAME_Player2: + case NAME_Player3: + case NAME_Player4: + case NAME_Player5: + case NAME_Player6: + case NAME_Player7: + case NAME_Player8: + return TRANSLATION(TRANSLATION_Players, name.GetIndex() - NAME_Player1); + } int *t = customTranslationMap.CheckKey(FName(name, true)); return (t != nullptr)? *t : -1; diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index 4ca2f203fc..1680f4df08 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -110,7 +110,7 @@ extern TArray BloodTranslationColors; int CreateBloodTranslation(PalEntry color); -int R_FindCustomTranslation(const char *name); +int R_FindCustomTranslation(FName name); void R_ParseTrnslate(); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index a34e12f7db..908850e3e2 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7609,7 +7609,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) { bool writable; ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested. - if (ArgList[i]->ValueType != TypeNullPtr) + if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr) { ArgList[i]->RequestAddress(ctx, &writable); ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 3f7f27e437..1b93e22a51 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -700,6 +700,10 @@ void InitThingdef() PStruct *sstruct = NewNativeStruct("Sector", nullptr); auto sptr = NewPointer(sstruct); sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); + + // expose the glibal Multiplayer variable. + PField *multif = new PField("multiplayer", TypeBool, VARF_Native | VARF_ReadOnly | VARF_Static, (intptr_t)&multiplayer); + GlobalSymbols.AddSymbol(multif); // set up a variable for the global level data structure PStruct *lstruct = NewNativeStruct("LevelLocals", nullptr); @@ -708,8 +712,9 @@ void InitThingdef() // set up a variable for the DEH data PStruct *dstruct = NewNativeStruct("DehInfo", nullptr); - PField *dehi = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh); - GlobalSymbols.AddSymbol(dehi); + PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh); + + GlobalSymbols.AddSymbol(dehf); // set up a variable for the global players array. PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 3507e45a8b..7144c64e59 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -102,6 +102,7 @@ zscript/heretic/weaponcrossbow.txt zscript/heretic/weapongauntlets.txt zscript/heretic/weaponmace.txt zscript/heretic/weaponblaster.txt +zscript/heretic/weaponskullrod.txt zscript/hexen/baseweapons.txt zscript/hexen/korax.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 3eb855007e..1b13d05ffc 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -5,6 +5,7 @@ class Actor : Thinker native const ONCEILINGZ = 2147483647.0; const FLOATRANDZ = ONCEILINGZ-1; const TELEFRAG_DAMAGE = 1000000; + const MinVel = 1./65536; // flags are not defined here, the native fields for those get synthesized from the internal tables. @@ -263,6 +264,7 @@ class Actor : Thinker native virtual native int DoSpecialDamage (Actor target, int damage, Name damagetype); virtual native bool UseInventory(Inventory item); + native void AdjustPlayerAngle(FTranslatedLineTarget t); native static readonly GetDefaultByType(class cls); native static double GetDefaultSpeed(class type); @@ -273,6 +275,7 @@ class Actor : Thinker native native bool GiveBody (int num, int max=0); native bool HitFloor(); native bool isTeammate(Actor other); + native int PlayerNumber(); native void RestoreDamage(); native int SpawnHealth(); @@ -342,6 +345,7 @@ class Actor : Thinker native // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native Inventory FindInventory(class itemtype, bool subclass = false); + native Inventory GiveInventoryType(class itemtype); native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); native double GetDistance(bool checkz, int ptr = AAPTR_TARGET); native double GetAngle(int flags, int ptr = AAPTR_DEFAULT); @@ -720,7 +724,7 @@ class Actor : Thinker native 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(double anglestart = 0, double angleend = 0, double pitchstart = 0, double pitchend = 0, int flags = 0, int ptr = AAPTR_DEFAULT); - native void A_SetTranslation(string transname); + native void A_SetTranslation(name 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); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 160c1c5145..13aa480a99 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -122,6 +122,12 @@ struct State native native bool bDehacked; } -struct Sector native +struct F3DFloor native { } + +struct Sector native +{ + native double, Sector, F3DFloor NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0); +} + diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 68b81dc2b0..70f8abed09 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -953,4 +953,32 @@ enum EWeaponPos { WEAPONBOTTOM = 128, WEAPONTOP = 32 -} \ No newline at end of file +} + +enum ETranslationTable +{ + TRANSLATION_Invalid, + TRANSLATION_Players, + TRANSLATION_PlayersExtra, + TRANSLATION_Standard, + TRANSLATION_LevelScripted, + TRANSLATION_Decals, + TRANSLATION_PlayerCorpses, + TRANSLATION_Decorate, + TRANSLATION_Blood, + TRANSLATION_RainPillar, + TRANSLATION_Custom, +}; + +enum EFindFloorCeiling +{ + FFCF_ONLYSPAWNPOS = 1, + FFCF_SAMESECTOR = 2, + FFCF_ONLY3DFLOORS = 4, // includes 3D midtexes + FFCF_3DRESTRICT = 8, // ignore 3D midtexes and floors whose floorz are above thing's z + FFCF_NOPORTALS = 16, // ignore portals (considers them impassable.) + FFCF_NOFLOOR = 32, + FFCF_NOCEILING = 64, + FFCF_RESTRICTEDPORTAL = 128, // current values in the iterator's return are through a restricted portal type (i.e. some features are blocked.) + FFCF_NODROPOFF = 256, // Caller does not need a dropoff (saves some time when checking portals) +}; diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt index c3c641b4ea..1b84d13feb 100644 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ b/wadsrc/static/zscript/heretic/hereticweaps.txt @@ -8,206 +8,6 @@ class HereticWeapon : Weapon } -// 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 -{ - 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; - } - - override int DoSpecialDamage (Actor target, int damage, Name damagetype) - { - Sorcerer2 s2 = Sorcerer2(target); - if (s2 != null && random[HornRodFX2]() < 96) - { // D'Sparil teleports away - s2.DSparilTeleport (); - return -1; - } - return damage; - } - -} - -// 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 diff --git a/wadsrc/static/zscript/heretic/weaponskullrod.txt b/wadsrc/static/zscript/heretic/weaponskullrod.txt new file mode 100644 index 0000000000..a8d77e1d8c --- /dev/null +++ b/wadsrc/static/zscript/heretic/weaponskullrod.txt @@ -0,0 +1,425 @@ +// 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"; + } + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FireSkullRodPL1 + // + //---------------------------------------------------------------------------- + + action void A_FireSkullRodPL1() + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + Actor mo = SpawnPlayerMissile ("HornRodFX1"); + // Randomize the first frame + if (mo && random[FireSkullRod]() > 128) + { + mo.SetState (mo.CurState.NextState); + } + } + + +} + +class SkullRodPowered : SkullRod +{ + Default + { + +WEAPON.POWERED_UP + Weapon.AmmoUse1 5; + Weapon.AmmoGive1 0; + Weapon.SisterWeapon "SkullRod"; + Tag "$TAG_SKULLRODP"; + } + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FireSkullRodPL2 + // + // The special2 field holds the player number that shot the rain missile. + // The special1 field holds the id of the rain sound. + // + //---------------------------------------------------------------------------- + + action void A_FireSkullRodPL2() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + // Use MissileActor instead of the first return value from P_SpawnPlayerMissile + // because we need to give info to it, even if it exploded immediately. + Actor mo, MissileActor; + [mo, MissileActor] = SpawnPlayerMissile ("HornRodFX2", angle, pLineTarget: t); + if (MissileActor != null) + { + if (t.linetarget && !t.unlinked) + { + MissileActor.tracer = t.linetarget; + } + MissileActor.A_PlaySound ("weapons/hornrodpowshoot", CHAN_WEAPON); + } + } + + +} + +// 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 +{ + Default + { + Radius 12; + Height 8; + Speed 22; + Damage 10; + Health 140; + Projectile; + RenderStyle "Add"; + SeeSound "weapons/hornrodpowshoot"; + DeathSound "weapons/hornrodpowhit"; + Obituary "$OB_MPPSKULLROD"; + } + + 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; + } + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + Sorcerer2 s2 = Sorcerer2(target); + if (s2 != null && random[HornRodFX2]() < 96) + { // D'Sparil teleports away + s2.DSparilTeleport (); + return -1; + } + return damage; + } + + //---------------------------------------------------------------------------- + // + // PROC A_AddPlayerRain + // + //---------------------------------------------------------------------------- + + void A_AddPlayerRain() + { + RainTracker tracker; + + if (target == null || target.health <= 0) + { // Shooter is dead or nonexistant + return; + } + + tracker = RainTracker(target.FindInventory("RainTracker")); + + // They player is only allowed two rainstorms at a time. Shooting more + // than that will cause the oldest one to terminate. + if (tracker != null) + { + if (tracker.Rain1 && tracker.Rain2) + { // Terminate an active rain + if (tracker.Rain1.health < tracker.Rain2.health) + { + if (tracker.Rain1.health > 16) + { + tracker.Rain1.health = 16; + } + tracker.Rain1 = null; + } + else + { + if (tracker.Rain2.health > 16) + { + tracker.Rain2.health = 16; + } + tracker.Rain2 = null; + } + } + } + else + { + tracker = RainTracker(target.GiveInventoryType("RainTracker")); + } + // Add rain mobj to list + if (tracker.Rain1) + { + tracker.Rain2 = self; + } + else + { + tracker.Rain1 = self; + } + ActiveSound = "misc/rain"; + } + + //---------------------------------------------------------------------------- + // + // PROC A_HideInCeiling + // + //---------------------------------------------------------------------------- + + void A_HideInCeiling() + { + // This no longer hides in the ceiling. It just makes the actor invisible and keeps it in place. + // We need its actual position to determine the correct ceiling height in A_SkullRodStorm. + bInvisible = true; + bSolid = false; + bMissile = false; + Vel = (0,0,0); + } + + //---------------------------------------------------------------------------- + // + // PROC A_SkullRodStorm + // + //---------------------------------------------------------------------------- + + void A_SkullRodStorm() + { + static const Name translations[] = + { + "RainPillar1", "RainPillar2", "RainPillar3", "RainPillar4", + "RainPillar5", "RainPillar6", "RainPillar7", "RainPillar8" + }; + + if (health-- == 0) + { + A_StopSound (CHAN_BODY); + if (target == null) + { // Player left the game + Destroy (); + return; + } + RainTracker tracker = RainTracker(target.FindInventory("RainTracker")); + if (tracker != null) + { + if (tracker.Rain1 == self) + { + tracker.Rain1 = null; + } + else if (tracker.Rain2 == self) + { + tracker.Rain2 = null; + } + } + Destroy (); + return; + } + if (Random[SkullRodStorm]() < 25) + { // Fudge rain frequency + return; + } + double xo = ((Random[SkullRodStorm]() & 127) - 64); + double yo = ((Random[SkullRodStorm]() & 127) - 64); + Vector3 spawnpos = Vec2OffsetZ(xo, yo, pos.z); + Actor mo = Spawn("RainPillar", spawnpos, ALLOW_REPLACE); + if (!mo) return; + + // Find the ceiling above the spawn location. This may come from 3D floors but will not reach through portals. + // (should probably be fixed for portals, too.) + double newz = mo.CurSector.NextHighestCeilingAt(mo.pos.x, mo.pos.y, mo.pos.z, mo.pos.z, FFCF_NOPORTALS) - mo.height; + mo.SetZ(newz); + + if (multiplayer && target.player) + { + mo.A_SetTranslation(translations[target.PlayerNumber()]); + } + mo.target = target; + mo.Vel.X = MinVel; // Force collision detection + mo.Vel.Z = -mo.Speed; + mo.CheckMissileSpawn (radius); + if (ActiveSound > 0) A_PlaySound(ActiveSound, CHAN_BODY, 1, true); + } + + +} + +// Rain pillar 1 ------------------------------------------------------------ + +class RainPillar : Actor +{ + Default + { + Radius 5; + Height 12; + Speed 12; + Damage 5; + Mass 5; + Projectile; + -ACTIVATEPCROSS + -ACTIVATEIMPACT + RenderStyle "Add"; + Obituary "$OB_MPPSKULLROD"; + } + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_RainImpact + // + //---------------------------------------------------------------------------- + + void A_RainImpact() + { + if (pos.z > floorz) + { + SetStateLabel("NotFloor"); + } + else if (random[RainImpact]() < 40) + { + HitFloor (); + } + } + + // Rain pillar 1 ------------------------------------------------------------ + + int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if (target.bBoss) + { // Decrease damage for bosses + damage = random[RainDamage](1, 8); + } + return damage; + } +} + +// Rain tracker "inventory" item -------------------------------------------- + +class RainTracker : Inventory +{ + Actor Rain1, Rain2; + + Default + { + +INVENTORY.UNDROPPABLE + } +} From 53ff7f0c73ea46193d029c58897ed3a1a8191999 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 16:35:07 +0100 Subject: [PATCH 358/471] - fixed: Do not allow empty function arguments pass. For unknown reasons the grammar accepts them as valid, so this needs to be checked when resolving them. --- src/scripting/codegeneration/codegen.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 908850e3e2..ab0bb96e13 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6820,6 +6820,16 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) ABORT(ctx.Class); bool error = false; + for (auto a : ArgList) + { + if (a == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Empty function argument."); + delete this; + return nullptr; + } + } + PFunction *afd = FindClassMemberFunction(ctx.Class, ctx.Class, MethodName, ScriptPosition, &error); if (afd != nullptr) @@ -7071,6 +7081,16 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) PClass *ccls = nullptr; + for (auto a : ArgList) + { + if (a == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Empty function argument."); + delete this; + return nullptr; + } + } + if (Self->ExprType == EFX_Identifier) { ccls = PClass::FindClass(static_cast(Self)->Identifier); From 4f370ba18106340af31ef29df076dbcd78336f40 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 18:13:08 +0100 Subject: [PATCH 359/471] - scriptified the Phoenix Rod, completing the Heretic weapons. --- src/CMakeLists.txt | 1 - src/g_heretic/a_hereticmisc.cpp | 1 - src/g_heretic/a_hereticweaps.cpp | 285 -------------- src/g_shared/a_artifacts.cpp | 2 +- src/g_shared/a_pickups.h | 1 + src/g_shared/a_weapons.cpp | 21 ++ wadsrc/static/zscript.txt | 2 +- .../static/zscript/heretic/hereticweaps.txt | 184 ---------- .../static/zscript/heretic/weaponphoenix.txt | 347 ++++++++++++++++++ wadsrc/static/zscript/shared/inventory.txt | 1 + 10 files changed, 372 insertions(+), 473 deletions(-) delete mode 100644 src/g_heretic/a_hereticweaps.cpp delete mode 100644 wadsrc/static/zscript/heretic/hereticweaps.txt create mode 100644 wadsrc/static/zscript/heretic/weaponphoenix.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d4edae81e9..434d0c5203 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -858,7 +858,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.h sc_man_scanner.re g_heretic/a_hereticartifacts.cpp - g_heretic/a_hereticweaps.cpp g_hexen/a_blastradius.cpp g_hexen/a_boostarmor.cpp g_hexen/a_clericflame.cpp diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 5929c1d865..af9d10ba5b 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -20,4 +20,3 @@ // Include all the other Heretic stuff here to reduce compile time #include "a_hereticartifacts.cpp" -#include "a_hereticweaps.cpp" diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp deleted file mode 100644 index 7ec0364130..0000000000 --- a/src/g_heretic/a_hereticweaps.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* -#include "templates.h" -#include "actor.h" -#include "info.h" -#include "s_sound.h" -#include "m_random.h" -#include "a_pickups.h" -#include "d_player.h" -#include "p_pspr.h" -#include "p_local.h" -#include "gstrings.h" -#include "gi.h" -#include "r_data/r_translate.h" -#include "vm.h" -#include "doomstat.h" -*/ - -static FRandom pr_boltspark ("BoltSpark"); -static FRandom pr_macerespawn ("MaceRespawn"); -static FRandom pr_maceatk ("FireMacePL1"); -static FRandom pr_bfx1 ("BlasterFX1"); -static FRandom pr_ripd ("RipperD"); -static FRandom pr_fb1 ("FireBlasterPL1"); -static FRandom pr_bfx1t ("BlasterFX1Tick"); -static FRandom pr_rp ("RainPillar"); -static FRandom pr_fsr1 ("FireSkullRodPL1"); -static FRandom pr_storm ("SkullRodStorm"); -static FRandom pr_impact ("RainImpact"); -static FRandom pr_pfx1 ("PhoenixFX1"); -static FRandom pr_pfx2 ("PhoenixFX2"); -static FRandom pr_fp2 ("FirePhoenixPL2"); - -#define FLAME_THROWER_TICS (10*TICRATE) - -void P_DSparilTeleport (AActor *actor); - -#define USE_BLSR_AMMO_1 1 -#define USE_BLSR_AMMO_2 5 -#define USE_SKRD_AMMO_1 1 -#define USE_SKRD_AMMO_2 5 -#define USE_PHRD_AMMO_1 1 -#define USE_PHRD_AMMO_2 1 -#define USE_MACE_AMMO_1 1 -#define USE_MACE_AMMO_2 5 - -extern bool P_AutoUseChaosDevice (player_t *player); - - -// --- Phoenix Rod ---------------------------------------------------------- - -class APhoenixRod : public AWeapon -{ - DECLARE_CLASS (APhoenixRod, AWeapon) -public: - - void Serialize(FSerializer &arc) - { - Super::Serialize (arc); - arc("flamecount", FlameCount); - } - int FlameCount; // for flamethrower duration -}; - -class APhoenixRodPowered : public APhoenixRod -{ - DECLARE_CLASS (APhoenixRodPowered, APhoenixRod) -public: - void EndPowerup (); -}; - -IMPLEMENT_CLASS(APhoenixRod, false, false) -IMPLEMENT_CLASS(APhoenixRodPowered, false, false) - -void APhoenixRodPowered::EndPowerup () -{ - DepleteAmmo (bAltFire); - Owner->player->refire = 0; - S_StopSound (Owner, CHAN_WEAPON); - Owner->player->ReadyWeapon = SisterWeapon; - P_SetPsprite(Owner->player, PSP_WEAPON, SisterWeapon->GetReadyState()); -} - -// Phoenix FX 2 ------------------------------------------------------------- - -class APhoenixFX2 : public AActor -{ - DECLARE_CLASS (APhoenixFX2, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(APhoenixFX2, false, false) - -int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->player && pr_pfx2 () < 128) - { // Freeze player for a bit - target->reactiontime += 4; - } - return damage; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FirePhoenixPL1 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - P_SpawnPlayerMissile (self, PClass::FindActor("PhoenixFX1")); - self->Thrust(self->Angles.Yaw + 180, 4); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_PhoenixPuff -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *puff; - DAngle ang; - - //[RH] Heretic never sets the target for seeking - //P_SeekerMissile (self, 5, 10); - puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE); - ang = self->Angles.Yaw + 90; - puff->Vel = DVector3(ang.ToVector(1.3), 0); - - puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE); - ang = self->Angles.Yaw - 90; - puff->Vel = DVector3(ang.ToVector(1.3), 0); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_InitPhoenixPL2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_InitPhoenixPL2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - if (self->player != NULL) - { - APhoenixRod *flamethrower = static_cast (self->player->ReadyWeapon); - if (flamethrower != NULL) - { - flamethrower->FlameCount = FLAME_THROWER_TICS; - } - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FirePhoenixPL2 -// -// Flame thrower effect. -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *mo; - - double slope; - FSoundID soundid; - player_t *player; - APhoenixRod *flamethrower; - - if (nullptr == (player = self->player)) - { - return 0; - } - - soundid = "weapons/phoenixpowshoot"; - - flamethrower = static_cast (player->ReadyWeapon); - if (flamethrower == nullptr || --flamethrower->FlameCount == 0) - { // Out of flame - P_SetPsprite(player, PSP_WEAPON, flamethrower->FindState("Powerdown")); - player->refire = 0; - S_StopSound (self, CHAN_WEAPON); - return 0; - } - - slope = -self->Angles.Pitch.TanClamped(); - double xo = pr_fp2.Random2() / 128.; - double yo = pr_fp2.Random2() / 128.; - DVector3 pos = self->Vec3Offset(xo, yo, 26 + slope - self->Floorclip); - - slope += 0.1; - mo = Spawn("PhoenixFX2", pos, ALLOW_REPLACE); - mo->target = self; - mo->Angles.Yaw = self->Angles.Yaw; - mo->VelFromAngle(); - mo->Vel += self->Vel.XY(); - mo->Vel.Z = mo->Speed * slope; - if (!player->refire || !S_IsActorPlayingSomething (self, CHAN_WEAPON, -1)) - { - S_Sound (self, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM); - } - P_CheckMissileSpawn (mo, self->radius); - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_ShutdownPhoenixPL2 -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ShutdownPhoenixPL2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - S_StopSound (self, CHAN_WEAPON); - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FlameEnd -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FlameEnd) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Vel.Z += 1.5; - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FloatPuff -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_FloatPuff) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Vel.Z += 1.8; - return 0; -} - diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 73b71e2ffb..8548816473 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1185,7 +1185,7 @@ void APowerWeaponLevel2::EndEffect () if (player->ReadyWeapon != NULL && player->ReadyWeapon->WeaponFlags & WIF_POWERED_UP) { - player->ReadyWeapon->EndPowerup (); + player->ReadyWeapon->CallEndPowerup (); } if (player->PendingWeapon != NULL && player->PendingWeapon != WP_NOCHANGE && player->PendingWeapon->WeaponFlags & WIF_POWERED_UP && diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index bf4af5a635..0cfd04147f 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -342,6 +342,7 @@ public: virtual void PostMorphWeapon (); virtual void EndPowerup (); + void CallEndPowerup(); enum { diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index b94a4770ca..02cd19fa6d 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -18,6 +18,7 @@ #include "d_net.h" #include "serializer.h" #include "thingdef.h" +#include "virtual.h" #define BONUSADD 6 @@ -789,6 +790,26 @@ void AWeapon::EndPowerup () } } +DEFINE_ACTION_FUNCTION(AWeapon, EndPowerup) +{ + PARAM_SELF_PROLOGUE(AWeapon); + self->EndPowerup(); + return 0; +} + +void AWeapon::CallEndPowerup() +{ + IFVIRTUAL(AWeapon, EndPowerup) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } + else EndPowerup(); +} + + //=========================================================================== // // AWeapon :: GetUpState diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 7144c64e59..fa0cebd965 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -85,7 +85,6 @@ 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 @@ -103,6 +102,7 @@ zscript/heretic/weapongauntlets.txt zscript/heretic/weaponmace.txt zscript/heretic/weaponblaster.txt zscript/heretic/weaponskullrod.txt +zscript/heretic/weaponphoenix.txt zscript/hexen/baseweapons.txt zscript/hexen/korax.txt diff --git a/wadsrc/static/zscript/heretic/hereticweaps.txt b/wadsrc/static/zscript/heretic/hereticweaps.txt deleted file mode 100644 index 1b84d13feb..0000000000 --- a/wadsrc/static/zscript/heretic/hereticweaps.txt +++ /dev/null @@ -1,184 +0,0 @@ - -class HereticWeapon : Weapon -{ - Default - { - Weapon.Kickback 150; - } -} - - -// 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 -{ - 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; - } - - override int DoSpecialDamage (Actor target, int damage, Name damagetype) - { - Sorcerer2 s2 = Sorcerer2(target); - if (s2 != null && random[HornRodFX2]() < 96) - { // D'Sparil teleports away - s2.DSparilTeleport (); - return -1; - } - return damage; - } - -} - -// 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/weaponphoenix.txt b/wadsrc/static/zscript/heretic/weaponphoenix.txt new file mode 100644 index 0000000000..554d52d216 --- /dev/null +++ b/wadsrc/static/zscript/heretic/weaponphoenix.txt @@ -0,0 +1,347 @@ + +class HereticWeapon : Weapon +{ + Default + { + Weapon.Kickback 150; + } +} + + +// Phoenix Rod -------------------------------------------------------------- + +class PhoenixRod : Weapon +{ + 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"; + } + + 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; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FirePhoenixPL1 + // + //---------------------------------------------------------------------------- + + action void A_FirePhoenixPL1() + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + SpawnPlayerMissile ("PhoenixFX1"); + Thrust(4, angle + 180); + } + + +} + +class PhoenixRodPowered : PhoenixRod +{ + const FLAME_THROWER_TICS = (10*TICRATE); + + private int FlameCount; // for flamethrower duration + + Default + { + +WEAPON.POWERED_UP + +WEAPON.MELEEWEAPON + Weapon.SisterWeapon "PhoenixRod"; + Weapon.AmmoGive 0; + Tag "$TAG_PHOENIXRODP"; + } + + 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; + } + + + override void EndPowerup () + { + DepleteAmmo (bAltFire); + Owner.player.refire = 0; + Owner.A_StopSound (CHAN_WEAPON); + Owner.player.ReadyWeapon = SisterWeapon; + Owner.player.SetPsprite(PSP_WEAPON, SisterWeapon.GetReadyState()); + } + + //---------------------------------------------------------------------------- + // + // PROC A_InitPhoenixPL2 + // + //---------------------------------------------------------------------------- + + action void A_InitPhoenixPL2() + { + if (player != null) + { + PhoenixRodPowered flamethrower = PhoenixRodPowered(player.ReadyWeapon); + if (flamethrower != null) + { + flamethrower.FlameCount = FLAME_THROWER_TICS; + } + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_FirePhoenixPL2 + // + // Flame thrower effect. + // + //---------------------------------------------------------------------------- + + action void A_FirePhoenixPL2() + { + if (player == null) + { + return; + } + + PhoenixRodPowered flamethrower = PhoenixRodPowered(player.ReadyWeapon); + + if (flamethrower == null || --flamethrower.FlameCount == 0) + { // Out of flame + player.SetPsprite(PSP_WEAPON, flamethrower.FindState("Powerdown")); + player.refire = 0; + A_StopSound (CHAN_WEAPON); + return; + } + + double slope = -clamp(tan(pitch), -5, 5); + double xo = Random2[FirePhoenixPL2]() / 128.; + double yo = Random2[FirePhoenixPL2]() / 128.; + Vector3 spawnpos = Vec3Offset(xo, yo, 26 + slope - Floorclip); + + slope += 0.1; + Actor mo = Spawn("PhoenixFX2", spawnpos, ALLOW_REPLACE); + mo.target = self; + mo.Angle = Angle; + mo.VelFromAngle(); + mo.Vel.XY += Vel.XY; + mo.Vel.Z = mo.Speed * slope; + if (!player.refire) + { + A_PlaySound("weapons/phoenixpowshoot", CHAN_WEAPON, 1, true); + } + mo.CheckMissileSpawn (radius); + } + + //---------------------------------------------------------------------------- + // + // PROC A_ShutdownPhoenixPL2 + // + //---------------------------------------------------------------------------- + + action void A_ShutdownPhoenixPL2() + { + if (player == null) + { + return; + } + A_StopSound (CHAN_WEAPON); + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + weapon.DepleteAmmo (weapon.bAltFire); + } + } + + +} + +// Phoenix FX 1 ------------------------------------------------------------- + +class PhoenixFX1 : Actor +{ + Default + { + Radius 11; + Height 8; + Speed 20; + Damage 20; + DamageType "Fire"; + Projectile; + +THRUGHOST + +SPECIALFIREDAMAGE + SeeSound "weapons/phoenixshoot"; + DeathSound "weapons/phoenixhit"; + Obituary "$OB_MPPHOENIXROD"; + } + + 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; + } + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + Sorcerer2 s2 = Sorcerer2(target); + if (s2 != null && random[HornRodFX2]() < 96) + { // D'Sparil teleports away + s2.DSparilTeleport (); + return -1; + } + return damage; + } + + //---------------------------------------------------------------------------- + // + // PROC A_PhoenixPuff + // + //---------------------------------------------------------------------------- + + void A_PhoenixPuff() + { + //[RH] Heretic never sets the target for seeking + //P_SeekerMissile (self, 5, 10); + Actor puff = Spawn("PhoenixPuff", Pos, ALLOW_REPLACE); + puff.Vel.XY = AngleToVector(Angle + 90, 1.3); + + puff = Spawn("PhoenixPuff", Pos, ALLOW_REPLACE); + puff.Vel.XY = AngleToVector(Angle - 90, 1.3); + } + + +} + +// 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 +{ + Default + { + Radius 6; + Height 8; + Speed 10; + Damage 2; + DamageType "Fire"; + Projectile; + RenderStyle "Add"; + Obituary "$OB_MPPPHOENIXROD"; + } + + 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; + } + + + int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if (target.player && Random[PhoenixFX2]() < 128) + { // Freeze player for a bit + target.reactiontime += 4; + } + return damage; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FlameEnd + // + //---------------------------------------------------------------------------- + + void A_FlameEnd() + { + Vel.Z += 1.5; + } + + //---------------------------------------------------------------------------- + // + // PROC A_FloatPuff + // + //---------------------------------------------------------------------------- + + void A_FloatPuff() + { + Vel.Z += 1.8; + } + + +} diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 12e521d53f..52a346ce15 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -569,6 +569,7 @@ class Weapon : StateProvider native } native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); + native virtual void EndPowerup(); virtual State GetReadyState () { From 0d6f37835fbeba30b24b5ffe3f19fbd7ff100867 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 18:41:00 +0100 Subject: [PATCH 360/471] - completed Heretic scriptification with the two remaining artifacts. --- src/CMakeLists.txt | 5 -- src/dobject.h | 5 -- src/g_heretic/a_hereticartifacts.cpp | 63 ------------------- src/g_heretic/a_hereticmisc.cpp | 22 ------- src/g_shared/a_morph.cpp | 9 +++ src/g_shared/a_pickups.cpp | 27 +++++++- src/g_shared/a_pickups.h | 1 + src/p_mobj.cpp | 7 +-- .../zscript/heretic/hereticartifacts.txt | 37 ++++++++++- wadsrc/static/zscript/shared/inventory.txt | 3 + wadsrc/static/zscript/shared/player.txt | 2 + 11 files changed, 77 insertions(+), 104 deletions(-) delete mode 100644 src/g_heretic/a_hereticartifacts.cpp delete mode 100644 src/g_heretic/a_hereticmisc.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 434d0c5203..215e88b52d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -824,7 +824,6 @@ endif() file( GLOB HEADER_FILES ${EXTRA_HEADER_DIRS} fragglescript/*.h - g_heretic/*.h g_hexen/*.h g_raven/*.h g_shared/*.h @@ -857,7 +856,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_heretic/a_hereticartifacts.cpp g_hexen/a_blastradius.cpp g_hexen/a_boostarmor.cpp g_hexen/a_clericflame.cpp @@ -1148,7 +1146,6 @@ set (PCH_SOURCES w_wad.cpp wi_stuff.cpp zstrformat.cpp - g_heretic/a_hereticmisc.cpp g_hexen/a_hexenmisc.cpp g_raven/a_artitele.cpp g_raven/a_minotaur.cpp @@ -1303,7 +1300,6 @@ endif() target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma ) include_directories( . - g_heretic g_hexen g_raven g_strife @@ -1436,7 +1432,6 @@ source_group("External\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/m 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\\Heretic Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_heretic/.+") source_group("Games\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+") 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/.+") diff --git a/src/dobject.h b/src/dobject.h index cb1074c0c4..7d27133dc3 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -467,11 +467,6 @@ public: void SerializeUserVars(FSerializer &arc); virtual void Serialize(FSerializer &arc); - void VMSuperCall() - { - ObjectFlags |= OF_SuperCall; - } - void ClearClass() { Class = NULL; diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp deleted file mode 100644 index 2fb45c1242..0000000000 --- a/src/g_heretic/a_hereticartifacts.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "s_sound.h" -#include "vm.h" -*/ - -// Tome of power ------------------------------------------------------------ - -class AArtiTomeOfPower : public APowerupGiver -{ - DECLARE_CLASS (AArtiTomeOfPower, APowerupGiver) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiTomeOfPower, false, false) - -bool AArtiTomeOfPower::Use (bool pickup) -{ - if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYTOMEOFPOWER)) - { // Attempt to undo chicken - if (!P_UndoPlayerMorph (Owner->player, Owner->player, MORPH_UNDOBYTOMEOFPOWER)) - { // Failed - if (!(Owner->player->MorphStyle & MORPH_FAILNOTELEFRAG)) - { - P_DamageMobj (Owner, NULL, NULL, TELEFRAG_DAMAGE, NAME_Telefrag); - } - } - else - { // Succeeded - S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_IDLE); - } - return true; - } - else - { - return Super::Use (pickup); - } -} - -// Time bomb ---------------------------------------------------------------- - -class AArtiTimeBomb : public AInventory -{ - DECLARE_CLASS (AArtiTimeBomb, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiTimeBomb, false, false) - -bool AArtiTimeBomb::Use (bool pickup) -{ - AActor *mo = Spawn("ActivatedTimeBomb", - Owner->Vec3Angle(24., Owner->Angles.Yaw, - Owner->Floorclip), ALLOW_REPLACE); - mo->target = Owner; - return true; -} - diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp deleted file mode 100644 index af9d10ba5b..0000000000 --- a/src/g_heretic/a_hereticmisc.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "actor.h" -#include "info.h" -#include "a_pickups.h" -#include "a_action.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "gstrings.h" -#include "p_enemy.h" -#include "a_specialspot.h" -#include "g_level.h" -#include "a_sharedglobal.h" -#include "templates.h" -#include "r_data/r_translate.h" -#include "doomstat.h" -#include "d_player.h" -#include "a_morph.h" -#include "p_spec.h" -#include "serializer.h" - -// Include all the other Heretic stuff here to reduce compile time -#include "a_hereticartifacts.cpp" diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 5514ae4137..5ab1e3eb9b 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -372,6 +372,15 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, return true; } +DEFINE_ACTION_FUNCTION(_PlayerInfo, UndoPlayerMorph) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_POINTER(player, player_t); + PARAM_INT_DEF(unmorphflag); + PARAM_BOOL_DEF(force); + ACTION_RETURN_BOOL(P_UndoPlayerMorph(self, player, unmorphflag, force)); +} + //--------------------------------------------------------------------------- // // FUNC P_MorphMonster diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 16a63a2ff4..ee68a16db0 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -20,6 +20,7 @@ #include "d_player.h" #include "p_spec.h" #include "serializer.h" +#include "virtual.h" static FRandom pr_restore ("RestorePos"); @@ -1005,6 +1006,30 @@ bool AInventory::Use (bool pickup) return false; } +DEFINE_ACTION_FUNCTION(AInventory, Use) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_BOOL(pickup); + ACTION_RETURN_BOOL(self->Use(pickup)); +} + +bool AInventory::CallUse(bool pickup) +{ + IFVIRTUAL(AInventory, Use) + { + VMValue params[2] = { (DObject*)this, pickup }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + return !!retval; + + } + else return Use(pickup); +} + + //=========================================================================== // // AInventory :: Hide @@ -1494,7 +1519,7 @@ bool AInventory::TryPickup (AActor *&toucher) copy->AttachToOwner (newtoucher); if (ItemFlags & IF_AUTOACTIVATE) { - if (copy->Use (true)) + if (copy->CallUse (true)) { if (--copy->Amount <= 0) { diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 0cfd04147f..f035efeea8 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -204,6 +204,7 @@ public: virtual void GoAwayAndDie (); virtual bool HandlePickup (AInventory *item); virtual bool Use (bool pickup); + bool CallUse(bool pickup); virtual void Travelled (); virtual void OwnerDied (); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f956d8911a..d845846db8 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -955,7 +955,7 @@ bool AActor::DoUseInventory (AInventory *item) { return false; } - if (!item->Use (false)) + if (!item->CallUse (false)) { return false; } @@ -974,7 +974,6 @@ DEFINE_ACTION_FUNCTION(AActor, UseInventory) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(item, AInventory); - self->VMSuperCall(); ACTION_RETURN_BOOL(self->DoUseInventory(item)); } @@ -4149,7 +4148,6 @@ void AActor::Tick () DEFINE_ACTION_FUNCTION(AActor, Tick) { PARAM_SELF_PROLOGUE(AActor); - self->VMSuperCall(); self->Tick(); return 0; } @@ -4708,7 +4706,6 @@ DEFINE_ACTION_FUNCTION(AActor, Activate) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(activator, AActor); - self->VMSuperCall(); self->Activate(activator); return 0; } @@ -4756,7 +4753,6 @@ DEFINE_ACTION_FUNCTION(AActor, Deactivate) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(activator, AActor); - self->VMSuperCall(); self->Deactivate(activator); return 0; } @@ -6797,7 +6793,6 @@ DEFINE_ACTION_FUNCTION(AActor, DoSpecialDamage) PARAM_OBJECT(target, AActor); PARAM_INT(damage); PARAM_NAME(damagetype); - self->VMSuperCall(); ACTION_RETURN_INT(self->DoSpecialDamage(target, damage, damagetype)); } diff --git a/wadsrc/static/zscript/heretic/hereticartifacts.txt b/wadsrc/static/zscript/heretic/hereticartifacts.txt index 50a25008a3..3ef265735a 100644 --- a/wadsrc/static/zscript/heretic/hereticartifacts.txt +++ b/wadsrc/static/zscript/heretic/hereticartifacts.txt @@ -47,7 +47,7 @@ Class ArtiInvisibility : PowerupGiver // Tome of power ------------------------------------------------------------ -Class ArtiTomeOfPower : PowerupGiver native +Class ArtiTomeOfPower : PowerupGiver { Default { @@ -65,6 +65,31 @@ Class ArtiTomeOfPower : PowerupGiver native PWBK A 350; Loop; } + + bool Use (bool pickup) + { + Playerinfo p = Owner.player; + if (p && p.morphTics && (p.MorphStyle & MRF_UNDOBYTOMEOFPOWER)) + { // Attempt to undo chicken + if (!p.UndoPlayerMorph (p, MRF_UNDOBYTOMEOFPOWER)) + { // Failed + if (!(p.MorphStyle & MRF_FAILNOTELEFRAG)) + { + Owner.DamageMobj (null, null, TELEFRAG_DAMAGE, 'Telefrag'); + } + } + else + { // Succeeded + Owner.A_PlaySound ("*evillaugh", CHAN_VOICE); + } + return true; + } + else + { + return Super.Use (pickup); + } + } + } @@ -99,7 +124,7 @@ Class ActivatedTimeBomb : Actor } -Class ArtiTimeBomb : Inventory native +Class ArtiTimeBomb : Inventory { Default { @@ -120,4 +145,12 @@ Class ArtiTimeBomb : Inventory native FBMB E 350; Loop; } + + override bool Use (bool pickup) + { + Actor mo = Spawn("ActivatedTimeBomb", Owner.Vec3Angle(24., Owner.angle, - Owner.Floorclip), ALLOW_REPLACE); + mo.target = Owner; + return true; + } + } diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 52a346ce15..c2c99453fa 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -25,6 +25,9 @@ class Inventory : Actor native Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"; } + virtual native bool Use (bool pickup); + + // These are regular functions for the item itself. private native void A_RestoreSpecialDoomThing(); private native void A_RestoreSpecialThing1(); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index ed95354f89..e76e637fe5 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -213,8 +213,10 @@ FWeaponSlots weapons; */ + native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false); native void SetPsprite(int id, State stat, bool pending = false); native void SetSafeFlash(Weapon weap, State flashstate, int index); native PSprite GetPSprite(int id); native PSprite FindPSprite(int id); + } From 6e1c6c4b33ac0360cb58b72a129423ba006f7293 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Nov 2016 19:52:35 +0100 Subject: [PATCH 361/471] - scriptified ArtiTeleport. - shortened ArtiEgg and ArtiPork's use state to a single function. --- src/CMakeLists.txt | 1 - src/g_game.cpp | 36 +++++++++++++ src/g_raven/a_artitele.cpp | 63 ----------------------- src/p_teleport.cpp | 11 ++++ wadsrc/static/zscript/actor.txt | 3 +- wadsrc/static/zscript/base.txt | 2 + wadsrc/static/zscript/constants.txt | 11 ++++ wadsrc/static/zscript/heretic/dsparil.txt | 2 +- wadsrc/static/zscript/raven/artiegg.txt | 18 +++---- wadsrc/static/zscript/raven/artitele.txt | 34 +++++++++++- 10 files changed, 104 insertions(+), 77 deletions(-) delete mode 100644 src/g_raven/a_artitele.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 215e88b52d..bca0e93712 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1147,7 +1147,6 @@ set (PCH_SOURCES wi_stuff.cpp zstrformat.cpp g_hexen/a_hexenmisc.cpp - g_raven/a_artitele.cpp g_raven/a_minotaur.cpp g_strife/a_strifestuff.cpp g_strife/strife_sbar.cpp diff --git a/src/g_game.cpp b/src/g_game.cpp index 810a29da10..9af9b4532f 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1536,6 +1536,23 @@ static FPlayerStart *SelectRandomDeathmatchSpot (int playernum, unsigned int sel return &deathmatchstarts[i]; } +DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart) +{ + PARAM_PROLOGUE; + unsigned int selections = deathmatchstarts.Size(); + unsigned int i = pr_dmspawn() % selections; + if (numret > 1) + { + ret[1].SetInt(deathmatchstarts[i].angle); + numret = 2; + } + if (numret > 0) + { + ret[0].SetVector(deathmatchstarts[i].pos); + } + return numret; +} + void G_DeathMatchSpawnPlayer (int playernum) { unsigned int selections; @@ -1577,6 +1594,7 @@ void G_DeathMatchSpawnPlayer (int playernum) if (mo != NULL) P_PlayerStartStomp(mo); } + // // G_PickPlayerStart // @@ -1614,6 +1632,24 @@ FPlayerStart *G_PickPlayerStart(int playernum, int flags) return &playerstarts[playernum]; } +DEFINE_ACTION_FUNCTION(DObject, G_PickPlayerStart) +{ + PARAM_PROLOGUE; + PARAM_INT(playernum); + PARAM_INT_DEF(flags); + auto ps = G_PickPlayerStart(playernum, flags); + if (numret > 1) + { + ret[1].SetInt(ps? ps->angle : 0); + numret = 2; + } + if (numret > 0) + { + ret[0].SetVector(ps ? ps->pos : DVector3(0, 0, 0)); + } + return numret; +} + // // G_QueueBody // diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp deleted file mode 100644 index 76c0bc402f..0000000000 --- a/src/g_raven/a_artitele.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "p_spec.h" -#include "gi.h" -#include "s_sound.h" -#include "m_random.h" -#include "doomstat.h" -#include "g_game.h" -#include "d_player.h" -#include "a_morph.h" - -static FRandom pr_tele ("TeleportSelf"); - -// Teleport (self) ---------------------------------------------------------- - -class AArtiTeleport : public AInventory -{ - DECLARE_CLASS (AArtiTeleport, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiTeleport, false, false) - -bool AArtiTeleport::Use (bool pickup) -{ - DVector3 dest; - int destAngle; - - if (deathmatch) - { - unsigned int selections = deathmatchstarts.Size (); - unsigned int i = pr_tele() % selections; - dest = deathmatchstarts[i].pos; - destAngle = deathmatchstarts[i].angle; - } - else - { - FPlayerStart *start = G_PickPlayerStart(int(Owner->player - players)); - dest = start->pos; - destAngle = start->angle; - } - dest.Z = ONFLOORZ; - P_Teleport (Owner, dest, (double)destAngle, TELF_SOURCEFOG | TELF_DESTFOG); - bool canlaugh = true; - if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYCHAOSDEVICE)) - { // Teleporting away will undo any morph effects (pig) - if (!P_UndoPlayerMorph (Owner->player, Owner->player, MORPH_UNDOBYCHAOSDEVICE) - && (Owner->player->MorphStyle & MORPH_FAILNOLAUGH)) - { - canlaugh = false; - } - } - if (canlaugh) - { // Full volume laugh - S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_NONE); - } - return true; -} - diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index 14055202a2..e9752ee53e 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -238,6 +238,17 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) return true; } +DEFINE_ACTION_FUNCTION(AActor, Teleport) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_ANGLE(an); + PARAM_INT(flags); + ACTION_RETURN_BOOL(P_Teleport(self, DVector3(x, y, z), an, flags)); +} + static AActor *SelectTeleDest (int tid, int tag, bool norandom) { AActor *searcher; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 1b13d05ffc..45b44f7673 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -306,6 +306,7 @@ class Actor : Thinker native native Actor OldSpawnMissile(Actor dest, class type, Actor owner = null); native Actor SpawnPuff(class pufftype, vector3 pos, double hitdir, double particledir, int updown, int flags = 0, Actor vict = null); + native bool Teleport(Vector3 pos, double angle, int flags); 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); @@ -318,7 +319,7 @@ class Actor : Thinker native native void NewChaseDir(); native bool CheckMissileRange(); native bool SetState(state st, bool nofunction = false); - native state FindState(statelabel st, bool exact = false); // do we need exact later? + native state FindState(statelabel st, bool exact = false); 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(); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 13aa480a99..6d0e777959 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -5,6 +5,8 @@ class Object native // These really should be global functions... native static int G_SkillPropertyInt(int p); native static double G_SkillPropertyFloat(int p); + native static vector3, int G_PickDeathmatchStart(); + native static vector3, int G_PickPlayerStart(int pnum, int flags = 0); /*virtual*/ native void Destroy(); } diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 70f8abed09..d87ad338a6 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -982,3 +982,14 @@ enum EFindFloorCeiling FFCF_RESTRICTEDPORTAL = 128, // current values in the iterator's return are through a restricted portal type (i.e. some features are blocked.) FFCF_NODROPOFF = 256, // Caller does not need a dropoff (saves some time when checking portals) }; + +enum ETeleport +{ + TELF_DESTFOG = 1, + TELF_SOURCEFOG = 2, + TELF_KEEPORIENTATION = 4, + TELF_KEEPVELOCITY = 8, + TELF_KEEPHEIGHT = 16, + TELF_ROTATEBOOM = 32, + TELF_ROTATEBOOMINVERSE = 64, +}; diff --git a/wadsrc/static/zscript/heretic/dsparil.txt b/wadsrc/static/zscript/heretic/dsparil.txt index e2cfca558d..54931b65e8 100644 --- a/wadsrc/static/zscript/heretic/dsparil.txt +++ b/wadsrc/static/zscript/heretic/dsparil.txt @@ -345,7 +345,7 @@ class Sorcerer2 : Actor { return; } - A_PlaySound (AttackSound, CHAN_BODY); + A_PlaySound (AttackSound, CHAN_BODY, 1, false, ATTN_NONE); if (CheckMeleeRange()) { int damage = random[Srcr2Atk](1, 8) * 20; diff --git a/wadsrc/static/zscript/raven/artiegg.txt b/wadsrc/static/zscript/raven/artiegg.txt index ef3c6e2be8..f0287048ec 100644 --- a/wadsrc/static/zscript/raven/artiegg.txt +++ b/wadsrc/static/zscript/raven/artiegg.txt @@ -47,11 +47,10 @@ class ArtiEgg : CustomInventory 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); + TNT1 A 0 + { + for (double i = -15; i <= 15; i += 7.5) A_FireCustomMissile("EggFX", i, 0, 0, 0, 1); + } Stop; } } @@ -103,11 +102,10 @@ class ArtiPork : CustomInventory 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); + TNT1 A 0 + { + for (double i = -15; i <= 15; i += 7.5) A_FireCustomMissile("PorkFX", i, 0, 0, 0, 1); + } Stop; } } diff --git a/wadsrc/static/zscript/raven/artitele.txt b/wadsrc/static/zscript/raven/artitele.txt index 9f21bd7337..3242db92e6 100644 --- a/wadsrc/static/zscript/raven/artitele.txt +++ b/wadsrc/static/zscript/raven/artitele.txt @@ -1,7 +1,7 @@ // Teleport (self) ---------------------------------------------------------- -class ArtiTeleport : Inventory native +class ArtiTeleport : Inventory { Default { @@ -22,6 +22,38 @@ class ArtiTeleport : Inventory native ATLP ABCB 4; Loop; } + + override bool Use (bool pickup) + { + Vector3 dest; + int destAngle; + + if (deathmatch) + { + [dest, destAngle] = G_PickDeathmatchStart(); + } + else + { + [dest, destAngle] = G_PickPlayerStart(Owner.PlayerNumber()); + } + dest.Z = ONFLOORZ; + Owner.Teleport (dest, destAngle, TELF_SOURCEFOG | TELF_DESTFOG); + bool canlaugh = true; + Playerinfo p = Owner.player; + if (p && p.morphTics && (p.MorphStyle & MRF_UNDOBYCHAOSDEVICE)) + { // Teleporting away will undo any morph effects (pig) + if (!p.UndoPlayerMorph (p, MRF_UNDOBYCHAOSDEVICE) && (p.MorphStyle & MRF_FAILNOLAUGH)) + { + canlaugh = false; + } + } + if (canlaugh) + { // Full volume laugh + A_PlaySound ("*evillaugh", CHAN_VOICE, 1, false, ATTN_NONE); + } + return true; + } + } From 7385cd70c04f471c6a3e5c2a4daba6463359d4c2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 01:14:47 +0100 Subject: [PATCH 362/471] - scriptified the Minotaur. Interesting tidbit: The damage calculation in P_MinotaurSlam had been incorrect for the Heretic version since the friendly Hexen Dark Servant was added, but nobody ever noticed in 14 years... --- src/CMakeLists.txt | 5 - src/actor.h | 2 + src/g_hexen/a_hexenmisc.cpp | 2 - src/g_hexen/a_summon.cpp | 85 ---- src/g_raven/a_minotaur.cpp | 623 ----------------------- src/g_raven/ravenshared.h | 29 -- src/g_shared/a_morph.cpp | 2 +- src/g_strife/a_alienspectres.cpp | 2 +- src/g_strife/a_strifestuff.cpp | 2 +- src/p_interaction.cpp | 26 +- src/p_map.cpp | 16 +- src/p_maputl.cpp | 8 + src/p_mobj.cpp | 47 +- src/p_user.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 79 ++- src/scripting/thingdef_data.cpp | 13 +- src/w_wad.cpp | 9 + wadsrc/static/zscript/actor.txt | 7 + wadsrc/static/zscript/base.txt | 31 ++ wadsrc/static/zscript/constants.txt | 14 + wadsrc/static/zscript/hexen/summon.txt | 68 ++- wadsrc/static/zscript/raven/minotaur.txt | 551 +++++++++++++++++++- 22 files changed, 834 insertions(+), 789 deletions(-) delete mode 100644 src/g_hexen/a_summon.cpp delete mode 100644 src/g_raven/a_minotaur.cpp delete mode 100644 src/g_raven/ravenshared.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bca0e93712..95db06b2fe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -825,7 +825,6 @@ file( GLOB HEADER_FILES ${EXTRA_HEADER_DIRS} fragglescript/*.h g_hexen/*.h - g_raven/*.h g_shared/*.h g_strife/*.h intermission/*.h @@ -878,7 +877,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_magestaff.cpp g_hexen/a_serpent.cpp g_hexen/a_spike.cpp - g_hexen/a_summon.cpp g_hexen/a_teleportother.cpp g_strife/a_acolyte.cpp g_strife/a_alienspectres.cpp @@ -1147,7 +1145,6 @@ set (PCH_SOURCES wi_stuff.cpp zstrformat.cpp g_hexen/a_hexenmisc.cpp - g_raven/a_minotaur.cpp g_strife/a_strifestuff.cpp g_strife/strife_sbar.cpp g_shared/a_action.cpp @@ -1300,7 +1297,6 @@ endif() target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma ) include_directories( . g_hexen - g_raven g_strife g_shared oplsynth @@ -1432,7 +1428,6 @@ source_group("External\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_D source_group("Externak\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+") source_group("Games\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+") -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("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+") diff --git a/src/actor.h b/src/actor.h index bdb5241d16..f6020d2922 100644 --- a/src/actor.h +++ b/src/actor.h @@ -628,6 +628,7 @@ public: // Called when actor dies virtual void Die (AActor *source, AActor *inflictor, int dmgflags = 0); + void CallDie(AActor *source, AActor *inflictor, int dmgflags = 0); // Perform some special damage action. Returns the amount of damage to do. // Returning -1 signals the damage routine to exit immediately @@ -660,6 +661,7 @@ public: // Actor had MF_SKULLFLY set and rammed into something // Returns false to stop moving and true to keep moving virtual bool Slam (AActor *victim); + bool CallSlam(AActor *victim); // Called by PIT_CheckThing() and needed for some Hexen things. // Returns -1 for normal behavior, 0 to return false, and 1 to return true. diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index f98305cbaf..f442df65e8 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -15,7 +15,6 @@ #include "p_lnspec.h" #include "p_terrain.h" #include "m_bbox.h" -#include "ravenshared.h" #include "v_palette.h" #include "g_game.h" #include "p_blockmap.h" @@ -47,5 +46,4 @@ #include "a_magestaff.cpp" #include "a_serpent.cpp" #include "a_spike.cpp" -#include "a_summon.cpp" #include "a_teleportother.cpp" diff --git a/src/g_hexen/a_summon.cpp b/src/g_hexen/a_summon.cpp deleted file mode 100644 index 58e50eeafc..0000000000 --- a/src/g_hexen/a_summon.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "s_sound.h" -#include "ravenshared.h" -#include "vm.h" -#include "g_level.h" -*/ - -void A_Summon (AActor *); - -// Dark Servant Artifact ---------------------------------------------------- - -class AArtiDarkServant : public AInventory -{ - DECLARE_CLASS (AArtiDarkServant, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiDarkServant, false, false) - -//============================================================================ -// -// Activate the summoning artifact -// -//============================================================================ - -bool AArtiDarkServant::Use (bool pickup) -{ - AActor *mo = P_SpawnPlayerMissile (Owner, PClass::FindActor("SummoningDoll")); - if (mo) - { - mo->target = Owner; - mo->tracer = Owner; - mo->Vel.Z = 5; - } - return true; -} - -//============================================================================ -// -// A_Summon -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_Summon) -{ - PARAM_SELF_PROLOGUE(AActor); - - AMinotaurFriend *mo; - - mo = Spawn(self->Pos(), ALLOW_REPLACE); - if (mo) - { - if (P_TestMobjLocation(mo) == false || !self->tracer) - { // Didn't fit - change back to artifact - mo->Destroy(); - AActor *arti = Spawn(self->Pos(), ALLOW_REPLACE); - if (arti) arti->flags |= MF_DROPPED; - return 0; - } - - mo->StartTime = level.maptime; - if (self->tracer->flags & MF_CORPSE) - { // Master dead - mo->tracer = NULL; // No master - } - else - { - mo->tracer = self->tracer; // Pointer to master - AInventory *power = Spawn(); - power->CallTryPickup(self->tracer); - mo->SetFriendPlayer(self->tracer->player); - } - - // Make smoke puff - Spawn("MinotaurSmoke", self->Pos(), ALLOW_REPLACE); - S_Sound(self, CHAN_VOICE, mo->ActiveSound, 1, ATTN_NORM); - } - return 0; -} diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp deleted file mode 100644 index cd0ab2669b..0000000000 --- a/src/g_raven/a_minotaur.cpp +++ /dev/null @@ -1,623 +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 "ravenshared.h" -#include "a_action.h" -#include "gi.h" -#include "w_wad.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) - -static FRandom pr_minotauratk1 ("MinotaurAtk1"); -static FRandom pr_minotaurdecide ("MinotaurDecide"); -static FRandom pr_atk ("MinotaurAtk2"); -static FRandom pr_minotauratk3 ("MinotaurAtk3"); -static FRandom pr_fire ("MntrFloorFire"); -static FRandom pr_minotaurslam ("MinotaurSlam"); -static FRandom pr_minotaurroam ("MinotaurRoam"); -static FRandom pr_minotaurchase ("MinotaurChase"); - -void P_MinotaurSlam (AActor *source, AActor *target); - -DECLARE_ACTION(A_MinotaurLook) - -IMPLEMENT_CLASS(AMinotaur, false, false) - -void AMinotaur::Tick () -{ - Super::Tick (); - - // The unfriendly Minotaur (Heretic's) is invulnerable while charging - if (!(flags5 & MF5_SUMMONEDMONSTER)) - { - // Get MF_SKULLFLY bit and shift it so it matches MF2_INVULNERABLE - DWORD flying = (flags & MF_SKULLFLY) << 3; - if ((flags2 & MF2_INVULNERABLE) != flying) - { - flags2 ^= MF2_INVULNERABLE; - } - } -} - -bool AMinotaur::Slam (AActor *thing) -{ - // Slamming minotaurs shouldn't move non-creatures - if (!(thing->flags3&MF3_ISMONSTER) && !thing->player) - { - return false; - } - return Super::Slam (thing); -} - -int AMinotaur::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - damage = Super::DoSpecialDamage (target, damage, damagetype); - if ((damage != -1) && (flags & MF_SKULLFLY)) - { // Slam only when in charge mode - P_MinotaurSlam (this, target); - return -1; - } - return damage; -} - -// Minotaur Friend ---------------------------------------------------------- - -IMPLEMENT_CLASS(AMinotaurFriend, false, false) - -void AMinotaurFriend::BeginPlay () -{ - Super::BeginPlay (); - StartTime = -1; -} - -void AMinotaurFriend::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - arc("starttime", StartTime); -} - -void AMinotaurFriend::Die (AActor *source, AActor *inflictor, int dmgflags) -{ - Super::Die (source, inflictor, dmgflags); - - if (tracer && tracer->health > 0 && tracer->player) - { - // Search thinker list for minotaur - TThinkerIterator iterator; - AMinotaurFriend *mo; - - while ((mo = iterator.Next()) != NULL) - { - if (mo->health <= 0) continue; - // [RH] Minotaurs can't be morphed, so this isn't needed - //if (!(mo->flags&MF_COUNTKILL)) continue; // for morphed minotaurs - if (mo->flags&MF_CORPSE) continue; - if (mo->StartTime >= 0 && (level.maptime - StartTime) >= MAULATORTICS) continue; - if (mo->tracer != NULL && mo->tracer->player == tracer->player) break; - } - - if (mo == NULL) - { - AInventory *power = tracer->FindInventory(PClass::FindActor("PowerMinotaur")); - if (power != NULL) - { - power->Destroy (); - } - } - } -} - -// Action functions for the minotaur ---------------------------------------- - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk1 -// -// Melee attack. -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDeath) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (Wads.CheckNumForName ("MNTRF1", ns_sprites) < 0 && - Wads.CheckNumForName ("MNTRF0", ns_sprites) < 0) - self->SetState(self->FindState ("FadeOut")); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk1) -{ - PARAM_SELF_PROLOGUE(AActor); - - player_t *player; - - if (!self->target) - { - return 0; - } - S_Sound (self, CHAN_WEAPON, "minotaur/melee", 1, ATTN_NORM); - if (self->CheckMeleeRange()) - { - int damage = pr_minotauratk1.HitDice (4); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - if ((player = self->target->player) != NULL && - player->mo == self->target) - { // Squish the player - player->deltaviewheight = -16; - } - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurDecide -// -// Choose a missile attack. -// -//---------------------------------------------------------------------------- - -#define MNTR_CHARGE_SPEED (13.) - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide) -{ - PARAM_SELF_PROLOGUE(AActor); - - bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER); - AActor *target; - double dist; - - target = self->target; - if (!target) - { - return 0; - } - if (!friendly) - { - S_Sound (self, CHAN_WEAPON, "minotaur/sight", 1, ATTN_NORM); - } - dist = self->Distance2D(target); - if (target->Top() > self->Z() - && target->Top() < self->Top() - && dist < (friendly ? 16*64. : 8*64.) - && dist > 1*64. - && pr_minotaurdecide() < 150) - { // Charge attack - // Don't call the state function right away - self->SetState (self->FindState ("Charge"), true); - self->flags |= MF_SKULLFLY; - if (!friendly) - { // Heretic's Minotaur is invulnerable during charge attack - self->flags2 |= MF2_INVULNERABLE; - } - A_FaceTarget (self); - self->VelFromAngle(MNTR_CHARGE_SPEED); - self->special1 = TICRATE/2; // Charge duration - } - else if (target->Z() == target->floorz - && dist < 9*64. - && pr_minotaurdecide() < (friendly ? 100 : 220)) - { // Floor fire attack - self->SetState (self->FindState ("Hammer")); - self->special2 = 0; - } - else - { // Swing attack - A_FaceTarget (self); - // Don't need to call P_SetMobjState because the current state - // falls through to the swing attack - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurCharge -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurCharge) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *puff; - - if (self->target == NULL) - { - return 0; - } - if (self->special1 > 0) - { - PClassActor *type; - - if (gameinfo.gametype == GAME_Heretic) - { - type = PClass::FindActor("PhoenixPuff"); - } - else - { - type = PClass::FindActor("PunchPuff"); - } - puff = Spawn (type, self->Pos(), ALLOW_REPLACE); - puff->Vel.Z = 2; - self->special1--; - } - else - { - self->flags &= ~MF_SKULLFLY; - self->flags2 &= ~MF2_INVULNERABLE; - self->SetState (self->SeeState); - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk2 -// -// Swing attack. -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - DAngle angle; - double vz; - double z; - bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER); - - if (self->target == NULL) - { - return 0; - } - S_Sound (self, CHAN_WEAPON, "minotaur/attack2", 1, ATTN_NORM); - if (self->CheckMeleeRange()) - { - int damage; - damage = pr_atk.HitDice (friendly ? 3 : 5); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; - } - z = self->Z() + 40; - PClassActor *fx = PClass::FindActor("MinotaurFX1"); - if (fx) - { - mo = P_SpawnMissileZ (self, z, self->target, fx); - if (mo != NULL) - { -// S_Sound (mo, CHAN_WEAPON, "minotaur/attack2", 1, ATTN_NORM); - vz = mo->Vel.Z; - angle = mo->Angles.Yaw; - P_SpawnMissileAngleZ (self, z, fx, angle-(45./8), vz); - P_SpawnMissileAngleZ (self, z, fx, angle+(45./8), vz); - P_SpawnMissileAngleZ (self, z, fx, angle-(45./16), vz); - P_SpawnMissileAngleZ (self, z, fx, angle+(45./16), vz); - } - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk3 -// -// Floor fire attack. -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk3) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - player_t *player; - bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER); - - if (!self->target) - { - return 0; - } - S_Sound (self, CHAN_VOICE, "minotaur/attack3", 1, ATTN_NORM); - if (self->CheckMeleeRange()) - { - int damage; - - damage = pr_minotauratk3.HitDice (friendly ? 3 : 5); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - if ((player = self->target->player) != NULL && - player->mo == self->target) - { // Squish the player - player->deltaviewheight = -16; - } - } - else - { - if (self->Floorclip > 0 && (i_compatflags & COMPATF_MINOTAUR)) - { - // only play the sound. - S_Sound (self, CHAN_WEAPON, "minotaur/fx2hit", 1, ATTN_NORM); - } - else - { - mo = P_SpawnMissile (self, self->target, PClass::FindActor("MinotaurFX2")); - if (mo != NULL) - { - S_Sound (mo, CHAN_WEAPON, "minotaur/attack1", 1, ATTN_NORM); - } - } - } - if (pr_minotauratk3() < 192 && self->special2 == 0) - { - self->SetState (self->FindState ("HammerLoop")); - self->special2 = 1; - } - return 0; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MntrFloorFire -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MntrFloorFire) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - self->SetZ(self->floorz); - double x = pr_fire.Random2() / 64.; - double y = pr_fire.Random2() / 64.; - - mo = Spawn("MinotaurFX3", self->Vec2OffsetZ(x, y, self->floorz), ALLOW_REPLACE); - mo->target = self->target; - mo->Vel.X = MinVel; // Force block checking - P_CheckMissileSpawn (mo, self->radius); - return 0; -} - -//--------------------------------------------------------------------------- -// -// FUNC P_MinotaurSlam -// -//--------------------------------------------------------------------------- - -void P_MinotaurSlam (AActor *source, AActor *target) -{ - DAngle angle; - double thrust; - int damage; - - angle = source->AngleTo(target); - thrust = 16 + pr_minotaurslam() / 64.; - 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.); - if (target->player) - { - target->reactiontime = 14+(pr_minotaurslam()&7); - } -} - -//---------------------------------------------------------------------------- -// -// Minotaur variables -// -// special1 charge duration countdown -// special2 internal to minotaur AI -// StartTime minotaur start time -// tracer pointer to player that spawned it -//---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- -// -// A_MinotaurRoam -// -//---------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurRoam) -{ - PARAM_SELF_PROLOGUE(AActor); - - // In case pain caused him to skip his fade in. - self->RenderStyle = STYLE_Normal; - - if (self->IsKindOf(RUNTIME_CLASS(AMinotaurFriend))) - { - AMinotaurFriend *self1 = static_cast (self); - - if (self1->StartTime >= 0 && (level.maptime - self1->StartTime) >= MAULATORTICS) - { - P_DamageMobj (self1, NULL, NULL, TELEFRAG_DAMAGE, NAME_None); - return 0; - } - } - - if (pr_minotaurroam() < 30) - CALL_ACTION(A_MinotaurLook, self); // adjust to closest target - - if (pr_minotaurroam() < 6) - { - //Choose new direction - self->movedir = pr_minotaurroam() % 8; - FaceMovementDirection (self); - } - if (!P_Move(self)) - { - // Turn - if (pr_minotaurroam() & 1) - self->movedir = (self->movedir + 1) % 8; - else - self->movedir = (self->movedir + 7) % 8; - FaceMovementDirection (self); - } - return 0; -} - - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurLook -// -// Look for enemy of player -//---------------------------------------------------------------------------- -#define MINOTAUR_LOOK_DIST (16*54.) - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->IsKindOf(RUNTIME_CLASS(AMinotaurFriend))) - { - CALL_ACTION(A_Look, self); - return 0; - } - - AActor *mo = NULL; - player_t *player; - double dist; - int i; - AActor *master = self->tracer; - - self->target = NULL; - if (deathmatch) // Quick search for players - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) continue; - player = &players[i]; - mo = player->mo; - if (mo == master) continue; - if (mo->health <= 0) continue; - dist = self->Distance2D(mo); - if (dist > MINOTAUR_LOOK_DIST) continue; - self->target = mo; - break; - } - } - - if (!self->target) // Near player monster search - { - if (master && (master->health>0) && (master->player)) - mo = P_RoughMonsterSearch(master, 20); - else - mo = P_RoughMonsterSearch(self, 20); - self->target = mo; - } - - if (!self->target) // Normal monster search - { - FActorIterator iterator (0); - - while ((mo = iterator.Next()) != NULL) - { - if (!(mo->flags3 & MF3_ISMONSTER)) continue; - if (mo->health <= 0) continue; - if (!(mo->flags & MF_SHOOTABLE)) continue; - dist = self->Distance2D(mo); - if (dist > MINOTAUR_LOOK_DIST) continue; - if ((mo == master) || (mo == self)) continue; - if ((mo->flags5 & MF5_SUMMONEDMONSTER) && (mo->tracer == master)) continue; - self->target = mo; - break; // Found actor to attack - } - } - - if (self->target) - { - self->SetState (self->SeeState, true); - } - else - { - self->SetState (self->FindState ("Roam"), true); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_MinotaurChase) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->IsKindOf(RUNTIME_CLASS(AMinotaurFriend))) - { - A_Chase (stack, self); - return 0; - } - - AMinotaurFriend *self1 = static_cast (self); - - // In case pain caused him to skip his fade in. - self1->RenderStyle = STYLE_Normal; - - if (self1->StartTime >= 0 && (level.maptime - self1->StartTime) >= MAULATORTICS) - { - P_DamageMobj (self1, NULL, NULL, TELEFRAG_DAMAGE, NAME_None); - return 0; - } - - if (pr_minotaurchase() < 30) - CALL_ACTION(A_MinotaurLook, self1); // adjust to closest target - - if (!self1->target || (self1->target->health <= 0) || - !(self1->target->flags&MF_SHOOTABLE)) - { // look for a new target - self1->SetIdle(); - return 0; - } - - FaceMovementDirection (self1); - self1->reactiontime = 0; - - // Melee attack - if (self1->MeleeState && self1->CheckMeleeRange ()) - { - if (self1->AttackSound) - { - S_Sound (self1, CHAN_WEAPON, self1->AttackSound, 1, ATTN_NORM); - } - self1->SetState (self1->MeleeState); - return 0; - } - - // Missile attack - if (self1->MissileState && P_CheckMissileRange(self1)) - { - self1->SetState (self1->MissileState); - return 0; - } - - // chase towards target - if (!P_Move (self1)) - { - P_NewChaseDir (self1); - FaceMovementDirection (self1); - } - - // Active sound - if (pr_minotaurchase() < 6) - { - self1->PlayActiveSound (); - } - return 0; -} - diff --git a/src/g_raven/ravenshared.h b/src/g_raven/ravenshared.h deleted file mode 100644 index 3c6019ae72..0000000000 --- a/src/g_raven/ravenshared.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __RAVENSHARED_H__ -#define __RAVENSHARED_H__ - -class AActor; - -class AMinotaur : public AActor -{ - DECLARE_CLASS (AMinotaur, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); - -public: - bool Slam (AActor *); - void Tick (); -}; - -class AMinotaurFriend : public AMinotaur -{ - DECLARE_CLASS (AMinotaurFriend, AMinotaur) -public: - int StartTime; - - void Die (AActor *source, AActor *inflictor, int dmgflags); - void BeginPlay (); - - void Serialize(FSerializer &arc); -}; - -#endif //__RAVENSHARED_H__ diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 5ab1e3eb9b..2f986c201b 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -704,7 +704,7 @@ void AMorphedMonster::Die (AActor *source, AActor *inflictor, int dmgflags) if (UnmorphedMe != NULL && (UnmorphedMe->flags & MF_UNMORPHED)) { UnmorphedMe->health = health; - UnmorphedMe->Die (source, inflictor, dmgflags); + UnmorphedMe->CallDie (source, inflictor, dmgflags); } } diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp index a1c20355fe..194bfd9e09 100644 --- a/src/g_strife/a_alienspectres.cpp +++ b/src/g_strife/a_alienspectres.cpp @@ -136,7 +136,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath) if (oracle->health > 0) { oracle->health = 0; - oracle->Die (self, self); + oracle->CallDie (self, self); } } player->GiveInventoryType (QuestItemClasses[22]); diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 7cccdd3f36..6815b1d49d 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -119,7 +119,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GetHurt) } if (self->health <= 0) { - self->Die (self->target, self->target); + self->CallDie (self->target, self->target); } return 0; } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index aece79edc4..8c28c46b31 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -58,6 +58,7 @@ #include "d_net.h" #include "d_netinf.h" #include "a_morph.h" +#include "virtual.h" static FRandom pr_obituary ("Obituary"); static FRandom pr_botrespawn ("BotRespawn"); @@ -342,7 +343,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) realthis->health = realgibhealth -1; // if morphed was gibbed, so must original be (where allowed)l } } - realthis->Die(source, inflictor, dmgflags); + realthis->CallDie(source, inflictor, dmgflags); } return; } @@ -761,7 +762,26 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) } } +DEFINE_ACTION_FUNCTION(AActor, Die) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(source, AActor); + PARAM_OBJECT(inflictor, AActor); + PARAM_INT(dmgflags); + self->Die(source, inflictor, dmgflags); + return 0; +} +void AActor::CallDie(AActor *source, AActor *inflictor, int dmgflags) +{ + IFVIRTUAL(AActor, Die) + { + VMValue params[4] = { (DObject*)this, source, inflictor, dmgflags }; + VMFrameStack stack; + stack.Call(func, params, 4, nullptr, 0, nullptr); + } + else return Die(source, inflictor, dmgflags); +} //--------------------------------------------------------------------------- @@ -1443,7 +1463,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, source = source->tracer; } } - target->Die (source, inflictor, flags); + target->CallDie (source, inflictor, flags); return damage; } } @@ -1794,7 +1814,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, target->DamageType = player->poisontype; } } - target->Die(source, source); + target->CallDie(source, source); return; } } diff --git a/src/p_map.cpp b/src/p_map.cpp index f1fa55cf91..e6265be8ce 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1245,7 +1245,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch // Check for skulls slamming into things if (tm.thing->flags & MF_SKULLFLY) { - bool res = tm.thing->Slam(tm.thing->BlockingMobj); + bool res = tm.thing->CallSlam(tm.thing->BlockingMobj); tm.thing->BlockingMobj = NULL; return res; } @@ -3278,7 +3278,7 @@ bool FSlide::BounceWall(AActor *mo) if (mo->flags & MF_MISSILE) P_ExplodeMissile(mo, line, NULL); else - mo->Die(NULL, NULL); + mo->CallDie(NULL, NULL); return true; } @@ -4611,6 +4611,18 @@ void P_TraceBleed(int damage, AActor *target, DAngle angle, DAngle pitch) P_TraceBleed(damage, target->PosPlusZ(target->Height/2), target, angle, pitch); } +DEFINE_ACTION_FUNCTION(AActor, TraceBleedAngle) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(damage); + PARAM_FLOAT(angle); + PARAM_FLOAT(pitch); + + P_TraceBleed(damage, self, angle, pitch); + return 0; +} + + //========================================================================== // // diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 0a1d831d85..5bb3bea0f0 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1690,6 +1690,14 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable) return P_BlockmapSearch (mo, distance, RoughBlockCheck, (void *)onlyseekable); } +DEFINE_ACTION_FUNCTION(AActor, RoughMonsterSearch) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(distance); + PARAM_BOOL_DEF(onlyseekable); + ACTION_RETURN_OBJECT(P_RoughMonsterSearch(self, distance, onlyseekable)); +} + AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params) { int blockX; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d845846db8..559efda821 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -49,7 +49,6 @@ #include "p_acs.h" #include "cmdlib.h" #include "decallib.h" -#include "ravenshared.h" #include "a_action.h" #include "a_keys.h" #include "p_conversation.h" @@ -1787,7 +1786,7 @@ bool AActor::FloorBounceMissile (secplane_t &plane) if (flags & MF_MISSILE) P_ExplodeMissile(this, NULL, NULL); else - Die(NULL, NULL); + CallDie(NULL, NULL); return true; } if (!(BounceFlags & BOUNCE_CanBounceWater)) @@ -1814,7 +1813,7 @@ bool AActor::FloorBounceMissile (secplane_t &plane) if (flags & MF_MISSILE) P_ExplodeMissile(this, NULL, NULL); else - Die(NULL, NULL); + CallDie(NULL, NULL); return true; } @@ -3313,6 +3312,31 @@ bool AActor::Slam (AActor *thing) return false; // stop moving } +DEFINE_ACTION_FUNCTION(AActor, Slam) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(thing, AActor); + ACTION_RETURN_BOOL(self->Slam(thing)); +} + +bool AActor::CallSlam(AActor *thing) +{ + IFVIRTUAL(AActor, Slam) + { + VMValue params[2] = { (DObject*)this, thing }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + return !!retval; + + } + else return Slam(thing); +} + + + bool AActor::SpecialBlastHandling (AActor *source, double strength) { return true; @@ -5495,7 +5519,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) else mobj->health = -mthing->health; if (mthing->health == 0) - mobj->Die(NULL, NULL); + mobj->CallDie(NULL, NULL); else if (mthing->health != 1) mobj->StartHealth = mobj->health; @@ -6902,6 +6926,14 @@ void AActor::SetIdle(bool nofunction) SetState(idle, nofunction); } +DEFINE_ACTION_FUNCTION(AActor, SetIdle) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(nofunction); + self->SetIdle(nofunction); + return 0; +} + int AActor::SpawnHealth() const { int defhealth = StartHealth ? StartHealth : GetDefault()->health; @@ -7351,6 +7383,13 @@ DEFINE_ACTION_FUNCTION(AActor, PlayerNumber) ACTION_RETURN_INT(self->player ? int(self->player - players) : 0); } +DEFINE_ACTION_FUNCTION(AActor, SetFriendPlayer) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER(player, player_t); + self->SetFriendPlayer(player); + return 0; +} //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/p_user.cpp b/src/p_user.cpp index 03df6a0ca2..f28bf9f42d 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1446,7 +1446,7 @@ void APlayerPawn::Die (AActor *source, AActor *inflictor, int dmgflags) if (player != NULL && player->mo != this) { // Make the real player die, too - player->mo->Die (source, inflictor, dmgflags); + player->mo->CallDie (source, inflictor, dmgflags); } else { diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index ab0bb96e13..8a5eddd2d5 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -185,6 +185,16 @@ FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name) } } +static PStruct *FindStructType(FName name) +{ + PStruct *ccls = PClass::FindClass(name); + if (ccls == nullptr) + { + ccls = dyn_cast(TypeTable.FindType(RUNTIME_CLASS(PStruct), 0, (intptr_t)name, nullptr)); + if (ccls == nullptr) ccls = dyn_cast(TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), 0, (intptr_t)name, nullptr)); + } + return ccls; +} //========================================================================== // // ExpEmit @@ -244,7 +254,7 @@ static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCall // //========================================================================== -static bool AreCompatiblePointerTypes(PType *dest, PType *source) +static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare = false) { if (dest->IsKindOf(RUNTIME_CLASS(PPointer)) && source->IsKindOf(RUNTIME_CLASS(PPointer))) { @@ -252,12 +262,13 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source) auto fromtype = static_cast(source); auto totype = static_cast(dest); if (fromtype == nullptr) return true; - if (totype->IsConst && !fromtype->IsConst) return false; + if (!forcompare && 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); + if (forcompare && tocls->IsDescendantOf(fromcls)) return true; return (fromcls->IsDescendantOf(tocls)); } } @@ -2211,6 +2222,14 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) } // Both types are the same so this is ok. } + else if (Right->ValueType->IsA(RUNTIME_CLASS(PNativeStruct)) && Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(Base->ValueType)->PointedType == Right->ValueType) + { + // allow conversion of native structs to pointers of the same type. This is necessary to assign elements from global arrays like players, sectors, etc. to local pointers. + // For all other types this is not needed. Structs are not assignable and classes can only exist as references. + bool writable; + Right->RequestAddress(ctx, &writable); + Right->ValueType = Base->ValueType; + } else { // pass it to FxTypeCast for complete handling. @@ -3267,7 +3286,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) else if (left->ValueType->GetRegType() == REGT_POINTER && right->ValueType->GetRegType() == REGT_POINTER) { if (left->ValueType != right->ValueType && right->ValueType != TypeNullPtr && left->ValueType != TypeNullPtr && - !AreCompatiblePointerTypes(left->ValueType, right->ValueType)) + !AreCompatiblePointerTypes(left->ValueType, right->ValueType, true)) { goto error; } @@ -5691,12 +5710,48 @@ FxMemberIdentifier::~FxMemberIdentifier() FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) { + PStruct *ccls = nullptr; CHECKRESOLVED(); + if (Object->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. + ccls = FindStructType(static_cast(Object)->Identifier); + if (ccls != nullptr) static_cast(Object)->noglobal = true; + } + SAFE_RESOLVE(Object, ctx); - // allow accessing the color chanels by mapping the type to a matching struct which defines them. - if (Object->ValueType == TypeColor) + // check for class or struct constants if the left side is a type name. + if (Object->ValueType == TypeError) + { + if (ccls != nullptr) + { + if (!ccls->IsKindOf(RUNTIME_CLASS(PClass)) || static_cast(ccls)->bExported) + { + PSymbol *sym; + if ((sym = ccls->Symbols.FindSymbol(Identifier, true)) != nullptr) + { + if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) + { + ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s.%s' as constant\n", ccls->TypeName.GetChars(), Identifier.GetChars()); + delete this; + return FxConstant::MakeConstant(sym, ScriptPosition); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Unable to access '%s.%s' in a static context\n", ccls->TypeName.GetChars(), Identifier.GetChars()); + delete this; + return nullptr; + } + } + } + } + } + + // allow accessing the color channels by mapping the type to a matching struct which defines them. + if (Object->ValueType == TypeColor) Object->ValueType = TypeColorStruct; if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) @@ -6635,12 +6690,12 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) if (!start.Konst) { - ExpEmit indexwork = indexv.Fixed ? ExpEmit(build, indexv.RegType) : indexv; int shiftbits = 0; while (1u << shiftbits < arraytype->ElementSize) { shiftbits++; } + ExpEmit indexwork = indexv.Fixed && arraytype->ElementSize > 1 ? ExpEmit(build, indexv.RegType) : indexv; if (1u << shiftbits == arraytype->ElementSize) { if (shiftbits > 0) @@ -7079,7 +7134,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) bool staticonly = false; bool novirtual = false; - PClass *ccls = nullptr; + PStruct *ccls = nullptr; for (auto a : ArgList) { @@ -7093,10 +7148,10 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (Self->ExprType == EFX_Identifier) { - ccls = PClass::FindClass(static_cast(Self)->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. - if (ccls != nullptr)static_cast(Self)->noglobal = true; + ccls = FindStructType(static_cast(Self)->Identifier); + if (ccls != nullptr) static_cast(Self)->noglobal = true; } SAFE_RESOLVE(Self, ctx); @@ -7105,17 +7160,13 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) { if (ccls != nullptr) { - if (ccls->bExported) + if (!ccls->IsKindOf(RUNTIME_CLASS(PClass)) || static_cast(ccls)->bExported) { cls = ccls; staticonly = true; goto isresolved; } } - else - { - // Todo: static struct members need to work as well. - } } if (Self->ExprType == EFX_Super) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 1b93e22a51..a6c9ff9f1e 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -43,6 +43,7 @@ #include "d_player.h" #include "p_effect.h" #include "autosegs.h" +#include "gi.h" static TArray properties; static TArray AFTable; @@ -721,7 +722,11 @@ void InitThingdef() pstruct->Size = sizeof(player_t); pstruct->Align = alignof(player_t); PArray *parray = NewArray(pstruct, MAXPLAYERS); - PField *playerf = new PField("players", pstruct, VARF_Native | VARF_Static, (intptr_t)&players); + PField *playerf = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players); + GlobalSymbols.AddSymbol(playerf); + + parray = NewArray(TypeBool, MAXPLAYERS); + playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); GlobalSymbols.AddSymbol(playerf); @@ -803,3 +808,9 @@ void InitThingdef() } } + +DEFINE_ACTION_FUNCTION(DObject, GameType) +{ + PARAM_PROLOGUE; + ACTION_RETURN_INT(gameinfo.gametype); +} diff --git a/src/w_wad.cpp b/src/w_wad.cpp index da369144a4..41833fc245 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -501,6 +501,15 @@ int FWadCollection::CheckNumForName (const char *name, int space, int wadnum, bo return i != NULL_INDEX ? i : -1; } +DEFINE_ACTION_FUNCTION(_Wads, CheckNumForName) +{ + PARAM_PROLOGUE; + PARAM_STRING(name); + PARAM_INT(ns); + PARAM_INT_DEF(wadnum); + PARAM_BOOL_DEF(exact); + ACTION_RETURN_INT(Wads.CheckNumForName(name, ns, wadnum, exact)); +} //========================================================================== // // W_GetNumForName diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 45b44f7673..a006c79ed5 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -262,6 +262,8 @@ class Actor : Thinker native virtual native void Activate(Actor activator); virtual native void Deactivate(Actor activator); virtual native int DoSpecialDamage (Actor target, int damage, Name damagetype); + virtual native void Die(Actor source, Actor inflictor, int dmgflags); + virtual native bool Slam(Actor victim); virtual native bool UseInventory(Inventory item); @@ -276,6 +278,7 @@ class Actor : Thinker native native bool HitFloor(); native bool isTeammate(Actor other); native int PlayerNumber(); + native void SetFriendPlayer(PlayerInfo player); native void RestoreDamage(); native int SpawnHealth(); @@ -296,6 +299,7 @@ class Actor : Thinker native native Actor SpawnMissileAngleZSpeed (double z, class type, double angle, double vz, double speed, Actor owner = null, bool checkspawn = true); native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); + native Actor RoughMonsterSearch(int distance, bool onlyseekable = false); void A_Light(int extralight) { if (player) player.extralight = clamp(extralight, -20, 20); } void A_Light0() { if (player) player.extralight = 0; } @@ -308,6 +312,9 @@ class Actor : Thinker native native bool Teleport(Vector3 pos, double angle, int flags); native void TraceBleed(int damage, Actor missile); + native void TraceBleedAngle(int damage, double angle, double pitch); + + native void SetIdle(bool nofunction = false); 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); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 6d0e777959..c91b7aaa49 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -7,6 +7,7 @@ class Object native native static double G_SkillPropertyFloat(int p); native static vector3, int G_PickDeathmatchStart(); native static vector3, int G_PickPlayerStart(int pnum, int flags = 0); + native static int GameType(); /*virtual*/ native void Destroy(); } @@ -133,3 +134,33 @@ struct Sector native native double, Sector, F3DFloor NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0); } +struct Wads +{ + enum WadNamespace + { + ns_hidden = -1, + + ns_global = 0, + ns_sprites, + ns_flats, + ns_colormaps, + ns_acslibrary, + ns_newtextures, + ns_bloodraw, + ns_bloodsfx, + ns_bloodmisc, + ns_strifevoices, + ns_hires, + ns_voxels, + + ns_specialzipdirectory, + ns_sounds, + ns_patches, + ns_graphics, + ns_music, + + ns_firstskin, + } + + native static int CheckNumForName(string name, int ns, int wadnum = -1, bool exact = false); +} \ No newline at end of file diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index d87ad338a6..eadf30bc75 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -993,3 +993,17 @@ enum ETeleport TELF_ROTATEBOOM = 32, TELF_ROTATEBOOMINVERSE = 64, }; + +enum EGameType +{ + GAME_Any = 0, + GAME_Doom = 1, + GAME_Heretic = 2, + GAME_Hexen = 4, + GAME_Strife = 8, + GAME_Chex = 16, //Chex is basically Doom, but we need to have a different set of actors. + + GAME_Raven = GAME_Heretic|GAME_Hexen, + GAME_DoomChex = GAME_Doom|GAME_Chex, + GAME_DoomStrifeChex = GAME_Doom|GAME_Strife|GAME_Chex +} diff --git a/wadsrc/static/zscript/hexen/summon.txt b/wadsrc/static/zscript/hexen/summon.txt index 06ceb7e174..c9e9b9295e 100644 --- a/wadsrc/static/zscript/hexen/summon.txt +++ b/wadsrc/static/zscript/hexen/summon.txt @@ -1,7 +1,7 @@ // Dark Servant Artifact ---------------------------------------------------- -class ArtiDarkServant : Inventory native +class ArtiDarkServant : Inventory { Default { @@ -23,6 +23,26 @@ class ArtiDarkServant : Inventory native SUMN A 350; Loop; } + + //============================================================================ + // + // Activate the summoning artifact + // + //============================================================================ + + override bool Use (bool pickup) + { + Actor mo = Owner.SpawnPlayerMissile ("SummoningDoll"); + if (mo) + { + mo.target = Owner; + mo.tracer = Owner; + mo.Vel.Z = 5; + } + return true; + } + + } // Summoning Doll ----------------------------------------------------------- @@ -36,8 +56,6 @@ class SummoningDoll : Actor +NOTELEPORT } - native void A_Summon(); - States { Spawn: @@ -48,6 +66,49 @@ class SummoningDoll : Actor SUMN A 4 A_Summon; Stop; } + + //============================================================================ + // + // A_Summon + // + //============================================================================ + + void A_Summon() + { + Actor mo = Spawn("MinotaurFriend", pos, ALLOW_REPLACE); + if (mo) + { + if (mo.TestMobjLocation() == false || !tracer) + { // Didn't fit - change back to artifact + mo.Destroy(); + Actor arti = Spawn("ArtiDarkServant", Pos, ALLOW_REPLACE); + if (arti) arti.bDropped = true; + return; + } + + // Careful! The Minotaur might have been replaced + // so only set the time if we got a genuine one. + MinotaurFriend m = MinotaurFriend(mo); + if (m) m.StartTime = level.maptime; + + if (tracer.bCorpse) + { // Master dead + mo.tracer = null; // No master + } + else + { + mo.tracer = tracer; // Pointer to master + Inventory power = Inventory(Spawn("PowerMinotaur")); + power.CallTryPickup(tracer); + mo.SetFriendPlayer(tracer.player); + } + + // Make smoke puff + Spawn("MinotaurSmoke", Pos, ALLOW_REPLACE); + A_PlaySound(mo.ActiveSound, CHAN_VOICE); + } + } + } // Minotaur Smoke ----------------------------------------------------------- @@ -69,3 +130,4 @@ class MinotaurSmoke : Actor Stop; } } + diff --git a/wadsrc/static/zscript/raven/minotaur.txt b/wadsrc/static/zscript/raven/minotaur.txt index 9bbbe81a0a..fa40cbec1f 100644 --- a/wadsrc/static/zscript/raven/minotaur.txt +++ b/wadsrc/static/zscript/raven/minotaur.txt @@ -1,5 +1,9 @@ -class Minotaur : Actor native +class Minotaur : Actor { + const MAULATORTICS = 25 * TICRATE; + const MNTR_CHARGE_SPEED =13.; + const MINOTAUR_LOOK_DIST = 16*54.; + Default { Health 3000; @@ -26,16 +30,6 @@ class Minotaur : Actor native 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: @@ -101,10 +95,478 @@ class Minotaur : Actor native MNTR E 10 A_BossDeath; Stop; } + + //--------------------------------------------------------------------------- + // + // FUNC P_MinotaurSlam + // + //--------------------------------------------------------------------------- + + void MinotaurSlam (Actor target) + { + double ang = AngleTo(target); + double thrust = 16 + random[MinotaurSlam]() / 64.; + target.VelFromAngle(ang, thrust); + int damage = random[MinotaurSlam](1, 8) * (bSummonedMonster? 4 : 6); + int newdam = target.DamageMobj (null, null, damage, 'Melee'); + target.TraceBleedAngle (newdam > 0 ? newdam : damage, ang, 0.); + if (target.player) + { + target.reactiontime = random[MinotaurSlam](14, 21); + } + } + + + //---------------------------------------------------------------------------- + // + // + // + //---------------------------------------------------------------------------- + + override void Tick () + { + Super.Tick (); + + // The unfriendly Minotaur (Heretic's) is invulnerable while charging + if (!bSummonedMonster) + { + bInvulnerable = bSkullFly; + } + } + + override bool Slam (Actor thing) + { + // Slamming minotaurs shouldn't move non-creatures + if (!thing.bIsMonster && !thing.player) + { + return false; + } + return Super.Slam (thing); + } + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + damage = Super.DoSpecialDamage (target, damage, damagetype); + if (damage != -1 && bSkullFly) + { // Slam only when in charge mode + MinotaurSlam (target); + return -1; + } + return damage; + } + + //---------------------------------------------------------------------------- + // + // PROC A_MinotaurAtk1 + // + // Melee attack. + // + //---------------------------------------------------------------------------- + + void A_MinotaurAtk1() + { + if (!target) + { + return; + } + A_PlaySound ("minotaur/melee", CHAN_WEAPON); + if (CheckMeleeRange()) + { + int damage = random[MinotaurAtk1](1, 8) * 4; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + PlayerInfo player = target.player; + if (player != null && player.mo == target) + { // Squish the player + player.deltaviewheight = -16; + } + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_MinotaurDecide + // + // Choose a missile attack. + // + //---------------------------------------------------------------------------- + + void A_MinotaurDecide() + { + bool friendly = bSummonedMonster; + + if (!target) + { + return; + } + if (!friendly) + { + A_PlaySound ("minotaur/sight", CHAN_WEAPON); + } + double dist = Distance2D(target); + if (target.pos.z + target.height > pos.z + && target.pos.z + target.height < pos.z + height + && dist < (friendly ? 16*64. : 8*64.) + && dist > 1*64. + && random[MinotaurDecide]() < 150) + { // Charge attack + // Don't call the state function right away + SetStateLabel("Charge", true); + bSkullFly = true; + if (!friendly) + { // Heretic's Minotaur is invulnerable during charge attack + bInvulnerable = true; + } + A_FaceTarget (); + VelFromAngle(MNTR_CHARGE_SPEED); + special1 = TICRATE/2; // Charge duration + } + else if (target.pos.z == target.floorz + && dist < 9*64. + && random[MinotaurDecide]() < (friendly ? 100 : 220)) + { // Floor fire attack + SetStateLabel("Hammer"); + special2 = 0; + } + else + { // Swing attack + A_FaceTarget (); + // Don't need to call P_SetMobjState because the current state + // falls through to the swing attack + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_MinotaurCharge + // + //---------------------------------------------------------------------------- + + void A_MinotaurCharge() + { + if (target == null) + { + return; + } + if (special1 > 0) + { + Class type; + + //if (gameinfo.gametype == GAME_Heretic) + if (gametype() == GAME_Heretic) + { + type = "PhoenixPuff"; + } + else + { + type = "PunchPuff"; + } + Actor puff = Spawn (type, Pos, ALLOW_REPLACE); + puff.Vel.Z = 2; + special1--; + } + else + { + bSkullFly = false; + bInvulnerable = false; + SetState (SeeState); + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_MinotaurAtk2 + // + // Swing attack. + // + //---------------------------------------------------------------------------- + + void A_MinotaurAtk2() + { + bool friendly = bSummonedMonster; + + if (target == null) + { + return; + } + A_PlaySound ("minotaur/attack2", CHAN_WEAPON); + if (CheckMeleeRange()) + { + int damage = random[MinotaurAtk2](1, 8) * (friendly ? 3 : 5); + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + return; + } + double z = pos.z + 40; + Class fx = "MinotaurFX1"; + Actor mo = SpawnMissileZ (z, target, fx); + if (mo != null) + { +// S_Sound (mo, CHAN_WEAPON, "minotaur/attack2", 1, ATTN_NORM); + double vz = mo.Vel.Z; + double ang = mo.angle; + SpawnMissileAngleZ (z, fx, ang-(45./8), vz); + SpawnMissileAngleZ (z, fx, ang+(45./8), vz); + SpawnMissileAngleZ (z, fx, ang-(45./16), vz); + SpawnMissileAngleZ (z, fx, ang+(45./16), vz); + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_MinotaurAtk3 + // + // Floor fire attack. + // + //---------------------------------------------------------------------------- + + void A_MinotaurAtk3() + { + bool friendly = bSummonedMonster; + + if (!target) + { + return; + } + A_PlaySound ("minotaur/attack3", CHAN_VOICE); + if (CheckMeleeRange()) + { + int damage = random[MinotaurAtk3](1, 8) * (friendly ? 3 : 5); + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + PlayerInfo player = target.player; + if (player != null && player.mo == target) + { // Squish the player + player.deltaviewheight = -16; + } + } + else + { + if (Floorclip > 0 && compat_minotaur) + { + // only play the sound. + A_PlaySound ("minotaur/fx2hit", CHAN_WEAPON); + } + else + { + Actor mo = SpawnMissile (target, "MinotaurFX2"); + if (mo != null) + { + mo.A_PlaySound ("minotaur/attack1", CHAN_WEAPON); + } + } + } + if (random[MinotaurAtk3]() < 192 && special2 == 0) + { + SetStateLabel ("HammerLoop"); + special2 = 1; + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_MinotaurDeath + // + //---------------------------------------------------------------------------- + + void A_MinotaurDeath() + { + if (Wads.CheckNumForName ("MNTRF1", Wads.ns_sprites) < 0 && + Wads.CheckNumForName ("MNTRF0", Wads.ns_sprites) < 0) + SetStateLabel("FadeOut"); + } + + + //---------------------------------------------------------------------------- + // + // A_MinotaurRoam + // + //---------------------------------------------------------------------------- + + void A_MinotaurRoam() + { + // In case pain caused him to skip his fade in. + A_SetRenderStyle(1, STYLE_Normal); + + MinotaurFriend mf = MinotaurFriend(self); + if (mf) + { + if (mf.StartTime >= 0 && (level.maptime - mf.StartTime) >= MAULATORTICS) + { + DamageMobj (null, null, TELEFRAG_DAMAGE, 'None'); + return; + } + } + + if (random[MinotaurRoam]() < 30) + A_MinotaurLook(); // adjust to closest target + + if (random[MinotaurRoam]() < 6) + { + //Choose new direction + movedir = random[MinotaurRoam]() % 8; + FaceMovementDirection (); + } + if (!MonsterMove()) + { + // Turn + if (random[MinotaurRoam]() & 1) + movedir = (movedir + 1) % 8; + else + movedir = (movedir + 7) % 8; + FaceMovementDirection (); + } + } + + + //---------------------------------------------------------------------------- + // + // PROC A_MinotaurLook + // + // Look for enemy of player + //---------------------------------------------------------------------------- + + void A_MinotaurLook() + { + if (!(self is "MinotaurFriend")) + { + A_Look(); + return; + } + + Actor mo = null; + PlayerInfo player; + double dist; + Actor master = tracer; + + target = null; + if (deathmatch) // Quick search for players + { + for (int i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; + player = players[i]; + mo = player.mo; + if (mo == master) continue; + if (mo.health <= 0) continue; + dist = Distance2D(mo); + if (dist > MINOTAUR_LOOK_DIST) continue; + target = mo; + break; + } + } + + if (!target) // Near player monster search + { + if (master && (master.health > 0) && (master.player)) + mo = master.RoughMonsterSearch(20); + else + mo = RoughMonsterSearch(20); + target = mo; + } + + if (!target) // Normal monster search + { + ThinkerIterator it = ThinkerIterator.Create("Actor"); + + while ((mo = Actor(it.Next())) != null) + { + if (!mo.bIsMonster) continue; + if (mo.health <= 0) continue; + if (!mo.bShootable) continue; + dist = Distance2D(mo); + if (dist > MINOTAUR_LOOK_DIST) continue; + if (mo == master || mo == self) continue; + if (mo.bSummonedMonster && mo.tracer == master) continue; + target = mo; + break; // Found actor to attack + } + } + + if (target) + { + SetState (SeeState, true); + } + else + { + SetStateLabel ("Roam", true); + } + } + + //---------------------------------------------------------------------------- + // + // PROC A_MinotaurChase + // + //---------------------------------------------------------------------------- + + void A_MinotaurChase() + { + MinotaurFriend mf = MinotaurFriend(self); + if (!mf) + { + A_Chase(); + return; + } + + + // In case pain caused him to skip his fade in. + A_SetRenderStyle(1, STYLE_Normal); + + if (mf.StartTime >= 0 && (level.maptime - mf.StartTime) >= MAULATORTICS) + { + DamageMobj (null, null, TELEFRAG_DAMAGE, 'None'); + return; + } + + if (random[MinotaurChase]() < 30) + A_MinotaurLook(); // adjust to closest target + + if (!target || (target.health <= 0) || !target.bShootable) + { // look for a new target + SetIdle(); + return; + } + + FaceMovementDirection (); + reactiontime = 0; + + // Melee attack + if (MeleeState && CheckMeleeRange ()) + { + if (AttackSound) + { + A_PlaySound (AttackSound, CHAN_WEAPON); + } + SetState (MeleeState); + return; + } + + // Missile attack + if (MissileState && CheckMissileRange()) + { + SetState (MissileState); + return; + } + + // chase towards target + if (!MonsterMove ()) + { + NewChaseDir (); + FaceMovementDirection (); + } + + // Active sound + if (random[MinotaurChase]() < 6) + { + PlayActiveSound (); + } + } } -class MinotaurFriend : Minotaur native +class MinotaurFriend : Minotaur { + int StartTime; + Default { Health 2500; @@ -132,6 +594,51 @@ class MinotaurFriend : Minotaur native Death: Goto FadeOut; } + + //---------------------------------------------------------------------------- + // + // + // + //---------------------------------------------------------------------------- + + override void BeginPlay () + { + Super.BeginPlay (); + StartTime = -1; + } + + override void Die (Actor source, Actor inflictor, int dmgflags) + { + Super.Die (source, inflictor, dmgflags); + + if (tracer && tracer.health > 0 && tracer.player) + { + // Search thinker list for minotaur + ThinkerIterator it = ThinkerIterator.Create("MinotaurFriend"); + MinotaurFriend mo; + + while ((mo = MinotaurFriend(it.Next())) != null) + { + if (mo.health <= 0) continue; + // [RH] Minotaurs can't be morphed, so this isn't needed + //if (!(mo.flags&MF_COUNTKILL)) continue; // for morphed minotaurs + if (mo.bCorpse) continue; + if (mo.StartTime >= 0 && (level.maptime - StartTime) >= MAULATORTICS) continue; + if (mo.tracer != null && mo.tracer.player == tracer.player) break; + } + + if (mo == null) + { + Inventory power = tracer.FindInventory("PowerMinotaur"); + if (power != null) + { + power.Destroy (); + } + } + } + } + + } // Minotaur FX 1 ------------------------------------------------------------ @@ -179,8 +686,6 @@ class MinotaurFX2 : MinotaurFX1 DeathSound "minotaur/fx2hit"; } - native void A_MntrFloorFire(); - states { Spawn: @@ -191,6 +696,24 @@ class MinotaurFX2 : MinotaurFX1 FX13 JKLM 4 Bright; Stop; } + + //---------------------------------------------------------------------------- + // + // PROC A_MntrFloorFire + // + //---------------------------------------------------------------------------- + + void A_MntrFloorFire() + { + SetZ(floorz); + double x = Random2[MntrFloorFire]() / 64.; + double y = Random2[MntrFloorFire]() / 64.; + + Actor mo = Spawn("MinotaurFX3", Vec2OffsetZ(x, y, floorz), ALLOW_REPLACE); + mo.target = target; + mo.Vel.X = MinVel; // Force block checking + mo.CheckMissileSpawn (radius); + } } // Minotaur FX 3 ------------------------------------------------------------ From 4e802652c7871c945e167d995792623960f8c8b4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 09:51:14 +0100 Subject: [PATCH 363/471] - scriptified ArtiBlastRadius. --- src/CMakeLists.txt | 1 - src/g_hexen/a_blastradius.cpp | 158 ------------------ src/g_hexen/a_hexenmisc.cpp | 1 - src/p_enemy.cpp | 10 +- src/p_mobj.cpp | 11 +- src/p_sectors.cpp | 45 +++++ src/r_defs.h | 4 +- wadsrc/static/zscript/actor.txt | 3 +- wadsrc/static/zscript/base.txt | 66 ++++++++ wadsrc/static/zscript/heretic/hereticmisc.txt | 8 + .../static/zscript/heretic/weaponphoenix.txt | 10 -- wadsrc/static/zscript/hexen/blastradius.txt | 131 +++++++++++++++ 12 files changed, 273 insertions(+), 175 deletions(-) delete mode 100644 src/g_hexen/a_blastradius.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 95db06b2fe..d53429d051 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_blastradius.cpp g_hexen/a_boostarmor.cpp g_hexen/a_clericflame.cpp g_hexen/a_clericholy.cpp diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp deleted file mode 100644 index 0776e107f5..0000000000 --- a/src/g_hexen/a_blastradius.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -*/ - -/* For reference, the default values: -#define BLAST_RADIUS_DIST 255*F.RACUNIT -#define BLAST_SPEED 20*F.RACUNIT -#define BLAST_FULLSTRENGTH 255 -*/ - -// Disc of Repulsion -------------------------------------------------------- - -//========================================================================== -// -// AArtiBlastRadius :: BlastActor -// -//========================================================================== - -void BlastActor (AActor *victim, double strength, double speed, AActor *Owner, PClassActor *blasteffect, bool dontdamage) -{ - DAngle angle; - AActor *mo; - DVector3 pos; - - if (!victim->SpecialBlastHandling (Owner, strength)) - { - return; - } - - angle = Owner->AngleTo(victim); - DVector2 move = angle.ToVector(speed); - victim->Vel.X = move.X; - victim->Vel.Y = move.Y; - - // Spawn blast puff - angle -= 180.; - pos = victim->Vec3Offset( - (victim->radius + 1) * angle.Cos(), - (victim->radius + 1) * angle.Sin(), - (victim->Height / 2) - victim->Floorclip); - mo = Spawn (blasteffect, pos, ALLOW_REPLACE); - if (mo) - { - mo->Vel.X = victim->Vel.X; - mo->Vel.Y = victim->Vel.Y; - } - if (victim->flags & MF_MISSILE) - { - // [RH] Floor and ceiling huggers should not be blasted vertically. - if (!(victim->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))) - { - mo->Vel.Z = victim->Vel.Z = 8; - } - } - else - { - victim->Vel.Z = 1000. / victim->Mass; - } - if (victim->player) - { - // Players handled automatically - } - else if (!dontdamage) - { - victim->flags2 |= MF2_BLASTED; - } - if (victim->flags6 & MF6_TOUCHY) - { // Touchy objects die when blasted - victim->flags6 &= ~MF6_ARMED; // Disarm - P_DamageMobj(victim, Owner, Owner, victim->health, NAME_Melee, DMG_FORCED); - } -} - -enum -{ - BF_USEAMMO = 1, - BF_DONTWARN = 2, - BF_AFFECTBOSSES = 4, - BF_NOIMPACTDAMAGE = 8, -}; - -//========================================================================== -// -// AArtiBlastRadius :: Activate -// -// Blast all actors away -// -//========================================================================== - -DEFINE_ACTION_FUNCTION (AActor, A_Blast) -{ - 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; - - if (self->player && (blastflags & BF_USEAMMO) && ACTION_CALL_FROM_PSPRITE()) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && !weapon->DepleteAmmo(weapon->bAltFire)) - { - return 0; - } - } - - S_Sound (self, CHAN_AUTO, blastsound, 1, ATTN_NORM); - - if (!(blastflags & BF_DONTWARN)) - { - P_NoiseAlert (self, self); - } - while ( (mo = iterator.Next ()) ) - { - if ((mo == self) || ((mo->flags2 & MF2_BOSS) && !(blastflags & BF_AFFECTBOSSES)) - || (mo->flags2 & MF2_DORMANT) || (mo->flags3 & MF3_DONTBLAST)) - { // Not a valid monster: originator, boss, dormant, or otherwise protected - continue; - } - if ((mo->flags & MF_ICECORPSE) || (mo->flags3 & MF3_CANBLAST)) - { - // Let these special cases go - } - else if ((mo->flags3 & MF3_ISMONSTER) && (mo->health <= 0)) - { - continue; - } - else if (!(mo->player) && - !(mo->flags & MF_MISSILE) && - !(mo->flags3 & (MF3_ISMONSTER|MF3_CANBLAST)) && - !(mo->flags6 & (MF6_TOUCHY|MF6_VULNERABLE))) - { // Must be monster, player, missile, touchy or vulnerable - continue; - } - if (self->Distance2D(mo) > radius) - { // Out of range - continue; - } - if (mo->Sector->PortalGroup != self->Sector->PortalGroup && !P_CheckSight(self, mo)) - { - // in another region and cannot be seen. - continue; - } - BlastActor (mo, strength, speed, self, blasteffect, !!(blastflags & BF_NOIMPACTDAMAGE)); - } - return 0; -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index f442df65e8..2384a8518f 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,7 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_blastradius.cpp" #include "a_boostarmor.cpp" #include "a_clericflame.cpp" #include "a_clericholy.cpp" diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index db237e8bb2..a4be4dd1b0 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -262,7 +262,15 @@ void P_NoiseAlert (AActor *target, AActor *emitter, bool splash, double maxdist) } } - +DEFINE_ACTION_FUNCTION(AActor, NoiseAlert) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(emitter, AActor); + PARAM_BOOL_DEF(splash); + PARAM_FLOAT_DEF(maxdist); + P_NoiseAlert(self, emitter, splash, maxdist); + return 0; +} //---------------------------------------------------------------------------- diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 559efda821..e9c6a2980d 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -22,7 +22,6 @@ //----------------------------------------------------------------------------- // HEADER FILES ------------------------------------------------------------ - #include #include "templates.h" #include "i_system.h" @@ -3342,6 +3341,16 @@ bool AActor::SpecialBlastHandling (AActor *source, double strength) return true; } +// This only gets called from the script side so we do not need a native wrapper like for the other virtual methods. +DEFINE_ACTION_FUNCTION(AActor, SpecialBlastHandling) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(source, AActor); + PARAM_FLOAT(strength); + ACTION_RETURN_BOOL(self->SpecialBlastHandling(source, strength)); +} + + int AActor::SpecialMissileHit (AActor *victim) { return -1; diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index e93d718cd6..841401226a 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -1265,3 +1265,48 @@ int side_t::GetLightLevel (bool foggy, int baselight, bool is3dlight, int *pfake } return baselight; } + + +DEFINE_FIELD_X(Sector, sector_t, floorplane) +DEFINE_FIELD_X(Sector, sector_t, ceilingplane) +DEFINE_FIELD_X(Sector, sector_t, ColorMap) +DEFINE_FIELD_X(Sector, sector_t, SoundTarget) +DEFINE_FIELD_X(Sector, sector_t, special) +DEFINE_FIELD_X(Sector, sector_t, lightlevel) +DEFINE_FIELD_X(Sector, sector_t, seqType) +DEFINE_FIELD_X(Sector, sector_t, sky) +DEFINE_FIELD_X(Sector, sector_t, SeqName) +DEFINE_FIELD_X(Sector, sector_t, centerspot) +DEFINE_FIELD_X(Sector, sector_t, validcount) +DEFINE_FIELD_X(Sector, sector_t, thinglist) +DEFINE_FIELD_X(Sector, sector_t, friction) +DEFINE_FIELD_X(Sector, sector_t, movefactor) +DEFINE_FIELD_X(Sector, sector_t, terrainnum) +DEFINE_FIELD_X(Sector, sector_t, floordata) +DEFINE_FIELD_X(Sector, sector_t, ceilingdata) +DEFINE_FIELD_X(Sector, sector_t, lightingdata) +DEFINE_FIELD_X(Sector, sector_t, interpolations) +DEFINE_FIELD_X(Sector, sector_t, soundtraversed) +DEFINE_FIELD_X(Sector, sector_t, stairlock) +DEFINE_FIELD_X(Sector, sector_t, prevsec) +DEFINE_FIELD_X(Sector, sector_t, nextsec) +DEFINE_FIELD_X(Sector, sector_t, linecount) +DEFINE_FIELD_X(Sector, sector_t, lines) +DEFINE_FIELD_X(Sector, sector_t, heightsec) +DEFINE_FIELD_X(Sector, sector_t, bottommap) +DEFINE_FIELD_X(Sector, sector_t, midmap) +DEFINE_FIELD_X(Sector, sector_t, topmap) +DEFINE_FIELD_X(Sector, sector_t, touching_thinglist) +DEFINE_FIELD_X(Sector, sector_t, render_thinglist) +DEFINE_FIELD_X(Sector, sector_t, gravity) +DEFINE_FIELD_X(Sector, sector_t, damagetype) +DEFINE_FIELD_X(Sector, sector_t, damageamount) +DEFINE_FIELD_X(Sector, sector_t, damageinterval) +DEFINE_FIELD_X(Sector, sector_t, leakydamage) +DEFINE_FIELD_X(Sector, sector_t, ZoneNumber) +DEFINE_FIELD_X(Sector, sector_t, MoreFlags) +DEFINE_FIELD_X(Sector, sector_t, Flags) +DEFINE_FIELD_X(Sector, sector_t, SecActTarget) +DEFINE_FIELD_X(Sector, sector_t, Portals) +DEFINE_FIELD_X(Sector, sector_t, PortalGroup) +DEFINE_FIELD_X(Sector, sector_t, sectornum) diff --git a/src/r_defs.h b/src/r_defs.h index 2d16d28f9d..f33baeedc3 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -983,8 +983,8 @@ public: BYTE soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 // jff 2/26/98 lockout machinery for stairbuilding SBYTE stairlock; // -2 on first locked -1 after thinker done 0 normally - SWORD prevsec; // -1 or number of sector for previous step - SWORD nextsec; // -1 or number of next step sector + int prevsec; // -1 or number of sector for previous step + int nextsec; // -1 or number of next step sector short linecount; struct line_t **lines; // [linecount] size diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index a006c79ed5..62d88237fd 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -265,6 +265,7 @@ class Actor : Thinker native virtual native void Die(Actor source, Actor inflictor, int dmgflags); virtual native bool Slam(Actor victim); virtual native bool UseInventory(Inventory item); + virtual native bool SpecialBlastHandling (Actor source, double strength); native void AdjustPlayerAngle(FTranslatedLineTarget t); @@ -279,6 +280,7 @@ class Actor : Thinker native native bool isTeammate(Actor other); native int PlayerNumber(); native void SetFriendPlayer(PlayerInfo player); + native void NoiseAlert(Actor emitter, bool splash = false, double maxdist = 0); native void RestoreDamage(); native int SpawnHealth(); @@ -669,7 +671,6 @@ class Actor : Thinker native native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); native void A_CustomComboAttack(class missiletype, double 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, double strength = 255, double radius = 255, double 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, double 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"); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index c91b7aaa49..3766bb6b24 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -131,6 +131,72 @@ struct F3DFloor native struct Sector native { + //secplane_t floorplane, ceilingplane; + //FDynamicColormap *ColorMap; // [RH] Per-sector colormap + + native Actor SoundTarget; + + native int16 special; + native int16 lightlevel; + native int16 seqType; + + native int sky; + native Name SeqName; + + native readonly Vector2 centerspot; + native int validcount; + //AActor* thinglist; + + native double friction, movefactor; + native int terrainnum[2]; + + // thinker_t for reversable actions + //SectorEffect floordata; + //SectorEffect ceilingdata; + //SectorEffect lightingdata; + + enum EInterpolationType + { + CeilingMove, + FloorMove, + CeilingScroll, + FloorScroll + }; + //Interpolation interpolations[4]; + + native uint8 soundtraversed; + native int8 stairlock; + native int prevsec; + native int nextsec; + + native readonly int16 linecount; + //line_t **lines; + + native readonly Sector heightsec; + + native uint bottommap, midmap, topmap; + + //struct msecnode_t *touching_thinglist; + //struct msecnode_t *render_thinglist; + + native double gravity; + native Name damagetype; + native int damageamount; + native int16 damageinterval; + native int16 leakydamage; + + native uint16 ZoneNumber; + native uint16 MoreFlags; + native uint Flags; + + native SectorAction SecActTarget; + + native readonly uint Portals[2]; + native readonly int PortalGroup; + + native readonly int sectornum; + + native double, Sector, F3DFloor NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0); } diff --git a/wadsrc/static/zscript/heretic/hereticmisc.txt b/wadsrc/static/zscript/heretic/hereticmisc.txt index 4cb094d06b..ea79f5f803 100644 --- a/wadsrc/static/zscript/heretic/hereticmisc.txt +++ b/wadsrc/static/zscript/heretic/hereticmisc.txt @@ -1,4 +1,12 @@ +class HereticWeapon : Weapon +{ + Default + { + Weapon.Kickback 150; + } +} + // Pod ---------------------------------------------------------------------- class Pod : Actor diff --git a/wadsrc/static/zscript/heretic/weaponphoenix.txt b/wadsrc/static/zscript/heretic/weaponphoenix.txt index 554d52d216..6b949b8f61 100644 --- a/wadsrc/static/zscript/heretic/weaponphoenix.txt +++ b/wadsrc/static/zscript/heretic/weaponphoenix.txt @@ -1,13 +1,3 @@ - -class HereticWeapon : Weapon -{ - Default - { - Weapon.Kickback 150; - } -} - - // Phoenix Rod -------------------------------------------------------------- class PhoenixRod : Weapon diff --git a/wadsrc/static/zscript/hexen/blastradius.txt b/wadsrc/static/zscript/hexen/blastradius.txt index 17ac75dc32..a9c631318a 100644 --- a/wadsrc/static/zscript/hexen/blastradius.txt +++ b/wadsrc/static/zscript/hexen/blastradius.txt @@ -20,6 +20,137 @@ class ArtiBlastRadius : CustomInventory Use: TNT1 A 0 A_Blast; } + +} + +//========================================================================== +// +// A_Blast is public to Actor +// +//========================================================================== + +extend class Actor +{ + /* For reference, the default values: + #define BLAST_RADIUS_DIST 255.0 + #define BLAST_SPEED 20.0 + #define BLAST_FULLSTRENGTH 255 + */ + + //========================================================================== + // + // AArtiBlastRadius :: BlastActor + // + //========================================================================== + + private void BlastActor (Actor victim, double strength, double speed, Class blasteffect, bool dontdamage) + { + if (!victim.SpecialBlastHandling (self, strength)) + { + return; + } + + double ang = AngleTo(victim); + Vector2 move = AngleToVector(ang, speed); + victim.Vel.XY = move; + + // Spawn blast puff + ang -= 180.; + Vector3 spawnpos = victim.Vec3Offset( + (victim.radius + 1) * cos(ang), + (victim.radius + 1) * sin(ang), + (victim.Height / 2) - victim.Floorclip); + Actor mo = Spawn (blasteffect, spawnpos, ALLOW_REPLACE); + if (mo) + { + mo.Vel.XY = victim.Vel.XY; + } + if (victim.bMissile) + { + // [RH] Floor and ceiling huggers should not be blasted vertically. + if (!victim.bFloorHugger && !victim.bCeilingHugger) + { + mo.Vel.Z = victim.Vel.Z = 8; + } + } + else + { + victim.Vel.Z = 1000. / victim.Mass; + } + if (victim.player) + { + // Players handled automatically + } + else if (!dontdamage) + { + victim.bBlasted = true; + } + if (victim.bTouchy) + { // Touchy objects die when blasted + victim.bArmed = false; // Disarm + victim.DamageMobj(self, self, victim.health, 'Melee', DMG_FORCED); + } + } + + //========================================================================== + // + // AArtiBlastRadius :: Activate + // + // Blast all actors away + // + //========================================================================== + + action void A_Blast(int blastflags = 0, double strength = 255, double radius = 255, double speed = 20, class blasteffect = "BlastEffect", sound blastsound = "BlastRadius") + { + + Weapon weapon = player.ReadyWeapon; + if (player && (blastflags & BF_USEAMMO) && invoker == weapon && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + + { + if (weapon != null && !weapon.DepleteAmmo(weapon.bAltFire)) + { + return; + } + } + + A_PlaySound (blastsound, CHAN_AUTO); + + if (!(blastflags & BF_DONTWARN)) + { + NoiseAlert (self); + } + ThinkerIterator it = ThinkerIterator.Create("Actor"); + Actor mo; + while ( (mo = Actor(it.Next ())) ) + { + if (mo == self || (mo.bBoss && !(blastflags & BF_AFFECTBOSSES)) || mo.bDormant || mo.bDontBlast) + { // Not a valid monster: originator, boss, dormant, or otherwise protected + continue; + } + if (mo.bIceCorpse || mo.bCanBlast) + { + // Let these special cases go + } + else if (mo.bIsMonster && mo.health <= 0) + { + continue; + } + else if (!mo.player && !mo.bMissile && !mo.bIsMonster && !mo.bCanBlast && !mo.bTouchy && !mo.bVulnerable) + { // Must be monster, player, missile, touchy or vulnerable + continue; + } + if (Distance2D(mo) > radius) + { // Out of range + continue; + } + if (mo.CurSector.PortalGroup != CurSector.PortalGroup && !CheckSight(mo)) + { + // in another region and cannot be seen. + continue; + } + BlastActor (mo, strength, speed, blasteffect, !!(blastflags & BF_NOIMPACTDAMAGE)); + } + } } // Blast Effect ------------------------------------------------------------- From f508a57bb85d83c83d13d672094614030852b9eb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 10:08:25 +0100 Subject: [PATCH 364/471] - scriptified ArtiBoostArmor. --- src/CMakeLists.txt | 1 - src/g_hexen/a_boostarmor.cpp | 64 ---------------------- src/g_hexen/a_hexenmisc.cpp | 1 - wadsrc/static/zscript/hexen/boostarmor.txt | 47 +++++++++++++++- 4 files changed, 46 insertions(+), 67 deletions(-) delete mode 100644 src/g_hexen/a_boostarmor.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d53429d051..41419df79f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_boostarmor.cpp g_hexen/a_clericflame.cpp g_hexen/a_clericholy.cpp g_hexen/a_clericmace.cpp diff --git a/src/g_hexen/a_boostarmor.cpp b/src/g_hexen/a_boostarmor.cpp deleted file mode 100644 index b910f63e78..0000000000 --- a/src/g_hexen/a_boostarmor.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "gi.h" -#include "s_sound.h" -*/ - -// Boost Armor Artifact (Dragonskin Bracers) -------------------------------- - -class AArtiBoostArmor : public AInventory -{ - DECLARE_CLASS (AArtiBoostArmor, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiBoostArmor, false, false) - -bool AArtiBoostArmor::Use (bool pickup) -{ - int count = 0; - - if (gameinfo.gametype == GAME_Hexen) - { - AHexenArmor *armor; - - for (int i = 0; i < 4; ++i) - { - armor = Spawn(); - armor->flags |= MF_DROPPED; - armor->health = i; - armor->Amount = 1; - if (!armor->CallTryPickup (Owner)) - { - armor->Destroy (); - } - else - { - count++; - } - } - return count != 0; - } - else - { - ABasicArmorBonus *armor = Spawn(); - armor->flags |= MF_DROPPED; - armor->SaveAmount = 50; - armor->MaxSaveAmount = 300; - if (!armor->CallTryPickup (Owner)) - { - armor->Destroy (); - return false; - } - else - { - return true; - } - } -} - diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 2384a8518f..fa8d151a7f 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,7 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_boostarmor.cpp" #include "a_clericflame.cpp" #include "a_clericholy.cpp" #include "a_clericmace.cpp" diff --git a/wadsrc/static/zscript/hexen/boostarmor.txt b/wadsrc/static/zscript/hexen/boostarmor.txt index 4c14b69bc9..f8c797c99c 100644 --- a/wadsrc/static/zscript/hexen/boostarmor.txt +++ b/wadsrc/static/zscript/hexen/boostarmor.txt @@ -1,7 +1,7 @@ // Boost Armor Artifact (Dragonskin Bracers) -------------------------------- -class ArtiBoostArmor : Inventory native +class ArtiBoostArmor : Inventory { Default { @@ -21,4 +21,49 @@ class ArtiBoostArmor : Inventory native BRAC ABCDEFGH 4 Bright; Loop; } + + override bool Use (bool pickup) + { + int count = 0; + + if (gametype() == GAME_Hexen) + { + HexenArmor armor; + + for (int i = 0; i < 4; ++i) + { + armor = HexenArmor(Spawn("HexenArmor")); + armor.bDropped = true; + armor.health = i; + armor.Amount = 1; + if (!armor.CallTryPickup (Owner)) + { + armor.Destroy (); + } + else + { + count++; + } + } + return count != 0; + } + else + { + BasicArmorBonus armor = BasicArmorBonus(Spawn("BasicArmorBonus")); + armor.bDropped = true; + armor.SaveAmount = 50; + armor.MaxSaveAmount = 300; + if (!armor.CallTryPickup (Owner)) + { + armor.Destroy (); + return false; + } + else + { + return true; + } + } + } + + } From bc1e4eff7208d9d29c3374531764c5d9b8d5d09b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 10:30:41 +0100 Subject: [PATCH 365/471] - scriptified the Cleric's flame weapon. Also fixed the angle calculations for the circle flame. --- src/CMakeLists.txt | 1 - src/g_hexen/a_clericflame.cpp | 138 -------------------- src/g_hexen/a_hexenmisc.cpp | 1 - wadsrc/static/zscript/hexen/clericflame.txt | 101 +++++++++++++- 4 files changed, 94 insertions(+), 147 deletions(-) delete mode 100644 src/g_hexen/a_clericflame.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 41419df79f..376d33887d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_clericflame.cpp g_hexen/a_clericholy.cpp g_hexen/a_clericmace.cpp g_hexen/a_clericstaff.cpp diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp deleted file mode 100644 index d4f86ecd5b..0000000000 --- a/src/g_hexen/a_clericflame.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "a_action.h" -#include "p_pspr.h" -#include "gstrings.h" -#include "a_hexenglobal.h" -#include "vm.h" -*/ - -const double FLAMESPEED = 0.45; -const double FLAMEROTSPEED = 2.; - -static FRandom pr_missile ("CFlameMissile"); - -void A_CFlameAttack (AActor *); -void A_CFlameRotate (AActor *); -void A_CFlamePuff (AActor *); -void A_CFlameMissile (AActor *); - -// Flame Missile ------------------------------------------------------------ - - -//============================================================================ -// -// A_CFlameAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CFlameAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - P_SpawnPlayerMissile (self, PClass::FindActor("CFlameMissile")); - S_Sound (self, CHAN_WEAPON, "ClericFlameFire", 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_CFlamePuff -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CFlamePuff) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->renderflags &= ~RF_INVISIBLE; - self->Vel.Zero(); - S_Sound (self, CHAN_BODY, "ClericFlameExplode", 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_CFlameMissile -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CFlameMissile) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - DAngle an; - double dist; - AActor *mo; - - self->renderflags &= ~RF_INVISIBLE; - S_Sound (self, CHAN_BODY, "ClericFlameExplode", 1, ATTN_NORM); - AActor *BlockingMobj = self->BlockingMobj; - if (BlockingMobj && BlockingMobj->flags&MF_SHOOTABLE) - { // Hit something, so spawn the flame circle around the thing - dist = BlockingMobj->radius + 18; - for (i = 0; i < 4; i++) - { - an = i*45.; - mo = Spawn ("CircleFlame", BlockingMobj->Vec3Angle(dist, an, 5), ALLOW_REPLACE); - if (mo) - { - mo->Angles.Yaw = an; - mo->target = self->target; - mo->VelFromAngle(FLAMESPEED); - mo->specialf1 = mo->Vel.X; - mo->specialf2 = mo->Vel.Y; - mo->tics -= pr_missile()&3; - } - mo = Spawn("CircleFlame", BlockingMobj->Vec3Angle(dist, an, 5), ALLOW_REPLACE); - if(mo) - { - mo->Angles.Yaw = an + 180.; - mo->target = self->target; - mo->VelFromAngle(-FLAMESPEED); - mo->specialf1 = mo->Vel.X; - mo->specialf2 = mo->Vel.Y; - mo->tics -= pr_missile()&3; - } - } - self->SetState (self->SpawnState); - } - return 0; -} - -//============================================================================ -// -// A_CFlameRotate -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CFlameRotate) -{ - PARAM_SELF_PROLOGUE(AActor); - - DAngle an = self->Angles.Yaw + 90.; - self->VelFromAngle(FLAMEROTSPEED, an); - self->Vel += DVector2(self->specialf1, self->specialf2); - - self->Angles.Yaw += 6.; - return 0; -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index fa8d151a7f..cbe9d3c12a 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,7 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_clericflame.cpp" #include "a_clericholy.cpp" #include "a_clericmace.cpp" #include "a_clericstaff.cpp" diff --git a/wadsrc/static/zscript/hexen/clericflame.txt b/wadsrc/static/zscript/hexen/clericflame.txt index 37e4149f92..d222a07db3 100644 --- a/wadsrc/static/zscript/hexen/clericflame.txt +++ b/wadsrc/static/zscript/hexen/clericflame.txt @@ -16,8 +16,6 @@ class CWeapFlame : ClericWeapon Tag "$TAG_CWEAPFLAME"; } - action native void A_CFlameAttack(); - States { Spawn: @@ -43,6 +41,29 @@ class CWeapFlame : ClericWeapon CFLM G 2; Goto Ready; } + + //============================================================================ + // + // A_CFlameAttack + // + //============================================================================ + + action void A_CFlameAttack() + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + SpawnPlayerMissile ("CFlameMissile"); + A_PlaySound ("ClericFlameFire", CHAN_WEAPON); + } } // Floor Flame -------------------------------------------------------------- @@ -127,6 +148,9 @@ class FlamePuff2 : FlamePuff class CircleFlame : Actor { + const FLAMESPEED = 0.45; + const FLAMEROTSPEED = 2.; + Default { Radius 6; @@ -140,8 +164,6 @@ class CircleFlame : Actor Obituary "$OB_MPCWEAPFLAME"; } - native void A_CFlameRotate(); - States { Spawn: @@ -166,6 +188,20 @@ class CircleFlame : Actor CFCF TUVWXYZ 3 Bright; Stop; } + + //============================================================================ + // + // A_CFlameRotate + // + //============================================================================ + + void A_CFlameRotate() + { + double an = Angle + 90.; + VelFromAngle(FLAMEROTSPEED, an); + Vel.XY += (specialf1, specialf2); + Angle += 6; + } } // Flame Missile ------------------------------------------------------------ @@ -184,9 +220,6 @@ class CFlameMissile : FastProjectile Obituary "$OB_MPCWEAPFLAME"; } - native void A_CFlamePuff(); - native void A_CFlameMissile(); - States { Spawn: @@ -232,4 +265,58 @@ class CFlameMissile : FastProjectile } } + //============================================================================ + // + // A_CFlamePuff + // + //============================================================================ + + void A_CFlamePuff() + { + bInvisible = false; + Vel = (0,0,0); + A_PlaySound ("ClericFlameExplode", CHAN_BODY); + } + + //============================================================================ + // + // A_CFlameMissile + // + //============================================================================ + + void A_CFlameMissile() + { + bInvisible = false; + A_PlaySound ("ClericFlameExplode", CHAN_BODY); + if (BlockingMobj && BlockingMobj.bShootable) + { // Hit something, so spawn the flame circle around the thing + double dist = BlockingMobj.radius + 18; + for (int i = 0; i < 4; i++) + { + double an = i*45.; + Actor mo = Spawn ("CircleFlame", BlockingMobj.Vec3Angle(dist, an, 5), ALLOW_REPLACE); + if (mo) + { + mo.angle = an; + mo.target = target; + mo.VelFromAngle(CircleFlame.FLAMESPEED); + mo.specialf1 = mo.Vel.X; + mo.specialf2 = mo.Vel.Y; + mo.tics -= random[FlameMissile]()&3; + } + an += 180; + mo = Spawn("CircleFlame", BlockingMobj.Vec3Angle(dist, an, 5), ALLOW_REPLACE); + if(mo) + { + mo.angle = an; + mo.target = target; + mo.VelFromAngle(-CircleFlame.FLAMESPEED); + mo.specialf1 = mo.Vel.X; + mo.specialf2 = mo.Vel.Y; + mo.tics -= random[FlameMissile]()&3; + } + } + SetState (SpawnState); + } + } } From 177aa6ec42ee787b4d91a974c762cf1b6dc2dfb8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 13:18:48 +0100 Subject: [PATCH 366/471] - converted half of ClericHoly. (Making a commit before starting on the more complex stuff.) - added a 'constructor' for color values. --- src/actor.h | 1 + src/g_hexen/a_clericholy.cpp | 343 --------------------- src/g_hexen/a_hexenglobal.h | 8 - src/g_hexen/a_korax.cpp | 5 +- src/g_shared/a_pickups.cpp | 21 ++ src/g_shared/a_pickups.h | 1 + src/p_mobj.cpp | 20 +- src/scripting/codegeneration/codegen.cpp | 78 ++++- src/scripting/codegeneration/codegen.h | 19 ++ src/scripting/thingdef_data.cpp | 1 + src/scripting/zscript/zcc-parse.lemon | 2 +- src/v_blend.cpp | 2 +- wadsrc/static/zscript/actor.txt | 2 + wadsrc/static/zscript/constants.txt | 8 + wadsrc/static/zscript/hexen/clericboss.txt | 17 +- wadsrc/static/zscript/hexen/clericholy.txt | 294 +++++++++++++++++- wadsrc/static/zscript/shared/inventory.txt | 1 + 17 files changed, 455 insertions(+), 368 deletions(-) diff --git a/src/actor.h b/src/actor.h index f6020d2922..92e277d48b 100644 --- a/src/actor.h +++ b/src/actor.h @@ -386,6 +386,7 @@ enum ActorFlag7 MF7_NOKILLSCRIPTS = 0x01000000, // [JM] No "KILL" Script on death whatsoever, even if forced by GameInfo. MF7_SPRITEANGLE = 0x02000000, // [MC] Utilize the SpriteAngle property and lock the rotation to the degrees specified. MF7_SMASHABLE = 0x04000000, // dies if hitting the floor. + MF7_NOSHIELDREFLECT = 0x08000000, // will not be reflected by shields. }; // --- mobj.renderflags --- diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index 52ff4179df..8ffb5be27f 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -24,332 +24,8 @@ static FRandom pr_wraithvergedrop ("WraithvergeDrop"); void SpawnSpiritTail (AActor *spirit); -//========================================================================== -// Cleric's Wraithverge (Holy Symbol?) -------------------------------------- - -class ACWeapWraithverge : public AClericWeapon -{ - DECLARE_CLASS (ACWeapWraithverge, AClericWeapon) -public: - - void Serialize(FSerializer &arc) - { - Super::Serialize (arc); - arc("cholycount", CHolyCount); - } - PalEntry GetBlend () - { - if (paletteflash & PF_HEXENWEAPONS) - { - if (CHolyCount == 3) - return PalEntry(128, 70, 70, 70); - else if (CHolyCount == 2) - return PalEntry(128, 100, 100, 100); - else if (CHolyCount == 1) - return PalEntry(128, 130, 130, 130); - else - return PalEntry(0, 0, 0, 0); - } - else - { - return PalEntry (CHolyCount * 128 / 3, 131, 131, 131); - } - } - BYTE CHolyCount; -}; - -IMPLEMENT_CLASS(ACWeapWraithverge, false, false) - // Holy Spirit -------------------------------------------------------------- -IMPLEMENT_CLASS(AHolySpirit, false, false) - -bool AHolySpirit::Slam(AActor *thing) -{ - if (thing->flags&MF_SHOOTABLE && thing != target) - { - if (multiplayer && !deathmatch && thing->player && target->player) - { // don't attack other co-op players - return true; - } - if (thing->flags2&MF2_REFLECTIVE - && (thing->player || thing->flags2&MF2_BOSS)) - { - tracer = target; - target = thing; - return true; - } - if (thing->flags3&MF3_ISMONSTER || thing->player) - { - tracer = thing; - } - if (pr_spiritslam() < 96) - { - int dam = 12; - if (thing->player || thing->flags2&MF2_BOSS) - { - dam = 3; - // ghost burns out faster when attacking players/bosses - health -= 6; - } - P_DamageMobj(thing, this, target, dam, NAME_Melee); - if (pr_spiritslam() < 128) - { - Spawn("HolyPuff", Pos(), ALLOW_REPLACE); - S_Sound(this, CHAN_WEAPON, "SpiritAttack", 1, ATTN_NORM); - if (thing->flags3&MF3_ISMONSTER && pr_spiritslam() < 128) - { - thing->Howl(); - } - } - } - if (thing->health <= 0) - { - tracer = NULL; - } - } - return true; -} - -bool AHolySpirit::SpecialBlastHandling (AActor *source, double strength) -{ - if (tracer == source) - { - tracer = target; - target = source; - GC::WriteBarrier(this, source); - } - return true; -} - -//============================================================================ -// -// A_CHolyAttack2 -// -// Spawns the spirits -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack2) -{ - PARAM_SELF_PROLOGUE(AActor); - - int j; - AActor *mo; - - for (j = 0; j < 4; j++) - { - mo = Spawn (self->Pos(), ALLOW_REPLACE); - if (!mo) - { - continue; - } - switch (j) - { // float bob index - - case 0: - mo->WeaveIndexZ = pr_holyatk2() & 7; // upper-left - break; - case 1: - mo->WeaveIndexZ = 32 + (pr_holyatk2() & 7); // upper-right - break; - case 2: - mo->WeaveIndexXY = 32 + (pr_holyatk2() & 7); // lower-left - break; - case 3: - mo->WeaveIndexXY = 32 + (pr_holyatk2() & 7); - mo->WeaveIndexZ = 32 + (pr_holyatk2() & 7); - break; - } - mo->SetZ(self->Z()); - mo->Angles.Yaw = self->Angles.Yaw + 67.5 - 45.*j; - mo->Thrust(); - mo->target = self->target; - mo->args[0] = 10; // initial turn value - mo->args[1] = 0; // initial look angle - if (deathmatch) - { // Ghosts last slightly less longer in DeathMatch - mo->health = 85; - } - if (self->tracer) - { - mo->tracer = self->tracer; - mo->flags |= MF_NOCLIP|MF_SKULLFLY; - mo->flags &= ~MF_MISSILE; - } - SpawnSpiritTail (mo); - } - return 0; -} - -//============================================================================ -// -// SpawnSpiritTail -// -//============================================================================ - -void SpawnSpiritTail (AActor *spirit) -{ - AActor *tail, *next; - int i; - - tail = Spawn ("HolyTail", spirit->Pos(), ALLOW_REPLACE); - tail->target = spirit; // parent - for (i = 1; i < 3; i++) - { - next = Spawn ("HolyTailTrail", spirit->Pos(), ALLOW_REPLACE); - tail->tracer = next; - tail = next; - } - tail->tracer = NULL; // last tail bit -} - -//============================================================================ -// -// A_CHolyAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - ACWeapWraithverge *weapon = static_cast (self->player->ReadyWeapon); - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - AActor *missile = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("HolyMissile"), self->Angles.Yaw, &t); - if (missile != NULL && !t.unlinked) - { - missile->tracer = t.linetarget; - } - - weapon->CHolyCount = 3; - S_Sound (self, CHAN_WEAPON, "HolySymbolFire", 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_CHolyPalette -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CHolyPalette) -{ - PARAM_ACTION_PROLOGUE(AActor); - - if (self->player != NULL) - { - ACWeapWraithverge *weapon = static_cast (self->player->ReadyWeapon); - if (weapon != NULL && weapon->CHolyCount != 0) - { - weapon->CHolyCount--; - } - } - return 0; -} - -//============================================================================ -// -// CHolyTailFollow -// -//============================================================================ - -static void CHolyTailFollow(AActor *actor, double dist) -{ - AActor *child; - DAngle an; - double oldDistance, newDistance; - - while (actor) - { - child = actor->tracer; - if (child) - { - an = actor->AngleTo(child); - oldDistance = child->Distance2D(actor); - if (P_TryMove(child, actor->Pos().XY() + an.ToVector(dist), true)) - { - newDistance = child->Distance2D(actor) - 1; - if (oldDistance < 1) - { - if (child->Z() < actor->Z()) - { - child->SetZ(actor->Z() - dist); - } - else - { - child->SetZ(actor->Z() + dist); - } - } - else - { - child->SetZ(actor->Z() + (newDistance * (child->Z() - actor->Z()) / oldDistance)); - } - } - } - actor = child; - dist -= 1; - } -} - -//============================================================================ -// -// CHolyTailRemove -// -//============================================================================ - -static void CHolyTailRemove (AActor *actor) -{ - AActor *next; - - while (actor) - { - next = actor->tracer; - actor->Destroy (); - actor = next; - } -} - -//============================================================================ -// -// A_CHolyTail -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CHolyTail) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *parent; - - parent = self->target; - - if (parent == NULL || parent->health <= 0) // better check for health than current state - it's safer! - { // Ghost removed, so remove all tail parts - CHolyTailRemove (self); - return 0; - } - else - { - if (P_TryMove(self, parent->Vec2Angle(14., parent->Angles.Yaw, true), true)) - { - self->SetZ(parent->Z() - 5.); - } - CHolyTailFollow(self, 10); - } - return 0; -} - //============================================================================ // // CHolyFindTarget @@ -495,22 +171,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_CHolyCheckScream) return 0; } -//============================================================================ -// -// A_ClericAttack -// (for the ClericBoss) -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ClericAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->target) return 0; - - AActor * missile = P_SpawnMissileZ (self, self->Z() + 40., self->target, PClass::FindActor ("HolyMissile")); - if (missile != NULL) missile->tracer = NULL; // No initial target - S_Sound (self, CHAN_WEAPON, "HolySymbolFire", 1, ATTN_NORM); - return 0; -} - diff --git a/src/g_hexen/a_hexenglobal.h b/src/g_hexen/a_hexenglobal.h index 3455b684df..dc174b32ab 100644 --- a/src/g_hexen/a_hexenglobal.h +++ b/src/g_hexen/a_hexenglobal.h @@ -5,14 +5,6 @@ void AdjustPlayerAngle(AActor *pmo, FTranslatedLineTarget *t); -class AHolySpirit : public AActor -{ - DECLARE_CLASS (AHolySpirit, AActor) -public: - bool Slam (AActor *thing); - bool SpecialBlastHandling (AActor *source, double strength); -}; - class AFighterWeapon : public AWeapon { DECLARE_CLASS (AFighterWeapon, AWeapon); diff --git a/src/g_hexen/a_korax.cpp b/src/g_hexen/a_korax.cpp index 2824d8c0aa..8a459ffd4b 100644 --- a/src/g_hexen/a_korax.cpp +++ b/src/g_hexen/a_korax.cpp @@ -189,8 +189,11 @@ void KSpiritInit (AActor *spirit, AActor *korax) spirit->args[0] = 10; // initial turn value spirit->args[1] = 0; // initial look angle +#if 0 // Temporarily deactivated. // Spawn a tail for spirit - SpawnSpiritTail (spirit); + HolyTail.SpawnSpiritTail (spirit); +#endif + } //============================================================================ diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index ee68a16db0..b026a61d76 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1324,6 +1324,27 @@ PalEntry AInventory::GetBlend () return 0; } +DEFINE_ACTION_FUNCTION(AInventory, GetBlend) +{ + PARAM_SELF_PROLOGUE(AInventory); + ACTION_RETURN_INT(self->GetBlend()); +} + +PalEntry AInventory::CallGetBlend() +{ + IFVIRTUAL(AInventory, GetBlend) + { + VMValue params[1] = { (DObject*)this }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + return retval; + } + else return GetBlend(); +} + //=========================================================================== // // AInventory :: PrevItem diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index f035efeea8..bd252437d6 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -215,6 +215,7 @@ public: virtual int AlterWeaponSprite (visstyle_t *vis); virtual PalEntry GetBlend (); + PalEntry CallGetBlend(); protected: virtual bool TryPickup (AActor *&toucher); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index e9c6a2980d..7e9b8a96b4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3284,6 +3284,13 @@ void AActor::Howl () } } +DEFINE_ACTION_FUNCTION(AActor, Howl) +{ + PARAM_SELF_PROLOGUE(AActor); + self->Howl(); + return 0; +} + bool AActor::Slam (AActor *thing) { flags &= ~MF_SKULLFLY; @@ -3367,8 +3374,7 @@ bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle) if (absangle(angle, thing->Angles.Yaw) > 45) return true; // Let missile explode - if (thing->IsKindOf (RUNTIME_CLASS(AHolySpirit))) // shouldn't this be handled by another flag??? - return true; + if (thing->flags7 & MF7_NOSHIELDREFLECT) return true; if (pr_reflect () < 128) angle += 45; @@ -7349,6 +7355,16 @@ DEFINE_ACTION_FUNCTION(AActor, SetXYZ) return 0; } +DEFINE_ACTION_FUNCTION(AActor, Vec2Angle) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(length); + PARAM_ANGLE(angle); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_VEC2(self->Vec2Angle(length, angle, absolute)); +} + + DEFINE_ACTION_FUNCTION(AActor, Vec3Angle) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8a5eddd2d5..4562f3ef7d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6969,13 +6969,19 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) switch (MethodName) { + case NAME_Color: + if (ArgList.Size() == 3 || ArgList.Size() == 4) + { + func = new FxColorLiteral(ArgList, ScriptPosition); + break; + } + // fall through 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: case NAME_SpriteID: @@ -8090,6 +8096,76 @@ ExpEmit FxGetClass::Emit(VMFunctionBuilder *build) return to; } +//========================================================================== +// +// +//========================================================================== + +FxColorLiteral::FxColorLiteral(FArgumentList &args, FScriptPosition &sc) + :FxExpression(EFX_ColorLiteral, sc) +{ + ArgList = std::move(args); +} + +FxExpression *FxColorLiteral::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + unsigned constelements = 0; + assert(ArgList.Size() == 3 || ArgList.Size() == 4); + if (ArgList.Size() == 3) ArgList.Insert(0, nullptr); + for (int i = 0; i < 4; i++) + { + if (ArgList[i] != nullptr) + { + SAFE_RESOLVE(ArgList[i], ctx); + if (!ArgList[i]->IsInteger()) + { + ScriptPosition.Message(MSG_ERROR, "Integer expected for color component"); + delete this; + return nullptr; + } + if (ArgList[i]->isConstant()) + { + constval += clamp(static_cast(ArgList[i])->GetValue().GetInt(), 0, 255) << (24 - i * 8); + delete ArgList[i]; + ArgList[i] = nullptr; + constelements++; + } + } + else constelements++; + } + if (constelements == 4) + { + auto x = new FxConstant(constval, ScriptPosition); + x->ValueType = TypeColor; + delete this; + return x; + } + ValueType = TypeColor; + return this; +} + +ExpEmit FxColorLiteral::Emit(VMFunctionBuilder *build) +{ + ExpEmit out(build, REGT_INT); + build->Emit(OP_LK, out.RegNum, build->GetConstantInt(constval)); + for (int i = 0; i < 4; i++) + { + if (ArgList[i] != nullptr) + { + assert(!ArgList[i]->isConstant()); + ExpEmit in = ArgList[i]->Emit(build); + in.Free(build); + ExpEmit work(build, REGT_INT); + build->Emit(OP_MAX_RK, work.RegNum, in.RegNum, build->GetConstantInt(0)); + build->Emit(OP_MIN_RK, work.RegNum, work.RegNum, build->GetConstantInt(255)); + if (i != 3) build->Emit(OP_SLL_RI, work.RegNum, work.RegNum, 24 - (i * 8)); + build->Emit(OP_OR_RR, out.RegNum, out.RegNum, work.RegNum); + } + } + return out; +} + //========================================================================== // // FxSequence :: Resolve diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index d7547a198e..1110cd6b61 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -287,6 +287,7 @@ enum EFxType EFX_CVar, EFX_NamedNode, EFX_GetClass, + EFX_ColorLiteral, EFX_COUNT }; @@ -1540,6 +1541,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxColorLiteral +// +//========================================================================== + +class FxColorLiteral : public FxExpression +{ + FArgumentList ArgList; + int constval = 0; + +public: + + FxColorLiteral(FArgumentList &args, FScriptPosition &sc); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxVMFunctionCall diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index a6c9ff9f1e..7a3d3a7c67 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -296,6 +296,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF7, NOKILLSCRIPTS, AActor, flags7), DEFINE_FLAG(MF7, SPRITEANGLE, AActor, flags7), DEFINE_FLAG(MF7, SMASHABLE, AActor, flags7), + DEFINE_FLAG(MF7, NOSHIELDREFLECT, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 379d1516ef..d22746cf89 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -740,7 +740,7 @@ type_name(X) ::= DOT dottable_id(A). /* 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 VECTOR2 VECTOR3 NAME MAP ARRAY VOID STATE. + SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 NAME MAP ARRAY VOID STATE COLOR UINT8 INT8 UINT16 INT16. /* Aggregate types */ %type aggregate_type {ZCC_Type *} diff --git a/src/v_blend.cpp b/src/v_blend.cpp index c13ed547c2..ffc16cd5ce 100644 --- a/src/v_blend.cpp +++ b/src/v_blend.cpp @@ -104,7 +104,7 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int // [RH] All powerups can affect the screen blending now for (AInventory *item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory) { - PalEntry color = item->GetBlend (); + PalEntry color = item->CallGetBlend (); if (color.a != 0) { V_AddBlend (color.r/255.f, color.g/255.f, color.b/255.f, color.a/255.f, blend); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 62d88237fd..ccf3fb3749 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -339,6 +339,7 @@ class Actor : Thinker native native void SetZ(double z); native vector3 Vec3Offset(double x, double y, double z, bool absolute = false); native vector3 Vec3Angle(double length, double angle, double z = 0, bool absolute = false); + native vector2 Vec2Angle(double length, double angle, bool absolute = false); native vector3 Vec2OffsetZ(double x, double y, double atz, bool absolute = false); native void VelFromAngle(double speed = 0, double angle = 0); native void Thrust(double speed = 0, double angle = 0); @@ -351,6 +352,7 @@ class Actor : Thinker native native double DistanceBySpeed(Actor other, double speed); native name GetSpecies(); native void PlayActiveSound(); + native void Howl(); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index eadf30bc75..5f86282a89 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1007,3 +1007,11 @@ enum EGameType GAME_DoomChex = GAME_Doom|GAME_Chex, GAME_DoomStrifeChex = GAME_Doom|GAME_Strife|GAME_Chex } + +enum PaletteFlashFlags +{ + PF_HEXENWEAPONS = 1, + PF_POISON = 2, + PF_ICE = 4, + PF_HAZARD = 8, +}; diff --git a/wadsrc/static/zscript/hexen/clericboss.txt b/wadsrc/static/zscript/hexen/clericboss.txt index a2019bae53..4bf2235171 100644 --- a/wadsrc/static/zscript/hexen/clericboss.txt +++ b/wadsrc/static/zscript/hexen/clericboss.txt @@ -18,8 +18,6 @@ class ClericBoss : Actor Obituary "$OBCBOSS"; } - native void A_ClericAttack(); - States { Spawn: @@ -79,4 +77,19 @@ class ClericBoss : Actor FDTH V 4 Bright ; Stop; } + + //============================================================================ + // + // A_ClericAttack + // + //============================================================================ + + void A_ClericAttack() + { + if (!target) return; + + Actor missile = SpawnMissileZ (pos.z + 40., target, "HolyMissile"); + if (missile != null) missile.tracer = null; // No initial target + A_PlaySound ("HolySymbolFire", CHAN_WEAPON); + } } diff --git a/wadsrc/static/zscript/hexen/clericholy.txt b/wadsrc/static/zscript/hexen/clericholy.txt index 1a4372f4db..593462d008 100644 --- a/wadsrc/static/zscript/hexen/clericholy.txt +++ b/wadsrc/static/zscript/hexen/clericholy.txt @@ -76,8 +76,10 @@ class WraithvergeDrop : Actor // Cleric's Wraithverge (Holy Symbol?) -------------------------------------- -class CWeapWraithverge : ClericWeapon native +class CWeapWraithverge : ClericWeapon { + int CHolyCount; + Default { Health 3; @@ -96,8 +98,6 @@ class CWeapWraithverge : ClericWeapon native Inventory.PickupSound "WeaponBuild"; } - action native void A_CHolyAttack(); - action native void A_CHolyPalette(); States { @@ -122,6 +122,66 @@ class CWeapWraithverge : ClericWeapon native CHLY G 2 Offset (0, 36) A_CHolyPalette; Goto Ready; } + + override color GetBlend () + { + if (paletteflash & PF_HEXENWEAPONS) + { + if (CHolyCount == 3) + return Color(128, 70, 70, 70); + else if (CHolyCount == 2) + return Color(128, 100, 100, 100); + else if (CHolyCount == 1) + return Color(128, 130, 130, 130); + else + return Color(0, 0, 0, 0); + } + else + { + return Color(CHolyCount * 128 / 3, 131, 131, 131); + } + } + + //============================================================================ + // + // A_CHolyAttack + // + //============================================================================ + + action void A_CHolyAttack() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + Actor missile = SpawnPlayerMissile ("HolyMissile", angle, pLineTarget:t); + if (missile != null && !t.unlinked) + { + missile.tracer = t.linetarget; + } + + invoker.CHolyCount = 3; + A_PlaySound ("HolySymbolFire", CHAN_WEAPON); + } + + //============================================================================ + // + // A_CHolyPalette + // + //============================================================================ + + action void A_CHolyPalette() + { + if (invoker.CHolyCount > 0) invoker.CHolyCount--; + } } // Holy Missile ------------------------------------------------------------- @@ -139,8 +199,6 @@ class HolyMissile : Actor +EXTREMEDEATH } - native void A_CHolyAttack2(); - States { Spawn: @@ -149,6 +207,60 @@ class HolyMissile : Actor SPIR P 1 Bright A_CHolyAttack2; Stop; } + + //============================================================================ + // + // A_CHolyAttack2 + // + // Spawns the spirits + //============================================================================ + + void A_CHolyAttack2() + { + for (int j = 0; j < 4; j++) + { + Actor mo = Spawn("HolySpirit", Pos, ALLOW_REPLACE); + if (!mo) + { + continue; + } + switch (j) + { // float bob index + + case 0: + mo.WeaveIndexZ = random[HolyAtk2]() & 7; // upper-left + break; + case 1: + mo.WeaveIndexZ = 32 + (random[HolyAtk2]() & 7); // upper-right + break; + case 2: + mo.WeaveIndexXY = 32 + (random[HolyAtk2]() & 7); // lower-left + break; + case 3: + mo.WeaveIndexXY = 32 + (random[HolyAtk2]() & 7); + mo.WeaveIndexZ = 32 + (random[HolyAtk2]() & 7); + break; + } + mo.SetZ(pos.z); + mo.angle = angle + 67.5 - 45.*j; + mo.Thrust(); + mo.target = target; + mo.args[0] = 10; // initial turn value + mo.args[1] = 0; // initial look angle + if (deathmatch) + { // Ghosts last slightly less longer in DeathMatch + mo.health = 85; + } + if (tracer) + { + mo.tracer = tracer; + mo.bNoClip = true; + mo.bSkullFly = true; + mo.bMissile = false; + } + HolyTail.SpawnSpiritTail (mo); + } + } } // Holy Missile Puff -------------------------------------------------------- @@ -192,7 +304,7 @@ class HolyPuff : Actor // Holy Spirit -------------------------------------------------------------- -class HolySpirit : Actor native +class HolySpirit : Actor { Default { @@ -204,7 +316,7 @@ class HolySpirit : Actor native Projectile; +RIPPER +SEEKERMISSILE +FOILINVUL +SKYEXPLODE +NOEXPLODEFLOOR +CANBLAST - +EXTREMEDEATH + +EXTREMEDEATH +NOSHIELDREFLECT RenderStyle "Translucent"; Alpha 0.4; DeathSound "SpiritDie"; @@ -226,6 +338,70 @@ class HolySpirit : Actor native SPIR FGHI 4; Stop; } + + //============================================================================ + // + // + // + //============================================================================ + + override bool Slam(Actor thing) + { + if (thing.bShootable && thing != target) + { + if (multiplayer && !deathmatch && thing.player && target.player) + { // don't attack other co-op players + return true; + } + if (thing.bReflective && (thing.player || thing.bBoss)) + { + tracer = target; + target = thing; + return true; + } + if (thing.bIsMonster || thing.player) + { + tracer = thing; + } + if (random[SpiritSlam]() < 96) + { + int dam = 12; + if (thing.player || thing.bBoss) + { + dam = 3; + // ghost burns out faster when attacking players/bosses + health -= 6; + } + thing.DamageMobj(self, target, dam, 'Melee'); + if (random[SpiritSlam]() < 128) + { + Spawn("HolyPuff", Pos, ALLOW_REPLACE); + A_PlaySound("SpiritAttack", CHAN_WEAPON); + if (thing.bIsMonster && random[SpiritSlam]() < 128) + { + thing.Howl(); + } + } + } + if (thing.health <= 0) + { + tracer = null; + } + } + return true; + } + + override bool SpecialBlastHandling (Actor source, double strength) + { + if (tracer == source) + { + tracer = target; + target = source; + } + return true; + } + + } // Holy Tail ---------------------------------------------------------------- @@ -242,8 +418,6 @@ class HolyTail : Actor Alpha 0.6; } - native void A_CHolyTail(); - States { Spawn: @@ -253,6 +427,108 @@ class HolyTail : Actor SPIR D -1; Stop; } + + //============================================================================ + // + // SpawnSpiritTail + // + //============================================================================ + + static void SpawnSpiritTail (Actor spirit) + { + Actor tail = Spawn ("HolyTail", spirit.Pos, ALLOW_REPLACE); + tail.target = spirit; // parent + for (int i = 1; i < 3; i++) + { + Actor next = Spawn ("HolyTailTrail", spirit.Pos, ALLOW_REPLACE); + tail.tracer = next; + tail = next; + } + tail.tracer = null; // last tail bit + } + + //============================================================================ + // + // CHolyTailFollow + // + //============================================================================ + + private void CHolyTailFollow(double dist) + { + Actor mo = self; + while (mo) + { + Actor child = mo.tracer; + if (child) + { + double an = mo.AngleTo(child); + double oldDistance = child.Distance2D(mo); + if (child.TryMove(mo.Pos.XY + AngleToVector(an, dist), true)) + { + double newDistance = child.Distance2D(mo) - 1; + if (oldDistance < 1) + { + if (child.pos.z < mo.pos.z) + { + child.SetZ(mo.pos.z - dist); + } + else + { + child.SetZ(mo.pos.z + dist); + } + } + else + { + child.SetZ(mo.pos.z + (newDistance * (child.pos.z - mo.pos.z) / oldDistance)); + } + } + } + mo = child; + dist -= 1; + } + } + + //============================================================================ + // + // CHolyTailRemove + // + //============================================================================ + + private void CHolyTailRemove () + { + Actor mo = self; + while (mo) + { + Actor next = mo.tracer; + mo.Destroy (); + mo = next; + } + } + + //============================================================================ + // + // A_CHolyTail + // + //============================================================================ + + void A_CHolyTail() + { + Actor parent = self.target; + + if (parent == null || parent.health <= 0) // better check for health than current state - it's safer! + { // Ghost removed, so remove all tail parts + CHolyTailRemove (); + return; + } + else + { + if (TryMove(parent.Vec2Angle(14., parent.Angle, true), true)) + { + self.SetZ(parent.pos.z - 5.); + } + CHolyTailFollow(10); + } + } } // Holy Tail Trail --------------------------------------------------------- diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index c2c99453fa..f87331470c 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -26,6 +26,7 @@ class Inventory : Actor native } virtual native bool Use (bool pickup); + virtual native color GetBlend (); // These are regular functions for the item itself. From 4fcb397346b1ffd1a68eb8777a40d89086b20940 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 14:06:41 +0100 Subject: [PATCH 367/471] - scriptified the remaining parts of the Wraithverge. --- src/CMakeLists.txt | 1 - src/g_hexen/a_clericholy.cpp | 173 --------------------- src/g_hexen/a_hexenmisc.cpp | 1 - wadsrc/static/zscript/hexen/clericholy.txt | 142 ++++++++++++++++- 4 files changed, 136 insertions(+), 181 deletions(-) delete mode 100644 src/g_hexen/a_clericholy.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 376d33887d..c1242853d5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_clericholy.cpp g_hexen/a_clericmace.cpp g_hexen/a_clericstaff.cpp g_hexen/a_fighteraxe.cpp diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp deleted file mode 100644 index 8ffb5be27f..0000000000 --- a/src/g_hexen/a_clericholy.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "m_random.h" -#include "s_sound.h" -#include "a_hexenglobal.h" -#include "gstrings.h" -#include "a_weaponpiece.h" -#include "vm.h" -#include "g_level.h" -#include "doomstat.h" -*/ - -#define BLAST_FULLSTRENGTH 255 - -static FRandom pr_holyatk2 ("CHolyAtk2"); -static FRandom pr_holyseeker ("CHolySeeker"); -static FRandom pr_holyweave ("CHolyWeave"); -static FRandom pr_holyseek ("CHolySeek"); -static FRandom pr_checkscream ("CCheckScream"); -static FRandom pr_spiritslam ("CHolySlam"); -static FRandom pr_wraithvergedrop ("WraithvergeDrop"); - -void SpawnSpiritTail (AActor *spirit); - -// Holy Spirit -------------------------------------------------------------- - -//============================================================================ -// -// CHolyFindTarget -// -//============================================================================ - -static void CHolyFindTarget (AActor *actor) -{ - AActor *target; - - if ( (target = P_RoughMonsterSearch (actor, 6, true)) ) - { - actor->tracer = target; - actor->flags |= MF_NOCLIP|MF_SKULLFLY; - actor->flags &= ~MF_MISSILE; - } -} - -//============================================================================ -// -// CHolySeekerMissile -// -// Similar to P_SeekerMissile, but seeks to a random Z on the target -//============================================================================ - -static void CHolySeekerMissile (AActor *actor, DAngle thresh, DAngle turnMax) -{ - int dir; - DAngle delta; - AActor *target; - double newZ; - double deltaZ; - - target = actor->tracer; - if (target == NULL) - { - return; - } - if (!(target->flags&MF_SHOOTABLE) - || (!(target->flags3&MF3_ISMONSTER) && !target->player)) - { // Target died/target isn't a player or creature - actor->tracer = NULL; - actor->flags &= ~(MF_NOCLIP | MF_SKULLFLY); - actor->flags |= MF_MISSILE; - CHolyFindTarget(actor); - return; - } - dir = P_FaceMobj (actor, target, &delta); - if (delta > thresh) - { - delta /= 2; - if (delta > turnMax) - { - delta = turnMax; - } - } - if (dir) - { // Turn clockwise - actor->Angles.Yaw += delta; - } - else - { // Turn counter clockwise - actor->Angles.Yaw -= delta; - } - actor->VelFromAngle(); - - if (!(level.time&15) - || actor->Z() > target->Top() - || actor->Top() < target->Z()) - { - newZ = target->Z() + ((pr_holyseeker()*target->Height) / 256.); - deltaZ = newZ - actor->Z(); - if (fabs(deltaZ) > 15) - { - if (deltaZ > 0) - { - deltaZ = 15; - } - else - { - deltaZ = -15; - } - } - actor->Vel.Z = deltaZ / actor->DistanceBySpeed(target, actor->Speed); - } - return; -} - -//============================================================================ -// -// A_CHolySeek -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CHolySeek) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->health--; - if (self->health <= 0) - { - self->Vel.X /= 4; - self->Vel.Y /= 4; - self->Vel.Z = 0; - self->SetState (self->FindState(NAME_Death)); - self->tics -= pr_holyseek()&3; - return 0; - } - if (self->tracer) - { - CHolySeekerMissile (self, (double)self->args[0], self->args[0]*2.); - if (!((level.time+7)&15)) - { - self->args[0] = 5+(pr_holyseek()/20); - } - } - - int xyspeed = (pr_holyweave() % 5); - int zspeed = (pr_holyweave() % 5); - A_Weave(self, xyspeed, zspeed, 4., 2.); - return 0; -} - -//============================================================================ -// -// A_CHolyCheckScream -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CHolyCheckScream) -{ - PARAM_SELF_PROLOGUE(AActor); - - CALL_ACTION(A_CHolySeek, self); - if (pr_checkscream() < 20) - { - S_Sound (self, CHAN_VOICE, "SpiritActive", 1, ATTN_NORM); - } - if (!self->tracer) - { - CHolyFindTarget(self); - } - return 0; -} - diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index cbe9d3c12a..7bd38ceaba 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,7 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_clericholy.cpp" #include "a_clericmace.cpp" #include "a_clericstaff.cpp" #include "a_fighteraxe.cpp" diff --git a/wadsrc/static/zscript/hexen/clericholy.txt b/wadsrc/static/zscript/hexen/clericholy.txt index 593462d008..33b69bf25a 100644 --- a/wadsrc/static/zscript/hexen/clericholy.txt +++ b/wadsrc/static/zscript/hexen/clericholy.txt @@ -323,9 +323,6 @@ class HolySpirit : Actor Obituary "$OB_MPCWEAPWRAITHVERGE"; } - native void A_CHolySeek(); - native void A_CHolyCheckScream(); - States { Spawn: @@ -401,7 +398,140 @@ class HolySpirit : Actor return true; } - + //============================================================================ + // + // CHolyFindTarget + // + //============================================================================ + + private void CHolyFindTarget () + { + Actor target; + + if ( (target = RoughMonsterSearch (6, true)) ) + { + tracer = target; + bNoClip = true; + bSkullFly = true; + bMissile = false; + } + } + + //============================================================================ + // + // CHolySeekerMissile + // + // Similar to P_SeekerMissile, but seeks to a random Z on the target + //============================================================================ + + private void CHolySeekerMissile (double thresh, double turnMax) + { + Actor target = tracer; + if (target == NULL) + { + return; + } + if (!target.bShootable || (!target.bIsMonster && !target.player)) + { // Target died/target isn't a player or creature + tracer = null; + bNoClip = false; + bSkullFly = false; + bMissile = true; + CHolyFindTarget(); + return; + } + double ang = deltaangle(angle, AngleTo(target)); + double delta = abs(ang); + + if (delta > thresh) + { + delta /= 2; + if (delta > turnMax) + { + delta = turnMax; + } + } + if (ang > 0) + { // Turn clockwise + angle += delta; + } + else + { // Turn counter clockwise + angle -= delta; + } + VelFromAngle(); + + if (!(level.time&15) + || pos.z > target.pos.z + target.height + || pos.z + height < target.pos.z) + { + double newZ = target.pos.z + ((random[HolySeeker]()*target.Height) / 256.); + double deltaZ = newZ - pos.z; + if (abs(deltaZ) > 15) + { + if (deltaZ > 0) + { + deltaZ = 15; + } + else + { + deltaZ = -15; + } + } + Vel.Z = deltaZ / DistanceBySpeed(target, Speed); + } + } + + //============================================================================ + // + // A_CHolySeek + // + //============================================================================ + + void A_CHolySeek() + { + health--; + if (health <= 0) + { + Vel.X /= 4; + Vel.Y /= 4; + Vel.Z = 0; + SetStateLabel ("Death"); + tics -= random[HolySeeker]()&3; + return; + } + if (tracer) + { + CHolySeekerMissile (args[0], args[0]*2.); + if (!((level.time+7)&15)) + { + args[0] = 5+(random[HolySeeker]()/20); + } + } + + int xyspeed = (random[HolySeeker]() % 5); + int zspeed = (random[HolySeeker]() % 5); + A_Weave(xyspeed, zspeed, 4., 2.); + } + + //============================================================================ + // + // A_CHolyCheckScream + // + //============================================================================ + + void A_CHolyCheckScream() + { + A_CHolySeek(); + if (random[HolyScream]() < 20) + { + A_PlaySound ("SpiritActive", CHAN_VOICE); + } + if (!tracer) + { + CHolyFindTarget(); + } + } } // Holy Tail ---------------------------------------------------------------- @@ -513,7 +643,7 @@ class HolyTail : Actor void A_CHolyTail() { - Actor parent = self.target; + Actor parent = target; if (parent == null || parent.health <= 0) // better check for health than current state - it's safer! { // Ghost removed, so remove all tail parts @@ -524,7 +654,7 @@ class HolyTail : Actor { if (TryMove(parent.Vec2Angle(14., parent.Angle, true), true)) { - self.SetZ(parent.pos.z - 5.); + SetZ(parent.pos.z - 5.); } CHolyTailFollow(10); } From 659a592f16829ac7ec643af7a13ac0ad885ccc02 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 16:25:10 +0100 Subject: [PATCH 368/471] - scriptified Korax. --- src/CMakeLists.txt | 1 - src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_korax.cpp | 502 -------------------------- wadsrc/static/zscript/hexen/korax.txt | 428 +++++++++++++++++++++- 4 files changed, 413 insertions(+), 519 deletions(-) delete mode 100644 src/g_hexen/a_korax.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c1242853d5..828c7fc34a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -867,7 +867,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_heresiarch.cpp g_hexen/a_hexenspecialdecs.cpp g_hexen/a_iceguy.cpp - g_hexen/a_korax.cpp g_hexen/a_magecone.cpp g_hexen/a_magelightning.cpp g_hexen/a_magestaff.cpp diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 7bd38ceaba..3fb334cb15 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -36,7 +36,6 @@ #include "a_heresiarch.cpp" #include "a_hexenspecialdecs.cpp" #include "a_iceguy.cpp" -#include "a_korax.cpp" #include "a_magecone.cpp" #include "a_magelightning.cpp" #include "a_magestaff.cpp" diff --git a/src/g_hexen/a_korax.cpp b/src/g_hexen/a_korax.cpp deleted file mode 100644 index 8a459ffd4b..0000000000 --- a/src/g_hexen/a_korax.cpp +++ /dev/null @@ -1,502 +0,0 @@ -//=========================================================================== -// Korax Variables -// tracer last teleport destination -// special2 set if "below half" script not yet run -// -// Korax Scripts (reserved) -// 249 Tell scripts that we are below half health -// 250-254 Control scripts (254 is only used when less than half health) -// 255 Death script -// -// Korax TIDs (reserved) -// 245 Reserved for Korax himself -// 248 Initial teleport destination -// 249 Teleport destination -// 250-254 For use in respective control scripts -// 255 For use in death script (spawn spots) -//=========================================================================== - -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "p_spec.h" -#include "s_sound.h" -#include "a_action.h" -#include "m_random.h" -#include "i_system.h" -#include "vm.h" -#include "g_level.h" -*/ - -const int KORAX_SPIRIT_LIFETIME = 5*TICRATE/5; // 5 seconds -const int KORAX_COMMAND_HEIGHT = 120; -const int KORAX_COMMAND_OFFSET = 27; - -const int KORAX_TID = 245; -const int KORAX_FIRST_TELEPORT_TID = 248; -const int KORAX_TELEPORT_TID = 249; - -const int KORAX_DELTAANGLE = 85; -const int KORAX_ARM_EXTENSION_SHORT = 40; -const int KORAX_ARM_EXTENSION_LONG = 55; - -const int KORAX_ARM1_HEIGHT = 108; -const int KORAX_ARM2_HEIGHT = 82; -const int KORAX_ARM3_HEIGHT = 54; -const int KORAX_ARM4_HEIGHT = 104; -const int KORAX_ARM5_HEIGHT = 86; -const int KORAX_ARM6_HEIGHT = 53; - -const double KORAX_BOLT_HEIGHT = 48.; -const int KORAX_BOLT_LIFETIME = 3; - - - -static FRandom pr_koraxchase ("KoraxChase"); -static FRandom pr_kspiritinit ("KSpiritInit"); -static FRandom pr_koraxdecide ("KoraxDecide"); -static FRandom pr_koraxmissile ("KoraxMissile"); -static FRandom pr_koraxcommand ("KoraxCommand"); -static FRandom pr_kspiritweave ("KSpiritWeave"); -static FRandom pr_kspiritseek ("KSpiritSeek"); -static FRandom pr_kspiritroam ("KSpiritRoam"); -static FRandom pr_kmissile ("SKoraxMissile"); - -void A_KoraxChase (AActor *); -void A_KoraxStep (AActor *); -void A_KoraxStep2 (AActor *); -void A_KoraxDecide (AActor *); -void A_KoraxBonePop (AActor *); -void A_KoraxMissile (AActor *); -void A_KoraxCommand (AActor *); -void A_KSpiritRoam (AActor *); -void A_KBolt (AActor *); -void A_KBoltRaise (AActor *); - -void KoraxFire (AActor *actor, PClassActor *type, int arm); -void KSpiritInit (AActor *spirit, AActor *korax); -AActor *P_SpawnKoraxMissile (const DVector3 &pos, AActor *source, AActor *dest, PClassActor *type); - -extern void SpawnSpiritTail (AActor *spirit); - -//============================================================================ -// -// A_KoraxChase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_KoraxChase) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *spot; - - if ((!self->special2) && (self->health <= (self->SpawnHealth()/2))) - { - FActorIterator iterator (KORAX_FIRST_TELEPORT_TID); - spot = iterator.Next (); - if (spot != NULL) - { - P_Teleport (self, spot->PosAtZ(ONFLOORZ), spot->Angles.Yaw, TELF_SOURCEFOG | TELF_DESTFOG); - } - - P_StartScript (self, NULL, 249, NULL, NULL, 0, 0); - self->special2 = 1; // Don't run again - - return 0; - } - - if (self->target == NULL) - { - return 0; - } - if (pr_koraxchase()<30) - { - self->SetState (self->MissileState); - } - else if (pr_koraxchase()<30) - { - S_Sound (self, CHAN_VOICE, "KoraxActive", 1, ATTN_NONE); - } - - // Teleport away - if (self->health < (self->SpawnHealth()>>1)) - { - if (pr_koraxchase()<10) - { - FActorIterator iterator (KORAX_TELEPORT_TID); - - if (self->tracer != NULL) - { // Find the previous teleport destination - do - { - spot = iterator.Next (); - } while (spot != NULL && spot != self->tracer); - } - - // Go to the next teleport destination - spot = iterator.Next (); - self->tracer = spot; - if (spot) - { - P_Teleport (self, spot->PosAtZ(ONFLOORZ), spot->Angles.Yaw, TELF_SOURCEFOG | TELF_DESTFOG); - } - } - } - return 0; -} - -//============================================================================ -// -// A_KoraxBonePop -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_KoraxBonePop) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - int i; - - // Spawn 6 spirits equalangularly - for (i = 0; i < 6; ++i) - { - mo = P_SpawnMissileAngle (self, PClass::FindActor("KoraxSpirit"), DAngle(60.*i), 5.); - if (mo) - { - KSpiritInit (mo, self); - } - } - - P_StartScript (self, NULL, 255, NULL, NULL, 0, 0); // Death script - return 0; -} - -//============================================================================ -// -// KSpiritInit -// -//============================================================================ - -void KSpiritInit (AActor *spirit, AActor *korax) -{ - spirit->health = KORAX_SPIRIT_LIFETIME; - - spirit->tracer = korax; // Swarm around korax - spirit->WeaveIndexZ = 32 + (pr_kspiritinit() & 7); // Float bob index - spirit->args[0] = 10; // initial turn value - spirit->args[1] = 0; // initial look angle - -#if 0 // Temporarily deactivated. - // Spawn a tail for spirit - HolyTail.SpawnSpiritTail (spirit); -#endif - -} - -//============================================================================ -// -// A_KoraxDecide -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_KoraxDecide) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (pr_koraxdecide()<220) - { - self->SetState (self->FindState("Attack")); - } - else - { - self->SetState (self->FindState("Command")); - } - return 0; -} - -//============================================================================ -// -// A_KoraxMissile -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_KoraxMissile) -{ - PARAM_SELF_PROLOGUE(AActor); - - static const struct { const char *type, *sound; } choices[6] = - { - { "WraithFX1", "WraithMissileFire" }, - { "Demon1FX1", "DemonMissileFire" }, - { "Demon2FX1", "DemonMissileFire" }, - { "FireDemonMissile", "FireDemonAttack" }, - { "CentaurFX", "CentaurLeaderAttack" }, - { "SerpentFX", "CentaurLeaderAttack" } - }; - - int type = pr_koraxmissile() % 6; - int i; - PClassActor *info; - - S_Sound(self, CHAN_VOICE, "KoraxAttack", 1, ATTN_NORM); - - info = PClass::FindActor(choices[type].type); - if (info == NULL) - { - I_Error("Unknown Korax missile: %s\n", choices[type].type); - } - - // Fire all 6 missiles at once - S_Sound(self, CHAN_WEAPON, choices[type].sound, 1, ATTN_NONE); - for (i = 0; i < 6; ++i) - { - KoraxFire(self, info, i); - } - return 0; -} - -//============================================================================ -// -// A_KoraxCommand -// -// Call action code scripts (250-254) -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_KoraxCommand) -{ - PARAM_SELF_PROLOGUE(AActor); - DAngle ang; - int numcommands; - - S_Sound (self, CHAN_VOICE, "KoraxCommand", 1, ATTN_NORM); - - // Shoot stream of lightning to ceiling - ang = self->Angles.Yaw - 90; - DVector3 pos = self->Vec3Angle(KORAX_COMMAND_OFFSET, ang, KORAX_COMMAND_HEIGHT); - Spawn("KoraxBolt", pos, ALLOW_REPLACE); - - if (self->health <= (self->SpawnHealth() >> 1)) - { - numcommands = 5; - } - else - { - numcommands = 4; - } - - P_StartScript (self, NULL, 250+(pr_koraxcommand()%numcommands), NULL, NULL, 0, 0); - return 0; -} - -//============================================================================ -// -// KoraxFire -// -// Arm projectiles -// arm positions numbered: -// 1 top left -// 2 middle left -// 3 lower left -// 4 top right -// 5 middle right -// 6 lower right -// -//============================================================================ - -void KoraxFire (AActor *actor, PClassActor *type, int arm) -{ - static const int extension[6] = - { - KORAX_ARM_EXTENSION_SHORT, - KORAX_ARM_EXTENSION_LONG, - KORAX_ARM_EXTENSION_LONG, - KORAX_ARM_EXTENSION_SHORT, - KORAX_ARM_EXTENSION_LONG, - KORAX_ARM_EXTENSION_LONG - }; - static const int armheight[6] = - { - KORAX_ARM1_HEIGHT, - KORAX_ARM2_HEIGHT, - KORAX_ARM3_HEIGHT, - KORAX_ARM4_HEIGHT, - KORAX_ARM5_HEIGHT, - KORAX_ARM6_HEIGHT - }; - - DAngle ang = actor->Angles.Yaw + (arm < 3 ? -KORAX_DELTAANGLE : KORAX_DELTAANGLE); - DVector3 pos = actor->Vec3Angle(extension[arm], ang, armheight[arm] - actor->Floorclip); - P_SpawnKoraxMissile (pos, actor, actor->target, type); -} - -//============================================================================ -// -// A_KSpiritSeeker -// -//============================================================================ - -static void A_KSpiritSeeker (AActor *actor, DAngle thresh, DAngle turnMax) -{ - int dir; - DAngle delta; - AActor *target; - double newZ; - double deltaZ; - - target = actor->tracer; - if (target == NULL) - { - return; - } - dir = P_FaceMobj (actor, target, &delta); - if (delta > thresh) - { - delta /= 2; - if(delta > turnMax) - { - delta = turnMax; - } - } - if(dir) - { // Turn clockwise - actor->Angles.Yaw += delta; - } - else - { // Turn counter clockwise - actor->Angles.Yaw -= delta; - } - actor->VelFromAngle(); - - if (!(level.time&15) - || actor->Z() > target->Z() + target->GetDefault()->Height - || actor->Top() < target->Z()) - { - newZ = target->Z() + pr_kspiritseek() * target->GetDefault()->Height / 256; - deltaZ = newZ-actor->Z(); - - if (fabs(deltaZ) > 15) - { - if(deltaZ > 0) - { - deltaZ = 15; - } - else - { - deltaZ = -15; - } - } - actor->Vel.Z = deltaZ + actor->DistanceBySpeed(target, actor->Speed); - } - return; -} - -//============================================================================ -// -// A_KSpiritRoam -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_KSpiritRoam) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->health-- <= 0) - { - S_Sound (self, CHAN_VOICE, "SpiritDie", 1, ATTN_NORM); - self->SetState (self->FindState("Death")); - } - else - { - if (self->tracer) - { - A_KSpiritSeeker(self, (double)self->args[0], self->args[0] * 2.); - } - int xyspeed = (pr_kspiritweave() % 5); - int zspeed = (pr_kspiritweave() % 5); - A_Weave(self, xyspeed, zspeed, 4., 2.); - - if (pr_kspiritroam()<50) - { - S_Sound (self, CHAN_VOICE, "SpiritActive", 1, ATTN_NONE); - } - } - return 0; -} - -//============================================================================ -// -// A_KBolt -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_KBolt) -{ - PARAM_SELF_PROLOGUE(AActor); - - // Countdown lifetime - if (self->special1-- <= 0) - { - self->Destroy (); - } - return 0; -} - -//============================================================================ -// -// A_KBoltRaise -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_KBoltRaise) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - // Spawn a child upward - double z = self->Z() + KORAX_BOLT_HEIGHT; - - if ((z + KORAX_BOLT_HEIGHT) < self->ceilingz) - { - mo = Spawn("KoraxBolt", self->PosAtZ(z), ALLOW_REPLACE); - if (mo) - { - mo->special1 = KORAX_BOLT_LIFETIME; - } - } - else - { - // Maybe cap it off here - } - return 0; -} - -//============================================================================ -// -// P_SpawnKoraxMissile -// -//============================================================================ - -AActor *P_SpawnKoraxMissile (const DVector3 &pos, AActor *source, AActor *dest, PClassActor *type) -{ - AActor *th; - DAngle an; - double dist; - - th = Spawn (type, pos, ALLOW_REPLACE); - th->target = source; // Originator - an = th->AngleTo(dest); - if (dest->flags & MF_SHADOW) - { // Invisible target - an += pr_kmissile.Random2() * (45/256.); - } - th->Angles.Yaw = an; - th->VelFromAngle(); - dist = dest->DistanceBySpeed(th, th->Speed); - th->Vel.Z = (dest->Z() - pos.Z + 30) / dist; - return (P_CheckMissileSpawn(th, source->radius) ? th : NULL); -} diff --git a/wadsrc/static/zscript/hexen/korax.txt b/wadsrc/static/zscript/hexen/korax.txt index 16bf172a46..1c1f31712f 100644 --- a/wadsrc/static/zscript/hexen/korax.txt +++ b/wadsrc/static/zscript/hexen/korax.txt @@ -1,5 +1,43 @@ +//=========================================================================== +// Korax Variables +// tracer last teleport destination +// special2 set if "below half" script not yet run +// +// Korax Scripts (reserved) +// 249 Tell scripts that we are below half health +// 250-254 Control scripts (254 is only used when less than half health) +// 255 Death script +// +// Korax TIDs (reserved) +// 245 Reserved for Korax himself +// 248 Initial teleport destination +// 249 Teleport destination +// 250-254 For use in respective control scripts +// 255 For use in death script (spawn spots) +//=========================================================================== + class Korax : Actor { + const KORAX_ARM_EXTENSION_SHORT = 40; + const KORAX_ARM_EXTENSION_LONG = 55; + + const KORAX_ARM1_HEIGHT = 108; + const KORAX_ARM2_HEIGHT = 82; + const KORAX_ARM3_HEIGHT = 54; + const KORAX_ARM4_HEIGHT = 104; + const KORAX_ARM5_HEIGHT = 86; + const KORAX_ARM6_HEIGHT = 53; + + const KORAX_FIRST_TELEPORT_TID = 248; + const KORAX_TELEPORT_TID = 249; + + const KORAX_DELTAANGLE = 85; + + const KORAX_COMMAND_HEIGHT = 120; + const KORAX_COMMAND_OFFSET = 27; + + const KORAX_SPIRIT_LIFETIME = 5*TICRATE/5; // 5 seconds + Default { Health 5000; @@ -24,12 +62,6 @@ class Korax : Actor 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: @@ -39,13 +71,11 @@ class Korax : Actor 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 C 3 A_KoraxStep; 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; + KORX A 3 A_KoraxStep; Loop; Pain: KORX H 5 A_Pain; @@ -79,6 +109,255 @@ class Korax : Actor KORX E 5 Bright; Goto See; } + + + void A_KoraxStep() + { + A_PlaySound("KoraxStep"); + A_Chase(); + } + + //============================================================================ + // + // A_KoraxChase + // + //============================================================================ + + + void A_KoraxChase() + { + if ((!special2) && (health <= (SpawnHealth()/2))) + { + ActorIterator it = ActorIterator.Create(KORAX_FIRST_TELEPORT_TID); + Actor spot = it.Next (); + if (spot != null) + { + Teleport ((spot.pos.xy, ONFLOORZ), spot.angle, TELF_SOURCEFOG | TELF_DESTFOG); + } + ACS_Execute(249, 0); + special2 = 1; // Don't run again + return; + } + + if (target == null) + { + return; + } + if (random[KoraxChase]() < 30) + { + SetState (MissileState); + } + else if (random[KoraxChase]() < 30) + { + A_PlaySound("KoraxActive", CHAN_VOICE, 1, false, ATTN_NONE); + } + + // Teleport away + if (health < (SpawnHealth() >> 1)) + { + if (random[KoraxChase]() < 10) + { + ActorIterator it = ActorIterator.Create(KORAX_TELEPORT_TID); + Actor spot; + + if (tracer != null) + { // Find the previous teleport destination + do + { + spot = it.Next (); + } while (spot != null && spot != tracer); + } + + // Go to the next teleport destination + spot = it.Next (); + tracer = spot; + if (spot) + { + Teleport ((spot.pos.xy, ONFLOORZ), spot.angle, TELF_SOURCEFOG | TELF_DESTFOG); + } + } + } + } + + //============================================================================ + // + // A_KoraxDecide + // + //============================================================================ + + void A_KoraxDecide() + { + if (random[KoraxDecide]() < 220) + { + SetStateLabel ("Attack"); + } + else + { + SetStateLabel ("Command"); + } + } + + //============================================================================ + // + // A_KoraxBonePop + // + //============================================================================ + + void A_KoraxBonePop() + { + // Spawn 6 spirits equalangularly + for (int i = 0; i < 6; ++i) + { + Actor mo = SpawnMissileAngle ("KoraxSpirit", 60.*i, 5.); + if (mo) + { + KSpiritInit (mo); + } + } + ACS_Execute(255, 0); + } + + //============================================================================ + // + // KSpiritInit + // + //============================================================================ + + private void KSpiritInit (Actor spirit) + { + spirit.health = KORAX_SPIRIT_LIFETIME; + + spirit.tracer = self; // Swarm around korax + spirit.WeaveIndexZ = 32 + (random[Kspiritnit]() & 7); // Float bob index + spirit.args[0] = 10; // initial turn value + spirit.args[1] = 0; // initial look angle + + // Spawn a tail for spirit + HolyTail.SpawnSpiritTail (spirit); + } + + //============================================================================ + // + // A_KoraxMissile + // + //============================================================================ + + void A_KoraxMissile() + { + static const class choices[] = + { + "WraithFX1", "Demon1FX1", "Demon2FX1", "FireDemonMissile", "CentaurFX", "SerpentFX" + }; + static const sound sounds[] = + { + "WraithMissileFire", "DemonMissileFire", "DemonMissileFire", "FireDemonAttack", "CentaurLeaderAttack", "SerpentLeaderAttack" + }; + int type = random[KoraxMissile]() % 6; + + A_PlaySound("KoraxAttack", CHAN_VOICE); + + // Fire all 6 missiles at once + A_PlaySound(sounds[type], CHAN_WEAPON, 1, false, ATTN_NONE); + class info = choices[type]; + for (int i = 0; i < 6; ++i) + { + KoraxFire(info, i); + } + } + + //============================================================================ + // + // KoraxFire + // + // Arm projectiles + // arm positions numbered: + // 1 top left + // 2 middle left + // 3 lower left + // 4 top right + // 5 middle right + // 6 lower right + // + //============================================================================ + + void KoraxFire (Class type, int arm) + { + static const int extension[] = + { + KORAX_ARM_EXTENSION_SHORT, + KORAX_ARM_EXTENSION_LONG, + KORAX_ARM_EXTENSION_LONG, + KORAX_ARM_EXTENSION_SHORT, + KORAX_ARM_EXTENSION_LONG, + KORAX_ARM_EXTENSION_LONG + }; + static const int armheight[] = + { + KORAX_ARM1_HEIGHT, + KORAX_ARM2_HEIGHT, + KORAX_ARM3_HEIGHT, + KORAX_ARM4_HEIGHT, + KORAX_ARM5_HEIGHT, + KORAX_ARM6_HEIGHT + }; + + double ang = angle + (arm < 3 ? -KORAX_DELTAANGLE : KORAX_DELTAANGLE); + Vector3 pos = Vec3Angle(extension[arm], ang, armheight[arm] - Floorclip); + SpawnKoraxMissile (pos, target, type); + } + + //============================================================================ + // + // P_SpawnKoraxMissile + // + //============================================================================ + + private void SpawnKoraxMissile (Vector3 pos, Actor dest, Class type) + { + Actor th = Spawn (type, pos, ALLOW_REPLACE); + th.target = self; // Originator + double an = th.AngleTo(dest); + if (dest.bShadow) + { // Invisible target + an += Random2[KoraxMissile]() * (45/256.); + } + th.angle = an; + th.VelFromAngle(); + double dist = dest.DistanceBySpeed(th, th.Speed); + th.Vel.Z = (dest.pos.z - pos.Z + 30) / dist; + th.CheckMissileSpawn(radius); + } + + //============================================================================ + // + // A_KoraxCommand + // + // Call action code scripts (250-254) + // + //============================================================================ + + void A_KoraxCommand() + { + int numcommands; + + A_PlaySound("KoraxCommand", CHAN_VOICE); + + // Shoot stream of lightning to ceiling + double ang = angle - 90; + Vector3 pos = Vec3Angle(KORAX_COMMAND_OFFSET, ang, KORAX_COMMAND_HEIGHT); + Spawn("KoraxBolt", pos, ALLOW_REPLACE); + + if (health <= (SpawnHealth() >> 1)) + { + numcommands = 5; + } + else + { + numcommands = 4; + } + + ACS_Execute(250 + (random[KoraxCommand]()%numcommands), 0); + } } class KoraxSpirit : Actor @@ -94,8 +373,6 @@ class KoraxSpirit : Actor Alpha 0.4; } - native void A_KSpiritRoam(); - States { Spawn: @@ -105,10 +382,98 @@ class KoraxSpirit : Actor SPIR DEFGHI 5; Stop; } + + //============================================================================ + // + // A_KSpiritSeeker + // + //============================================================================ + + private void KSpiritSeeker (double thresh, double turnMax) + { + Actor target = tracer; + if (target == null) + { + return; + } + double dir = deltaangle(angle, AngleTo(target)); + double delta = abs(dir); + if (delta > thresh) + { + delta /= 2; + if(delta > turnMax) + { + delta = turnMax; + } + } + if(dir > 0) + { // Turn clockwise + angle += delta; + } + else + { // Turn counter clockwise + angle -= delta; + } + VelFromAngle(); + + if (!(level.time&15) + || pos.z > target.pos.z + target.Default.Height + || pos.z + height < target.pos.z) + { + double newZ = target.pos.z + random[KoraxRoam]() * target.Default.Height / 256; + double deltaZ = newZ - pos.z; + + if (abs(deltaZ) > 15) + { + if(deltaZ > 0) + { + deltaZ = 15; + } + else + { + deltaZ = -15; + } + } + Vel.Z = deltaZ + DistanceBySpeed(target, Speed); + } + } + + //============================================================================ + // + // A_KSpiritRoam + // + //============================================================================ + + void A_KSpiritRoam() + { + if (health-- <= 0) + { + A_PlaySound("SpiritDie", CHAN_VOICE); + SetStateLabel ("Death"); + } + else + { + if (tracer) + { + KSpiritSeeker(args[0], args[0] * 2.); + } + int xyspeed = (random[KoraxRoam]() % 5); + int zspeed = (random[KoraxRoam]() % 5); + A_Weave(xyspeed, zspeed, 4., 2.); + + if (random[KoraxRoam]() < 50) + { + A_PlaySound("SpiritActive", CHAN_VOICE, 1, false, ATTN_NONE); + } + } + } } class KoraxBolt : Actor { + const KORAX_BOLT_HEIGHT = 48.; + const KORAX_BOLT_LIFETIME = 3; + Default { Radius 15; @@ -119,9 +484,6 @@ class KoraxBolt : Actor RenderStyle "Add"; } - native void A_KBolt(); - native void A_KBoltRaise(); - States { Spawn: @@ -130,4 +492,40 @@ class KoraxBolt : Actor MLFX IJKLM 2 Bright A_KBolt; Stop; } + + //============================================================================ + // + // A_KBolt + // + //============================================================================ + + void A_KBolt() + { + // Countdown lifetime + if (special1-- <= 0) + { + Destroy (); + } + } + + //============================================================================ + // + // A_KBoltRaise + // + //============================================================================ + + void A_KBoltRaise() + { + // Spawn a child upward + double z = pos.z + KORAX_BOLT_HEIGHT; + + if ((z + KORAX_BOLT_HEIGHT) < ceilingz) + { + Actor mo = Spawn("KoraxBolt", (pos.xy, z), ALLOW_REPLACE); + if (mo) + { + mo.special1 = KORAX_BOLT_LIFETIME; + } + } + } } From 997e4a2ac40a68bad6cb8cde02938f31335adc48 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 19:23:22 +0100 Subject: [PATCH 369/471] - scriptified the remaining Cleric weapons. --- src/CMakeLists.txt | 2 - src/g_hexen/a_clericmace.cpp | 59 ------ src/g_hexen/a_clericstaff.cpp | 199 -------------------- src/g_hexen/a_hexenmisc.cpp | 2 - src/p_interaction.cpp | 9 + src/p_user.cpp | 6 + src/scripting/zscript/zcc_parser.cpp | 2 + wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/hexen/clericmace.txt | 42 ++++- wadsrc/static/zscript/hexen/clericstaff.txt | 156 ++++++++++++++- wadsrc/static/zscript/shared/player.txt | 4 +- 11 files changed, 210 insertions(+), 272 deletions(-) delete mode 100644 src/g_hexen/a_clericmace.cpp delete mode 100644 src/g_hexen/a_clericstaff.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 828c7fc34a..42dc50f982 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,8 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_clericmace.cpp - g_hexen/a_clericstaff.cpp g_hexen/a_fighteraxe.cpp g_hexen/a_fighterhammer.cpp g_hexen/a_fighterplayer.cpp diff --git a/src/g_hexen/a_clericmace.cpp b/src/g_hexen/a_clericmace.cpp deleted file mode 100644 index a15196cf8b..0000000000 --- a/src/g_hexen/a_clericmace.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* -#include "m_random.h" -#include "p_local.h" -#include "a_hexenglobal.h" -#include "vm.h" -*/ - -static FRandom pr_maceatk ("CMaceAttack"); - -//=========================================================================== -// -// A_CMaceAttack -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - DAngle slope; - int i; - player_t *player; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - - PClassActor *hammertime = PClass::FindActor("HammerPuff"); - - damage = 25+(pr_maceatk()&15); - for (i = 0; i < 16; i++) - { - for (int j = 1; j >= -1; j -= 2) - { - angle = player->mo->Angles.Yaw + j*i*(45. / 16); - slope = P_AimLineAttack(player->mo, angle, 2 * MELEERANGE, &t); - if (t.linetarget) - { - P_LineAttack(player->mo, angle, 2 * MELEERANGE, slope, damage, NAME_Melee, hammertime, true, &t); - if (t.linetarget != NULL) - { - AdjustPlayerAngle(player->mo, &t); - return 0; - } - } - } - } - // didn't find any creatures, so try to strike any walls - player->mo->weaponspecial = 0; - - angle = player->mo->Angles.Yaw; - slope = P_AimLineAttack (player->mo, angle, MELEERANGE); - P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, hammertime); - return 0; -} diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp deleted file mode 100644 index ef7beaffa0..0000000000 --- a/src/g_hexen/a_clericstaff.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "a_action.h" -#include "p_pspr.h" -#include "gstrings.h" -#include "a_hexenglobal.h" -#include "vm.h" -*/ - -static FRandom pr_staffcheck ("CStaffCheck"); -static FRandom pr_blink ("CStaffBlink"); - -// Serpent Staff Missile ---------------------------------------------------- - -class ACStaffMissile : public AActor -{ - DECLARE_CLASS (ACStaffMissile, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(ACStaffMissile, false, false) - -int ACStaffMissile::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - // Cleric Serpent Staff does poison damage - if (target->player) - { - P_PoisonPlayer (target->player, this, this->target, 20); - damage >>= 1; - } - return damage; -} - -//============================================================================ -// -// A_CStaffCheck -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) -{ - PARAM_ACTION_PROLOGUE(AActor); - - APlayerPawn *pmo; - int damage; - int newLife, max; - DAngle angle; - DAngle slope; - int i; - player_t *player; - FTranslatedLineTarget t; - PClassActor *puff; - - if (nullptr == (player = self->player)) - { - return 0; - } - AWeapon *weapon = self->player->ReadyWeapon; - - pmo = player->mo; - damage = 20 + (pr_staffcheck() & 15); - max = pmo->GetMaxHealth(); - puff = PClass::FindActor("CStaffPuff"); - for (i = 0; i < 3; i++) - { - for (int j = 1; j >= -1; j -= 2) - { - angle = pmo->Angles.Yaw + j*i*(45. / 16); - slope = P_AimLineAttack(pmo, angle, 1.5 * MELEERANGE, &t, 0., ALF_CHECK3D); - if (t.linetarget) - { - P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage, NAME_Melee, puff, false, &t); - if (t.linetarget != nullptr) - { - pmo->Angles.Yaw = t.angleFromSource; - if (((t.linetarget->player && (!t.linetarget->IsTeammate(pmo) || level.teamdamage != 0)) || t.linetarget->flags3&MF3_ISMONSTER) - && (!(t.linetarget->flags2&(MF2_DORMANT | MF2_INVULNERABLE)))) - { - newLife = player->health + (damage >> 3); - newLife = newLife > max ? max : newLife; - if (newLife > player->health) - { - pmo->health = player->health = newLife; - } - if (weapon != nullptr) - { - FState * newstate = weapon->FindState("Drain"); - if (newstate != nullptr) P_SetPsprite(player, PSP_WEAPON, newstate); - } - } - if (weapon != nullptr) - { - weapon->DepleteAmmo(weapon->bAltFire, false); - } - } - return 0; - } - } - } - return 0; -} - -//============================================================================ -// -// A_CStaffAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *mo; - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->Angles.Yaw - 3.0); - if (mo) - { - mo->WeaveIndexXY = 32; - } - mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->Angles.Yaw + 3.0); - if (mo) - { - mo->WeaveIndexXY = 0; - } - S_Sound (self, CHAN_WEAPON, "ClericCStaffFire", 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_CStaffMissileSlither -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) -{ - PARAM_SELF_PROLOGUE(AActor); - - A_Weave(self, 3, 0, 1., 0.); - return 0; -} - -//============================================================================ -// -// A_CStaffInitBlink -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CStaffInitBlink) -{ - PARAM_ACTION_PROLOGUE(AActor); - - self->weaponspecial = (pr_blink()>>1)+20; - return 0; -} - -//============================================================================ -// -// A_CStaffCheckBlink -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheckBlink) -{ - PARAM_ACTION_PROLOGUE(AActor); - - if (self->player && self->player->ReadyWeapon) - { - if (!--self->weaponspecial) - { - P_SetPsprite(self->player, PSP_WEAPON, self->player->ReadyWeapon->FindState ("Blink")); - self->weaponspecial = (pr_blink()+50)>>2; - } - else - { - DoReadyWeapon(self); - } - } - return 0; -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 3fb334cb15..101bcf1457 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,8 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_clericmace.cpp" -#include "a_clericstaff.cpp" #include "a_fighteraxe.cpp" #include "a_fighterhammer.cpp" #include "a_fighterplayer.cpp" diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 8c28c46b31..040e05ce07 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1734,6 +1734,15 @@ bool P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poi return true; } +DEFINE_ACTION_FUNCTION(_PlayerInfo, PoisonPlayer) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_OBJECT(poisoner, AActor); + PARAM_OBJECT(source, AActor); + PARAM_INT(poison); + ACTION_RETURN_BOOL(P_PoisonPlayer(self, poisoner, source, poison)); +} + //========================================================================== // // P_PoisonDamage - Similar to P_DamageMobj diff --git a/src/p_user.cpp b/src/p_user.cpp index f28bf9f42d..eadbda10e1 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1207,6 +1207,12 @@ int APlayerPawn::GetMaxHealth() const return MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth); } +DEFINE_ACTION_FUNCTION(APlayerPawn, GetMaxHealth) +{ + PARAM_SELF_PROLOGUE(APlayerPawn); + ACTION_RETURN_INT(self->GetMaxHealth()); +} + //=========================================================================== // // APlayerPawn :: UpdateWaterLevel diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 401a15c251..9d24d0cb10 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -406,10 +406,12 @@ void ParseScripts() int lump, lastlump = 0; FScriptPosition::ResetErrorCounter(); + while ((lump = Wads.FindLump("ZSCRIPT", &lastlump)) != -1) { DoParse(lump); } + } /* diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index ccf3fb3749..2b1ba6a5a7 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -592,7 +592,6 @@ class Actor : Thinker native 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(); diff --git a/wadsrc/static/zscript/hexen/clericmace.txt b/wadsrc/static/zscript/hexen/clericmace.txt index 5e00b9c3b7..b6f42c7e46 100644 --- a/wadsrc/static/zscript/hexen/clericmace.txt +++ b/wadsrc/static/zscript/hexen/clericmace.txt @@ -13,8 +13,6 @@ class CWeapMace : ClericWeapon Tag "$TAG_CWEAPMACE"; } - action native void A_CMaceAttack(); - States { Select: @@ -46,4 +44,44 @@ class CWeapMace : ClericWeapon CMCE A 1 Offset (8, 45); Goto Ready; } + + //=========================================================================== + // + // A_CMaceAttack + // + //=========================================================================== + + action void A_CMaceAttack() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + int damage = 25+(random[MaceAtk]()&15); + for (int i = 0; i < 16; i++) + { + for (int j = 1; j >= -1; j -= 2) + { + double ang = angle + j*i*(45. / 16); + double slope = AimLineAttack(ang, 2 * MELEERANGE, t); + if (t.linetarget) + { + LineAttack(ang, 2 * MELEERANGE, slope, damage, 'Melee', "HammerPuff", true, t); + if (t.linetarget != null) + { + AdjustPlayerAngle(t); + return; + } + } + } + } + // didn't find any creatures, so try to strike any walls + weaponspecial = 0; + + double slope = AimLineAttack (angle, MELEERANGE); + LineAttack (angle, MELEERANGE, slope, damage, 'Melee', "HammerPuff"); + } } diff --git a/wadsrc/static/zscript/hexen/clericstaff.txt b/wadsrc/static/zscript/hexen/clericstaff.txt index 7ae0e9da37..0d7ca0a99c 100644 --- a/wadsrc/static/zscript/hexen/clericstaff.txt +++ b/wadsrc/static/zscript/hexen/clericstaff.txt @@ -16,11 +16,6 @@ class CWeapStaff : ClericWeapon 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: @@ -55,11 +50,132 @@ class CWeapStaff : ClericWeapon CSSF K 10 Offset (0, 36); Goto Ready + 2; } + + //============================================================================ + // + // A_CStaffCheck + // + //============================================================================ + + action void A_CStaffCheck() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + Weapon weapon = player.ReadyWeapon; + + int damage = 20 + (random[StaffCheck]() & 15); + int max = player.mo.GetMaxHealth(); + for (int i = 0; i < 3; i++) + { + for (int j = 1; j >= -1; j -= 2) + { + double ang = angle + j*i*(45. / 16); + double slope = AimLineAttack(ang, 1.5 * MELEERANGE, t, 0., ALF_CHECK3D); + if (t.linetarget) + { + LineAttack(ang, 1.5 * MELEERANGE, slope, damage, 'Melee', "CStaffPuff", false, t); + if (t.linetarget != null) + { + angle = t.angleFromSource; + if (((t.linetarget.player && (!t.linetarget.IsTeammate(self) || level.teamdamage != 0)) || t.linetarget.bIsMonster) + && (!t.linetarget.bDormant && !bInvulnerable)) + { + int newLife = player.health + (damage >> 3); + newLife = newLife > max ? max : newLife; + if (newLife > player.health) + { + health = player.health = newLife; + } + if (weapon != null) + { + State newstate = weapon.FindState("Drain"); + if (newstate != null) player.SetPsprite(PSP_WEAPON, newstate); + } + } + if (weapon != null) + { + weapon.DepleteAmmo(weapon.bAltFire, false); + } + } + return; + } + } + } + } + + //============================================================================ + // + // A_CStaffAttack + // + //============================================================================ + + action void A_CStaffAttack() + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + Actor mo = SpawnPlayerMissile ("CStaffMissile", angle - 3.0); + if (mo) + { + mo.WeaveIndexXY = 32; + } + mo = SpawnPlayerMissile ("CStaffMissile", angle + 3.0); + if (mo) + { + mo.WeaveIndexXY = 0; + } + A_PlaySound ("ClericCStaffFire", CHAN_WEAPON); + } + + //============================================================================ + // + // A_CStaffInitBlink + // + //============================================================================ + + action void A_CStaffInitBlink() + { + weaponspecial = (random[CStaffBlink]() >> 1) + 20; + } + + //============================================================================ + // + // A_CStaffCheckBlink + // + //============================================================================ + + action void A_CStaffCheckBlink() + { + if (player && player.ReadyWeapon) + { + if (!--weaponspecial) + { + player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.FindState ("Blink")); + weaponspecial = (random[CStaffBlink]() + 50) >> 2; + } + else + { + A_WeaponReady(); + } + } + } } // Serpent Staff Missile ---------------------------------------------------- -class CStaffMissile : Actor native +class CStaffMissile : Actor { Default { @@ -82,6 +198,34 @@ class CStaffMissile : Actor native CSSF HI 3 Bright; Stop; } + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + // Cleric Serpent Staff does poison damage + if (target.player) + { + target.player.PoisonPlayer (self, self.target, 20); + damage >>= 1; + } + return damage; + } + +} + +extend class Actor +{ + + //============================================================================ + // + // A_CStaffMissileSlither + // + //============================================================================ + + void A_CStaffMissileSlither() + { + A_Weave(3, 0, 1., 0.); + } + } // Serpent Staff Puff ------------------------------------------------------- diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index e76e637fe5..48d62688b6 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -78,7 +78,8 @@ class PlayerPawn : Actor native virtual void MorphPlayerThink() { } - + + native int GetMaxHealth(); } class PlayerChunk : PlayerPawn native @@ -214,6 +215,7 @@ FWeaponSlots weapons; native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false); + native bool PoisonPlayer(Actor poisoner, Actor source, int poison); native void SetPsprite(int id, State stat, bool pending = false); native void SetSafeFlash(Weapon weap, State flashstate, int index); native PSprite GetPSprite(int id); From e541c27622de448cad9a3610b65a5b31405e62c9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 19:48:30 +0100 Subject: [PATCH 370/471] - scriptified the weapon's state getter methods - as preparation for the fighter axe. --- src/g_hexen/a_fighteraxe.cpp | 32 ----------- src/g_shared/a_pickups.h | 12 ++--- src/g_shared/a_weapons.cpp | 63 +++++++++++++++++----- wadsrc/static/zscript/hexen/fighteraxe.txt | 24 ++++++++- wadsrc/static/zscript/shared/inventory.txt | 25 +++++++++ 5 files changed, 104 insertions(+), 52 deletions(-) diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index fde3a9c18a..7036def950 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -21,38 +21,6 @@ static FRandom pr_axeatk ("FAxeAtk"); // The Fighter's Axe -------------------------------------------------------- -class AFWeapAxe : public AFighterWeapon -{ - DECLARE_CLASS (AFWeapAxe, AFighterWeapon) -public: - FState *GetUpState (); - FState *GetDownState (); - FState *GetReadyState (); - FState *GetAtkState (bool hold); -}; - -IMPLEMENT_CLASS(AFWeapAxe, false, false) - -FState *AFWeapAxe::GetUpState () -{ - return Ammo1->Amount ? FindState ("SelectGlow") : Super::GetUpState(); -} - -FState *AFWeapAxe::GetDownState () -{ - return Ammo1->Amount ? FindState ("DeselectGlow") : Super::GetDownState(); -} - -FState *AFWeapAxe::GetReadyState () -{ - return Ammo1->Amount ? FindState ("ReadyGlow") : Super::GetReadyState(); -} - -FState *AFWeapAxe::GetAtkState (bool hold) -{ - return Ammo1->Amount ? FindState ("FireGlow") : Super::GetAtkState(hold); -} - //============================================================================ // // A_FAxeCheckReady diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index bd252437d6..bc83199316 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -335,12 +335,12 @@ public: virtual bool Use (bool pickup); virtual void Destroy() override; - virtual FState *GetUpState (); - virtual FState *GetDownState (); - virtual FState *GetReadyState (); - virtual FState *GetAtkState (bool hold); - virtual FState *GetAltAtkState (bool hold); - virtual FState *GetStateForButtonName (FName button); + FState *GetUpState (); + FState *GetDownState (); + FState *GetReadyState (); + FState *GetAtkState (bool hold); + FState *GetAltAtkState (bool hold); + FState *GetStateForButtonName (FName button); virtual void PostMorphWeapon (); virtual void EndPowerup (); diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 02cd19fa6d..e9d931520e 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -818,7 +818,16 @@ void AWeapon::CallEndPowerup() FState *AWeapon::GetUpState () { - return FindState(NAME_Select); + IFVIRTUAL(AWeapon, GetUpState) + { + VMValue params[1] = { (DObject*)this }; + VMReturn ret; + VMFrameStack stack; + FState *retval; + ret.PointerAt((void**)&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + return retval; + } } //=========================================================================== @@ -829,7 +838,16 @@ FState *AWeapon::GetUpState () FState *AWeapon::GetDownState () { - return FindState(NAME_Deselect); + IFVIRTUAL(AWeapon, GetDownState) + { + VMValue params[1] = { (DObject*)this }; + VMReturn ret; + VMFrameStack stack; + FState *retval; + ret.PointerAt((void**)&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + return retval; + } } //=========================================================================== @@ -840,7 +858,16 @@ FState *AWeapon::GetDownState () FState *AWeapon::GetReadyState () { - return FindState(NAME_Ready); + IFVIRTUAL(AWeapon, GetReadyState) + { + VMValue params[1] = { (DObject*)this }; + VMReturn ret; + VMFrameStack stack; + FState *retval; + ret.PointerAt((void**)&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + return retval; + } } //=========================================================================== @@ -851,11 +878,16 @@ FState *AWeapon::GetReadyState () FState *AWeapon::GetAtkState (bool hold) { - FState * state=NULL; - - if (hold) state = FindState(NAME_Hold); - if (state == NULL) state = FindState(NAME_Fire); - return state; + IFVIRTUAL(AWeapon, GetAtkState) + { + VMValue params[2] = { (DObject*)this, hold }; + VMReturn ret; + VMFrameStack stack; + FState *retval; + ret.PointerAt((void**)&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + return retval; + } } //=========================================================================== @@ -866,11 +898,16 @@ FState *AWeapon::GetAtkState (bool hold) FState *AWeapon::GetAltAtkState (bool hold) { - FState * state=NULL; - - if (hold) state = FindState(NAME_AltHold); - if (state == NULL) state = FindState(NAME_AltFire); - return state; + IFVIRTUAL(AWeapon, GetAltAtkState) + { + VMValue params[2] = { (DObject*)this, hold }; + VMReturn ret; + VMFrameStack stack; + FState *retval; + ret.PointerAt((void**)&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + return retval; + } } //=========================================================================== diff --git a/wadsrc/static/zscript/hexen/fighteraxe.txt b/wadsrc/static/zscript/hexen/fighteraxe.txt index 30b235192d..35049ab9a0 100644 --- a/wadsrc/static/zscript/hexen/fighteraxe.txt +++ b/wadsrc/static/zscript/hexen/fighteraxe.txt @@ -1,7 +1,7 @@ // The Fighter's Axe -------------------------------------------------------- -class FWeapAxe : FighterWeapon native +class FWeapAxe : FighterWeapon { Default { @@ -79,6 +79,28 @@ class FWeapAxe : FighterWeapon native FAXE A 1; Goto ReadyGlow; } + + override State GetUpState () + { + return Ammo1.Amount ? FindState ("SelectGlow") : Super.GetUpState(); + } + + override State GetDownState () + { + return Ammo1.Amount ? FindState ("DeselectGlow") : Super.GetDownState(); + } + + override State GetReadyState () + { + return Ammo1.Amount ? FindState ("ReadyGlow") : Super.GetReadyState(); + } + + override State GetAtkState (bool hold) + { + return Ammo1.Amount ? FindState ("FireGlow") : Super.GetAtkState(hold); + } + + } // Axe Puff ----------------------------------------------------------------- diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index f87331470c..f6c95f8bd6 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -580,6 +580,31 @@ class Weapon : StateProvider native return FindState('Ready'); } + virtual State GetUpState () + { + return FindState('Select'); + } + + virtual State GetDownState () + { + return FindState('Deselect'); + } + + virtual State GetAtkState (bool hold) + { + State s = null; + if (hold) s = FindState('Hold'); + if (s == null) s = FindState('Fire'); + return s; + } + + virtual State GetAltAtkState (bool hold) + { + State s = null; + if (hold) s = FindState('AltHold'); + if (s == null) s = FindState('AltFire'); + return s; + } native action void A_ZoomFactor(double scale = 1, int flags = 0); native action void A_SetCrosshair(int xhair); From bdad526f62a51d8808b00c1f77d583d6e68f2db1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 21:03:00 +0100 Subject: [PATCH 371/471] - scriptified the Fighter's axe. --- src/CMakeLists.txt | 1 - src/g_hexen/a_fighteraxe.cpp | 245 --------------------- src/g_hexen/a_hexenmisc.cpp | 1 - wadsrc/static/zscript/hexen/fighteraxe.txt | 189 +++++++++++++++- 4 files changed, 182 insertions(+), 254 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 42dc50f982..58a6994778 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_fighteraxe.cpp g_hexen/a_fighterhammer.cpp g_hexen/a_fighterplayer.cpp g_hexen/a_fighterquietus.cpp diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index 7036def950..e69de29bb2 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -1,245 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "a_action.h" -#include "p_pspr.h" -#include "gstrings.h" -#include "a_hexenglobal.h" -#include "vm.h" -*/ - -DECLARE_ACTION(A_Raise) - -#define AXERANGE (2.25 * MELEERANGE) - -static FRandom pr_axeatk ("FAxeAtk"); - -// The Fighter's Axe -------------------------------------------------------- - -//============================================================================ -// -// A_FAxeCheckReady -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReady) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - if (player->ReadyWeapon->Ammo1->Amount) - { - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState ("ReadyGlow")); - } - else - { - DoReadyWeapon(self); - } - return 0; -} - -//============================================================================ -// -// A_FAxeCheckReadyG -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - if (player->ReadyWeapon->Ammo1->Amount <= 0) - { - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState ("Ready")); - } - else - { - DoReadyWeapon(self); - } - return 0; -} - -//============================================================================ -// -// A_FAxeCheckUp -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUp) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - if (player->ReadyWeapon->Ammo1->Amount) - { - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState ("SelectGlow")); - } - else - { - CALL_ACTION(A_Raise, self); - } - return 0; -} - -//============================================================================ -// -// A_FAxeCheckUpG -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - if (player->ReadyWeapon->Ammo1->Amount <= 0) - { - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState ("Select")); - } - else - { - CALL_ACTION(A_Raise, self); - } - return 0; -} - -//============================================================================ -// -// A_FAxeCheckAtk -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - if (player->ReadyWeapon->Ammo1->Amount) - { - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState ("FireGlow")); - } - return 0; -} - -//============================================================================ -// -// A_FAxeAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int power; - int damage; - DAngle slope; - int i; - int useMana; - player_t *player; - AWeapon *weapon; - PClassActor *pufftype; - FTranslatedLineTarget t; - - if (nullptr == (player = self->player)) - { - return 0; - } - AActor *pmo=player->mo; - - damage = 40+(pr_axeatk()&15); - damage += pr_axeatk()&7; - power = 0; - weapon = player->ReadyWeapon; - if (player->ReadyWeapon->Ammo1->Amount > 0) - { - damage <<= 1; - power = 6; - pufftype = PClass::FindActor ("AxePuffGlow"); - useMana = 1; - } - else - { - pufftype = PClass::FindActor ("AxePuff"); - useMana = 0; - } - for (i = 0; i < 16; i++) - { - for (int j = 1; j >= -1; j -= 2) - { - angle = pmo->Angles.Yaw + j*i*(45. / 16); - slope = P_AimLineAttack(pmo, angle, AXERANGE, &t); - if (t.linetarget) - { - P_LineAttack(pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true, &t); - if (t.linetarget != nullptr) - { - if (t.linetarget->flags3&MF3_ISMONSTER || t.linetarget->player) - { - t.linetarget->Thrust(t.angleFromSource, power); - } - AdjustPlayerAngle(pmo, &t); - useMana++; - goto axedone; - } - } - } - } - // didn't find any creatures, so try to strike any walls - pmo->weaponspecial = 0; - - angle = pmo->Angles.Yaw; - slope = P_AimLineAttack (pmo, angle, MELEERANGE); - P_LineAttack (pmo, angle, MELEERANGE, slope, damage, NAME_Melee, pufftype, true); - -axedone: - if (useMana == 2) - { - AWeapon *weapon = player->ReadyWeapon; - if (weapon != nullptr) - { - weapon->DepleteAmmo (weapon->bAltFire, false); - - if ((weapon->Ammo1 == nullptr || weapon->Ammo1->Amount == 0) && - (!(weapon->WeaponFlags & WIF_PRIMARY_USES_BOTH) || - weapon->Ammo2 == nullptr || weapon->Ammo2->Amount == 0)) - { - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState ("Fire") + 5); - } - } - } - return 0; -} - diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 101bcf1457..f2b8d8866a 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,7 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_fighteraxe.cpp" #include "a_fighterhammer.cpp" #include "a_fighterplayer.cpp" #include "a_fighterquietus.cpp" diff --git a/wadsrc/static/zscript/hexen/fighteraxe.txt b/wadsrc/static/zscript/hexen/fighteraxe.txt index 35049ab9a0..a0d1deba1a 100644 --- a/wadsrc/static/zscript/hexen/fighteraxe.txt +++ b/wadsrc/static/zscript/hexen/fighteraxe.txt @@ -3,6 +3,8 @@ class FWeapAxe : FighterWeapon { + const AXERANGE = (2.25 * MELEERANGE); + Default { Weapon.SelectionOrder 1500; @@ -17,13 +19,6 @@ class FWeapAxe : FighterWeapon 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: @@ -45,6 +40,7 @@ class FWeapAxe : FighterWeapon FAXE D 1 Offset (-5, 70) A_FAxeAttack; FAXE D 2 Offset (-25, 90); FAXE E 1 Offset (15, 32); + EndAttack: FAXE E 2 Offset (10, 54); FAXE E 7 Offset (10, 150); FAXE A 1 Offset (0, 60) A_ReFire; @@ -101,6 +97,185 @@ class FWeapAxe : FighterWeapon } + + //============================================================================ + // + // A_FAxeCheckReady + // + //============================================================================ + + action void A_FAxeCheckReady() + { + if (player == null) + { + return; + } + Weapon w = player.ReadyWeapon; + if (w.Ammo1 && w.Ammo1.Amount > 0) + { + player.SetPsprite(PSP_WEAPON, w.FindState("ReadyGlow")); + } + else + { + A_WeaponReady(); + } + } + + //============================================================================ + // + // A_FAxeCheckReadyG + // + //============================================================================ + + action void A_FAxeCheckReadyG() + { + if (player == null) + { + return; + } + Weapon w = player.ReadyWeapon; + if (!w.Ammo1 || w.Ammo1.Amount <= 0) + { + player.SetPsprite(PSP_WEAPON, w.FindState("Ready")); + } + else + { + A_WeaponReady(); + } + } + + //============================================================================ + // + // A_FAxeCheckUp + // + //============================================================================ + + action void A_FAxeCheckUp() + { + if (player == null) + { + return; + } + Weapon w = player.ReadyWeapon; + if (w.Ammo1 && w.Ammo1.Amount > 0) + { + player.SetPsprite(PSP_WEAPON, w.FindState("SelectGlow")); + } + else + { + A_Raise(); + } + } + + //============================================================================ + // + // A_FAxeCheckUpG + // + //============================================================================ + + action void A_FAxeCheckUpG() + { + if (player == null) + { + return; + } + Weapon w = player.ReadyWeapon; + if (!w.Ammo1 || w.Ammo1.Amount <= 0) + { + player.SetPsprite(PSP_WEAPON, w.FindState("Select")); + } + else + { + A_Raise(); + } + } + + //============================================================================ + // + // A_FAxeCheckAtk + // + //============================================================================ + + action void A_FAxeCheckAtk() + { + if (player == null) + { + return; + } + Weapon w = player.ReadyWeapon; + if (w.Ammo1 && w.Ammo1.Amount > 0) + { + player.SetPsprite(PSP_WEAPON, w.FindState("FireGlow")); + } + } + + //============================================================================ + // + // A_FAxeAttack + // + //============================================================================ + + action void A_FAxeAttack() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + int damage = 40+(random[AxeAtk]() & 15); + damage += random[AxeAtk]() & 7; + int power = 0; + Weapon weapon = player.ReadyWeapon; + class pufftype; + int usemana; + if ((usemana = (weapon.Ammo1 && weapon.Ammo1.Amount > 0))) + { + damage <<= 1; + power = 6; + pufftype = "AxePuffGlow"; + } + else + { + pufftype = "AxePuff"; + } + for (int i = 0; i < 16; i++) + { + for (int j = 1; j >= -1; j -= 2) + { + double ang = angle + j*i*(45. / 16); + double slope = AimLineAttack(ang, AXERANGE, t); + if (t.linetarget) + { + LineAttack(ang, AXERANGE, slope, damage, 'Melee', pufftype, true, t); + if (t.linetarget != null) + { + if (t.linetarget.bIsMonster || t.linetarget.player) + { + t.linetarget.Thrust(power, t.angleFromSource); + } + AdjustPlayerAngle(t); + + weapon.DepleteAmmo (weapon.bAltFire, false); + + if ((weapon.Ammo1 == null || weapon.Ammo1.Amount == 0) && + (!(weapon.bPrimary_Uses_Both) || + weapon.Ammo2 == null || weapon.Ammo2.Amount == 0)) + { + player.SetPsprite(PSP_WEAPON, weapon.FindState("EndAttack")); + } + return; + } + } + } + } + // didn't find any creatures, so try to strike any walls + self.weaponspecial = 0; + + double slope = AimLineAttack (angle, MELEERANGE); + LineAttack (angle, MELEERANGE, slope, damage, 'Melee', pufftype, true); + } } // Axe Puff ----------------------------------------------------------------- From 178db4bb098ea3a45d1f492a945cc6ca451d218c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 21:39:20 +0100 Subject: [PATCH 372/471] - scriptified the fighter's hammer. --- src/CMakeLists.txt | 1 - src/g_hexen/a_fighteraxe.cpp | 0 src/g_hexen/a_fighterhammer.cpp | 124 ------------------ src/g_hexen/a_hexenmisc.cpp | 1 - src/g_shared/a_weapons.cpp | 10 ++ wadsrc/static/zscript/hexen/fighterhammer.txt | 88 ++++++++++++- wadsrc/static/zscript/shared/inventory.txt | 8 ++ 7 files changed, 102 insertions(+), 130 deletions(-) delete mode 100644 src/g_hexen/a_fighteraxe.cpp delete mode 100644 src/g_hexen/a_fighterhammer.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 58a6994778..c3e2419004 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_fighterhammer.cpp g_hexen/a_fighterplayer.cpp g_hexen/a_fighterquietus.cpp g_hexen/a_flechette.cpp diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/g_hexen/a_fighterhammer.cpp b/src/g_hexen/a_fighterhammer.cpp deleted file mode 100644 index 84eca78b79..0000000000 --- a/src/g_hexen/a_fighterhammer.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "a_action.h" -#include "p_pspr.h" -#include "gstrings.h" -#include "a_hexenglobal.h" -#include "vm.h" -*/ - -const double HAMMER_RANGE = 1.5 * MELEERANGE; - -static FRandom pr_hammeratk ("FHammerAtk"); - -//============================================================================ -// -// A_FHammerAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - DAngle slope; - int i; - player_t *player; - FTranslatedLineTarget t; - PClassActor *hammertime; - - if (NULL == (player = self->player)) - { - return 0; - } - AActor *pmo=player->mo; - - damage = 60+(pr_hammeratk()&63); - hammertime = PClass::FindActor("HammerPuff"); - for (i = 0; i < 16; i++) - { - for (int j = 1; j >= -1; j -= 2) - { - angle = pmo->Angles.Yaw + j*i*(45. / 32); - slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE, &t, 0., ALF_CHECK3D); - if (t.linetarget != NULL) - { - P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &t); - if (t.linetarget != NULL) - { - AdjustPlayerAngle(pmo, &t); - if (t.linetarget->flags3 & MF3_ISMONSTER || t.linetarget->player) - { - t.linetarget->Thrust(t.angleFromSource, 10); - } - pmo->weaponspecial = false; // Don't throw a hammer - goto hammerdone; - } - } - } - } - // didn't find any targets in meleerange, so set to throw out a hammer - angle = pmo->Angles.Yaw; - slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, NULL, 0., ALF_CHECK3D); - if (P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true) != NULL) - { - pmo->weaponspecial = false; - } - else - { - pmo->weaponspecial = true; - } -hammerdone: - // Don't spawn a hammer if the player doesn't have enough mana - if (player->ReadyWeapon == NULL || - !player->ReadyWeapon->CheckAmmo (player->ReadyWeapon->bAltFire ? - AWeapon::AltFire : AWeapon::PrimaryFire, false, true)) - { - pmo->weaponspecial = false; - } - return 0; -} - -//============================================================================ -// -// A_FHammerThrow -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FHammerThrow) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *mo; - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - - if (!player->mo->weaponspecial) - { - return 0; - } - AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire, false)) - return 0; - } - mo = P_SpawnPlayerMissile (player->mo, PClass::FindActor("HammerMissile")); - if (mo) - { - mo->special1 = 0; - } - return 0; -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index f2b8d8866a..f098006c7a 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,7 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_fighterhammer.cpp" #include "a_fighterplayer.cpp" #include "a_fighterquietus.cpp" #include "a_flechette.cpp" diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index e9d931520e..2d2c3eb015 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -664,6 +664,16 @@ bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo, int am return false; } +DEFINE_ACTION_FUNCTION(AWeapon, CheckAmmo) +{ + PARAM_SELF_PROLOGUE(AWeapon); + PARAM_INT(mode); + PARAM_BOOL(autoswitch); + PARAM_BOOL_DEF(require); + PARAM_INT_DEF(ammocnt); + ACTION_RETURN_BOOL(self->CheckAmmo(mode, autoswitch, require, ammocnt)); +} + //=========================================================================== // // AWeapon :: DepleteAmmo diff --git a/wadsrc/static/zscript/hexen/fighterhammer.txt b/wadsrc/static/zscript/hexen/fighterhammer.txt index f415cbb722..655e59379c 100644 --- a/wadsrc/static/zscript/hexen/fighterhammer.txt +++ b/wadsrc/static/zscript/hexen/fighterhammer.txt @@ -3,6 +3,8 @@ class FWeapHammer : FighterWeapon { + const HAMMER_RANGE = 1.5 * MELEERANGE; + Default { +BLOODSPLATTER @@ -18,9 +20,6 @@ class FWeapHammer : FighterWeapon Tag "$TAG_FWEAPHAMMER"; } - action native void A_FHammerAttack(); - action native void A_FHammerThrow(); - States { Spawn: @@ -50,6 +49,87 @@ class FWeapHammer : FighterWeapon FHMR A 1; Goto Ready; } + + //============================================================================ + // + // A_FHammerAttack + // + //============================================================================ + + action void A_FHammerAttack() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + int damage = 60+(random[HammerAtk]() & 63); + for (int i = 0; i < 16; i++) + { + for (int j = 1; j >= -1; j -= 2) + { + double ang = angle + j*i*(45. / 32); + double slope = AimLineAttack(ang, HAMMER_RANGE, t, 0., ALF_CHECK3D); + if (t.linetarget != null) + { + LineAttack(ang, HAMMER_RANGE, slope, damage, 'Melee', "HammerPuff", true, t); + if (t.linetarget != null) + { + AdjustPlayerAngle(t); + if (t.linetarget.bIsMonster || t.linetarget.player) + { + t.linetarget.Thrust(10, t.angleFromSource); + } + weaponspecial = false; // Don't throw a hammer + return; + } + } + } + } + // didn't find any targets in meleerange, so set to throw out a hammer + double slope = AimLineAttack (angle, HAMMER_RANGE, null, 0., ALF_CHECK3D); + weaponspecial = (LineAttack (angle, HAMMER_RANGE, slope, damage, 'Melee', "HammerPuff", true) == null); + + // Don't spawn a hammer if the player doesn't have enough mana + if (player.ReadyWeapon == null || + !player.ReadyWeapon.CheckAmmo (player.ReadyWeapon.bAltFire ? + Weapon.AltFire : Weapon.PrimaryFire, false, true)) + { + weaponspecial = false; + } + } + + //============================================================================ + // + // A_FHammerThrow + // + //============================================================================ + + action void A_FHammerThrow() + { + if (player == null) + { + return; + } + + if (!weaponspecial) + { + return; + } + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire, false)) + return; + } + Actor mo = SpawnPlayerMissile ("HammerMissile"); + if (mo) + { + mo.special1 = 0; + } + } } // Hammer Missile ----------------------------------------------------------- @@ -76,7 +156,7 @@ class HammerMissile : Actor FHFX CDEFGH 2 Bright; Loop; Death: - FHFX I 3 Bright A_SetTranslucent(1,1); + FHFX I 3 Bright A_SetRenderStyle(1, STYLE_Add); FHFX J 3 Bright; FHFX K 3 Bright A_Explode (128, 128, 0); FHFX LM 3 Bright; diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index f6c95f8bd6..54a2b0ba9c 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -529,6 +529,13 @@ class PuzzleItem : Inventory native class Weapon : StateProvider native { + enum EFireMode + { + PrimaryFire, + AltFire, + EitherFire + }; + native uint WeaponFlags; native class AmmoType1, AmmoType2; // Types of ammo used by this weapon native int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon @@ -572,6 +579,7 @@ class Weapon : StateProvider native Stop; } + native bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1); native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); native virtual void EndPowerup(); From 80f233cd0b77d0ca264329d524298e32175ef99b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 22:25:49 +0100 Subject: [PATCH 373/471] - scriptified the fighter's fist. --- src/CMakeLists.txt | 1 - src/g_hexen/a_fighterplayer.cpp | 142 -------------------- src/g_hexen/a_hexenglobal.h | 20 --- src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_magestaff.cpp | 8 ++ src/g_shared/a_weapons.cpp | 5 + wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/hexen/baseweapons.txt | 39 +++++- wadsrc/static/zscript/hexen/fighterfist.txt | 81 ++++++++++- 9 files changed, 129 insertions(+), 169 deletions(-) delete mode 100644 src/g_hexen/a_fighterplayer.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c3e2419004..a57ae9c3a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_fighterplayer.cpp g_hexen/a_fighterquietus.cpp g_hexen/a_flechette.cpp g_hexen/a_flies.cpp diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp deleted file mode 100644 index 4f1d1fd3b6..0000000000 --- a/src/g_hexen/a_fighterplayer.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "a_action.h" -#include "a_hexenglobal.h" -#include "vm.h" -*/ - -IMPLEMENT_CLASS(AFighterWeapon, false, false) -IMPLEMENT_CLASS(AClericWeapon, false, false) -IMPLEMENT_CLASS(AMageWeapon, false, false) - -static FRandom pr_fpatk ("FPunchAttack"); - -//============================================================================ -// -// AdjustPlayerAngle -// -//============================================================================ - -#define MAX_ANGLE_ADJUST (5.) - -void AdjustPlayerAngle (AActor *pmo, FTranslatedLineTarget *t) -{ - // normally this will adjust relative to the actual direction to the target, - // but with arbitrary portals that cannot be calculated so using the actual - // attack angle is the only option. - DAngle atkangle = t->unlinked ? t->angleFromSource : pmo->AngleTo(t->linetarget); - DAngle difference = deltaangle(pmo->Angles.Yaw, atkangle); - if (fabs(difference) > MAX_ANGLE_ADJUST) - { - if (difference > 0) - { - pmo->Angles.Yaw += MAX_ANGLE_ADJUST; - } - else - { - pmo->Angles.Yaw -= MAX_ANGLE_ADJUST; - } - } - else - { - pmo->Angles.Yaw = t->angleFromSource; - } -} - -DEFINE_ACTION_FUNCTION(AActor, AdjustPlayerAngle) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_POINTER(t, FTranslatedLineTarget); - AdjustPlayerAngle(self, t); - return 0; -} -//============================================================================ -// -// TryPunch -// -// Returns true if an actor was punched, false if not. -// -//============================================================================ - -static bool TryPunch(APlayerPawn *pmo, DAngle angle, int damage, int power) -{ - PClassActor *pufftype; - FTranslatedLineTarget t; - DAngle slope; - - slope = P_AimLineAttack (pmo, angle, 2*MELEERANGE, &t); - if (t.linetarget != NULL) - { - if (++pmo->weaponspecial >= 3) - { - damage <<= 1; - power *= 3; - pufftype = PClass::FindActor("HammerPuff"); - } - else - { - pufftype = PClass::FindActor("PunchPuff"); - } - P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true, &t); - if (t.linetarget != NULL) - { - if (t.linetarget->player != NULL || - (t.linetarget->Mass != INT_MAX && (t.linetarget->flags3 & MF3_ISMONSTER))) - { - t.linetarget->Thrust(t.angleFromSource, power); - } - AdjustPlayerAngle (pmo, &t); - return true; - } - } - return false; -} - -//============================================================================ -// -// A_FPunchAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - int damage; - int i; - player_t *player; - - if (nullptr == (player = self->player)) - { - return 0; - } - APlayerPawn *pmo = player->mo; - - damage = 40+(pr_fpatk()&15); - for (i = 0; i < 16; i++) - { - if (TryPunch(pmo, pmo->Angles.Yaw + i*(45./16), damage, 2) || - TryPunch(pmo, pmo->Angles.Yaw - i*(45./16), damage, 2)) - { // hit something - if (pmo->weaponspecial >= 3) - { - pmo->weaponspecial = 0; - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState("Fire2")); - S_Sound (pmo, CHAN_VOICE, "*fistgrunt", 1, ATTN_NORM); - } - return 0; - } - } - // didn't find any creatures, so try to strike any walls - pmo->weaponspecial = 0; - - DAngle slope = P_AimLineAttack (pmo, pmo->Angles.Yaw, MELEERANGE); - P_LineAttack (pmo, pmo->Angles.Yaw, MELEERANGE, slope, damage, NAME_Melee, PClass::FindActor("PunchPuff"), true); - return 0; -} diff --git a/src/g_hexen/a_hexenglobal.h b/src/g_hexen/a_hexenglobal.h index dc174b32ab..277d1bff11 100644 --- a/src/g_hexen/a_hexenglobal.h +++ b/src/g_hexen/a_hexenglobal.h @@ -3,26 +3,6 @@ #include "d_player.h" -void AdjustPlayerAngle(AActor *pmo, FTranslatedLineTarget *t); - -class AFighterWeapon : public AWeapon -{ - DECLARE_CLASS (AFighterWeapon, AWeapon); -public: -}; - -class AClericWeapon : public AWeapon -{ - DECLARE_CLASS (AClericWeapon, AWeapon); -public: -}; - -class AMageWeapon : public AWeapon -{ - DECLARE_CLASS (AMageWeapon, AWeapon); -public: -}; - class AArtiPoisonBag : public AInventory { DECLARE_CLASS (AArtiPoisonBag, AInventory) diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index f098006c7a..49c1369b31 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,7 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_fighterplayer.cpp" #include "a_fighterquietus.cpp" #include "a_flechette.cpp" #include "a_flies.cpp" diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index 78d9edec04..27e9f57321 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -11,6 +11,14 @@ #include "doomstat.h" */ +class AMageWeapon : public AWeapon +{ + DECLARE_CLASS (AMageWeapon, AWeapon); +public: +}; + +IMPLEMENT_CLASS(AMageWeapon, false, false) + static FRandom pr_mstafftrack ("MStaffTrack"); static FRandom pr_bloodscourgedrop ("BloodScourgeDrop"); diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 2d2c3eb015..b19896e91a 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -838,6 +838,7 @@ FState *AWeapon::GetUpState () stack.Call(func, params, 1, &ret, 1, nullptr); return retval; } + return nullptr; } //=========================================================================== @@ -858,6 +859,7 @@ FState *AWeapon::GetDownState () stack.Call(func, params, 1, &ret, 1, nullptr); return retval; } + return nullptr; } //=========================================================================== @@ -878,6 +880,7 @@ FState *AWeapon::GetReadyState () stack.Call(func, params, 1, &ret, 1, nullptr); return retval; } + return nullptr; } //=========================================================================== @@ -898,6 +901,7 @@ FState *AWeapon::GetAtkState (bool hold) stack.Call(func, params, 2, &ret, 1, nullptr); return retval; } + return nullptr; } //=========================================================================== @@ -918,6 +922,7 @@ FState *AWeapon::GetAltAtkState (bool hold) stack.Call(func, params, 2, &ret, 1, nullptr); return retval; } + return nullptr; } //=========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2b1ba6a5a7..34d74760cb 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -268,7 +268,6 @@ class Actor : Thinker native virtual native bool SpecialBlastHandling (Actor source, double strength); - native void AdjustPlayerAngle(FTranslatedLineTarget t); native static readonly GetDefaultByType(class cls); native static double GetDefaultSpeed(class type); native void RemoveFromHash(); diff --git a/wadsrc/static/zscript/hexen/baseweapons.txt b/wadsrc/static/zscript/hexen/baseweapons.txt index eb685a873c..4c84ed7804 100644 --- a/wadsrc/static/zscript/hexen/baseweapons.txt +++ b/wadsrc/static/zscript/hexen/baseweapons.txt @@ -1,7 +1,7 @@ // 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 +class FighterWeapon : Weapon { Default { @@ -10,7 +10,7 @@ class FighterWeapon : Weapon native } } -class ClericWeapon : Weapon native +class ClericWeapon : Weapon { Default { @@ -27,3 +27,38 @@ class MageWeapon : Weapon native Inventory.ForbiddenTo "FighterPlayer", "ClericPlayer"; } } + +extend class Actor +{ + //============================================================================ + // + // AdjustPlayerAngle + // + //============================================================================ + + const MAX_ANGLE_ADJUST = (5.); + + void AdjustPlayerAngle(FTranslatedLineTarget t) + { + // normally this will adjust relative to the actual direction to the target, + // but with arbitrary portals that cannot be calculated so using the actual + // attack angle is the only option. + double atkangle = t.unlinked ? t.angleFromSource : AngleTo(t.linetarget); + double difference = deltaangle(Angle, atkangle); + if (abs(difference) > MAX_ANGLE_ADJUST) + { + if (difference > 0) + { + angle += MAX_ANGLE_ADJUST; + } + else + { + angle -= MAX_ANGLE_ADJUST; + } + } + else + { + angle = t.angleFromSource; + } + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/hexen/fighterfist.txt b/wadsrc/static/zscript/hexen/fighterfist.txt index 8428ebe7da..712055e6e7 100644 --- a/wadsrc/static/zscript/hexen/fighterfist.txt +++ b/wadsrc/static/zscript/hexen/fighterfist.txt @@ -13,8 +13,6 @@ class FWeapFist : FighterWeapon Tag "$TAG_FWEAPFIST"; } - action native void A_FPunchAttack(); - States { Select: @@ -44,6 +42,85 @@ class FWeapFist : FighterWeapon FPCH E 10 Offset (0, 150); Goto Ready; } + + //============================================================================ + // + // TryPunch + // + // Returns true if an actor was punched, false if not. + // + //============================================================================ + + private action bool TryPunch(double angle, int damage, int power) + { + Class pufftype; + FTranslatedLineTarget t; + + double slope = AimLineAttack (angle, 2*MELEERANGE, t); + if (t.linetarget != null) + { + if (++weaponspecial >= 3) + { + damage <<= 1; + power *= 3; + pufftype = "HammerPuff"; + } + else + { + pufftype = "PunchPuff"; + } + LineAttack (angle, 2*MELEERANGE, slope, damage, 'Melee', pufftype, true, t); + if (t.linetarget != null) + { + // The mass threshold has been changed to CommanderKeen's value which has been used most often for 'unmovable' stuff. + if (t.linetarget.player != null || + (t.linetarget.Mass < 10000000 && (t.linetarget.bIsMonster))) + { + if (!t.linetarget.bDontThrust) + t.linetarget.Thrust(power, t.angleFromSource); + } + AdjustPlayerAngle(t); + return true; + } + } + return false; + } + + //============================================================================ + // + // A_FPunchAttack + // + //============================================================================ + + action void A_FPunchAttack() + { + if (player == null) + { + return; + } + + int damage = 40 + (random[FighterAtk]() & 15); + for (int i = 0; i < 16; i++) + { + if (TryPunch(angle + i*(45./16), damage, 2) || + TryPunch(angle - i*(45./16), damage, 2)) + { // hit something + if (weaponspecial >= 3) + { + weaponspecial = 0; + player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.FindState("Fire2")); + A_PlaySound ("*fistgrunt", CHAN_VOICE); + } + return; + } + } + // didn't find any creatures, so try to strike any walls + weaponspecial = 0; + + double slope = AimLineAttack (angle, MELEERANGE); + LineAttack (angle, MELEERANGE, slope, damage, 'Melee', "PunchPuff", true); + } + } // Punch puff --------------------------------------------------------------- From 796c262285c3cbafe669346acfe2ef8a5506b609 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Nov 2016 23:05:16 +0100 Subject: [PATCH 374/471] - scriptified the Quietus. --- src/CMakeLists.txt | 1 - src/g_hexen/a_fighterquietus.cpp | 146 ------------------ src/g_hexen/a_hexenmisc.cpp | 1 - wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/hexen/baseweapons.txt | 20 +++ wadsrc/static/zscript/hexen/fighterboss.txt | 20 ++- .../static/zscript/hexen/fighterquietus.txt | 61 +++++++- 7 files changed, 94 insertions(+), 156 deletions(-) delete mode 100644 src/g_hexen/a_fighterquietus.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a57ae9c3a3..06028ecff9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_fighterquietus.cpp g_hexen/a_flechette.cpp g_hexen/a_flies.cpp g_hexen/a_healingradius.cpp diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp deleted file mode 100644 index 458d1415bf..0000000000 --- a/src/g_hexen/a_fighterquietus.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "p_pspr.h" -#include "gstrings.h" -#include "a_hexenglobal.h" -#include "a_weaponpiece.h" -#include "vm.h" -*/ - -static FRandom pr_quietusdrop ("QuietusDrop"); -static FRandom pr_fswordflame ("FSwordFlame"); - -//========================================================================== - -//============================================================================ -// -// A_DropQuietusPieces -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DropWeaponPieces) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS(p1, AActor); - PARAM_CLASS(p2, AActor); - PARAM_CLASS(p3, AActor); - - for (int i = 0, j = 0; i < 3; ++i) - { - PClassActor *cls = j == 0 ? p1 : j == 1 ? p2 : p3; - if (cls) - { - AActor *piece = Spawn (cls, self->Pos(), ALLOW_REPLACE); - if (piece != NULL) - { - piece->Vel = self->Vel + DAngle(i*120.).ToVector(1); - piece->flags |= MF_DROPPED; - j = (j == 0) ? (pr_quietusdrop() & 1) + 1 : 3-j; - } - } - } - return 0; -} - - - -// Fighter Sword Missile ---------------------------------------------------- - -class AFSwordMissile : public AActor -{ - DECLARE_CLASS (AFSwordMissile, AActor) -public: - int DoSpecialDamage(AActor *victim, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(AFSwordMissile, false, false) - -int AFSwordMissile::DoSpecialDamage(AActor *victim, int damage, FName damagetype) -{ - if (victim->player) - { - damage -= damage >> 2; - } - return damage; -} - -//============================================================================ -// -// A_FSwordAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FSwordAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player; - - if (NULL == (player = self->player)) - { - return 0; - } - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - P_SpawnPlayerMissile (self, 0, 0, -10, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw + (45./4)); - P_SpawnPlayerMissile (self, 0, 0, -5, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw + (45./8)); - P_SpawnPlayerMissile (self, 0, 0, 0, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw); - P_SpawnPlayerMissile (self, 0, 0, 5, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw - (45./8)); - P_SpawnPlayerMissile (self, 0, 0, 10, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw - (45./4)); - S_Sound (self, CHAN_WEAPON, "FighterSwordFire", 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_FSwordFlames -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FSwordFlames) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - - for (i = 1+(pr_fswordflame()&3); i; i--) - { - double xo = (pr_fswordflame() - 128) / 16.; - double yo = (pr_fswordflame() - 128) / 16.; - double zo = (pr_fswordflame() - 128) / 8.; - Spawn ("FSwordFlame", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - } - return 0; -} - -//============================================================================ -// -// A_FighterAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FighterAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->target) return 0; - - P_SpawnMissileAngle(self, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw + (45. / 4), 0); - P_SpawnMissileAngle(self, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw + (45. / 8), 0); - P_SpawnMissileAngle(self, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw, 0); - P_SpawnMissileAngle(self, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw - (45. / 8), 0); - P_SpawnMissileAngle(self, RUNTIME_CLASS(AFSwordMissile), self->Angles.Yaw - (45. / 4), 0); - S_Sound (self, CHAN_WEAPON, "FighterSwordFire", 1, ATTN_NORM); - return 0; -} - diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 49c1369b31..e00b725832 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,7 +24,6 @@ #include "serializer.h" // Include all the Hexen stuff here to reduce compile time -#include "a_fighterquietus.cpp" #include "a_flechette.cpp" #include "a_flies.cpp" #include "a_healingradius.cpp" diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 34d74760cb..0adc0f1eba 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -688,7 +688,6 @@ class Actor : Thinker native 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_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/hexen/baseweapons.txt b/wadsrc/static/zscript/hexen/baseweapons.txt index 4c84ed7804..b7e2bd398a 100644 --- a/wadsrc/static/zscript/hexen/baseweapons.txt +++ b/wadsrc/static/zscript/hexen/baseweapons.txt @@ -61,4 +61,24 @@ extend class Actor angle = t.angleFromSource; } } + + //============================================================================ + // + // A_DropQuietusPieces + // + //============================================================================ + + void A_DropWeaponPieces(class p1, class p2, class p3) + { + for (int i = 0, j = 0; i < 3; ++i) + { + Actor piece = Spawn (j == 0 ? p1 : j == 1 ? p2 : p3, Pos, ALLOW_REPLACE); + if (piece != null) + { + piece.Vel = self.Vel + AngleToVector(i * 120., 1); + piece.bDropped = true; + j = (j == 0) ? (random[PieceDrop]() & 1) + 1 : 3-j; + } + } + } } \ No newline at end of file diff --git a/wadsrc/static/zscript/hexen/fighterboss.txt b/wadsrc/static/zscript/hexen/fighterboss.txt index 8e862de30c..9871cf5717 100644 --- a/wadsrc/static/zscript/hexen/fighterboss.txt +++ b/wadsrc/static/zscript/hexen/fighterboss.txt @@ -19,8 +19,6 @@ class FighterBoss : Actor Obituary "$OB_FBOSS"; } - native void A_FighterAttack(); - States { Spawn: @@ -80,4 +78,22 @@ class FighterBoss : Actor FDTH V 4 Bright; Stop; } + + //============================================================================ + // + // A_FighterAttack + // + //============================================================================ + + void A_FighterAttack() + { + if (!target) return; + + SpawnMissileAngle("FSwordMissile", Angle + (45. / 4), 0); + SpawnMissileAngle("FSwordMissile", Angle + (45. / 8), 0); + SpawnMissileAngle("FSwordMissile", Angle, 0); + SpawnMissileAngle("FSwordMissile", Angle - (45. / 8), 0); + SpawnMissileAngle("FSwordMissile", Angle - (45. / 4), 0); + A_PlaySound ("FighterSwordFire", CHAN_WEAPON); + } } diff --git a/wadsrc/static/zscript/hexen/fighterquietus.txt b/wadsrc/static/zscript/hexen/fighterquietus.txt index 7c94f7901f..53388eece0 100644 --- a/wadsrc/static/zscript/hexen/fighterquietus.txt +++ b/wadsrc/static/zscript/hexen/fighterquietus.txt @@ -97,8 +97,6 @@ class FWeapQuietus : FighterWeapon Tag "$TAG_FWEAPQUIETUS"; } - action native void A_FSwordAttack(); - States { Spawn: @@ -127,11 +125,40 @@ class FWeapQuietus : FighterWeapon FSRD B 1 Bright Offset (5, 40); Goto Ready; } + + //============================================================================ + // + // A_FSwordAttack + // + //============================================================================ + + action void A_FSwordAttack() + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + SpawnPlayerMissile ("FSwordMissile", Angle + (45./4),0, 0, -10); + SpawnPlayerMissile ("FSwordMissile", Angle + (45./8),0, 0, -5); + SpawnPlayerMissile ("FSwordMissile", Angle ,0, 0, 0); + SpawnPlayerMissile ("FSwordMissile", Angle - (45./8),0, 0, 5); + SpawnPlayerMissile ("FSwordMissile", Angle - (45./4),0, 0, 10); + A_PlaySound ("FighterSwordFire", CHAN_WEAPON); + } + + } // Fighter Sword Missile ---------------------------------------------------- -class FSwordMissile : Actor native +class FSwordMissile : Actor { Default { @@ -146,8 +173,6 @@ class FSwordMissile : Actor native Obituary "$OB_MPFWEAPQUIETUS"; } - native void A_FSwordFlames(); - States { Spawn: @@ -164,6 +189,32 @@ class FSwordMissile : Actor native FSFX KLM 3 Bright; Stop; } + + override int DoSpecialDamage(Actor victim, int damage, Name damagetype) + { + if (victim.player) + { + damage -= damage >> 2; + } + return damage; + } + + //============================================================================ + // + // A_FSwordFlames + // + //============================================================================ + + void A_FSwordFlames() + { + for (int i = 1+(random[FSwordFlame]()&3); i; i--) + { + double xo = (random[FSwordFlame]() - 128) / 16.; + double yo = (random[FSwordFlame]() - 128) / 16.; + double zo = (random[FSwordFlame]() - 128) / 8.; + Spawn ("FSwordFlame", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + } + } } // Fighter Sword Flame ------------------------------------------------------ From 69d4d36429fbe96d91ca23222dfbfc8a37c81e04 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 00:18:07 +0100 Subject: [PATCH 375/471] - scriptified ArtiHealingRadius. - allow switch/case with names. - fixed break jump target handling for switch/case. This only worked when the break was in the outermost compound statement, those in inner ones were missed. --- src/g_hexen/a_healingradius.cpp | 95 ------------------- src/g_hexen/a_hexenmisc.cpp | 1 - src/p_mobj.cpp | 9 +- src/p_user.cpp | 13 +++ src/scripting/codegeneration/codegen.cpp | 68 ++++++++----- src/scripting/codegeneration/codegen.h | 3 + wadsrc/static/zscript/actor.txt | 2 + wadsrc/static/zscript/hexen/healingradius.txt | 68 ++++++++++++- wadsrc/static/zscript/shared/player.txt | 12 +++ 9 files changed, 151 insertions(+), 120 deletions(-) delete mode 100644 src/g_hexen/a_healingradius.cpp diff --git a/src/g_hexen/a_healingradius.cpp b/src/g_hexen/a_healingradius.cpp deleted file mode 100644 index bf18a7e0ef..0000000000 --- a/src/g_hexen/a_healingradius.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "s_sound.h" -#include "m_random.h" -#include "a_action.h" -#include "a_hexenglobal.h" -#include "gi.h" -#include "doomstat.h" -*/ - -#define HEAL_RADIUS_DIST 255. - -static FRandom pr_healradius ("HealRadius"); - -// Healing Radius Artifact -------------------------------------------------- - -class AArtiHealingRadius : public AInventory -{ - DECLARE_CLASS (AArtiHealingRadius, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiHealingRadius, false, false) - -bool AArtiHealingRadius::Use (bool pickup) -{ - bool effective = false; - FName mode; - - if (Owner->IsKindOf(RUNTIME_CLASS(APlayerPawn))) - { - mode = static_cast(Owner->GetClass())->HealingRadiusType; - } - - for (int i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i] && - players[i].mo != NULL && - players[i].mo->health > 0 && - players[i].mo->Distance2D (Owner) <= HEAL_RADIUS_DIST) - { - // Q: Is it worth it to make this selectable as a player property? - // A: Probably not - but it sure doesn't hurt. - bool gotsome=false; - switch (mode) - { - case NAME_Armor: - for (int j = 0; j < 4; ++j) - { - AHexenArmor *armor = Spawn (); - armor->health = j; - armor->Amount = 1; - if (!armor->CallTryPickup (players[i].mo)) - { - armor->Destroy (); - } - else - { - gotsome = true; - } - } - break; - - case NAME_Mana: - { - int amount = 50 + (pr_healradius() % 50); - - if (players[i].mo->GiveAmmo (dyn_cast(PClass::FindClass(NAME_Mana1)), amount) || - players[i].mo->GiveAmmo (dyn_cast(PClass::FindClass(NAME_Mana2)), amount)) - { - gotsome = true; - } - break; - } - - default: - //case NAME_Health: - gotsome = P_GiveBody (players[i].mo, 50 + (pr_healradius()%50)); - break; - } - if (gotsome) - { - S_Sound (players[i].mo, CHAN_AUTO, "MysticIncant", 1, ATTN_NORM); - effective=true; - } - } - } - return effective; - -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index e00b725832..4fc0d45909 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -26,7 +26,6 @@ // Include all the Hexen stuff here to reduce compile time #include "a_flechette.cpp" #include "a_flies.cpp" -#include "a_healingradius.cpp" #include "a_heresiarch.cpp" #include "a_hexenspecialdecs.cpp" #include "a_iceguy.cpp" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7e9b8a96b4..5abc02e966 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1093,7 +1093,6 @@ DEFINE_ACTION_FUNCTION(AActor, GiveInventoryType) ACTION_RETURN_OBJECT(self->GiveInventoryType(type)); } - //============================================================================ // // AActor :: GiveAmmo @@ -1122,6 +1121,14 @@ bool AActor::GiveAmmo (PClassAmmo *type, int amount) return false; } +DEFINE_ACTION_FUNCTION(AActor, GiveAmmo) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(type, AAmmo); + PARAM_INT(amount); + ACTION_RETURN_BOOL(self->GiveAmmo(type, amount)); +} + //============================================================================ // // AActor :: ClearInventory diff --git a/src/p_user.cpp b/src/p_user.cpp index eadbda10e1..ce78d04a83 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3175,6 +3175,19 @@ DEFINE_FIELD(APlayerPawn, FlechetteType) DEFINE_FIELD(APlayerPawn, DamageFade) DEFINE_FIELD(APlayerPawn, ViewBob) +DEFINE_FIELD(PClassPlayerPawn, HealingRadiusType) +DEFINE_FIELD(PClassPlayerPawn, DisplayName) +DEFINE_FIELD(PClassPlayerPawn, SoundClass) +DEFINE_FIELD(PClassPlayerPawn, Face) +DEFINE_FIELD(PClassPlayerPawn, Portrait) +DEFINE_FIELD(PClassPlayerPawn, Slot) +DEFINE_FIELD(PClassPlayerPawn, InvulMode) +DEFINE_FIELD(PClassPlayerPawn, HexenArmor) +DEFINE_FIELD(PClassPlayerPawn, ColorRangeStart) +DEFINE_FIELD(PClassPlayerPawn, ColorRangeEnd) +DEFINE_FIELD(PClassPlayerPawn, ColorSets) +DEFINE_FIELD(PClassPlayerPawn, PainFlashes) + DEFINE_FIELD_X(PlayerInfo, player_t, mo) DEFINE_FIELD_X(PlayerInfo, player_t, playerstate) DEFINE_FIELD_X(PlayerInfo, player_t, original_oldbuttons) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4562f3ef7d..0fb6b172fc 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -8338,7 +8338,7 @@ bool FxCompoundStatement::CheckLocalVariable(FName name) FxSwitchStatement::FxSwitchStatement(FxExpression *cond, FArgumentList &content, const FScriptPosition &pos) : FxExpression(EFX_SwitchStatement, pos) { - Condition = new FxIntCast(cond, false); + Condition = cond; Content = std::move(content); } @@ -8352,6 +8352,12 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(Condition, ctx); + if (Condition->ValueType != TypeName) + { + Condition = new FxIntCast(Condition, false); + SAFE_RESOLVE(Condition, ctx); + } + if (Content.Size() == 0) { ScriptPosition.Message(MSG_WARNING, "Empty switch statement"); @@ -8370,15 +8376,15 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) } } + auto outerctrl = ctx.ControlStmt; + ctx.ControlStmt = this; + 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; - } + SAFE_RESOLVE(line, ctx); + line->NeedResult = false; } + ctx.ControlStmt = outerctrl; if (Condition->isConstant()) { @@ -8398,6 +8404,12 @@ FxExpression *FxSwitchStatement::Resolve(FCompileContext &ctx) auto casestmt = static_cast(content[i]); if (casestmt->Condition == nullptr) defaultindex = i; else if (casestmt->CaseValue == static_cast(Condition)->GetValue().GetInt()) caseindex = i; + if (casestmt->Condition && casestmt->Condition->ValueType != Condition->ValueType) + { + casestmt->Condition->ScriptPosition.Message(MSG_ERROR, "Type mismatch in case statement"); + delete this; + return nullptr; + } } if (content[i]->ExprType == EFX_JumpStatement && static_cast(content[i])->Token == TK_Break) { @@ -8478,7 +8490,6 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) ca.jumpaddress = build->Emit(OP_JMP, 0); } size_t DefaultAddress = build->Emit(OP_JMP, 0); - TArray BreakAddresses; bool defaultset = false; for (auto line : Content) @@ -8504,22 +8515,14 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) } 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) + for (auto addr : Breaks) { - build->BackpatchToHere(addr); + build->BackpatchToHere(addr->Address); } if (!defaultset) build->BackpatchToHere(DefaultAddress); Content.DeleteAndClear(); @@ -8555,7 +8558,7 @@ bool FxSwitchStatement::CheckReturn() FxCaseStatement::FxCaseStatement(FxExpression *cond, const FScriptPosition &pos) : FxExpression(EFX_CaseStatement, pos) { - Condition = cond? new FxIntCast(cond, false) : nullptr; + Condition = cond; } FxCaseStatement::~FxCaseStatement() @@ -8576,7 +8579,17 @@ FxExpression *FxCaseStatement::Resolve(FCompileContext &ctx) delete this; return nullptr; } - CaseValue = static_cast(Condition)->GetValue().GetInt(); + // Case labels can be ints or names. + if (Condition->ValueType != TypeName) + { + Condition = new FxIntCast(Condition, false); + SAFE_RESOLVE(Condition, ctx); + CaseValue = static_cast(Condition)->GetValue().GetInt(); + } + else + { + CaseValue = static_cast(Condition)->GetValue().GetName(); + } } return this; } @@ -8747,10 +8760,13 @@ bool FxIfStatement::CheckReturn() FxExpression *FxLoopStatement::Resolve(FCompileContext &ctx) { + auto outerctrl = ctx.ControlStmt; auto outer = ctx.Loop; + ctx.ControlStmt = this; ctx.Loop = this; auto x = DoResolve(ctx); ctx.Loop = outer; + ctx.ControlStmt = outerctrl; return x; } @@ -9074,9 +9090,17 @@ FxExpression *FxJumpStatement::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); - if (ctx.Loop != nullptr) + if (ctx.ControlStmt != nullptr) { - ctx.Loop->Jumps.Push(this); + if (ctx.ControlStmt == ctx.Loop || Token == TK_Continue) + { + ctx.Loop->Jumps.Push(this); + } + else + { + // break in switch. + static_cast(ctx.ControlStmt)->Breaks.Push(this); + } return this; } else diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 1110cd6b61..ae0581e05b 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -72,6 +72,7 @@ typedef TDeletingArray FArgumentList; struct FCompileContext { + FxExpression *ControlStmt = nullptr; FxLoopStatement *Loop = nullptr; FxCompoundStatement *Block = nullptr; PPrototype *ReturnProto; @@ -1656,6 +1657,8 @@ class FxSwitchStatement : public FxExpression TArray CaseAddresses; public: + TArray Breaks; + FxSwitchStatement(FxExpression *cond, FArgumentList &content, const FScriptPosition &pos); ~FxSwitchStatement(); FxExpression *Resolve(FCompileContext&); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0adc0f1eba..cefcd6511a 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -357,6 +357,8 @@ class Actor : Thinker native native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native Inventory FindInventory(class itemtype, bool subclass = false); native Inventory GiveInventoryType(class itemtype); + native bool GiveAmmo (Class type, int amount); + native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); native double GetDistance(bool checkz, int ptr = AAPTR_TARGET); native double GetAngle(int flags, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/hexen/healingradius.txt b/wadsrc/static/zscript/hexen/healingradius.txt index 94d8e2dd5c..52b87c15b8 100644 --- a/wadsrc/static/zscript/hexen/healingradius.txt +++ b/wadsrc/static/zscript/hexen/healingradius.txt @@ -1,8 +1,10 @@ // Healing Radius Artifact -------------------------------------------------- -class ArtiHealingRadius : Inventory native +class ArtiHealingRadius : Inventory { + const HEAL_RADIUS_DIST = 255.; + Default { +COUNTITEM @@ -21,6 +23,70 @@ class ArtiHealingRadius : Inventory native Spawn: HRAD ABCDEFGHIJKLMNOP 4 Bright; Loop; + } + + override bool Use (bool pickup) + { + bool effective = false; + Name mode = 'Health'; + + PlayerPawn pp = PlayerPawn(Owner); + if (pp) mode = pp.HealingRadiusType; + + for (int i = 0; i < MAXPLAYERS; ++i) + { + PlayerPawn mo = players[i].mo; + if (playeringame[i] && mo != null && mo.health > 0 && mo.Distance2D (Owner) <= HEAL_RADIUS_DIST) + { + // Q: Is it worth it to make this selectable as a player property? + // A: Probably not - but it sure doesn't hurt. + bool gotsome=false; + switch (mode) + { + case 'Armor': + for (int j = 0; j < 4; ++j) + { + HexenArmor armor = HexenArmor(Spawn("HexenArmor")); + armor.health = j; + armor.Amount = 1; + if (!armor.CallTryPickup (mo)) + { + armor.Destroy (); + } + else + { + gotsome = true; + } + } + break; + + case 'Mana': + { + int amount = 50 + (random[HealRadius]() % 50); + + if (mo.GiveAmmo ("Mana1", amount) || + mo.GiveAmmo ("Mana2", amount)) + { + gotsome = true; + } + break; + } + + default: + //case NAME_Health: + gotsome = mo.GiveBody (50 + (random[HealRadius]() % 50)); + break; + } + if (gotsome) + { + mo.A_PlaySound ("MysticIncant", CHAN_AUTO); + effective=true; + } + } + } + return effective; + } + } diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 48d62688b6..2d5be62781 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -8,6 +8,18 @@ class PlayerPawn : Actor native native int PlayerFlags; native Inventory InvFirst; // first inventory item displayed on inventory bar native Inventory InvSel; // selected inventory item + native meta String DisplayName; // Display name (used in menus, etc.) + native meta String SoundClass; // Sound class + native meta String Face; // Doom status bar face (when used) + native meta String Portrait; + native meta String Slot[10]; + native meta Name InvulMode; + native meta Name HealingRadiusType; + native meta double HexenArmor[5]; + native meta uint8 ColorRangeStart; // Skin color range + native meta uint8 ColorRangeEnd; + //FPlayerColorSetMap ColorSets; + //PainFlashList PainFlashes; // [GRB] Player class properties native double JumpZ; From ab03b016e9263d03b368a3b4298e5d95bb529558 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 00:41:06 +0100 Subject: [PATCH 376/471] - scriptified the IceGuy. --- src/CMakeLists.txt | 2 - src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_iceguy.cpp | 132 ------------------------- src/p_mobj.cpp | 14 +++ wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/hexen/iceguy.txt | 103 ++++++++++++++++++- 6 files changed, 113 insertions(+), 141 deletions(-) delete mode 100644 src/g_hexen/a_iceguy.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 06028ecff9..c5a54d1ba2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -857,10 +857,8 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_flechette.cpp g_hexen/a_flies.cpp - g_hexen/a_healingradius.cpp g_hexen/a_heresiarch.cpp g_hexen/a_hexenspecialdecs.cpp - g_hexen/a_iceguy.cpp g_hexen/a_magecone.cpp g_hexen/a_magelightning.cpp g_hexen/a_magestaff.cpp diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 4fc0d45909..3223575c81 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -28,7 +28,6 @@ #include "a_flies.cpp" #include "a_heresiarch.cpp" #include "a_hexenspecialdecs.cpp" -#include "a_iceguy.cpp" #include "a_magecone.cpp" #include "a_magelightning.cpp" #include "a_magestaff.cpp" diff --git a/src/g_hexen/a_iceguy.cpp b/src/g_hexen/a_iceguy.cpp deleted file mode 100644 index 1163a117a3..0000000000 --- a/src/g_hexen/a_iceguy.cpp +++ /dev/null @@ -1,132 +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 "vm.h" -*/ - -static FRandom pr_iceguylook ("IceGuyLook"); -static FRandom pr_iceguychase ("IceGuyChase"); - -static const char *WispTypes[2] = -{ - "IceGuyWisp1", - "IceGuyWisp2", -}; - -//============================================================================ -// -// A_IceGuyLook -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_IceGuyLook) -{ - PARAM_SELF_PROLOGUE(AActor); - - double dist; - DAngle an; - - CALL_ACTION(A_Look, self); - if (pr_iceguylook() < 64) - { - dist = (pr_iceguylook() - 128) * self->radius / 128.; - an = self->Angles.Yaw + 90; - Spawn(WispTypes[pr_iceguylook() & 1], self->Vec3Angle(dist, an, 60.), ALLOW_REPLACE); - } - return 0; -} - -//============================================================================ -// -// A_IceGuyChase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_IceGuyChase) -{ - PARAM_SELF_PROLOGUE(AActor); - - double dist; - DAngle an; - AActor *mo; - - A_Chase(stack, self); - if (pr_iceguychase() < 128) - { - dist = (pr_iceguychase() - 128) * self->radius / 128.; - an = self->Angles.Yaw + 90; - mo = Spawn(WispTypes[pr_iceguylook() & 1], self->Vec3Angle(dist, an, 60.), ALLOW_REPLACE); - if (mo) - { - mo->Vel = self->Vel; - mo->target = self; - } - } - return 0; -} - -//============================================================================ -// -// A_IceGuyAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_IceGuyAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if(!self->target) - { - return 0; - } - P_SpawnMissileXYZ(self->Vec3Angle(self->radius / 2, self->Angles.Yaw + 90, 40.), self, self->target, PClass::FindActor("IceGuyFX")); - P_SpawnMissileXYZ(self->Vec3Angle(self->radius / 2, self->Angles.Yaw - 90, 40.), self, self->target, PClass::FindActor("IceGuyFX")); - S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_IceGuyDie -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_IceGuyDie) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Vel.Zero(); - self->Height = self->GetDefault()->Height; - CALL_ACTION(A_FreezeDeathChunks, self); - return 0; -} - -//============================================================================ -// -// A_IceGuyMissileExplode -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_IceGuyMissileExplode) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - unsigned int i; - - for (i = 0; i < 8; i++) - { - mo = P_SpawnMissileAngleZ (self, self->Z()+3, PClass::FindActor("IceGuyFX2"), DAngle(i*45.), -0.3); - if (mo) - { - mo->target = self->target; - } - } - return 0; -} - diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5abc02e966..2e87729d0a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6375,6 +6375,20 @@ AActor *P_SpawnMissileXYZ (DVector3 pos, AActor *source, AActor *dest, PClassAct return (!checkspawn || P_CheckMissileSpawn (th, source->radius)) ? th : NULL; } +DEFINE_ACTION_FUNCTION(AActor, SpawnMissileXYZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_OBJECT(dest, AActor); + PARAM_CLASS(type, AActor); + PARAM_BOOL_DEF(check); + PARAM_OBJECT_DEF(owner, AActor); + ACTION_RETURN_OBJECT(P_SpawnMissileXYZ(DVector3(x,y,z), self, dest, type, check, owner)); +} + + AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassActor *type) { if (source == NULL) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index cefcd6511a..92f1073fd5 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -296,6 +296,7 @@ class Actor : Thinker native native bool TestMobjLocation(); 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 SpawnMissileXYZ(Vector3 pos, Actor dest, Class type, bool checkspawn = true, Actor owner = null); native Actor SpawnMissileZ (double z, Actor dest, class type); native Actor SpawnMissileAngleZSpeed (double z, class type, double angle, double vz, double speed, Actor owner = null, bool checkspawn = true); native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); @@ -592,7 +593,6 @@ class Actor : Thinker native native void A_FreezeDeath(); native void A_FreezeDeathChunks(); native void A_GenericFreezeDeath(); - native void A_IceGuyDie(); native void A_PlayerScream(); native void A_SkullPop(class skulltype = "BloodySkull"); native void A_CheckPlayerDone(); diff --git a/wadsrc/static/zscript/hexen/iceguy.txt b/wadsrc/static/zscript/hexen/iceguy.txt index 8081d5a61d..41105b728e 100644 --- a/wadsrc/static/zscript/hexen/iceguy.txt +++ b/wadsrc/static/zscript/hexen/iceguy.txt @@ -22,9 +22,6 @@ class IceGuy : Actor Obituary "$OB_ICEGUY"; } - native void A_IceGuyLook(); - native void A_IceGuyChase(); - native void A_IceGuyAttack(); States { @@ -51,6 +48,84 @@ class IceGuy : Actor ICEY A -1; Goto See; } + + //============================================================================ + // + // SpawnWisp + // + //============================================================================ + + private void SpawnWisp() + { + static const class WispTypes[] = { "IceGuyWisp1", "IceGuyWisp2" }; + + double dist = (random[IceGuyLook]() - 128) * radius / 128.; + double an = angle + 90; + Actor mo = Spawn(WispTypes[random[IceGuyLook]() & 1], Vec3Angle(dist, an, 60.), ALLOW_REPLACE); + if (mo) + { + mo.Vel = Vel; + mo.target = self; + } + } + + //============================================================================ + // + // A_IceGuyLook + // + //============================================================================ + + void A_IceGuyLook() + { + A_Look(); + if (random[IceGuyLook]() < 64) SpawnWisp(); + } + + //============================================================================ + // + // A_IceGuyChase + // + //============================================================================ + + void A_IceGuyChase() + { + A_Chase(); + if (random[IceGuyLook]() < 128) SpawnWisp(); + } + + //============================================================================ + // + // A_IceGuyAttack + // + //============================================================================ + + void A_IceGuyAttack() + { + if(!target) + { + return; + } + SpawnMissileXYZ(Vec3Angle(radius / 2, angle + 90, 40.), target, "IceGuyFX"); + SpawnMissileXYZ(Vec3Angle(radius / 2, angle - 90, 40.), target, "IceGuyFX"); + A_PlaySound (AttackSound, CHAN_WEAPON); + } +} + +extend class Actor +{ + //============================================================================ + // + // A_IceGuyDie (globally accessible) + // + //============================================================================ + + void A_IceGuyDie() + { + Vel = (0,0,0); + Height = Default.Height; + A_FreezeDeathChunks(); + } + } // Ice Guy Projectile ------------------------------------------------------- @@ -69,8 +144,6 @@ class IceGuyFX : Actor DeathSound "IceGuyMissileExplode"; } - native void A_IceGuyMissileExplode(); - States { Spawn: @@ -83,6 +156,25 @@ class IceGuyFX : Actor ICPR H 3 Bright; Stop; } + + + //============================================================================ + // + // A_IceGuyMissileExplode + // + //============================================================================ + + void A_IceGuyMissileExplode() + { + for (int i = 0; i < 8; i++) + { + Actor mo = SpawnMissileAngleZ (pos.z+3, "IceGuyFX2", i*45., -0.3); + if (mo) + { + mo.target = target; + } + } + } } // Ice Guy Projectile's Puff ------------------------------------------------ @@ -183,3 +275,4 @@ class IceGuyWisp2 : IceGuyWisp1 Stop; } } + From 6eff1cb8be81ebc5b33603a3437b53f4679fc92d Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Sat, 26 Nov 2016 12:45:17 +0100 Subject: [PATCH 377/471] - Fixed more GCC/Clang warnings. --- src/memarena.cpp | 4 ++-- src/memarena.h | 6 +++--- src/p_actionfunctions.cpp | 2 +- src/p_pspr.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 14 +++++++++++++- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/memarena.cpp b/src/memarena.cpp index e6e9edd6e7..8ea8b5806b 100644 --- a/src/memarena.cpp +++ b/src/memarena.cpp @@ -72,11 +72,11 @@ static inline void *RoundPointer(void *ptr) // //========================================================================== -FMemArena::FMemArena(int bs) +FMemArena::FMemArena(size_t blocksize) { TopBlock = NULL; FreeBlocks = NULL; - BlockSize = bs; + BlockSize = blocksize; } //========================================================================== diff --git a/src/memarena.h b/src/memarena.h index cc0c8f148f..3601469bf8 100644 --- a/src/memarena.h +++ b/src/memarena.h @@ -40,7 +40,7 @@ class FMemArena { public: - FMemArena(int blocksize = 10*1024); + FMemArena(size_t blocksize = 10*1024); ~FMemArena(); void *Alloc(size_t size); @@ -55,7 +55,7 @@ protected: Block *TopBlock; Block *FreeBlocks; - int BlockSize; + size_t BlockSize; }; // An arena specializing in storage of FStrings. It knows how to free them, @@ -87,4 +87,4 @@ private: }; -#endif \ No newline at end of file +#endif diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 95bcb3e25e..d33695a1b8 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -143,7 +143,7 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) // 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, state->ActionFunc->PrintableName.GetChars()); + owner->TypeName.GetChars(), int(state - owner->OwnedStates), state->ActionFunc->PrintableName.GetChars()); state->ActionFunc = nullptr; } diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index eddeb3430d..e2ea3084db 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -409,7 +409,7 @@ void DPSprite::SetState(FState *newstate, bool pending) // 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, newstate->ActionFunc->PrintableName.GetChars()); + owner->TypeName.GetChars(), int(newstate - owner->OwnedStates), newstate->ActionFunc->PrintableName.GetChars()); newstate->ActionFunc = nullptr; } if (newstate->CallAction(Owner->mo, Caller, &stp, &nextstate)) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 0fb6b172fc..1e06f5751b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7771,7 +7771,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } VMFunction *vmfunc = Function->Variants[0].Implementation; - bool staticcall = (vmfunc->Final || vmfunc->VirtualIndex == -1 || NoVirtual); + bool staticcall = (vmfunc->Final || vmfunc->VirtualIndex == ~0u || NoVirtual); count = 0; // Emit code to pass implied parameters diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 98ebc17d93..56f991287e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1469,6 +1469,9 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n break; } break; + + default: + break; } break; } @@ -1520,6 +1523,9 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n } break; } + + default: + break; } if (retval != TypeError && retval->MemberOnly && !formember) { @@ -1997,6 +2003,9 @@ void ZCCCompiler::InitDefaults() case AST_FlagStmt: ProcessDefaultFlag(ti, static_cast(content)); break; + + default: + break; } content = static_cast(content->SiblingNext); } while (content != d->Content); @@ -3215,6 +3224,9 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } return new FxMultiAssign(args, ConvertNode(ass->Sources), *ast); } + + default: + break; } // only for development. I_Error is more convenient here than a normal error. I_Error("ConvertNode encountered unsupported node of type %d", ast->NodeType); @@ -3234,4 +3246,4 @@ FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *h } while (node != head); } return args; -} \ No newline at end of file +} From 096c51d5464df360e1ba2dd5b75b07805f33dcce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 10:40:43 +0100 Subject: [PATCH 378/471] - changed AInventory::HandlePickup to work iteratively instead of recursively. Two reasons for this: 1. if this has to be routed through the VM each recursion will cost 1000 bytes of stack space which simply is not good. 2. having the virtual function only care about the item itself but not the entire inventory chain is a lot less error prone for scripting. Since the scripting interface needs a separate caller function anyway this seemed like a good time to change it. The same will be done for the other chained inventory handlers as well. --- src/CMakeLists.txt | 1 - src/dobjtype.cpp | 1 + src/g_game.cpp | 8 ++--- src/g_hexen/a_hexenglobal.h | 15 -------- src/g_shared/a_armor.cpp | 8 ----- src/g_shared/a_artifacts.cpp | 4 --- src/g_shared/a_keys.cpp | 4 --- src/g_shared/a_pickups.cpp | 49 ++++++++++++++++----------- src/g_shared/a_pickups.h | 1 + src/g_shared/a_weaponpiece.h | 2 ++ src/g_shared/a_weapons.cpp | 4 --- src/g_shared/sbarinfo.cpp | 1 + src/g_strife/a_coin.cpp | 4 --- src/g_strife/a_strifeweapons.cpp | 4 --- src/p_mobj.cpp | 11 +++++- src/scripting/thingdef.cpp | 1 + src/scripting/thingdef_properties.cpp | 8 ++--- wadsrc/static/zscript/actor.txt | 1 + 18 files changed, 55 insertions(+), 72 deletions(-) delete mode 100644 src/g_hexen/a_hexenglobal.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5a54d1ba2..3686546984 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_flechette.cpp g_hexen/a_flies.cpp g_hexen/a_heresiarch.cpp g_hexen/a_hexenspecialdecs.cpp diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 079890f863..e9f574ea43 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -45,6 +45,7 @@ #include "autosegs.h" #include "v_text.h" #include "a_pickups.h" +#include "a_artifacts.h" #include "a_weaponpiece.h" #include "d_player.h" #include "doomerrors.h" diff --git a/src/g_game.cpp b/src/g_game.cpp index 9af9b4532f..350669cfea 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -478,15 +478,15 @@ CCMD (useflechette) { // Select from one of arti_poisonbag1-3, whichever the player has static const ENamedName bagnames[3] = { + NAME_ArtiPoisonBag3, // use type 3 first because that's the default when the player has none specified. NAME_ArtiPoisonBag1, - NAME_ArtiPoisonBag2, - NAME_ArtiPoisonBag3 + NAME_ArtiPoisonBag2 }; if (who == NULL) return; - PClassActor *type = GetFlechetteType(who); + PClassActor *type = who->FlechetteType; if (type != NULL) { AInventory *item; @@ -497,7 +497,7 @@ CCMD (useflechette) } } - // The default flechette could not be found. Try all 3 types then. + // The default flechette could not be found, or the player had no default. Try all 3 types then. for (int j = 0; j < 3; ++j) { AInventory *item; diff --git a/src/g_hexen/a_hexenglobal.h b/src/g_hexen/a_hexenglobal.h deleted file mode 100644 index 277d1bff11..0000000000 --- a/src/g_hexen/a_hexenglobal.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __A_HEXENGLOBAL_H__ -#define __A_HEXENGLOBAL_H__ - -#include "d_player.h" - -class AArtiPoisonBag : public AInventory -{ - DECLARE_CLASS (AArtiPoisonBag, AInventory) -public: - bool HandlePickup (AInventory *item); - AInventory *CreateCopy (AActor *other); - void BeginPlay (); -}; - -#endif //__A_HEXENGLOBAL_H__ diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 6be1472bfc..25d45d35db 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -115,10 +115,6 @@ bool ABasicArmor::HandlePickup (AInventory *item) armor->SaveAmount = int(armor->SaveAmount * G_SkillProperty(SKILLP_ArmorFactor)); } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } @@ -474,10 +470,6 @@ bool AHexenArmor::HandlePickup (AInventory *item) } return true; } - else if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 8548816473..99a4f46d84 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -309,10 +309,6 @@ bool APowerup::HandlePickup (AInventory *item) power->ItemFlags |= IF_PICKUPGOOD; return true; } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index 51962c1b08..fc9363be58 100644 --- a/src/g_shared/a_keys.cpp +++ b/src/g_shared/a_keys.cpp @@ -487,10 +487,6 @@ bool AKey::HandlePickup (AInventory *item) item->ItemFlags |= IF_PICKUPGOOD; return true; } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index b026a61d76..3ce3dc776e 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -183,10 +183,6 @@ bool AAmmo::HandlePickup (AInventory *item) } return true; } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } @@ -718,13 +714,39 @@ bool AInventory::HandlePickup (AInventory *item) } return true; } - if (Inventory != NULL) + return false; +} + +DEFINE_ACTION_FUNCTION(AInventory, HandlePickup) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_OBJECT(item, AInventory); + ACTION_RETURN_BOOL(self->HandlePickup(item)); +} + +bool AInventory::CallHandlePickup(AInventory *item) +{ + auto self = this; + while (self != nullptr) { - return Inventory->HandlePickup (item); + IFVIRTUAL(AActor, HandlePickup) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[2] = { (DObject*)self, (DObject*)item }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + if (retval) return true; + } + else if (self->HandlePickup(item)) return true; + self = self->Inventory; } return false; } + //=========================================================================== // // AInventory :: GoAway @@ -1480,7 +1502,7 @@ bool AInventory::TryPickup (AActor *&toucher) // picked up, then it leaves the flag cleared. ItemFlags &= ~IF_PICKUPGOOD; - if (toucher->Inventory != NULL && toucher->Inventory->HandlePickup (this)) + if (toucher->Inventory != NULL && toucher->Inventory->CallHandlePickup (this)) { // Let something else the player is holding intercept the pickup. if (!(ItemFlags & IF_PICKUPGOOD)) @@ -1892,10 +1914,6 @@ bool AHealthPickup::HandlePickup (AInventory *item) { return Super::HandlePickup (item); } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } @@ -2044,14 +2062,7 @@ bool ABackpackItem::HandlePickup (AInventory *item) item->ItemFlags |= IF_PICKUPGOOD; return true; } - else if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } - else - { - return false; - } + return false; } //=========================================================================== diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index bc83199316..2fe680231f 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -203,6 +203,7 @@ public: virtual bool GoAway (); virtual void GoAwayAndDie (); virtual bool HandlePickup (AInventory *item); + bool CallHandlePickup(AInventory *item); virtual bool Use (bool pickup); bool CallUse(bool pickup); virtual void Travelled (); diff --git a/src/g_shared/a_weaponpiece.h b/src/g_shared/a_weaponpiece.h index 88f3da02c7..3a6fbcbd7c 100644 --- a/src/g_shared/a_weaponpiece.h +++ b/src/g_shared/a_weaponpiece.h @@ -1,3 +1,5 @@ +#pragma once +#include "a_pickups.h" // class PClassWeaponPiece : public PClassInventory diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index b19896e91a..c2feebec67 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -346,10 +346,6 @@ bool AWeapon::HandlePickup (AInventory *item) } return true; } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index a005c1adae..ed91be4c73 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -50,6 +50,7 @@ #include "sbarinfo.h" #include "gi.h" #include "r_data/r_translate.h" +#include "a_artifacts.h" #include "a_weaponpiece.h" #include "a_strifeglobal.h" #include "g_level.h" diff --git a/src/g_strife/a_coin.cpp b/src/g_strife/a_coin.cpp index 53cc59f506..f74d92e552 100644 --- a/src/g_strife/a_coin.cpp +++ b/src/g_strife/a_coin.cpp @@ -41,10 +41,6 @@ bool ACoin::HandlePickup (AInventory *item) } return true; } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 0268682f33..1909ec7816 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -786,10 +786,6 @@ bool ASigil::HandlePickup (AInventory *item) } return true; } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } return false; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2e87729d0a..c7cf50f5e4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -41,7 +41,6 @@ #include "c_dispatch.h" #include "b_bot.h" //Added by MC: #include "stats.h" -#include "a_hexenglobal.h" #include "a_sharedglobal.h" #include "gi.h" #include "sbar.h" @@ -69,6 +68,7 @@ #include "serializer.h" #include "r_utility.h" #include "thingdef.h" +#include "d_player.h" #include "virtual.h" // MACROS ------------------------------------------------------------------ @@ -7436,6 +7436,15 @@ DEFINE_ACTION_FUNCTION(AActor, SetFriendPlayer) self->SetFriendPlayer(player); return 0; } + +DEFINE_ACTION_FUNCTION(AActor, ClearBounce) +{ + PARAM_SELF_PROLOGUE(AActor); + self->BounceFlags = 0; + return 0; +} + + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index d6c53dd8de..5708f89d29 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -57,6 +57,7 @@ #include "m_argv.h" #include "p_local.h" #include "doomerrors.h" +#include "a_artifacts.h" #include "a_weaponpiece.h" #include "p_conversation.h" #include "v_text.h" diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 8968dc1d6f..8586d32af2 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -39,7 +39,7 @@ */ #include "gi.h" -#include "actor.h" +#include "d_player.h" #include "info.h" #include "tarray.h" #include "w_wad.h" @@ -57,8 +57,7 @@ #include "p_effect.h" #include "v_palette.h" #include "doomerrors.h" -#include "a_hexenglobal.h" -#include "a_weaponpiece.h" +#include "a_artifacts.h" #include "p_conversation.h" #include "v_text.h" #include "thingdef.h" @@ -69,6 +68,7 @@ #include "teaminfo.h" #include "v_video.h" #include "r_data/colormaps.h" +#include "a_weaponpiece.h" #include "vmbuilder.h" extern TArray OptionalClassPtrs; @@ -2800,7 +2800,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, morphweapon, S, PlayerPawn) DEFINE_CLASS_PROPERTY_PREFIX(player, flechettetype, S, PlayerPawn) { PROP_STRING_PARM(str, 0); - defaults->FlechetteType = FindClassTentative(str, RUNTIME_CLASS(AArtiPoisonBag)); + defaults->FlechetteType = FindClassTentative(str, PClass::FindActor("ArtiPoisonBag")); } //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 92f1073fd5..8acd261f3b 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -280,6 +280,7 @@ class Actor : Thinker native native int PlayerNumber(); native void SetFriendPlayer(PlayerInfo player); native void NoiseAlert(Actor emitter, bool splash = false, double maxdist = 0); + native void ClearBounce(); native void RestoreDamage(); native int SpawnHealth(); From b10ffb5133837d8f64942366d92fd7e54fee05b1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 11:59:47 +0100 Subject: [PATCH 379/471] - exported a few more functions. - refactored the ModifyDamage interface to be more scripting friendly. In general it should be avoided having to call directly into chained inventory functions because they are very problematic and prone to errors. So this got wrapped into a single handler (on AActor, not AInventory!) which will later make it easier to refactor the parameters of ModifyDamage to work better for scripting and avoid the chaining. --- src/actor.h | 1 + src/g_shared/a_pickups.cpp | 25 +++++++++++++++++++++- src/g_shared/a_pickups.h | 1 + src/p_interaction.cpp | 25 +++++++++++++--------- src/p_mobj.cpp | 25 ++++++++++++++++++++++ wadsrc/static/zscript/actor.txt | 2 ++ wadsrc/static/zscript/shared/inventory.txt | 2 ++ wadsrc/static/zscript/shared/player.txt | 1 + 8 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/actor.h b/src/actor.h index 92e277d48b..4c0f33dde6 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1420,6 +1420,7 @@ public: } int ApplyDamageFactor(FName damagetype, int damage) const; + int GetModifiedDamage(FName damagetype, int damage, bool passive); }; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 3ce3dc776e..a57d90bcd6 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -822,6 +822,29 @@ AInventory *AInventory::CreateCopy (AActor *other) return copy; } +DEFINE_ACTION_FUNCTION(AInventory, CreateCopy) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_OBJECT(self->CreateCopy(other)); +} + +AInventory *AInventory::CallCreateCopy(AActor *other) +{ + IFVIRTUAL(AActor, CreateCopy) + { + VMValue params[2] = { (DObject*)this, (DObject*)other }; + VMReturn ret; + VMFrameStack stack; + AInventory *retval; + ret.PointerAt((void**)&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + return retval; + } + else return CreateCopy(other); +} + + //=========================================================================== // // AInventory::CreateTossable @@ -1538,7 +1561,7 @@ bool AInventory::TryPickup (AActor *&toucher) { // Add the item to the inventory. It is not already there, or HandlePickup // would have already taken care of it. - AInventory *copy = CreateCopy (toucher); + AInventory *copy = CallCreateCopy (toucher); if (copy == NULL) { return false; diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 2fe680231f..429b2ab905 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -199,6 +199,7 @@ public: virtual void AttachToOwner (AActor *other); virtual void DetachFromOwner (); virtual AInventory *CreateCopy (AActor *other); + AInventory *CallCreateCopy(AActor *other); virtual AInventory *CreateTossable (); virtual bool GoAway (); virtual void GoAwayAndDie (); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 040e05ce07..c2d958050e 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1105,15 +1105,15 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, damage = int(damage * source->DamageMultiply); // Handle active damage modifiers (e.g. PowerDamage) - if (damage > 0 && source->Inventory != NULL) + if (damage > 0) { - source->Inventory->ModifyDamage(damage, mod, damage, false); + damage = source->GetModifiedDamage(mod, damage, false); } } // Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers. - if (damage > 0 && (target->Inventory != NULL) && !(flags & DMG_NO_PROTECT)) + if (damage > 0 && !(flags & DMG_NO_PROTECT)) { - target->Inventory->ModifyDamage(damage, mod, damage, true); + damage = target->GetModifiedDamage(mod, damage, true); } if (damage > 0 && !(flags & DMG_NO_FACTOR)) { @@ -1749,8 +1749,7 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, PoisonPlayer) // //========================================================================== -void P_PoisonDamage (player_t *player, AActor *source, int damage, - bool playPainSound) +void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPainSound) { AActor *target; @@ -1771,10 +1770,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, // Take half damage in trainer mode damage = int(damage * G_SkillProperty(SKILLP_DamageFactor)); // Handle passive damage modifiers (e.g. PowerProtection) - if (target->Inventory != NULL) - { - target->Inventory->ModifyDamage(damage, player->poisontype, damage, true); - } + damage = target->GetModifiedDamage(player->poisontype, damage, true); // Modify with damage factors damage = target->ApplyDamageFactor(player->poisontype, damage); @@ -1845,6 +1841,15 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, */ } +DEFINE_ACTION_FUNCTION(_PlayerInfo, PoisonDamage) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_OBJECT(source, AActor); + PARAM_INT(damage); + PARAM_BOOL(playsound); + P_PoisonDamage(self, source, damage, playsound); + return 0; +} CCMD (kill) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index c7cf50f5e4..ad1c317e8b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7158,6 +7158,23 @@ DEFINE_ACTION_FUNCTION(AActor, ClearCounters) return 0; } +int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive) +{ + if (Inventory != nullptr) + Inventory->ModifyDamage(damage, damagetype, damage, false); + + return damage; +} + +DEFINE_ACTION_FUNCTION(AActor, GetModifiedDamage) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_NAME(type); + PARAM_INT(damage); + PARAM_BOOL(passive); + ACTION_RETURN_INT(self->GetModifiedDamage(type, damage, passive)); +} + int AActor::ApplyDamageFactor(FName damagetype, int damage) const { damage = int(damage * DamageFactor); @@ -7168,6 +7185,14 @@ int AActor::ApplyDamageFactor(FName damagetype, int damage) const return damage; } +DEFINE_ACTION_FUNCTION(AActor, ApplyDamageFactor) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_NAME(type); + PARAM_INT(damage); + ACTION_RETURN_INT(self->ApplyDamageFactor(type, damage)); +} + void AActor::SetTranslation(FName trname) { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 8acd261f3b..64a62a8225 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -303,6 +303,8 @@ class Actor : Thinker native native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); native Actor RoughMonsterSearch(int distance, bool onlyseekable = false); + native int ApplyDamageFactor(FName damagetype, int damage); + native int GetModifiedDamage(FName damagetype, int damage, bool passive); void A_Light(int extralight) { if (player) player.extralight = clamp(extralight, -20, 20); } void A_Light0() { if (player) player.extralight = 0; } diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 54a2b0ba9c..dab317ea62 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -27,6 +27,8 @@ class Inventory : Actor native virtual native bool Use (bool pickup); virtual native color GetBlend (); + virtual native bool HandlePickup(Inventory item); + virtual native Inventory CreateCopy(Actor other); // These are regular functions for the item itself. diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 2d5be62781..136feb32e1 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -228,6 +228,7 @@ FWeaponSlots weapons; native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false); native bool PoisonPlayer(Actor poisoner, Actor source, int poison); + native PoisonDamage(Actor source, int damage, bool playPainSound) native void SetPsprite(int id, State stat, bool pending = false); native void SetSafeFlash(Weapon weap, State flashstate, int index); native PSprite GetPSprite(int id); From 36f559ecb726cdfe9bbdc11a15970ff3135f34c5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 12:18:06 +0100 Subject: [PATCH 380/471] - fixed bad definition of struct grammar which tried to resolve from right to left, creating large amounts of recursion and strange problems with PlayerInfo. - added a command line option to generate a parser trace file. - fixed a syntax error in player.txt. --- src/scripting/zscript/zcc-parse.lemon | 2 +- src/scripting/zscript/zcc_parser.cpp | 20 +++++++++++--------- wadsrc/static/zscript/shared/player.txt | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index d22746cf89..ccd7e6e845 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -299,7 +299,7 @@ opt_struct_body(X) ::= error. { X = NULL; } struct_body(X) ::= struct_member(X). -struct_body(X) ::= struct_member(A) struct_body(B). { X = A; /*X-overwrites-A*/ AppendTreeNodeSibling(X, B); } +struct_body(X) ::= struct_body(A) struct_member(B). { X = A; /*X-overwrites-A*/ AppendTreeNodeSibling(X, B); } struct_member(X) ::= declarator(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ } diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 9d24d0cb10..989ec10aef 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -302,12 +302,15 @@ static void DoParse(int lumpnum) 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 + + FILE *f = nullptr; + const char *tracefile = Args->CheckValue("-tracefile"); + if (tracefile != nullptr) + { + f = fopen(tracefile, "w"); + char prompt = '\0'; + ZCCParseTrace(f, &prompt); + } sc.OpenLumpNum(lumpnum); auto saved = sc.SavePos(); @@ -341,6 +344,7 @@ static void DoParse(int lumpnum) } } + if (f) fprintf(f, "Starting parsing %s\n", sc.String); ParseSingleFile(sc.String, 0, parser, state); } } @@ -356,12 +360,10 @@ static void DoParse(int lumpnum) I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); } -#ifdef TRACE - if (f != NULL) + if (f != nullptr) { fclose(f); } -#endif // Make a dump of the AST before running the compiler for diagnostic purposes. if (Args->CheckParm("-dumpast")) diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 136feb32e1..c7615e9c20 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -228,7 +228,7 @@ FWeaponSlots weapons; native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false); native bool PoisonPlayer(Actor poisoner, Actor source, int poison); - native PoisonDamage(Actor source, int damage, bool playPainSound) + native void PoisonDamage(Actor source, int damage, bool playPainSound); native void SetPsprite(int id, State stat, bool pending = false); native void SetSafeFlash(Weapon weap, State flashstate, int index); native PSprite GetPSprite(int id); From 3dd323ac0d34abf8d0cd0517e566c2df26453174 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 12:52:54 +0100 Subject: [PATCH 381/471] - scriptified the Flechette. Not fully tested yet. - fixed issues with the refactoring of the recent commits. This one starts again. - added builtins for TextureID. Note about builtins: Currently they are just hacked into the compiler backend. They really should be made part of the respective types to keep matters clean and allow more widespread use of builtins to create more efficient code. --- src/g_hexen/a_flechette.cpp | 455 --------------------- src/g_hexen/a_hexenmisc.cpp | 5 +- src/g_hexen/a_hexenspecialdecs.cpp | 14 - src/g_shared/a_pickups.cpp | 12 +- src/namedef.h | 5 + src/scripting/codegeneration/codegen.cpp | 46 +++ wadsrc/static/zscript/actor.txt | 4 +- wadsrc/static/zscript/hexen/flechette.txt | 375 ++++++++++++++++- wadsrc/static/zscript/shared/inventory.txt | 1 + 9 files changed, 424 insertions(+), 493 deletions(-) delete mode 100644 src/g_hexen/a_flechette.cpp diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp deleted file mode 100644 index 77917c4022..0000000000 --- a/src/g_hexen/a_flechette.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "s_sound.h" -#include "m_random.h" -#include "a_action.h" -#include "a_hexenglobal.h" -#include "w_wad.h" -#include "vm.h" -#include "g_level.h" -*/ - -EXTERN_CVAR(Bool, sv_unlimited_pickup) - -static FRandom pr_poisonbag ("PoisonBag"); -static FRandom pr_poisoncloud ("PoisonCloud"); -static FRandom pr_poisoncloudd ("PoisonCloudDamage"); - -DECLARE_ACTION(A_CheckThrowBomb) - -// Poison Bag Artifact (Flechette) ------------------------------------------ - -IMPLEMENT_CLASS(AArtiPoisonBag, false, false) - -// Poison Bag 1 (The Cleric's) ---------------------------------------------- - -class AArtiPoisonBag1 : public AArtiPoisonBag -{ - DECLARE_CLASS (AArtiPoisonBag1, AArtiPoisonBag) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiPoisonBag1, false, false) - -bool AArtiPoisonBag1::Use (bool pickup) -{ - AActor *mo = Spawn("PoisonBag", Owner->Vec3Offset( - 16 * Owner->Angles.Yaw.Cos(), - 24 * Owner->Angles.Yaw.Sin(), - -Owner->Floorclip + 8), ALLOW_REPLACE); - if (mo) - { - mo->target = Owner; - return true; - } - return false; -} - -// Poison Bag 2 (The Mage's) ------------------------------------------------ - -class AArtiPoisonBag2 : public AArtiPoisonBag -{ - DECLARE_CLASS (AArtiPoisonBag2, AArtiPoisonBag) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiPoisonBag2, false, false) - -bool AArtiPoisonBag2::Use (bool pickup) -{ - AActor *mo = Spawn("FireBomb", Owner->Vec3Offset( - 16 * Owner->Angles.Yaw.Cos(), - 24 * Owner->Angles.Yaw.Sin(), - -Owner->Floorclip + 8), ALLOW_REPLACE); - if (mo) - { - mo->target = Owner; - return true; - } - return false; -} - -// Poison Bag 3 (The Fighter's) --------------------------------------------- - -class AArtiPoisonBag3 : public AArtiPoisonBag -{ - DECLARE_CLASS (AArtiPoisonBag3, AArtiPoisonBag) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiPoisonBag3, false, false) - -bool AArtiPoisonBag3::Use (bool pickup) -{ - AActor *mo; - - mo = Spawn("ThrowingBomb", Owner->PosPlusZ(35. - Owner->Floorclip + (Owner->player? Owner->player->crouchoffset : 0)), ALLOW_REPLACE); - if (mo) - { - mo->Angles.Yaw = Owner->Angles.Yaw + (((pr_poisonbag() & 7) - 4) * (360./256.)); - - /* Original flight code from Hexen - * mo->momz = 4*F.RACUNIT+((player->lookdir)<<(F.RACBITS-4)); - * mo->z += player->lookdir<<(F.RACBITS-4); - * P_ThrustMobj(mo, mo->angle, mo->info->speed); - * mo->momx += player->mo->momx>>1; - * mo->momy += player->mo->momy>>1; - */ - - // When looking straight ahead, it uses a z velocity of 4 while the xy velocity - // is as set by the projectile. To accommodate this with a proper trajectory, we - // aim the projectile ~20 degrees higher than we're looking at and increase the - // speed we fire at accordingly. - DAngle orgpitch = -Owner->Angles.Pitch; - DAngle modpitch = clamp(-Owner->Angles.Pitch + 20, -89., 89.); - DAngle angle = mo->Angles.Yaw; - double speed = DVector2(mo->Speed, 4.).Length(); - double xyscale = speed * modpitch.Cos(); - - mo->Vel.Z = speed * modpitch.Sin(); - mo->Vel.X = xyscale * angle.Cos() + Owner->Vel.X / 2; - mo->Vel.Y = xyscale * angle.Sin() + Owner->Vel.Y / 2; - mo->AddZ(mo->Speed * orgpitch.Sin()); - - mo->target = Owner; - mo->tics -= pr_poisonbag()&3; - P_CheckMissileSpawn(mo, Owner->radius); - return true; - } - return false; -} - -// Poison Bag 4 (Generic Giver) ---------------------------------------------- - -class AArtiPoisonBagGiver : public AArtiPoisonBag -{ - DECLARE_CLASS (AArtiPoisonBagGiver, AArtiPoisonBag) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiPoisonBagGiver, false, false) - -bool AArtiPoisonBagGiver::Use (bool pickup) -{ - PClassActor *missiletype = PClass::FindActor(this->GetClass()->MissileName); - if (missiletype != NULL) - { - AActor *mo = Spawn (missiletype, Owner->Pos(), ALLOW_REPLACE); - if (mo != NULL) - { - if (mo->IsKindOf(RUNTIME_CLASS(AInventory))) - { - AInventory *inv = static_cast(mo); - if (inv->CallTryPickup(Owner)) - return true; - } - mo->Destroy(); // Destroy if not inventory or couldn't be picked up - } - } - return false; -} - -// Poison Bag 5 (Generic Thrower) ---------------------------------------------- - -class AArtiPoisonBagShooter : public AArtiPoisonBag -{ - DECLARE_CLASS (AArtiPoisonBagShooter, AArtiPoisonBag) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiPoisonBagShooter, false, false) - -bool AArtiPoisonBagShooter::Use (bool pickup) -{ - PClassActor *missiletype = PClass::FindActor(this->GetClass()->MissileName); - if (missiletype != NULL) - { - AActor *mo = P_SpawnPlayerMissile(Owner, missiletype); - if (mo != NULL) - { - // automatic handling of seeker missiles - if (mo->flags2 & MF2_SEEKERMISSILE) - { - mo->tracer = Owner->target; - } - return true; - } - } - return false; -} - -//============================================================================ -// -// GetFlechetteType -// -//============================================================================ - -PClassActor *GetFlechetteType(AActor *other) -{ - PClassActor *spawntype = NULL; - if (other->IsKindOf(RUNTIME_CLASS(APlayerPawn))) - { - spawntype = static_cast(other)->FlechetteType; - } - if (spawntype == NULL) - { - // default fallback if nothing valid defined. - spawntype = RUNTIME_CLASS(AArtiPoisonBag3); - } - return spawntype; -} - -//============================================================================ -// -// AArtiPoisonBag :: HandlePickup -// -//============================================================================ - -bool AArtiPoisonBag::HandlePickup (AInventory *item) -{ - // Only do special handling when picking up the base class - if (item->GetClass() != RUNTIME_CLASS(AArtiPoisonBag)) - { - return Super::HandlePickup (item); - } - - if (GetClass() == GetFlechetteType(Owner)) - { - if (Amount < MaxAmount || sv_unlimited_pickup) - { - Amount += item->Amount; - if (Amount > MaxAmount && !sv_unlimited_pickup) - { - Amount = MaxAmount; - } - item->ItemFlags |= IF_PICKUPGOOD; - } - return true; - } - if (Inventory != NULL) - { - return Inventory->HandlePickup (item); - } - return false; -} - -//============================================================================ -// -// AArtiPoisonBag :: CreateCopy -// -//============================================================================ - -AInventory *AArtiPoisonBag::CreateCopy (AActor *other) -{ - // Only the base class gets special handling - if (GetClass() != RUNTIME_CLASS(AArtiPoisonBag)) - { - return Super::CreateCopy (other); - } - - AInventory *copy; - PClassActor *spawntype = GetFlechetteType(other); - copy = static_cast(Spawn (spawntype)); - copy->Amount = Amount; - copy->MaxAmount = MaxAmount; - GoAwayAndDie (); - return copy; -} - -//============================================================================ -// -// AArtiPoisonBag :: BeginPlay -// -//============================================================================ - -void AArtiPoisonBag::BeginPlay () -{ - Super::BeginPlay (); - // If a subclass's specific icon is not defined, let it use the base class's. - if (!Icon.isValid()) - { - AInventory *defbag; - // Why doesn't this work? - //defbag = GetDefault(); - defbag = (AInventory *)GetDefaultByType (RUNTIME_CLASS(AArtiPoisonBag)); - Icon = defbag->Icon; - } -} - -// Poison Cloud ------------------------------------------------------------- - -class APoisonCloud : public AActor -{ - DECLARE_CLASS (APoisonCloud, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); - void BeginPlay (); -}; - -IMPLEMENT_CLASS(APoisonCloud, false, false) - -void APoisonCloud::BeginPlay () -{ - Vel.X = MinVel; // missile objects must move to impact other objects - special1 = 24+(pr_poisoncloud()&7); - special2 = 0; -} - -int APoisonCloud::DoSpecialDamage (AActor *victim, int damage, FName damagetype) -{ - if (victim->player) - { - bool mate = (target != NULL && victim->player != target->player && victim->IsTeammate (target)); - bool dopoison; - - if (!mate) - { - dopoison = victim->player->poisoncount < 4; - } - else - { - dopoison = victim->player->poisoncount < (int)(4. * level.teamdamage); - } - - if (dopoison) - { - int damage = 15 + (pr_poisoncloudd()&15); - if (mate) - { - damage = (int)(damage * level.teamdamage); - } - // Handle passive damage modifiers (e.g. PowerProtection) - if (victim->Inventory != NULL) - { - victim->Inventory->ModifyDamage(damage, damagetype, damage, true); - } - // Modify with damage factors - damage = victim->ApplyDamageFactor(damagetype, damage); - if (damage > 0) - { - P_PoisonDamage (victim->player, this, - 15+(pr_poisoncloudd()&15), false); // Don't play painsound - - // If successful, play the poison sound. - if (P_PoisonPlayer (victim->player, this, this->target, 50)) - S_Sound (victim, CHAN_VOICE, "*poison", 1, ATTN_NORM); - } - } - return -1; - } - else if (!(victim->flags3 & MF3_ISMONSTER)) - { // only damage monsters/players with the poison cloud - return -1; - } - return damage; -} - -//=========================================================================== -// -// A_PoisonBagInit -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagInit) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - mo = Spawn (self->PosPlusZ(28.), ALLOW_REPLACE); - if (mo) - { - mo->target = self->target; - } - return 0; -} - -//=========================================================================== -// -// A_PoisonBagCheck -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagCheck) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (--self->special1 <= 0) - { - self->SetState (self->FindState ("Death")); - } - else - { - return 0; - } - return 0; -} - -//=========================================================================== -// -// A_PoisonBagDamage -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_PoisonBagDamage) -{ - PARAM_SELF_PROLOGUE(AActor); - - int bobIndex; - - P_RadiusAttack (self, self->target, 4, 40, self->DamageType, RADF_HURTSOURCE); - bobIndex = self->special2; - self->AddZ(BobSin(bobIndex) / 16); - self->special2 = (bobIndex + 1) & 63; - return 0; -} - -//=========================================================================== -// -// A_CheckThrowBomb -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_CheckThrowBomb) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (--self->health <= 0) - { - self->SetState (self->FindState(NAME_Death)); - } - return 0; -} - -//=========================================================================== -// -// A_CheckThrowBomb2 -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_CheckThrowBomb2) -{ - 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.)) - { - self->SetState (self->SpawnState + 6); - self->SetZ(self->floorz); - self->Vel.Z = 0; - self->BounceFlags = BOUNCE_None; - self->flags &= ~MF_MISSILE; - } - CALL_ACTION(A_CheckThrowBomb, self); - return 0; -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 3223575c81..ae4399526f 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -1,11 +1,10 @@ -#include "actor.h" +#include "d_player.h" #include "info.h" #include "p_local.h" #include "s_sound.h" #include "a_action.h" #include "m_random.h" #include "a_sharedglobal.h" -#include "a_hexenglobal.h" #include "i_system.h" #include "gi.h" #include "g_level.h" @@ -22,9 +21,9 @@ #include "p_maputl.h" #include "p_spec.h" #include "serializer.h" +#include "a_pickups.h" // Include all the Hexen stuff here to reduce compile time -#include "a_flechette.cpp" #include "a_flies.cpp" #include "a_heresiarch.cpp" #include "a_hexenspecialdecs.cpp" diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index 1745e6efc4..899d9326d0 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -264,20 +264,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_LeafCheck) return 0; } -//=========================================================================== -// -// A_PoisonShroom -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_PoisonShroom) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->tics = 128 + (pr_shroom() << 1); - return 0; -} - //=========================================================================== // // A_SoAExplode - Suit of Armor Explode diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index a57d90bcd6..2172d2a0cc 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -729,7 +729,7 @@ bool AInventory::CallHandlePickup(AInventory *item) auto self = this; while (self != nullptr) { - IFVIRTUAL(AActor, HandlePickup) + IFVIRTUAL(AInventory, HandlePickup) { // Without the type cast this picks the 'void *' assignment... VMValue params[2] = { (DObject*)self, (DObject*)item }; @@ -794,6 +794,14 @@ void AInventory::GoAwayAndDie () } } +DEFINE_ACTION_FUNCTION(AInventory, GoAwayAndDie) +{ + PARAM_SELF_PROLOGUE(AInventory); + self->GoAwayAndDie(); + return 0; +} + + //=========================================================================== // // AInventory :: CreateCopy @@ -831,7 +839,7 @@ DEFINE_ACTION_FUNCTION(AInventory, CreateCopy) AInventory *AInventory::CallCreateCopy(AActor *other) { - IFVIRTUAL(AActor, CreateCopy) + IFVIRTUAL(AInventory, CreateCopy) { VMValue params[2] = { (DObject*)this, (DObject*)other }; VMReturn ret; diff --git a/src/namedef.h b/src/namedef.h index 779c2e1329..413b681245 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -746,6 +746,11 @@ xx(StateLabel) xx(SpriteID) xx(TextureID) xx(Overlay) +xx(IsValid) +xx(IsNull) +xx(Exists) +xx(SetInvalid) +xx(SetNull) xx(A_Punch) xx(A_FirePistol) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 1e06f5751b..72d79647f0 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -7192,6 +7192,52 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } } + // Note: These builtins would better be relegated to the actual type objects, instead of polluting this file, but that's a task for later. + + // Texture builtins. + if (Self->ValueType == TypeTextureID) + { + if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull) + { + if (ArgList.Size() > 0) + { + ScriptPosition.Message(MSG_ERROR, "too many parameters in call to %s", MethodName.GetChars()); + delete this; + return nullptr; + } + // No need to create a dedicated node here, all builtins map directly to trivial operations. + Self->ValueType = TypeSInt32; // all builtins treat the texture index as integer. + FxExpression *x; + switch (MethodName) + { + case NAME_IsValid: + x = new FxCompareRel('>', Self, new FxConstant(0, ScriptPosition)); + break; + + case NAME_IsNull: + x = new FxCompareEq(TK_Eq, Self, new FxConstant(0, ScriptPosition)); + break; + + case NAME_Exists: + x = new FxCompareRel(TK_Geq, Self, new FxConstant(0, ScriptPosition)); + break; + + case NAME_SetInvalid: + x = new FxAssign(Self, new FxConstant(-1, ScriptPosition)); + break; + + case NAME_SetNull: + x = new FxAssign(Self, new FxConstant(0, ScriptPosition)); + break; + } + Self = nullptr; + SAFE_RESOLVE(x, ctx); + if (MethodName == NAME_SetInvalid || MethodName == NAME_SetNull) x->ValueType = TypeVoid; // override the default type of the assignment operator. + delete this; + return x; + } + } + if (Self->IsVector()) { // handle builtins: Vectors got 2: Length and Unit. diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 64a62a8225..884bcc8a52 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -303,8 +303,8 @@ class Actor : Thinker native native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); native Actor RoughMonsterSearch(int distance, bool onlyseekable = false); - native int ApplyDamageFactor(FName damagetype, int damage); - native int GetModifiedDamage(FName damagetype, int damage, bool passive); + native int ApplyDamageFactor(Name damagetype, int damage); + native int GetModifiedDamage(Name damagetype, int damage, bool passive); void A_Light(int extralight) { if (player) player.extralight = clamp(extralight, -20, 20); } void A_Light0() { if (player) player.extralight = 0; } diff --git a/wadsrc/static/zscript/hexen/flechette.txt b/wadsrc/static/zscript/hexen/flechette.txt index c024770640..f8f6a0b8a3 100644 --- a/wadsrc/static/zscript/hexen/flechette.txt +++ b/wadsrc/static/zscript/hexen/flechette.txt @@ -10,8 +10,6 @@ class PoisonBag : Actor +NOBLOCKMAP +NOGRAVITY } - native void A_PoisonBagInit(); - States { Spawn: @@ -21,6 +19,21 @@ class PoisonBag : Actor PSBG C 1 A_PoisonBagInit; Stop; } + + //=========================================================================== + // + // A_PoisonBagInit + // + //=========================================================================== + + void A_PoisonBagInit() + { + Actor mo = Spawn("PoisonCloud", (pos.xy, 28), ALLOW_REPLACE); + if (mo) + { + mo.target = target; + } + } } // Fire Bomb (Flechette used by Mage) --------------------------------------- @@ -74,9 +87,6 @@ class ThrowingBomb : Actor DeathSound "FlechetteExplode"; } - native void A_CheckThrowBomb(); - native void A_CheckThrowBomb2(); - States { Spawn: @@ -84,6 +94,7 @@ class ThrowingBomb : Actor THRW BCDE 3 A_CheckThrowBomb; THRW F 3 A_CheckThrowBomb2; Loop; + Tail: THRW G 6 A_CheckThrowBomb; THRW F 4 A_CheckThrowBomb; THRW H 6 A_CheckThrowBomb; @@ -102,11 +113,46 @@ class ThrowingBomb : Actor CFCF Z 3 Bright; Stop; } + + //=========================================================================== + // + // A_CheckThrowBomb + // + //=========================================================================== + + void A_CheckThrowBomb() + { + if (--health <= 0) + { + SetStateLabel("Death"); + } + } + + //=========================================================================== + // + // A_CheckThrowBomb2 + // + //=========================================================================== + + void A_CheckThrowBomb2() + { + // [RH] Check using actual velocity, although the vel.z < 2 check still stands + if (Vel.Z < 2 && Vel.Length() < 1.5) + { + SetStateLabel("Tail"); + SetZ(floorz); + Vel.Z = 0; + ClearBounce(); + bMissile = false; + } + A_CheckThrowBomb(); + } + } // Poison Bag Artifact (Flechette) ------------------------------------------ -class ArtiPoisonBag : Inventory native +class ArtiPoisonBag : Inventory { Default { @@ -125,64 +171,262 @@ class ArtiPoisonBag : Inventory native PSBG A -1; Stop; } + + //============================================================================ + // + // AArtiPoisonBag :: BeginPlay + // + //============================================================================ + + override void BeginPlay () + { + Super.BeginPlay (); + // If a subclass's specific icon is not defined, let it use the base class's. + if (!Icon.isValid()) + { + Inventory defbag = Inventory(GetDefaultByType("ArtiPoisonBag")); + Icon = defbag.Icon; + } + } + + //============================================================================ + // + // GetFlechetteType + // + //============================================================================ + + private class GetFlechetteType(Actor other) + { + class spawntype = null; + PlayerPawn pp = PlayerPawn(other); + if (pp) + { + spawntype = pp.FlechetteType; + } + if (spawntype == null) + { + // default fallback if nothing valid defined. + spawntype = "ArtiPoisonBag3"; + } + return spawntype; + } + + //============================================================================ + // + // AArtiPoisonBag :: HandlePickup + // + //============================================================================ + + override bool HandlePickup (Inventory item) + { + // Only do special handling when picking up the base class + if (item.GetClass() != "ArtiPoisonBag") + { + return Super.HandlePickup (item); + } + + if (GetClass() == GetFlechetteType(Owner)) + { + if (Amount < MaxAmount || sv_unlimited_pickup) + { + Amount += item.Amount; + if (Amount > MaxAmount && !sv_unlimited_pickup) + { + Amount = MaxAmount; + } + item.bPickupGood = true; + } + return true; + } + return false; + } + + //============================================================================ + // + // AArtiPoisonBag :: CreateCopy + // + //============================================================================ + + override Inventory CreateCopy (Actor other) + { + // Only the base class gets special handling + if (GetClass() != "ArtiPoisonBag") + { + return Super.CreateCopy (other); + } + + class spawntype = GetFlechetteType(other); + Inventory copy = Inventory(Spawn (spawntype)); + copy.Amount = Amount; + copy.MaxAmount = MaxAmount; + GoAwayAndDie (); + return copy; + } } // Poison Bag 1 (The Cleric's) ---------------------------------------------- -class ArtiPoisonBag1 : ArtiPoisonBag native +class ArtiPoisonBag1 : ArtiPoisonBag { Default { Inventory.Icon "ARTIPSB1"; Tag "$TAG_ARTIPOISONBAG1"; } + + override bool Use (bool pickup) + { + Actor mo = Spawn("PoisonBag", Owner.Vec3Offset( + 16 * cos(Owner.angle), + 24 * sin(Owner.angle), + -Owner.Floorclip + 8), ALLOW_REPLACE); + if (mo) + { + mo.target = Owner; + return true; + } + return false; + } + } // Poison Bag 2 (The Mage's) ------------------------------------------------ -class ArtiPoisonBag2 : ArtiPoisonBag native +class ArtiPoisonBag2 : ArtiPoisonBag { Default { Inventory.Icon "ARTIPSB2"; Tag "$TAG_ARTIPOISONBAG2"; } + + override bool Use (bool pickup) + { + Actor mo = Spawn("FireBomb", Owner.Vec3Offset( + 16 * cos(Owner.angle), + 24 * sin(Owner.angle), + -Owner.Floorclip + 8), ALLOW_REPLACE); + if (mo) + { + mo.target = Owner; + return true; + } + return false; + } + } // Poison Bag 3 (The Fighter's) --------------------------------------------- -class ArtiPoisonBag3 : ArtiPoisonBag native +class ArtiPoisonBag3 : ArtiPoisonBag { Default { Inventory.Icon "ARTIPSB3"; Tag "$TAG_ARTIPOISONBAG3"; } + + override bool Use (bool pickup) + { + Actor mo = Spawn("ThrowingBomb", Owner.Pos + (0,0,35. - Owner.Floorclip + (Owner.player? Owner.player.crouchoffset : 0)), ALLOW_REPLACE); + if (mo) + { + mo.angle = Owner.angle + (((random[PoisonBag]() & 7) - 4) * (360./256.)); + + /* Original flight code from Hexen + * mo.momz = 4*F.RACUNIT+((player.lookdir)<<(F.RACBITS-4)); + * mo.z += player.lookdir<<(F.RACBITS-4); + * P_ThrustMobj(mo, mo.ang, mo.info.speed); + * mo.momx += player.mo.momx>>1; + * mo.momy += player.mo.momy>>1; + */ + + // When looking straight ahead, it uses a z velocity of 4 while the xy velocity + // is as set by the projectile. To accommodate self with a proper trajectory, we + // aim the projectile ~20 degrees higher than we're looking at and increase the + // speed we fire at accordingly. + double orgpitch = -Owner.Pitch; + double modpitch = clamp(-Owner.Pitch + 20, -89., 89.); + double ang = mo.angle; + double speed = (mo.Speed, 4.).Length(); + double xyscale = speed * cos(modpitch); + + mo.Vel.Z = speed * sin(modpitch); + mo.Vel.X = xyscale * cos(ang) + Owner.Vel.X / 2; + mo.Vel.Y = xyscale * sin(ang) + Owner.Vel.Y / 2; + mo.AddZ(mo.Speed * sin(modpitch)); + + mo.target = Owner; + mo.tics -= random[PoisonBag]()&3; + mo.CheckMissileSpawn(Owner.radius); + return true; + } + return false; + } + + } // Poison Bag 4 (Custom Giver) ---------------------------------------------- -class ArtiPoisonBagGiver : ArtiPoisonBag native +class ArtiPoisonBagGiver : ArtiPoisonBag { Default { Inventory.Icon "ARTIPSB4"; } + + override bool Use (bool pickup) + { + Class missiletype = MissileName; + if (missiletype != null) + { + Actor mo = Spawn (missiletype, Owner.Pos, ALLOW_REPLACE); + if (mo != null) + { + Inventory inv = Inventory(mo); + if (inv && inv.CallTryPickup(Owner)) return true; + mo.Destroy(); // Destroy if not inventory or couldn't be picked up + } + } + return false; + } + } // Poison Bag 5 (Custom Thrower) -------------------------------------------- -class ArtiPoisonBagShooter : ArtiPoisonBag native +class ArtiPoisonBagShooter : ArtiPoisonBag { Default { Inventory.Icon "ARTIPSB5"; } + + override bool Use (bool pickup) + { + Class missiletype = MissileName; + if (missiletype != null) + { + Actor mo = Owner.SpawnPlayerMissile(missiletype); + if (mo != null) + { + // automatic handling of seeker missiles + if (mo.bSeekerMissile) + { + mo.tracer = Owner.target; + } + return true; + } + } + return false; + } + } // Poison Cloud ------------------------------------------------------------- -class PoisonCloud : Actor native +class PoisonCloud : Actor { Default { @@ -198,9 +442,6 @@ class PoisonCloud : Actor native DamageType "PoisonCloud"; } - native void A_PoisonBagDamage(); - native void A_PoisonBagCheck(); - States { Spawn: @@ -215,6 +456,97 @@ class PoisonCloud : Actor native PSBG FD 6; Stop; } + + //=========================================================================== + // + // + // + //=========================================================================== + + override void BeginPlay () + { + Vel.X = MinVel; // missile objects must move to impact other objects + special1 = 24+(random[PoisonCloud]() & 7); + special2 = 0; + } + + //=========================================================================== + // + // + // + //=========================================================================== + + override int DoSpecialDamage (Actor victim, int damage, Name damagetype) + { + if (victim.player) + { + bool mate = (target != null && victim.player != target.player && victim.IsTeammate (target)); + bool dopoison; + + if (!mate) + { + dopoison = victim.player.poisoncount < 4; + } + else + { + dopoison = victim.player.poisoncount < (int)(4. * level.teamdamage); + } + + if (dopoison) + { + int damage = 15 + (random[PoisonCloud]()&15); + if (mate) + { + damage = (int)(damage * level.teamdamage); + } + // Handle passive damage modifiers (e.g. PowerProtection) + damage = victim.GetModifiedDamage(damagetype, damage, true); + // Modify with damage factors + damage = victim.ApplyDamageFactor(damagetype, damage); + if (damage > 0) + { + victim.player.PoisonDamage (self, 15 + (random[PoisonCloud]() & 15), false); // Don't play painsound + + // If successful, play the poison sound. + if (victim.player.PoisonPlayer (self, self.target, 50)) + victim.A_PlaySound ("*poison", CHAN_VOICE); + } + } + return -1; + } + else if (!victim.bIsMonster) + { // only damage monsters/players with the poison cloud + return -1; + } + return damage; + } + + //=========================================================================== + // + // A_PoisonBagCheck + // + //=========================================================================== + + void A_PoisonBagCheck() + { + if (--special1 <= 0) + { + SetStateLabel("Death"); + } + } + + //=========================================================================== + // + // A_PoisonBagDamage + // + //=========================================================================== + + void A_PoisonBagDamage() + { + A_Explode(4, 40); + AddZ(BobSin(special2) / 16); + special2 = (special2 + 1) & 63; + } } // Poison Shroom ------------------------------------------------------------ @@ -238,8 +570,6 @@ class ZPoisonShroom : PoisonBag DeathSound "PoisonShroomDeath"; } - native void A_PoisonShroom(); - States { Spawn: @@ -255,5 +585,16 @@ class ZPoisonShroom : PoisonBag SHRM F -1; Stop; } + + //=========================================================================== + // + // A_PoisonShroom + // + //=========================================================================== + + void A_PoisonShroom() + { + tics = 128 + (random[PoisonShroom]() << 1); + } } diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index dab317ea62..25c94cb87a 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -30,6 +30,7 @@ class Inventory : Actor native virtual native bool HandlePickup(Inventory item); virtual native Inventory CreateCopy(Actor other); + native void GoAwayAndDie(); // These are regular functions for the item itself. private native void A_RestoreSpecialDoomThing(); From f409a24d2d0ee06c5adb9de9c509724ef05c0232 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 15:50:58 +0100 Subject: [PATCH 382/471] - fixed: Readonly pointers never were flagged as such. - fixed: Assignment from a readonly to a read-allowed pointer must be an error. - made GetDefaultByType a builtin so that it can do proper type assignment to the result, which for a function would be problematic in this case, even if automatic type deduction was implemented. Since this returns the class defaults which are not a real object, the result cannot be subjected to a type cast. - error out if a type cast of a readonly pointer is attempted. - fixed: FxBooleanNot could clobber a local variable because it used the source register to manipulate the result. --- src/dobjtype.cpp | 2 +- src/namedef.h | 1 + src/scripting/codegeneration/codegen.cpp | 100 +++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 19 ++++ src/scripting/vm/vmframe.cpp | 2 +- wadsrc/static/zscript/actor.txt | 3 +- wadsrc/static/zscript/hexen/flechette.txt | 11 ++- 7 files changed, 125 insertions(+), 13 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index e9f574ea43..88c31d0078 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1688,7 +1688,7 @@ PPointer *NewPointer(PType *type, bool isconst) PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, &bucket); if (ptype == NULL) { - ptype = new PPointer(type); + ptype = new PPointer(type, isconst); TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, bucket); } return static_cast(ptype); diff --git a/src/namedef.h b/src/namedef.h index 413b681245..3a4a1c1800 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -286,6 +286,7 @@ xx(Random2) xx(RandomPick) xx(FRandomPick) xx(GetClass) +xx(GetDefaultByType) xx(Exp) xx(Log10) xx(Ceil) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 72d79647f0..db09a0387a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -262,7 +262,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar auto fromtype = static_cast(source); auto totype = static_cast(dest); if (fromtype == nullptr) return true; - if (!forcompare && totype->IsConst && !fromtype->IsConst) return false; + if (!forcompare && totype->IsConst != fromtype->IsConst) return false; if (fromtype == totype) return true; if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass))) { @@ -1874,10 +1874,13 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) assert(Operand->ValueType == TypeBool); assert(ValueType == TypeBool || IsInteger()); // this may have been changed by an int cast. ExpEmit from = Operand->Emit(build); + from.Free(build); + ExpEmit to(build, REGT_INT); 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; + + build->Emit(OP_XOR_RK, to.RegNum, from.RegNum, build->GetConstantInt(1)); + return to; } //========================================================================== @@ -4309,7 +4312,18 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); SAFE_RESOLVE(expr, ctx); + if (expr->ExprType == EFX_GetDefaultByType) + { + int a = 0; + } bool constflag = expr->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(expr->ValueType)->IsConst; + if (constflag) + { + // readonly pointers are normally only used for class defaults which lack type information to be cast properly, so we have to error out here. + ScriptPosition.Message(MSG_ERROR, "Cannot cast a readonly pointer"); + delete this; + return nullptr; + } expr = new FxTypeCast(expr, NewPointer(RUNTIME_CLASS(DObject), constflag), true, true); expr = expr->Resolve(ctx); if (expr == nullptr) @@ -7012,6 +7026,14 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } break; + case NAME_GetDefaultByType: + if (CheckArgSize(NAME_GetDefaultByType, ArgList, 1, 1, ScriptPosition)) + { + func = new FxGetDefaultByType(ArgList[0]); + ArgList[0] = nullptr; + } + break; + case NAME_Random: // allow calling Random without arguments to default to (0, 255) if (ArgList.Size() == 0) @@ -8147,6 +8169,78 @@ ExpEmit FxGetClass::Emit(VMFunctionBuilder *build) // //========================================================================== +FxGetDefaultByType::FxGetDefaultByType(FxExpression *self) + :FxExpression(EFX_GetDefaultByType, self->ScriptPosition) +{ + Self = self; +} + +FxGetDefaultByType::~FxGetDefaultByType() +{ + SAFE_DELETE(Self); +} + +FxExpression *FxGetDefaultByType::Resolve(FCompileContext &ctx) +{ + SAFE_RESOLVE(Self, ctx); + PClass *cls = nullptr; + + if (Self->ValueType == TypeString || Self->ValueType == TypeName) + { + if (Self->isConstant()) + { + cls = PClass::FindActor(static_cast(Self)->GetValue().GetName()); + if (cls == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type, but got %s", static_cast(Self)->GetValue().GetString().GetChars()); + delete this; + return nullptr; + } + Self = new FxConstant(cls, NewClassPointer(cls), ScriptPosition); + } + else + { + // this is the ugly case. We do not know what we have and cannot do proper type casting. + // For now error out and let this case require explicit handling on the user side. + ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type", static_cast(Self)->GetValue().GetString().GetChars()); + delete this; + return nullptr; + } + } + else + { + auto cp = dyn_cast(Self->ValueType); + if (cp == nullptr || !cp->ClassRestriction->IsDescendantOf(RUNTIME_CLASS(AActor))) + { + ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type"); + delete this; + return nullptr; + } + cls = cp->ClassRestriction; + } + ValueType = NewPointer(cls, true); + return this; +} + +ExpEmit FxGetDefaultByType::Emit(VMFunctionBuilder *build) +{ + ExpEmit op = Self->Emit(build); + op.Free(build); + ExpEmit to(build, REGT_POINTER); + if (op.Konst) + { + build->Emit(OP_LKP, to.RegNum, op.RegNum); + op = to; + } + build->Emit(OP_LO, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults))); + return to; +} + +//========================================================================== +// +// +//========================================================================== + FxColorLiteral::FxColorLiteral(FArgumentList &args, FScriptPosition &sc) :FxExpression(EFX_ColorLiteral, sc) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index ae0581e05b..e586f1fbe3 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -289,6 +289,7 @@ enum EFxType EFX_NamedNode, EFX_GetClass, EFX_ColorLiteral, + EFX_GetDefaultByType, EFX_COUNT }; @@ -1542,6 +1543,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxFlopFunctionCall +// +//========================================================================== + +class FxGetDefaultByType : public FxExpression +{ + FxExpression *Self; + +public: + + FxGetDefaultByType(FxExpression *self); + ~FxGetDefaultByType(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxColorLiteral diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 0ec6ec15b6..428266d0fa 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -424,7 +424,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur { bool allocated = false; try - { + { if (func->Native) { return static_cast(func)->NativeCall(this, params, func->DefaultArgs, numparams, results, numresults); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 884bcc8a52..739b5574fc 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -238,7 +238,7 @@ class Actor : Thinker native VisiblePitch 0, 0; DefaultStateUsage SUF_ACTOR|SUF_OVERLAY; } - + // Functions // 'parked' global functions. @@ -268,7 +268,6 @@ class Actor : Thinker native virtual native bool SpecialBlastHandling (Actor source, double strength); - native static readonly GetDefaultByType(class cls); native static double GetDefaultSpeed(class type); native void RemoveFromHash(); native string GetTag(string defstr = ""); diff --git a/wadsrc/static/zscript/hexen/flechette.txt b/wadsrc/static/zscript/hexen/flechette.txt index f8f6a0b8a3..fc9268c5b0 100644 --- a/wadsrc/static/zscript/hexen/flechette.txt +++ b/wadsrc/static/zscript/hexen/flechette.txt @@ -28,7 +28,7 @@ class PoisonBag : Actor void A_PoisonBagInit() { - Actor mo = Spawn("PoisonCloud", (pos.xy, 28), ALLOW_REPLACE); + Actor mo = Spawn("PoisonCloud", pos + (0, 0, 28), ALLOW_REPLACE); if (mo) { mo.target = target; @@ -184,8 +184,7 @@ class ArtiPoisonBag : Inventory // If a subclass's specific icon is not defined, let it use the base class's. if (!Icon.isValid()) { - Inventory defbag = Inventory(GetDefaultByType("ArtiPoisonBag")); - Icon = defbag.Icon; + Icon = GetDefaultByType("ArtiPoisonBag").Icon; } } @@ -469,7 +468,7 @@ class PoisonCloud : Actor special1 = 24+(random[PoisonCloud]() & 7); special2 = 0; } - + //=========================================================================== // // @@ -482,7 +481,7 @@ class PoisonCloud : Actor { bool mate = (target != null && victim.player != target.player && victim.IsTeammate (target)); bool dopoison; - + if (!mate) { dopoison = victim.player.poisoncount < 4; @@ -494,7 +493,7 @@ class PoisonCloud : Actor if (dopoison) { - int damage = 15 + (random[PoisonCloud]()&15); + damage = 15 + (random[PoisonCloud]() & 15); if (mate) { damage = (int)(damage * level.teamdamage); From aab304c0cf651f92c8db5500534be97b3224636d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 17:43:11 +0100 Subject: [PATCH 383/471] - fixed: Lemon includes ParseTrace only in debug builds so the option to use it must be #ifdef'd. --- src/scripting/zscript/zcc_parser.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 989ec10aef..3b2ada4c8c 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -303,6 +303,7 @@ static void DoParse(int lumpnum) parser = ZCCParseAlloc(malloc); ZCCParseState state; +#ifndef NDEBUG FILE *f = nullptr; const char *tracefile = Args->CheckValue("-tracefile"); if (tracefile != nullptr) @@ -311,6 +312,7 @@ static void DoParse(int lumpnum) char prompt = '\0'; ZCCParseTrace(f, &prompt); } +#endif sc.OpenLumpNum(lumpnum); auto saved = sc.SavePos(); @@ -360,10 +362,12 @@ static void DoParse(int lumpnum) I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); } +#ifndef NDEBUG if (f != nullptr) { fclose(f); } +#endif // Make a dump of the AST before running the compiler for diagnostic purposes. if (Args->CheckParm("-dumpast")) From de6969997aa088b5d3566be321e0bd835de5b8dd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 18:52:24 +0100 Subject: [PATCH 384/471] - scriptified Hexen's flies. A few notes: * this accesses the lines array in sector_t which effectively is a pointer to an array of pointers - a type the parser can not represent. The compiler has no problems with it, so for now it is defined internally. * array sizes were limited to 65536 entries because the 'bound' instruction only existed as an immediate version with no provisions for larger values. For the static map arrays 65536 is not sufficient so now there are alternative instructions for these cases. * despite the above, at the moment there is no proper bounds checking for arrays that have no fixed size. To do this, a lot more work is needed. The type system as-is is not prepared for such a scenario. --- src/p_mobj.cpp | 1 + src/p_sectors.cpp | 16 ++++ src/r_defs.h | 2 - src/scripting/codegeneration/codegen.cpp | 98 +++++++++++++-------- src/scripting/codegeneration/codegen.h | 1 + src/scripting/thingdef_data.cpp | 12 ++- src/scripting/vm/vmbuilder.cpp | 2 +- src/scripting/vm/vmdisasm.cpp | 1 - src/scripting/vm/vmexec.h | 21 +++++ src/scripting/vm/vmops.h | 2 + src/scripting/zscript/zcc_parser.cpp | 2 + wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/base.txt | 21 ++++- wadsrc/static/zscript/hexen/flies.txt | 106 ++++++++++++++++++++++- 14 files changed, 241 insertions(+), 45 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index ad1c317e8b..358e46e8c1 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -154,6 +154,7 @@ AActor::~AActor () extern FFlagDef InternalActorFlagDefs[]; extern FFlagDef ActorFlagDefs[]; +DEFINE_FIELD(AActor, snext) DEFINE_FIELD(AActor, player) DEFINE_FIELD_NAMED(AActor, __Pos, pos) DEFINE_FIELD_NAMED(AActor, __Pos.X, x) diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 841401226a..585c60f4bb 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -1310,3 +1310,19 @@ DEFINE_FIELD_X(Sector, sector_t, SecActTarget) DEFINE_FIELD_X(Sector, sector_t, Portals) DEFINE_FIELD_X(Sector, sector_t, PortalGroup) DEFINE_FIELD_X(Sector, sector_t, sectornum) + +DEFINE_FIELD_X(Line, line_t, v1) +DEFINE_FIELD_X(Line, line_t, v2) +DEFINE_FIELD_X(Line, line_t, delta) +DEFINE_FIELD_X(Line, line_t, flags) +DEFINE_FIELD_X(Line, line_t, activation) +DEFINE_FIELD_X(Line, line_t, special) +DEFINE_FIELD_X(Line, line_t, args) +DEFINE_FIELD_X(Line, line_t, alpha) +DEFINE_FIELD_X(Line, line_t, sidedef) +DEFINE_FIELD_X(Line, line_t, bbox) +DEFINE_FIELD_X(Line, line_t, frontsector) +DEFINE_FIELD_X(Line, line_t, backsector) +DEFINE_FIELD_X(Line, line_t, validcount) +DEFINE_FIELD_X(Line, line_t, locknumber) +DEFINE_FIELD_X(Line, line_t, portalindex) diff --git a/src/r_defs.h b/src/r_defs.h index f33baeedc3..9c2a822f21 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1191,9 +1191,7 @@ struct side_t struct line_t { vertex_t *v1, *v2; // vertices, from v1 to v2 -private: DVector2 delta; // precalculated v2 - v1 for side checking -public: uint32_t flags; uint32_t activation; // activation type int special; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index db09a0387a..f63629bb52 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6578,9 +6578,16 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) PArray *arraytype = dyn_cast(Array->ValueType); if (arraytype == nullptr) { - ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); - delete this; - return nullptr; + // Check if we got a pointer to an array. Some native data structures (like the line list in sectors) use this. + PPointer *ptype = dyn_cast(Array->ValueType); + if (ptype == nullptr || !ptype->PointedType->IsKindOf(RUNTIME_CLASS(PArray))) + { + ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); + delete this; + return nullptr; + } + arraytype = static_cast(ptype->PointedType); + arrayispointer = true; } if (index->isConstant()) { @@ -6592,37 +6599,40 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) return nullptr; } - // if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. - if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember) + if (!arrayispointer) { - auto parentfield = static_cast(Array)->membervar; - // PFields are garbage collected so this will be automatically taken care of later. - auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); - static_cast(Array)->membervar = newfield; - Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. - auto x = Array->Resolve(ctx); - Array = nullptr; - return x; - } - else if (Array->ExprType == EFX_GlobalVariable) - { - auto parentfield = static_cast(Array)->membervar; - auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); - static_cast(Array)->membervar = newfield; - Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. - auto x = Array->Resolve(ctx); - Array = nullptr; - return x; - } - else if (Array->ExprType == EFX_StackVariable) - { - auto parentfield = static_cast(Array)->membervar; - auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); - static_cast(Array)->ReplaceField(newfield); - Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. - auto x = Array->Resolve(ctx); - Array = nullptr; - return x; + // if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. + if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember) + { + auto parentfield = static_cast(Array)->membervar; + // PFields are garbage collected so this will be automatically taken care of later. + auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); + static_cast(Array)->membervar = newfield; + Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. + auto x = Array->Resolve(ctx); + Array = nullptr; + return x; + } + else if (Array->ExprType == EFX_GlobalVariable) + { + auto parentfield = static_cast(Array)->membervar; + auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); + static_cast(Array)->membervar = newfield; + Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. + auto x = Array->Resolve(ctx); + Array = nullptr; + return x; + } + else if (Array->ExprType == EFX_StackVariable) + { + auto parentfield = static_cast(Array)->membervar; + auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); + static_cast(Array)->ReplaceField(newfield); + Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. + auto x = Array->Resolve(ctx); + Array = nullptr; + return x; + } } } @@ -6644,8 +6654,17 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) { + PArray *arraytype; + + if (arrayispointer) + { + arraytype = static_cast(static_cast(Array->ValueType)->PointedType); + } + else + { + arraytype = static_cast(Array->ValueType); + } ExpEmit start = Array->Emit(build); - PArray *const arraytype = static_cast(Array->ValueType); /* what was this for? if (start.Konst) @@ -6700,7 +6719,16 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) else { ExpEmit indexv(index->Emit(build)); - build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); + // Todo: For dynamically allocated arrays (like global sector and linedef tables) we need to get the bound value in here somehow. + // Right now their bounds are not properly checked for. + if (arraytype->ElementCount > 65535) + { + build->Emit(OP_BOUND_K, indexv.RegNum, build->GetConstantInt(arraytype->ElementCount)); + } + else + { + build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); + } if (!start.Konst) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index e586f1fbe3..5d0af0b49a 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -1416,6 +1416,7 @@ public: FxExpression *index; bool AddressRequested; bool AddressWritable; + bool arrayispointer = false; FxArrayElement(FxExpression*, FxExpression*); ~FxArrayElement(); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 7a3d3a7c67..6f0cad099c 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -43,6 +43,7 @@ #include "d_player.h" #include "p_effect.h" #include "autosegs.h" +#include "p_maputl.h" #include "gi.h" static TArray properties; @@ -703,7 +704,11 @@ void InitThingdef() auto sptr = NewPointer(sstruct); sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); - // expose the glibal Multiplayer variable. + // expose the global validcount variable. + PField *vcf = new PField("validcount", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&validcount); + GlobalSymbols.AddSymbol(vcf); + + // expose the global Multiplayer variable. PField *multif = new PField("multiplayer", TypeBool, VARF_Native | VARF_ReadOnly | VARF_Static, (intptr_t)&multiplayer); GlobalSymbols.AddSymbol(multif); @@ -726,6 +731,11 @@ void InitThingdef() PField *playerf = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players); GlobalSymbols.AddSymbol(playerf); + // set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well... + // As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up. + pstruct = NewNativeStruct("Sector", nullptr); + pstruct->AddNativeField("lines", NewPointer(NewArray(NewPointer(NewNativeStruct("line", nullptr), false), 0x40000), false), myoffsetof(sector_t, lines), VARF_Native); + parray = NewArray(TypeBool, MAXPLAYERS); playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); GlobalSymbols.AddSymbol(playerf); diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 74b7a34000..f358fce7b6 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -779,6 +779,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c it.PrintableName = name; it.Function = new VMScriptFunction; it.Function->Name = functype->SymbolName; + it.Function->PrintableName = name; it.Function->ImplicitArgs = functype->GetImplicitArgs(); it.Proto = nullptr; it.FromDecorate = fromdecorate; @@ -881,7 +882,6 @@ void FFunctionBuildList::Build() DumpFunction(dump, sfunc, item.PrintableName.GetChars(), (int)item.PrintableName.Len()); codesize += sfunc->CodeSize; } - sfunc->PrintableName = item.PrintableName; sfunc->Unsafe = ctx.Unsafe; } catch (CRecoverableError &err) diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index cba67cbdc9..88962bf680 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -104,7 +104,6 @@ #define RIKIRI MODE_AI | MODE_BKI | MODE_CI #define RIKII8 MODE_AI | MODE_BKI | MODE_CIMMZ #define RIRIIs MODE_AI | MODE_BI | MODE_CIMMS -#define RIRI MODE_AI | MODE_BI | MODE_CUNUSED #define I8RIRI MODE_AIMMZ | MODE_BI | MODE_CI #define I8RIKI MODE_AIMMZ | MODE_BI | MODE_CKI #define I8KIRI MODE_AIMMZ | MODE_BKI | MODE_CI diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 4df76a73e7..06c6ade8e1 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -713,6 +713,7 @@ begin: assert(0); NEXTOP; + // Fixme: This really needs to throw something more informative than a number. Printing the message here instead of passing it to the exception is not sufficient. OP(BOUND): if (reg.d[a] >= BC) { @@ -722,6 +723,26 @@ begin: } NEXTOP; + OP(BOUND_K): + ASSERTKD(BC); + if (reg.d[a] >= konstd[BC]) + { + assert(false); + Printf("Array access out of bounds: Max. index = %u, current index = %u\n", konstd[BC], reg.d[a]); + THROW(X_ARRAY_OUT_OF_BOUNDS); + } + NEXTOP; + + OP(BOUND_R): + ASSERTD(B); + if (reg.d[a] >= reg.d[B]) + { + assert(false); + Printf("Array access out of bounds: Max. index = %u, current index = %u\n", reg.d[B], reg.d[a]); + THROW(X_ARRAY_OUT_OF_BOUNDS); + } + NEXTOP; + OP(CONCAT): ASSERTS(a); ASSERTS(B); ASSERTS(C); reg.s[a] = reg.s[B] + reg.s[C]; diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index b36f93881c..e5b6d34ebb 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -110,6 +110,8 @@ xx(CATCH, catch, CATCH, NOP, 0, 0), // A == 0: continue search on next try // A == 3: (pkB == ) then pc++ ; next instruction must JMP to another CATCH // for A > 0, exception is stored in pC xx(BOUND, bound, RII16, NOP, 0, 0), // if rA >= BC, throw exception +xx(BOUND_K, bound, LKI, NOP, 0, 0), // if rA >= const[BC], throw exception +xx(BOUND_R, bound, RIRI, NOP, 0, 0), // if rA >= rB, throw exception // String instructions. xx(CONCAT, concat, RSRSRS, NOP, 0, 0), // sA = sB..sC diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 3b2ada4c8c..64ac2c86d2 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -346,7 +346,9 @@ static void DoParse(int lumpnum) } } +#ifndef NDEBUG if (f) fprintf(f, "Starting parsing %s\n", sc.String); +#endif ParseSingleFile(sc.String, 0, parser, state); } } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 739b5574fc..7b2b99570b 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -11,6 +11,7 @@ class Actor : Thinker native // flags are not defined here, the native fields for those get synthesized from the internal tables. // for some comments on these fields, see their native representations in actor.h. + native readonly Actor snext; // next in sector list. native PlayerInfo Player; native readonly vector3 Pos; native vector3 Prev; diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 3766bb6b24..397ba4c325 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -129,6 +129,23 @@ struct F3DFloor native { } +struct Line native +{ + //native readonly vertex v1, v2; // vertices, from v1 to v2 + native readonly Vector2 delta; // precalculated v2 - v1 for side checking + native uint flags; + native uint activation; // activation type + native int special; + native int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width) + native double alpha; // <--- translucency (0=invisibile, FRACUNIT=opaque) + //native Side sidedef[2]; + native readonly double bbox[4]; // bounding box, for the extent of the LineDef. + native readonly Sector frontsector, backsector; + native int validcount; // if == validcount, already checked + native int locknumber; // [Dusk] lock number for special + native readonly uint portalindex; +} + struct Sector native { //secplane_t floorplane, ceilingplane; @@ -145,7 +162,7 @@ struct Sector native native readonly Vector2 centerspot; native int validcount; - //AActor* thinglist; + native Actor thinglist; native double friction, movefactor; native int terrainnum[2]; @@ -170,7 +187,7 @@ struct Sector native native int nextsec; native readonly int16 linecount; - //line_t **lines; + //line_t **lines; // this is defined internally to avoid exposing some overly complicated type to the parser native readonly Sector heightsec; diff --git a/wadsrc/static/zscript/hexen/flies.txt b/wadsrc/static/zscript/hexen/flies.txt index 464e6e9d94..d9800552ba 100644 --- a/wadsrc/static/zscript/hexen/flies.txt +++ b/wadsrc/static/zscript/hexen/flies.txt @@ -15,9 +15,6 @@ class LittleFly : Actor ActiveSound "FlyBuzz"; } - native void A_FlySearch(); - native void A_FlyBuzz(); - States { Spawn: @@ -27,4 +24,107 @@ class LittleFly : Actor AFLY ABCD 3 A_FlyBuzz; Loop; } + + //=========================================================================== + // + // FindCorpse + // + // Finds a corpse to buzz around. We can't use a blockmap check because + // corpses generally aren't linked into the blockmap. + // + //=========================================================================== + + private Actor FindCorpse(sector sec, int recurselimit) + { + Actor fallback = null; + sec.validcount = validcount; + + // Search the current sector + for (Actor check = sec.thinglist; check != null; check = check.snext) + { + if (check == self) + continue; + if (!check.bCorpse) + continue; + if (!CheckSight(check)) + continue; + fallback = check; + if (random[Fly](0,1)) // 50% chance to try to pick a different corpse + continue; + return check; + } + if (--recurselimit <= 0 || (fallback != null && random[Fly](0,1))) + { + return fallback; + } + // Try neighboring sectors + for (int i = 0; i < sec.linecount; ++i) + { + line ln = sec.lines[i]; + sector sec2 = (ln.frontsector == sec) ? ln.backsector : ln.frontsector; + if (sec2 != null && sec2.validcount != validcount) + { + Actor neighbor = FindCorpse(sec2, recurselimit); + if (neighbor != null) + { + return neighbor; + } + } + } + return fallback; + } + + void A_FlySearch() + { + // The version from the retail beta is not so great for general use: + // 1. Pick one of the first fifty thinkers at random. + // 2. Starting from that thinker, find one that is an actor, not itself, + // and within sight. Give up after 100 sequential thinkers. + // It's effectively useless if there are more than 150 thinkers on a map. + // + // 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. + validcount++; + Actor other = FindCorpse(CurSector, 5); + if (other != null) + { + target = other; + SetStateLabel("Buzz"); + } + } + + void A_FlyBuzz() + { + Actor targ = target; + + if (targ == null || !targ.bCorpse || random[Fly]() < 5) + { + SetIdle(); + return; + } + + Angle = AngleTo(targ); + args[0]++; + if (!TryMove(Pos.XY + AngleToVector(angle, 6), true)) + { + SetIdle(true); + return; + } + if (args[0] & 2) + { + Vel.X += (random[Fly]() - 128) / 512.; + Vel.Y += (random[Fly]() - 128) / 512.; + } + int zrand = random[Fly](); + if (targ.pos.Z + 5. < pos.z && zrand > 150) + { + zrand = -zrand; + } + Vel.Z = zrand / 512.; + if (random[Fly]() < 40) + { + A_PlaySound(ActiveSound, CHAN_VOICE, 0.5f, false, ATTN_STATIC); + } + } } From 5ce5466e186e013c482e2f4b8a06d21dc5b92066 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 20:14:43 +0100 Subject: [PATCH 385/471] - scriptified hexenspecialdecs. - made '->' a single token. Although ZScript does not use it, the parser tends to get confused and fatally chokes on leftover arrows so this ensures more robust error handling. --- src/CMakeLists.txt | 2 - src/g_hexen/a_flies.cpp | 110 ------ src/g_hexen/a_hexenmisc.cpp | 2 - src/g_hexen/a_hexenspecialdecs.cpp | 365 ------------------ src/g_level.cpp | 1 + src/p_things.cpp | 7 + src/sc_man_scanner.re | 3 +- src/sc_man_tokens.h | 1 + wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/base.txt | 1 + .../static/zscript/hexen/hexenspecialdecs.txt | 291 +++++++++++++- 11 files changed, 284 insertions(+), 500 deletions(-) delete mode 100644 src/g_hexen/a_flies.cpp delete mode 100644 src/g_hexen/a_hexenspecialdecs.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2164e0a8b2..6111d17148 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -859,9 +859,7 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_flies.cpp g_hexen/a_heresiarch.cpp - g_hexen/a_hexenspecialdecs.cpp g_hexen/a_magecone.cpp g_hexen/a_magelightning.cpp g_hexen/a_magestaff.cpp diff --git a/src/g_hexen/a_flies.cpp b/src/g_hexen/a_flies.cpp deleted file mode 100644 index 7281dd8f25..0000000000 --- a/src/g_hexen/a_flies.cpp +++ /dev/null @@ -1,110 +0,0 @@ -static FRandom pr_fly("GetOffMeFly"); - -//=========================================================================== -// -// FindCorpse -// -// Finds a corpse to buzz around. We can't use a blockmap check because -// corpses generally aren't linked into the blockmap. -// -//=========================================================================== - -static AActor *FindCorpse(AActor *fly, sector_t *sec, int recurselimit) -{ - AActor *fallback = NULL; - sec->validcount = validcount; - - // Search the current sector - for (AActor *check = sec->thinglist; check != NULL; check = check->snext) - { - if (check == fly) - continue; - if (!(check->flags & MF_CORPSE)) - continue; - if (!P_CheckSight(fly, check)) - continue; - fallback = check; - if (pr_fly(2)) // 50% chance to try to pick a different corpse - continue; - return check; - } - if (--recurselimit <= 0 || (fallback != NULL && pr_fly(2))) - { - return fallback; - } - // Try neighboring sectors - for (int i = 0; i < sec->linecount; ++i) - { - line_t *line = sec->lines[i]; - sector_t *sec2 = (line->frontsector == sec) ? line->backsector : line->frontsector; - if (sec2 != NULL && sec2->validcount != validcount) - { - AActor *neighbor = FindCorpse(fly, sec2, recurselimit); - if (neighbor != NULL) - { - return neighbor; - } - } - } - return fallback; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FlySearch) -{ - // The version from the retail beta is not so great for general use: - // 1. Pick one of the first fifty thinkers at random. - // 2. Starting from that thinker, find one that is an actor, not itself, - // and within sight. Give up after 100 sequential thinkers. - // It's effectively useless if there are more than 150 thinkers on a map. - // - // 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_SELF_PROLOGUE(AActor); - - validcount++; - AActor *other = FindCorpse(self, self->Sector, 5); - if (other != NULL) - { - self->target = other; - self->SetState(self->FindState("Buzz")); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_FlyBuzz) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *targ = self->target; - - if (targ == NULL || !(targ->flags & MF_CORPSE) || pr_fly() < 5) - { - self->SetIdle(); - return 0; - } - - self->Angles.Yaw = self->AngleTo(targ); - self->args[0]++; - if (!P_TryMove(self, self->Pos().XY() + self->Angles.Yaw.ToVector(6), true)) - { - self->SetIdle(true); - return 0; - } - if (self->args[0] & 2) - { - self->Vel.X += (pr_fly() - 128) / 512.; - self->Vel.Y += (pr_fly() - 128) / 512.; - } - int zrand = pr_fly(); - if (targ->Z() + 5. < self->Z() && zrand > 150) - { - zrand = -zrand; - } - self->Vel.Z = zrand / 512.; - if (pr_fly() < 40) - { - S_Sound(self, CHAN_VOICE, self->ActiveSound, 0.5f, ATTN_STATIC); - } - return 0; -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index ae4399526f..503ac6fbc7 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,9 +24,7 @@ #include "a_pickups.h" // Include all the Hexen stuff here to reduce compile time -#include "a_flies.cpp" #include "a_heresiarch.cpp" -#include "a_hexenspecialdecs.cpp" #include "a_magecone.cpp" #include "a_magelightning.cpp" #include "a_magestaff.cpp" diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp deleted file mode 100644 index 899d9326d0..0000000000 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* -** Decorations that do special things -*/ - -/* -#include "actor.h" -#include "info.h" -#include "a_action.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_lnspec.h" -#include "a_hexenglobal.h" -#include "vm.h" -#include "g_level.h" -#include "doomstat.h" -*/ - -static FRandom pr_pottery ("PotteryExplode"); -static FRandom pr_bit ("PotteryChooseBit"); -static FRandom pr_drip ("CorpseBloodDrip"); -static FRandom pr_foo ("CorpseExplode"); -static FRandom pr_leaf ("LeafSpawn"); -static FRandom pr_leafthrust ("LeafThrust"); -static FRandom pr_leafcheck ("LeafCheck"); -static FRandom pr_shroom ("PoisonShroom"); -static FRandom pr_soaexplode ("SoAExplode"); - -// Pottery1 ------------------------------------------------------------------ - -void A_PotteryExplode (AActor *); -void A_PotteryChooseBit (AActor *); -void A_PotteryCheck (AActor *); - -//============================================================================ -// -// A_PotteryExplode -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_PotteryExplode) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo = NULL; - int i; - - for(i = (pr_pottery()&3)+3; i; i--) - { - mo = Spawn ("PotteryBit", self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->SetState (mo->SpawnState + (pr_pottery()%5)); - mo->Vel.X = pr_pottery.Random2() / 64.; - mo->Vel.Y = pr_pottery.Random2() / 64.; - mo->Vel.Z = ((pr_pottery() & 7) + 5) * 0.75; - } - } - S_Sound (mo, CHAN_BODY, "PotteryExplode", 1, ATTN_NORM); - // Spawn an item? - PClassActor *type = P_GetSpawnableType(self->args[0]); - if (type != NULL) - { - if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) - || !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER)) - { // Only spawn monsters if not -nomonsters - Spawn (type, self->Pos(), ALLOW_REPLACE); - } - } - return 0; -} - -//============================================================================ -// -// A_PotteryChooseBit -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_PotteryChooseBit) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->SetState (self->FindState(NAME_Death) + 1 + 2*(pr_bit()%5)); - self->tics = 256+(pr_bit()<<1); - return 0; -} - -//============================================================================ -// -// A_PotteryCheck -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_PotteryCheck) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - - for(i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - AActor *pmo = players[i].mo; - if (P_CheckSight (self, pmo) && (absangle(pmo->AngleTo(self), pmo->Angles.Yaw) <= 45)) - { // Previous state (pottery bit waiting state) - self->SetState (self->state - 1); - return 0; - } - } - } - return 0; -} - -// Lynched corpse (no heart) ------------------------------------------------ - -class AZCorpseLynchedNoHeart : public AActor -{ -DECLARE_CLASS (AZCorpseLynchedNoHeart, AActor) -public: - void PostBeginPlay (); -}; - -IMPLEMENT_CLASS(AZCorpseLynchedNoHeart, false, false) - -void AZCorpseLynchedNoHeart::PostBeginPlay () -{ - Super::PostBeginPlay (); - Spawn ("BloodPool", PosAtZ(floorz), ALLOW_REPLACE); -} - -//============================================================================ -// -// A_CorpseBloodDrip -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CorpseBloodDrip) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (pr_drip() <= 128) - { - Spawn ("CorpseBloodDrip", self->PosPlusZ(self->Height / 2), ALLOW_REPLACE); - } - return 0; -} - -//============================================================================ -// -// A_CorpseExplode -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - int i; - - for (i = (pr_foo()&3)+3; i; i--) - { - mo = Spawn ("CorpseBit", self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->SetState (mo->SpawnState + (pr_foo()%3)); - mo->Vel.X = pr_foo.Random2() / 64.; - mo->Vel.Y = pr_foo.Random2() / 64.; - mo->Vel.Z = ((pr_foo() & 7) + 5) * 0.75; - } - } - // Spawn a skull - mo = Spawn ("CorpseBit", self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->SetState (mo->SpawnState + 3); - mo->Vel.X = pr_foo.Random2() / 64.; - mo->Vel.Y = pr_foo.Random2() / 64.; - mo->Vel.Z = ((pr_foo() & 7) + 5) * 0.75; - } - S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_IDLE); - self->Destroy (); - return 0; -} - -//============================================================================ -// -// A_LeafSpawn -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LeafSpawn) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - int i; - - for (i = (pr_leaf()&3)+1; i; i--) - { - double xo = pr_leaf.Random2() / 4.; - double yo = pr_leaf.Random2() / 4.; - double zo = pr_leaf() / 4.; - mo = Spawn (pr_leaf()&1 ? PClass::FindActor ("Leaf1") : PClass::FindActor ("Leaf2"), - self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - - if (mo) - { - mo->Thrust(pr_leaf() / 128. + 3); - mo->target = self; - mo->special1 = 0; - } - } - return 0; -} - -//============================================================================ -// -// A_LeafThrust -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LeafThrust) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (pr_leafthrust() <= 96) - { - self->Vel.Z += pr_leafthrust() / 128. + 1; - } - return 0; -} - -//============================================================================ -// -// A_LeafCheck -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LeafCheck) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->special1++; - if (self->special1 >= 20) - { - self->SetState (NULL); - return 0; - } - DAngle ang = self->target ? self->target->Angles.Yaw : self->Angles.Yaw; - if (pr_leafcheck() > 64) - { - if (self->Vel.X == 0 && self->Vel.Y == 0) - { - self->Thrust(ang, pr_leafcheck() / 128. + 1); - } - return 0; - } - self->SetState (self->SpawnState + 7); - self->Vel.Z = pr_leafcheck() / 128. + 1; - self->Thrust(ang, pr_leafcheck() / 128. + 2); - self->flags |= MF_MISSILE; - return 0; -} - -//=========================================================================== -// -// A_SoAExplode - Suit of Armor Explode -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_SoAExplode) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - int i; - - for (i = 0; i < 10; i++) - { - double xo = (pr_soaexplode() - 128) / 16.; - double yo = (pr_soaexplode() - 128) / 16.; - double zo = pr_soaexplode()*self->Height / 256.; - mo = Spawn ("ZArmorChunk", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - if (mo) - { - mo->SetState (mo->SpawnState + i); - mo->Vel.X = pr_soaexplode.Random2() / 64.; - mo->Vel.Y = pr_soaexplode.Random2() / 64.; - mo->Vel.Z = (pr_soaexplode() & 7) + 5; - } - } - // Spawn an item? - PClassActor *type = P_GetSpawnableType(self->args[0]); - if (type != NULL) - { - if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) - || !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER)) - { // Only spawn monsters if not -nomonsters - Spawn (type, self->Pos(), ALLOW_REPLACE); - } - } - S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_NORM); - self->Destroy (); - return 0; -} - -// Bell --------------------------------------------------------------------- - -class AZBell : public AActor -{ - DECLARE_CLASS (AZBell, AActor) -public: - void Activate (AActor *activator); -}; - -IMPLEMENT_CLASS(AZBell, false, false) - -void AZBell::Activate (AActor *activator) -{ - if (health > 0) - { - P_DamageMobj (this, activator, activator, 10, NAME_Melee, DMG_THRUSTLESS); // 'ring' the bell - } -} - -//=========================================================================== -// -// A_BellReset1 -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_BellReset1) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags |= MF_NOGRAVITY; - self->Height *= 4; - if (self->special) - { // Initiate death action - P_ExecuteSpecial(self->special, NULL, NULL, false, self->args[0], - self->args[1], self->args[2], self->args[3], self->args[4]); - self->special = 0; - } - return 0; -} - -//=========================================================================== -// -// A_BellReset2 -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_BellReset2) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags |= MF_SHOOTABLE; - self->flags &= ~MF_CORPSE; - self->flags6 &= ~MF6_KILLED; - self->health = 5; - return 0; -} - diff --git a/src/g_level.cpp b/src/g_level.cpp index 904b38b8a3..ea34dc95c7 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1889,6 +1889,7 @@ DEFINE_FIELD_BIT(FLevelLocals, flags2, missilesactivateimpact, LEVEL2_MISSILESAC DEFINE_FIELD_BIT(FLevelLocals, flags2, monsterfallingdamage, LEVEL2_MONSTERFALLINGDAMAGE) DEFINE_FIELD_BIT(FLevelLocals, flags2, checkswitchrange, LEVEL2_CHECKSWITCHRANGE) DEFINE_FIELD_BIT(FLevelLocals, flags2, polygrind, LEVEL2_POLYGRIND) +DEFINE_FIELD_BIT(FLevelLocals, flags2, nomonsters, LEVEL2_NOMONSTERS) //========================================================================== // diff --git a/src/p_things.cpp b/src/p_things.cpp index d94ba6a019..ea01d38ed1 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -520,6 +520,13 @@ PClassActor *P_GetSpawnableType(int spawnnum) return NULL; } +DEFINE_ACTION_FUNCTION(AActor, GetSpawnableType) +{ + PARAM_PROLOGUE; + PARAM_INT(num); + ACTION_RETURN_OBJECT(P_GetSpawnableType(num)); +} + struct MapinfoSpawnItem { FName classname; // DECORATE is read after MAPINFO so we do not have the actual classes available here yet. diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 59113e4a7d..a57cc34adc 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -162,13 +162,11 @@ std2: 'private' { RET(TK_Private); } 'dot' { RET(TK_Dot); } 'cross' { RET(TK_Cross); } - 'ignores' { RET(TK_Ignores); } 'localized' { RET(TK_Localized); } 'latent' { RET(TK_Latent); } 'singular' { RET(TK_Singular); } 'config' { RET(TK_Config); } 'coerce' { RET(TK_Coerce); } - 'iterator' { RET(TK_Iterator); } 'optional' { RET(TK_Optional); } 'export' { RET(TK_Export); } 'virtual' { RET(TK_Virtual); } @@ -240,6 +238,7 @@ std2: "<>=" { RET(TK_LtGtEq); } "**" { RET(TK_MulMul); } "::" { RET(TK_ColonColon); } + "->" { RET(TK_Arrow); } ";" { StateOptions = false; RET(';'); } "{" { StateOptions = false; RET('{'); } "}" { RET('}'); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index dfa6c044c6..c1ba10044d 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -33,6 +33,7 @@ xx(TK_Neq, "'!='") xx(TK_ApproxEq, "'~=='") xx(TK_LtGtEq, "'<>='") xx(TK_MulMul, "'**'") +xx(TK_Arrow, "'->'") xx(TK_Action, "'action'") xx(TK_Break, "'break'") xx(TK_Case, "'case'") diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 7b2b99570b..17dfea3930 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -270,6 +270,7 @@ class Actor : Thinker native native static double GetDefaultSpeed(class type); + native static class GetSpawnableType(int spawnnum); native void RemoveFromHash(); native string GetTag(string defstr = ""); native double GetBobOffset(double frac = 0); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 397ba4c325..c0894eda86 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -92,6 +92,7 @@ struct LevelLocals native native bool monsterfallingdamage; native bool checkswitchrange; native bool polygrind; + native bool nomonsters; // level_info_t *info cannot be done yet. } diff --git a/wadsrc/static/zscript/hexen/hexenspecialdecs.txt b/wadsrc/static/zscript/hexen/hexenspecialdecs.txt index 558ef8395c..feebf515f1 100644 --- a/wadsrc/static/zscript/hexen/hexenspecialdecs.txt +++ b/wadsrc/static/zscript/hexen/hexenspecialdecs.txt @@ -95,7 +95,6 @@ class Pottery1 : Actor +NOICEDEATH } - native void A_PotteryExplode(); States { @@ -106,6 +105,40 @@ class Pottery1 : Actor POT1 A 0 A_PotteryExplode; Stop; } + + //============================================================================ + // + // A_PotteryExplode + // + //============================================================================ + + void A_PotteryExplode() + { + Actor mo = null; + int i; + + for(i = (random[Pottery]()&3)+3; i; i--) + { + mo = Spawn ("PotteryBit", Pos, ALLOW_REPLACE); + if (mo) + { + mo.SetState (mo.SpawnState + (random[Pottery]()%5)); + mo.Vel.X = random2[Pottery]() / 64.; + mo.Vel.Y = random2[Pottery]() / 64.; + mo.Vel.Z = ((random[Pottery]() & 7) + 5) * 0.75; + } + } + mo.A_PlaySound ("PotteryExplode", CHAN_BODY); + // Spawn an item? + Class type = GetSpawnableType(args[0]); + if (type != null) + { + if (!(level.nomonsters || sv_nomonsters) || !(GetDefaultByType (type).bIsMonster)) + { // Only spawn monsters if not -nomonsters + Spawn (type, Pos, ALLOW_REPLACE); + } + } + } } // Pottery2 ----------------------------------------------------------------- @@ -144,6 +177,8 @@ class Pottery3 : Pottery1 class PotteryBit : Actor { + State LoopState; + Default { Radius 5; @@ -153,9 +188,6 @@ class PotteryBit : Actor +NOICEDEATH } - native void A_PotteryChooseBit(); - native void A_PotteryCheck(); - States { Spawn: @@ -185,6 +217,42 @@ class PotteryBit : Actor PBIT J 1 A_PotteryCheck; Stop; } + + //============================================================================ + // + // A_PotteryChooseBit + // + //============================================================================ + + void A_PotteryChooseBit() + { + static const statelabel bits[] = { "Pottery1", "Pottery2", "Pottery3", "Pottery4", "Pottery5" }; + LoopState = FindState(bits[random[PotteryBit]() % 5]); // Save the state for jumping back to. + SetState (LoopState); + tics = 256 + (random[PotteryBit]() << 1); + } + + //============================================================================ + // + // A_PotteryCheck + // + //============================================================================ + + void A_PotteryCheck() + { + for(int i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + Actor pmo = players[i].mo; + if (CheckSight (pmo) && (absangle(pmo.AngleTo(self), pmo.Angle) <= 45)) + { // jump back to previpusly set state. + SetState (LoopState); + return; + } + } + } + } } @@ -203,7 +271,7 @@ class BloodPool : Actor // Lynched corpse (no heart) ------------------------------------------------ -class ZCorpseLynchedNoHeart : Actor native +class ZCorpseLynchedNoHeart : Actor { Default { @@ -212,14 +280,32 @@ class ZCorpseLynchedNoHeart : Actor native +SOLID +SPAWNCEILING +NOGRAVITY } - native void A_CorpseBloodDrip(); - States { Spawn: CPS5 A 140 A_CorpseBloodDrip; Loop; } + + override void PostBeginPlay () + { + Super.PostBeginPlay (); + Spawn ("BloodPool", (pos.xy, floorz), ALLOW_REPLACE); + } + + //============================================================================ + // + // A_CorpseBloodDrip + // + //============================================================================ + + void A_CorpseBloodDrip() + { + if (random[CorpseDrip]() <= 128) + { + Spawn ("CorpseBloodDrip", pos + (0, 0, Height / 2), ALLOW_REPLACE); + } + } } @@ -289,8 +375,6 @@ class ZCorpseSitting : Actor DeathSound "FireDemonDeath"; } - native void A_CorpseExplode(); - States { Spawn: @@ -300,6 +384,40 @@ class ZCorpseSitting : Actor CPS6 A 1 A_CorpseExplode; Stop; } + + //============================================================================ + // + // A_CorpseExplode + // + //============================================================================ + + void A_CorpseExplode() + { + Actor mo; + + for (int i = (random[CorpseExplode]() & 3) + 3; i; i--) + { + mo = Spawn ("CorpseBit", Pos, ALLOW_REPLACE); + if (mo) + { + mo.SetState (mo.SpawnState + (random[CorpseExplode]() % 3)); + mo.Vel.X = random2[CorpseExplode]() / 64.; + mo.Vel.Y = random2[CorpseExplode]() / 64.; + mo.Vel.Z = ((random[CorpseExplode]() & 7) + 5) * 0.75; + } + } + // Spawn a skull + mo = Spawn ("CorpseBit", Pos, ALLOW_REPLACE); + if (mo) + { + mo.SetState (mo.SpawnState + 3); + mo.Vel.X = random2[CorpseExplode]() / 64.; + mo.Vel.Y = random2[CorpseExplode]() / 64.; + mo.Vel.Z = ((random[CorpseExplode]() & 7) + 5) * 0.75; + } + A_PlaySound (DeathSound, CHAN_BODY); + Destroy (); + } } @@ -313,7 +431,6 @@ class LeafSpawner : Actor +INVISIBLE } - native void A_LeafSpawn(); States { @@ -321,6 +438,32 @@ class LeafSpawner : Actor TNT1 A 20 A_LeafSpawn; Loop; } + + //============================================================================ + // + // A_LeafSpawn + // + //============================================================================ + + void A_LeafSpawn() + { + static const class leaves[] = { "Leaf1", "Leaf2" }; + + for (int i = (random[LeafSpawn]() & 3) + 1; i; i--) + { + double xo = random2[LeafSpawn]() / 4.; + double yo = random2[LeafSpawn]() / 4.; + double zo = random[LeafSpawn]() / 4.; + Actor mo = Spawn (leaves[random[LeafSpawn]()&1], Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + + if (mo) + { + mo.Thrust(random[LeafSpawn]() / 128. + 3); + mo.target = self; + mo.special1 = 0; + } + } + } } @@ -338,15 +481,13 @@ class Leaf1 : Actor +NOICEDEATH } - native void A_LeafThrust(); - native void A_LeafCheck(); - States { Spawn: LEF1 ABC 4; LEF1 D 4 A_LeafThrust; LEF1 EFG 4; + Looping: LEF1 H 4 A_LeafThrust; LEF1 I 4; LEF1 AB 4; @@ -359,6 +500,49 @@ class Leaf1 : Actor LEF3 D 10 A_LeafCheck; Wait; } + + //============================================================================ + // + // A_LeafThrust + // + //============================================================================ + + void A_LeafThrust() + { + if (random[LeafThrust]() <= 96) + { + Vel.Z += random[LeafThrust]() / 128. + 1; + } + } + + //============================================================================ + // + // A_LeafCheck + // + //============================================================================ + + void A_LeafCheck() + { + special1++; + if (special1 >= 20) + { + Destroy(); + return; + } + double ang = target ? target.angle : angle; + if (random[LeafCheck]() > 64) + { + if (Vel.X == 0 && Vel.Y == 0) + { + Thrust(random[LeafCheck]() / 128. + 1, ang); + } + return; + } + SetStateLabel ("Looping"); + Vel.Z = random[LeafCheck]() / 128. + 1; + Thrust(random[LeafCheck]() / 128. + 2, ang); + bMissile = true; + } } @@ -556,8 +740,6 @@ class ZSuitOfArmor : Actor DeathSound "SuitofArmorBreak"; } - native void A_SoAExplode(); - States { Spawn: @@ -567,6 +749,41 @@ class ZSuitOfArmor : Actor ZSUI A 1 A_SoAExplode; Stop; } + + //=========================================================================== + // + // A_SoAExplode - Suit of Armor Explode + // + //=========================================================================== + + void A_SoAExplode() + { + for (int i = 0; i < 10; i++) + { + double xo = (random[SoAExplode]() - 128) / 16.; + double yo = (random[SoAExplode]() - 128) / 16.; + double zo = random[SoAExplode]() * Height / 256.; + Actor mo = Spawn ("ZArmorChunk", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + if (mo) + { + mo.SetState (mo.SpawnState + i); + mo.Vel.X = random2[SoAExplode]() / 64.; + mo.Vel.Y = random2[SoAExplode]() / 64.; + mo.Vel.Z = (random[SoAExplode]() & 7) + 5; + } + } + // Spawn an item? + Class type = GetSpawnableType(args[0]); + if (type != null) + { + if (!(level.nomonsters || sv_nomonsters) || !(GetDefaultByType (type).bIsMonster)) + { // Only spawn monsters if not -nomonsters + Spawn (type, Pos, ALLOW_REPLACE); + } + } + A_PlaySound (DeathSound, CHAN_BODY); + Destroy (); + } } @@ -608,7 +825,7 @@ class ZArmorChunk : Actor // Bell --------------------------------------------------------------------- -class ZBell : Actor native +class ZBell : Actor { Default { @@ -621,9 +838,6 @@ class ZBell : Actor native DeathSound "BellRing"; } - native void A_BellReset1(); - native void A_BellReset2(); - States { Spawn: @@ -665,6 +879,45 @@ class ZBell : Actor native BBLL A 1 A_BellReset2; Goto Spawn; } + + override void Activate (Actor activator) + { + if (health > 0) A_Die(); + { + DamageMobj (activator, activator, 10, 'Melee', DMG_THRUSTLESS); // 'ring' the bell + } + } + + //=========================================================================== + // + // A_BellReset1 + // + //=========================================================================== + + void A_BellReset1() + { + bNoGravity = true; + Height = Default.Height; + if (special) + { // Initiate death action + A_CallSpecial(special, args[0], args[1], args[2], args[3], args[4]); + special = 0; + } + } + + //=========================================================================== + // + // A_BellReset2 + // + //=========================================================================== + + void A_BellReset2() + { + bShootable = true; + bCorpse = false; + bKilled = false; + health = 5; + } } From 7b5a5896355e1bd32304623ebb47872d7e51a7be Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 21:41:04 +0100 Subject: [PATCH 386/471] - scriptified Hexen's Frost shards. - scriptified all SpecialMissileHit methods. --- src/actor.h | 2 +- src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_magecone.cpp | 185 ------------------ src/g_hexen/a_magelightning.cpp | 93 --------- src/g_hexen/a_magestaff.cpp | 13 -- src/p_mobj.cpp | 15 +- wadsrc/static/zscript/actor.txt | 6 + wadsrc/static/zscript/hexen/magecone.txt | 144 +++++++++++++- wadsrc/static/zscript/hexen/magelightning.txt | 73 ++++++- wadsrc/static/zscript/hexen/magestaff.txt | 12 ++ 10 files changed, 242 insertions(+), 302 deletions(-) delete mode 100644 src/g_hexen/a_magecone.cpp diff --git a/src/actor.h b/src/actor.h index 4c0f33dde6..578b094ed6 100644 --- a/src/actor.h +++ b/src/actor.h @@ -667,7 +667,7 @@ public: // Called by PIT_CheckThing() and needed for some Hexen things. // Returns -1 for normal behavior, 0 to return false, and 1 to return true. // I'm not sure I like it this way, but it will do for now. - virtual int SpecialMissileHit (AActor *victim); + int SpecialMissileHit (AActor *victim); // Returns true if it's okay to switch target to "other" after being attacked by it. virtual bool OkayToSwitchTarget (AActor *other); diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 503ac6fbc7..e6f27c4346 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -25,7 +25,6 @@ // Include all the Hexen stuff here to reduce compile time #include "a_heresiarch.cpp" -#include "a_magecone.cpp" #include "a_magelightning.cpp" #include "a_magestaff.cpp" #include "a_serpent.cpp" diff --git a/src/g_hexen/a_magecone.cpp b/src/g_hexen/a_magecone.cpp deleted file mode 100644 index 102f681555..0000000000 --- a/src/g_hexen/a_magecone.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "a_action.h" -#include "p_pspr.h" -#include "gstrings.h" -#include "a_hexenglobal.h" -#include "vm.h" -*/ - -const int SHARDSPAWN_LEFT = 1; -const int SHARDSPAWN_RIGHT = 2; -const int SHARDSPAWN_UP = 4; -const int SHARDSPAWN_DOWN = 8; - -static FRandom pr_cone ("FireConePL1"); - -void A_FireConePL1 (AActor *actor); -void A_ShedShard (AActor *); - -// Frost Missile ------------------------------------------------------------ - -class AFrostMissile : public AActor -{ - DECLARE_CLASS (AFrostMissile, AActor) -public: - int DoSpecialDamage (AActor *victim, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(AFrostMissile, false, false) - -int AFrostMissile::DoSpecialDamage (AActor *victim, int damage, FName damagetype) -{ - if (special2 > 0) - { - damage <<= special2; - } - return damage; -} - -//============================================================================ -// -// A_FireConePL1 -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - DAngle slope; - int i; - AActor *mo; - bool conedone=false; - player_t *player; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - S_Sound (self, CHAN_WEAPON, "MageShardsFire", 1, ATTN_NORM); - - damage = 90+(pr_cone()&15); - for (i = 0; i < 16; i++) - { - angle = self->Angles.Yaw + i*(45./16); - slope = P_AimLineAttack (self, angle, MELEERANGE, &t, 0., ALF_CHECK3D); - if (t.linetarget) - { - P_DamageMobj (t.linetarget, self, self, damage, NAME_Ice, DMG_USEANGLE, t.angleFromSource.Degrees); - conedone = true; - break; - } - } - - // didn't find any creatures, so fire projectiles - if (!conedone) - { - mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(AFrostMissile)); - if (mo) - { - mo->special1 = SHARDSPAWN_LEFT|SHARDSPAWN_DOWN|SHARDSPAWN_UP - |SHARDSPAWN_RIGHT; - mo->special2 = 3; // Set sperm count (levels of reproductivity) - mo->target = self; - mo->args[0] = 3; // Mark Initial shard as super damage - } - } - return 0; -} - -//============================================================================ -// -// A_ShedShard -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ShedShard) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - int spawndir = self->special1; - int spermcount = self->special2; - - if (spermcount <= 0) - { - return 0; // No sperm left - } - self->special2 = 0; - spermcount--; - - // every so many calls, spawn a new missile in its set directions - if (spawndir & SHARDSPAWN_LEFT) - { - mo = P_SpawnMissileAngleZSpeed(self, self->Z(), RUNTIME_CLASS(AFrostMissile), - self->Angles.Yaw + 5, 0, (20. + 2 * spermcount), self->target); - if (mo) - { - mo->special1 = SHARDSPAWN_LEFT; - mo->special2 = spermcount; - mo->Vel.Z = self->Vel.Z; - mo->args[0] = (spermcount==3)?2:0; - } - } - if (spawndir & SHARDSPAWN_RIGHT) - { - mo = P_SpawnMissileAngleZSpeed(self, self->Z(), RUNTIME_CLASS(AFrostMissile), - self->Angles.Yaw - 5, 0, (20. + 2 * spermcount), self->target); - if (mo) - { - mo->special1 = SHARDSPAWN_RIGHT; - mo->special2 = spermcount; - mo->Vel.Z = self->Vel.Z; - mo->args[0] = (spermcount==3)?2:0; - } - } - if (spawndir & SHARDSPAWN_UP) - { - mo = P_SpawnMissileAngleZSpeed(self, self->Z() + 8., RUNTIME_CLASS(AFrostMissile), - self->Angles.Yaw, 0, (15. + 2 * spermcount), self->target); - if (mo) - { - mo->Vel.Z = self->Vel.Z; - if (spermcount & 1) // Every other reproduction - mo->special1 = SHARDSPAWN_UP | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; - else - mo->special1 = SHARDSPAWN_UP; - mo->special2 = spermcount; - mo->args[0] = (spermcount==3)?2:0; - } - } - if (spawndir & SHARDSPAWN_DOWN) - { - mo = P_SpawnMissileAngleZSpeed(self, self->Z() - 4., RUNTIME_CLASS(AFrostMissile), - self->Angles.Yaw, 0, (15. + 2 * spermcount), self->target); - if (mo) - { - mo->Vel.Z = self->Vel.Z; - if (spermcount & 1) // Every other reproduction - mo->special1 = SHARDSPAWN_DOWN | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; - else - mo->special1 = SHARDSPAWN_DOWN; - mo->special2 = spermcount; - mo->target = self->target; - mo->args[0] = (spermcount==3)?2:0; - } - } - return 0; -} diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index d5fcef880b..794e6660bf 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -25,99 +25,6 @@ static FRandom pr_hit ("LightningHit"); DECLARE_ACTION(A_LightningClip) DECLARE_ACTION(A_LightningZap) -// Lightning ---------------------------------------------------------------- - -class ALightning : public AActor -{ - DECLARE_CLASS (ALightning, AActor) -public: - int SpecialMissileHit (AActor *victim); -}; - -IMPLEMENT_CLASS(ALightning, false, false) - -int ALightning::SpecialMissileHit (AActor *thing) -{ - if (thing->flags&MF_SHOOTABLE && thing != target) - { - if (thing->Mass != INT_MAX) - { - thing->Vel.X += Vel.X / 16; - thing->Vel.Y += Vel.Y / 16; - } - if ((!thing->player && !(thing->flags2&MF2_BOSS)) - || !(level.time&1)) - { - P_DamageMobj(thing, this, target, 3, NAME_Electric); - if (!(S_IsActorPlayingSomething (this, CHAN_WEAPON, -1))) - { - S_Sound (this, CHAN_WEAPON, this->AttackSound, 1, ATTN_NORM); - } - if (thing->flags3&MF3_ISMONSTER && pr_hit() < 64) - { - thing->Howl (); - } - } - health--; - if (health <= 0 || thing->health <= 0) - { - return 0; - } - if (flags3 & MF3_FLOORHUGGER) - { - if (lastenemy && ! lastenemy->tracer) - { - lastenemy->tracer = thing; - } - } - else if (!tracer) - { - tracer = thing; - } - } - return 1; // lightning zaps through all sprites -} - -// Lightning Zap ------------------------------------------------------------ - -class ALightningZap : public AActor -{ - DECLARE_CLASS (ALightningZap, AActor) -public: - int SpecialMissileHit (AActor *thing); -}; - -IMPLEMENT_CLASS(ALightningZap, false, false) - -int ALightningZap::SpecialMissileHit (AActor *thing) -{ - AActor *lmo; - - if (thing->flags&MF_SHOOTABLE && thing != target) - { - lmo = lastenemy; - if (lmo) - { - if (lmo->flags3 & MF3_FLOORHUGGER) - { - if (lmo->lastenemy && !lmo->lastenemy->tracer) - { - lmo->lastenemy->tracer = thing; - } - } - else if (!lmo->tracer) - { - lmo->tracer = thing; - } - if (!(level.time&3)) - { - lmo->health--; - } - } - } - return -1; -} - //============================================================================ // // A_LightningReady diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index 27e9f57321..035744aba0 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -72,24 +72,11 @@ class AMageStaffFX2 : public AActor { DECLARE_CLASS(AMageStaffFX2, AActor) public: - int SpecialMissileHit (AActor *victim); bool SpecialBlastHandling (AActor *source, double strength); }; IMPLEMENT_CLASS(AMageStaffFX2, false, false) -int AMageStaffFX2::SpecialMissileHit (AActor *victim) -{ - if (victim != target && - !victim->player && - !(victim->flags2 & MF2_BOSS)) - { - P_DamageMobj (victim, this, target, 10, NAME_Fire); - return 1; // Keep going - } - return -1; -} - bool AMageStaffFX2::SpecialBlastHandling (AActor *source, double strength) { // Reflect to originator diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 358e46e8c1..250927a5a9 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3357,6 +3357,7 @@ bool AActor::SpecialBlastHandling (AActor *source, double strength) } // This only gets called from the script side so we do not need a native wrapper like for the other virtual methods. +// This will be removed, once all actors overriding this method are exported. DEFINE_ACTION_FUNCTION(AActor, SpecialBlastHandling) { PARAM_SELF_PROLOGUE(AActor); @@ -3365,10 +3366,20 @@ DEFINE_ACTION_FUNCTION(AActor, SpecialBlastHandling) ACTION_RETURN_BOOL(self->SpecialBlastHandling(source, strength)); } - +// This virtual method only exists on the script side. int AActor::SpecialMissileHit (AActor *victim) { - return -1; + IFVIRTUAL(AActor, SpecialMissileHit) + { + VMValue params[2] = { (DObject*)this, victim }; + VMReturn ret; + int retval; + VMFrameStack stack; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + return retval; + } + else return -1; } bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 17dfea3930..189f700908 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -6,6 +6,7 @@ class Actor : Thinker native const FLOATRANDZ = ONCEILINGZ-1; const TELEFRAG_DAMAGE = 1000000; const MinVel = 1./65536; + const LARGE_MASS = 10000000; // not INT_MAX on purpose // flags are not defined here, the native fields for those get synthesized from the internal tables. @@ -268,6 +269,11 @@ class Actor : Thinker native virtual native bool UseInventory(Inventory item); virtual native bool SpecialBlastHandling (Actor source, double strength); + virtual int SpecialMissileHit (Actor victim) // for this no native version exists + { + return -1; + } + native static double GetDefaultSpeed(class type); native static class GetSpawnableType(int spawnnum); diff --git a/wadsrc/static/zscript/hexen/magecone.txt b/wadsrc/static/zscript/hexen/magecone.txt index a9f2d29dcb..2bbd58f3d7 100644 --- a/wadsrc/static/zscript/hexen/magecone.txt +++ b/wadsrc/static/zscript/hexen/magecone.txt @@ -17,8 +17,6 @@ class MWeapFrost : MageWeapon Tag "$TAG_MWEAPFROST"; } - action native void A_FireConePL1(); - States { Spawn: @@ -45,12 +43,68 @@ class MWeapFrost : MageWeapon CONE A 10 A_ReFire; Goto Ready; } + + //============================================================================ + // + // A_FireConePL1 + // + //============================================================================ + + action void A_FireConePL1() + { + bool conedone=false; + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + A_PlaySound ("MageShardsFire", CHAN_WEAPON); + + int damage = 90+(random[MageCone]() & 15); + for (int i = 0; i < 16; i++) + { + double ang = angle + i*(45./16); + double slope = AimLineAttack (ang, MELEERANGE, t, 0., ALF_CHECK3D); + if (t.linetarget) + { + t.linetarget.DamageMobj (self, self, damage, 'Ice', DMG_USEANGLE, t.angleFromSource); + conedone = true; + break; + } + } + + // didn't find any creatures, so fire projectiles + if (!conedone) + { + Actor mo = SpawnPlayerMissile ("FrostMissile"); + if (mo) + { + mo.special1 = FrostMissile.SHARDSPAWN_LEFT|FrostMissile.SHARDSPAWN_DOWN|FrostMissile.SHARDSPAWN_UP|FrostMissile.SHARDSPAWN_RIGHT; + mo.special2 = 3; // Set sperm count (levels of reproductivity) + mo.target = self; + mo.args[0] = 3; // Mark Initial shard as super damage + } + } + } } // Frost Missile ------------------------------------------------------------ -class FrostMissile : Actor native +class FrostMissile : Actor { + const SHARDSPAWN_LEFT = 1; + const SHARDSPAWN_RIGHT = 2; + const SHARDSPAWN_UP = 4; + const SHARDSPAWN_DOWN = 8; + Default { Speed 25; @@ -63,8 +117,6 @@ class FrostMissile : Actor native Obituary "$OB_MPMWEAPFROST"; } - native void A_ShedShard(); - States { Spawn: @@ -77,6 +129,88 @@ class FrostMissile : Actor native SHEX ABCDE 5 Bright; Stop; } + + override int DoSpecialDamage (Actor victim, int damage, Name damagetype) + { + if (special2 > 0) + { + damage <<= special2; + } + return damage; + } + + //============================================================================ + // + // A_ShedShard + // + //============================================================================ + + void A_ShedShard() + { + int spawndir = special1; + int spermcount = special2; + Actor mo; + + if (spermcount <= 0) + { + return; // No sperm left + } + special2 = 0; + spermcount--; + + // every so many calls, spawn a new missile in its set directions + if (spawndir & SHARDSPAWN_LEFT) + { + mo = SpawnMissileAngleZSpeed(pos.z, "FrostMissile", angle + 5, 0, (20. + 2 * spermcount), target); + if (mo) + { + mo.special1 = SHARDSPAWN_LEFT; + mo.special2 = spermcount; + mo.Vel.Z = Vel.Z; + mo.args[0] = (spermcount==3)?2:0; + } + } + if (spawndir & SHARDSPAWN_RIGHT) + { + mo = SpawnMissileAngleZSpeed(pos.z, "FrostMissile", angle - 5, 0, (20. + 2 * spermcount), target); + if (mo) + { + mo.special1 = SHARDSPAWN_RIGHT; + mo.special2 = spermcount; + mo.Vel.Z = Vel.Z; + mo.args[0] = (spermcount==3)?2:0; + } + } + if (spawndir & SHARDSPAWN_UP) + { + mo = SpawnMissileAngleZSpeed(pos.z + 8., "FrostMissile", angle, 0, (15. + 2 * spermcount), target); + if (mo) + { + mo.Vel.Z = Vel.Z; + if (spermcount & 1) // Every other reproduction + mo.special1 = SHARDSPAWN_UP | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; + else + mo.special1 = SHARDSPAWN_UP; + mo.special2 = spermcount; + mo.args[0] = (spermcount==3)?2:0; + } + } + if (spawndir & SHARDSPAWN_DOWN) + { + mo = SpawnMissileAngleZSpeed(pos.z - 4., "FrostMissile", angle, 0, (15. + 2 * spermcount), target); + if (mo) + { + mo.Vel.Z = Vel.Z; + if (spermcount & 1) // Every other reproduction + mo.special1 = SHARDSPAWN_DOWN | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; + else + mo.special1 = SHARDSPAWN_DOWN; + mo.special2 = spermcount; + mo.target = target; + mo.args[0] = (spermcount==3)?2:0; + } + } + } } // Ice Shard ---------------------------------------------------------------- diff --git a/wadsrc/static/zscript/hexen/magelightning.txt b/wadsrc/static/zscript/hexen/magelightning.txt index 154776d155..b778451ac1 100644 --- a/wadsrc/static/zscript/hexen/magelightning.txt +++ b/wadsrc/static/zscript/hexen/magelightning.txt @@ -54,7 +54,7 @@ class MWeapLightning : MageWeapon // Ceiling Lightning -------------------------------------------------------- -class Lightning : Actor native +class Lightning : Actor { Default { @@ -63,6 +63,45 @@ class Lightning : Actor native ActiveSound "MageLightningContinuous"; Obituary "$OB_MPMWEAPLIGHTNING"; } + + override int SpecialMissileHit (Actor thing) + { + if (thing.bShootable && thing != target) + { + if (thing.Mass < LARGE_MASS) + { + thing.Vel.X += Vel.X / 16; + thing.Vel.Y += Vel.Y / 16; + } + if ((!thing.player && !thing.bBoss) || !(level.time&1)) + { + thing.DamageMobj(self, target, 3, 'Electric'); + A_PlaySound(self.AttackSound, CHAN_WEAPON, 1, true); + if (thing.bIsMonster && random[LightningHit]() < 64) + { + thing.Howl (); + } + } + health--; + if (health <= 0 || thing.health <= 0) + { + return 0; + } + if (bFloorHugger) + { + if (lastenemy && ! lastenemy.tracer) + { + lastenemy.tracer = thing; + } + } + else if (!tracer) + { + tracer = thing; + } + } + return 1; // lightning zaps through all sprites + } + } class LightningCeiling : Lightning @@ -141,7 +180,7 @@ class LightningFloor : LightningCeiling // Lightning Zap ------------------------------------------------------------ -class LightningZap : Actor native +class LightningZap : Actor { Default { @@ -166,4 +205,34 @@ class LightningZap : Actor native MLFX NOPQRSTU 2 Bright; Stop; } + + override int SpecialMissileHit (Actor thing) + { + Actor lmo; + + if (thing.bShootable && thing != target) + { + lmo = lastenemy; + if (lmo) + { + if (lmo.bFloorHugger) + { + if (lmo.lastenemy && !lmo.lastenemy.tracer) + { + lmo.lastenemy.tracer = thing; + } + } + else if (!lmo.tracer) + { + lmo.tracer = thing; + } + if (!(level.time&3)) + { + lmo.health--; + } + } + } + return -1; + } + } diff --git a/wadsrc/static/zscript/hexen/magestaff.txt b/wadsrc/static/zscript/hexen/magestaff.txt index c115428348..d485a72fa9 100644 --- a/wadsrc/static/zscript/hexen/magestaff.txt +++ b/wadsrc/static/zscript/hexen/magestaff.txt @@ -157,4 +157,16 @@ class MageStaffFX2 : Actor native MSP2 I 4 Bright; Stop; } + + override int SpecialMissileHit (Actor victim) + { + if (victim != target && !victim.player && !victim.bBoss) + { + victim.DamageMobj (self, target, 10, 'Fire'); + return 1; // Keep going + } + return -1; + } + + } From f9a13880667bd3e486bada16f425ca33e3b9f1d0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Nov 2016 22:14:18 +0100 Subject: [PATCH 387/471] - scriptified Hexen's lightning weapon. --- src/CMakeLists.txt | 2 - src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_magelightning.cpp | 274 ------------------ src/p_mobj.cpp | 9 + wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/hexen/magelightning.txt | 230 ++++++++++++++- 6 files changed, 228 insertions(+), 289 deletions(-) delete mode 100644 src/g_hexen/a_magelightning.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6111d17148..1abd8e71bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -860,8 +860,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.h sc_man_scanner.re g_hexen/a_heresiarch.cpp - g_hexen/a_magecone.cpp - g_hexen/a_magelightning.cpp g_hexen/a_magestaff.cpp g_hexen/a_serpent.cpp g_hexen/a_spike.cpp diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index e6f27c4346..45a407faa1 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -25,7 +25,6 @@ // Include all the Hexen stuff here to reduce compile time #include "a_heresiarch.cpp" -#include "a_magelightning.cpp" #include "a_magestaff.cpp" #include "a_serpent.cpp" #include "a_spike.cpp" diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp deleted file mode 100644 index 794e6660bf..0000000000 --- a/src/g_hexen/a_magelightning.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "a_action.h" -#include "p_pspr.h" -#include "gstrings.h" -#include "a_hexenglobal.h" -#include "vm.h" -#include "g_level.h" -*/ - -#define ZAGSPEED 1. - -static FRandom pr_lightningready ("LightningReady"); -static FRandom pr_lightningclip ("LightningClip"); -static FRandom pr_zap ("LightningZap"); -static FRandom pr_zapf ("LightningZapF"); -static FRandom pr_hit ("LightningHit"); - -DECLARE_ACTION(A_LightningClip) -DECLARE_ACTION(A_LightningZap) - -//============================================================================ -// -// A_LightningReady -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LightningReady) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DoReadyWeapon(self); - if (pr_lightningready() < 160) - { - S_Sound (self, CHAN_WEAPON, "MageLightningReady", 1, ATTN_NORM); - } - return 0; -} - -//============================================================================ -// -// A_LightningClip -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LightningClip) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *cMo; - AActor *target = NULL; - int zigZag; - - if (self->flags3 & MF3_FLOORHUGGER) - { - if (self->lastenemy == NULL) - { - return 0; - } - self->SetZ(self->floorz); - target = self->lastenemy->tracer; - } - else if (self->flags3 & MF3_CEILINGHUGGER) - { - self->SetZ(self->ceilingz - self->Height); - target = self->tracer; - } - if (self->flags3 & MF3_FLOORHUGGER) - { // floor lightning zig-zags, and forces the ceiling lightning to mimic - cMo = self->lastenemy; - zigZag = pr_lightningclip(); - if((zigZag > 128 && self->special1 < 2) || self->special1 < -2) - { - self->Thrust(self->Angles.Yaw + 90, ZAGSPEED); - if(cMo) - { - cMo->Thrust(self->Angles.Yaw + 90, ZAGSPEED); - } - self->special1++; - } - else - { - self->Thrust(self->Angles.Yaw - 90, ZAGSPEED); - if(cMo) - { - cMo->Thrust(self->Angles.Yaw - 90, ZAGSPEED); - } - self->special1--; - } - } - if(target) - { - if(target->health <= 0) - { - P_ExplodeMissile(self, NULL, NULL); - } - else - { - self->Angles.Yaw = self->AngleTo(target); - self->VelFromAngle(self->Speed / 2); - } - } - return 0; -} - - -//============================================================================ -// -// A_LightningZap -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LightningZap) -{ - PARAM_SELF_PROLOGUE(AActor); - - PClassActor *lightning = PClass::FindActor(self->GetClass()->MissileName); - AActor *mo; - - if (lightning == NULL) - { - lightning = PClass::FindActor(NAME_LightningZap); - } - - CALL_ACTION(A_LightningClip, self); - - self->health -= 8; - if (self->health <= 0) - { - self->SetState (self->FindState(NAME_Death)); - return 0; - } - double deltaX = (pr_zap() - 128) * self->radius / 256; - double deltaY = (pr_zap() - 128) * self->radius / 256; - double deltaZ = (self->flags3 & MF3_FLOORHUGGER) ? 10 : -10; - - mo = Spawn(lightning, self->Vec3Offset(deltaX, deltaY, deltaZ), ALLOW_REPLACE); - if (mo) - { - mo->lastenemy = self; - mo->Vel.X = self->Vel.X; - mo->Vel.Y = self->Vel.Y; - mo->Vel.Z = (self->flags3 & MF3_FLOORHUGGER) ? 20 : -20; - mo->target = self->target; - } - if ((self->flags3 & MF3_FLOORHUGGER) && pr_zapf() < 160) - { - S_Sound (self, CHAN_BODY, self->ActiveSound, 1, ATTN_NORM); - } - return 0; -} - -//============================================================================ -// -// A_MLightningAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MLightningAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - PARAM_CLASS_DEF(floor, AActor); - PARAM_CLASS_DEF(ceiling, AActor); - - AActor *fmo, *cmo; - - fmo = P_SpawnPlayerMissile (self, floor); - cmo = P_SpawnPlayerMissile (self, ceiling); - if (fmo) - { - fmo->special1 = 0; - fmo->lastenemy = cmo; - CALL_ACTION(A_LightningZap, fmo); - } - if (cmo) - { - cmo->tracer = NULL; - cmo->lastenemy = fmo; - CALL_ACTION(A_LightningZap, cmo); - } - S_Sound (self, CHAN_BODY, "MageLightningFire", 1, ATTN_NORM); - - if (self->player != NULL) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - weapon->DepleteAmmo (weapon->bAltFire); - } - } - return 0; -} - -//============================================================================ -// -// A_ZapMimic -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ZapMimic) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - mo = self->lastenemy; - if (mo) - { - if (mo->state >= mo->FindState(NAME_Death)) - { - P_ExplodeMissile (self, NULL, NULL); - } - else - { - self->Vel.X = mo->Vel.X; - self->Vel.Y = mo->Vel.Y; - } - } - return 0; -} - -//============================================================================ -// -// A_LastZap -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LastZap) -{ - PARAM_SELF_PROLOGUE(AActor); - PClassActor *lightning = PClass::FindActor(self->GetClass()->MissileName); - - AActor *mo; - - if (lightning == NULL) - { - lightning = PClass::FindActor(NAME_LightningZap); - } - mo = Spawn(lightning, self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->SetState (mo->FindState (NAME_Death)); - mo->Vel.Z = 40; - mo->SetDamage(0); - } - return 0; -} - -//============================================================================ -// -// A_LightningRemove -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_LightningRemove) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - mo = self->lastenemy; - if (mo) - { - mo->lastenemy = NULL; - P_ExplodeMissile (mo, NULL, NULL); - } - return 0; -} diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 250927a5a9..22b52d18b2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1751,6 +1751,15 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target) } } +DEFINE_ACTION_FUNCTION(AActor, ExplodeMissile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER_DEF(line, line_t); + PARAM_OBJECT_DEF(target, AActor); + P_ExplodeMissile(self, line, target); + return 0; +} + void AActor::PlayBounceSound(bool onfloor) { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 189f700908..94adbf227a 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -289,6 +289,7 @@ class Actor : Thinker native native void NoiseAlert(Actor emitter, bool splash = false, double maxdist = 0); native void ClearBounce(); + native void ExplodeMissile(line lin = null, Actor target = null); native void RestoreDamage(); native int SpawnHealth(); native void SetDamage(int dmg); diff --git a/wadsrc/static/zscript/hexen/magelightning.txt b/wadsrc/static/zscript/hexen/magelightning.txt index b778451ac1..343c960120 100644 --- a/wadsrc/static/zscript/hexen/magelightning.txt +++ b/wadsrc/static/zscript/hexen/magelightning.txt @@ -16,9 +16,6 @@ class MWeapLightning : MageWeapon Tag "$TAG_MWEAPLIGHTNING"; } - action native void A_LightningReady(); - action native void A_MLightningAttack(class floor = "LightningFloor", class ceiling = "LightningCeiling"); - States { Spawn: @@ -50,6 +47,57 @@ class MWeapLightning : MageWeapon MLNG B 2 Bright Offset (0, 40); Goto Ready; } + + //============================================================================ + // + // A_LightningReady + // + //============================================================================ + + action void A_LightningReady() + { + A_WeaponReady(); + if (random[LightningReady]() < 160) + { + A_PlaySound ("MageLightningReady", CHAN_WEAPON); + } + } + + //============================================================================ + // + // A_MLightningAttack + // + //============================================================================ + + action void A_MLightningAttack(class floor = "LightningFloor", class ceiling = "LightningCeiling") + { + LightningFloor fmo = LightningFloor(SpawnPlayerMissile (floor)); + LightningCeiling cmo = LightningCeiling(SpawnPlayerMissile (ceiling)); + if (fmo) + { + fmo.special1 = 0; + fmo.lastenemy = cmo; + fmo.A_LightningZap(); + } + if (cmo) + { + cmo.tracer = NULL; + cmo.lastenemy = fmo; + cmo.A_LightningZap(); + } + A_PlaySound ("MageLightningFire", CHAN_BODY); + + if (player != NULL) + { + Weapon weapon = player.ReadyWeapon; + if (weapon != NULL) + { + weapon.DepleteAmmo (weapon.bAltFire); + } + } + } + + } // Ceiling Lightning -------------------------------------------------------- @@ -76,7 +124,7 @@ class Lightning : Actor if ((!thing.player && !thing.bBoss) || !(level.time&1)) { thing.DamageMobj(self, target, 3, 'Electric'); - A_PlaySound(self.AttackSound, CHAN_WEAPON, 1, true); + A_PlaySound(AttackSound, CHAN_WEAPON, 1, true); if (thing.bIsMonster && random[LightningHit]() < 64) { thing.Howl (); @@ -106,6 +154,8 @@ class Lightning : Actor class LightningCeiling : Lightning { + const ZAGSPEED = 1; + Default { Health 144; @@ -118,10 +168,6 @@ class LightningCeiling : Lightning RenderStyle "Add"; } - native void A_LightningZap(); - native void A_LightningClip(); - native void A_LightningRemove(); - States { Spawn: @@ -143,6 +189,126 @@ class LightningCeiling : Lightning ACLO E 1050; Stop; } + + //============================================================================ + // + // A_LightningClip + // + //============================================================================ + + void A_LightningClip() + { + Actor cMo; + Actor target = NULL; + int zigZag; + + if (bFloorHugger) + { + if (lastenemy == NULL) + { + return; + } + SetZ(floorz); + target = lastenemy.tracer; + } + else if (bCeilingHugger) + { + SetZ(ceilingz - Height); + target = tracer; + } + if (bFloorHugger) + { // floor lightning zig-zags, and forces the ceiling lightning to mimic + cMo = lastenemy; + zigZag = random[LightningClip](); + if((zigZag > 128 && special1 < 2) || special1 < -2) + { + Thrust(ZAGSPEED, angle + 90); + if(cMo) + { + cMo.Thrust(ZAGSPEED, angle + 90); + } + special1++; + } + else + { + Thrust(ZAGSPEED,angle - 90); + if(cMo) + { + cMo.Thrust(ZAGSPEED, angle - 90); + } + special1--; + } + } + if(target) + { + if(target.health <= 0) + { + ExplodeMissile(); + } + else + { + angle = AngleTo(target); + VelFromAngle(Speed / 2); + } + } + } + + + //============================================================================ + // + // A_LightningZap + // + //============================================================================ + + void A_LightningZap() + { + Class lightning = MissileName; + if (lightning == NULL) lightning = "LightningZap"; + + A_LightningClip(); + + health -= 8; + if (health <= 0) + { + SetStateLabel ("Death"); + return; + } + double deltaX = (random[LightningZap]() - 128) * radius / 256; + double deltaY = (random[LightningZap]() - 128) * radius / 256; + double deltaZ = (bFloorHugger) ? 10 : -10; + + Actor mo = Spawn(lightning, Vec3Offset(deltaX, deltaY, deltaZ), ALLOW_REPLACE); + if (mo) + { + mo.lastenemy = self; + mo.Vel.X = Vel.X; + mo.Vel.Y = Vel.Y; + mo.Vel.Z = (bFloorHugger) ? 20 : -20; + mo.target = target; + } + if (bFloorHugger && random[LightningZap]() < 160) + { + A_PlaySound (ActiveSound, CHAN_BODY); + } + } + + //============================================================================ + // + // A_LightningRemove + // + //============================================================================ + + void A_LightningRemove() + { + Actor mo = lastenemy; + if (mo) + { + bNoTarget = true; // tell A_ZapMimic that we are dead. The original code did a state pointer compare which is not safe. + mo.lastenemy = NULL; + mo.ExplodeMissile (); + } + } + } // Floor Lightning ---------------------------------------------------------- @@ -156,8 +322,6 @@ class LightningFloor : LightningCeiling RenderStyle "Add"; } - native void A_LastZap(); - States { Spawn: @@ -176,6 +340,26 @@ class LightningFloor : LightningCeiling MLF2 P 1 Bright A_HideThing; Goto Super::Death + 19; } + + //============================================================================ + // + // A_LastZap + // + //============================================================================ + + void A_LastZap() + { + Class lightning = MissileName; + if (lightning == NULL) lightning = "LightningZap"; + + Actor mo = Spawn(lightning, self.Pos, ALLOW_REPLACE); + if (mo) + { + mo.SetStateLabel ("Death"); + mo.Vel.Z = 40; + mo.SetDamage(0); + } + } } // Lightning Zap ------------------------------------------------------------ @@ -194,8 +378,6 @@ class LightningZap : Actor Obituary "$OB_MPMWEAPLIGHTNING"; } - native void A_ZapMimic(); - States { Spawn: @@ -235,4 +417,28 @@ class LightningZap : Actor return -1; } + //============================================================================ + // + // A_ZapMimic + // + //============================================================================ + + void A_ZapMimic() + { + Actor mo = lastenemy; + if (mo) + { + if (mo.bNoTarget) + { + ExplodeMissile (); + } + else + { + Vel.X = mo.Vel.X; + Vel.Y = mo.Vel.Y; + } + } + } + + } From ebd2c27e0ab2cd54af4f7937f09d35c879f8cf79 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 00:49:10 +0100 Subject: [PATCH 388/471] - scriptified Hexen's Bloodscourge and Serpent. - merged the FrontBlock searcher for the Bloodscourge into RoughMonsterSearch. This also fixes the bug that the searcher was not initialized properly for the MageBoss. --- src/CMakeLists.txt | 2 - src/g_hexen/a_hexenmisc.cpp | 2 - src/g_hexen/a_magestaff.cpp | 260 ---------------- src/g_hexen/a_serpent.cpp | 311 -------------------- src/p_enemy.cpp | 6 + src/p_local.h | 2 +- src/p_maputl.cpp | 54 +++- src/p_mobj.cpp | 7 + src/p_terrain.cpp | 15 + src/scripting/thingdef_data.cpp | 1 + src/scripting/vm/vm.h | 1 + wadsrc/static/zscript/actor.txt | 4 +- wadsrc/static/zscript/base.txt | 21 +- wadsrc/static/zscript/hexen/baseweapons.txt | 2 +- wadsrc/static/zscript/hexen/mageboss.txt | 37 ++- wadsrc/static/zscript/hexen/magestaff.txt | 132 ++++++++- wadsrc/static/zscript/hexen/serpent.txt | 270 ++++++++++++++++- 17 files changed, 507 insertions(+), 620 deletions(-) delete mode 100644 src/g_hexen/a_magestaff.cpp delete mode 100644 src/g_hexen/a_serpent.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1abd8e71bd..40d227fa42 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -860,8 +860,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.h sc_man_scanner.re g_hexen/a_heresiarch.cpp - g_hexen/a_magestaff.cpp - g_hexen/a_serpent.cpp g_hexen/a_spike.cpp g_hexen/a_teleportother.cpp g_strife/a_acolyte.cpp diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 45a407faa1..4cfd359f8f 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -25,7 +25,5 @@ // Include all the Hexen stuff here to reduce compile time #include "a_heresiarch.cpp" -#include "a_magestaff.cpp" -#include "a_serpent.cpp" #include "a_spike.cpp" #include "a_teleportother.cpp" diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp deleted file mode 100644 index 035744aba0..0000000000 --- a/src/g_hexen/a_magestaff.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "p_local.h" -#include "m_random.h" -#include "s_sound.h" -#include "a_hexenglobal.h" -#include "gstrings.h" -#include "a_weaponpiece.h" -#include "vm.h" -#include "doomstat.h" -*/ - -class AMageWeapon : public AWeapon -{ - DECLARE_CLASS (AMageWeapon, AWeapon); -public: -}; - -IMPLEMENT_CLASS(AMageWeapon, false, false) - -static FRandom pr_mstafftrack ("MStaffTrack"); -static FRandom pr_bloodscourgedrop ("BloodScourgeDrop"); - -void A_MStaffTrack (AActor *); -void A_DropBloodscourgePieces (AActor *); -void A_MStaffAttack (AActor *actor); -void A_MStaffPalette (AActor *actor); - -static AActor *FrontBlockCheck (AActor *mo, int index, void *); -static divline_t BlockCheckLine; - -//========================================================================== -// The Mages's Staff (Bloodscourge) ----------------------------------------- - -class AMWeapBloodscourge : public AMageWeapon -{ - DECLARE_CLASS (AMWeapBloodscourge, AMageWeapon) -public: - - void Serialize(FSerializer &arc) - { - Super::Serialize (arc); - arc("mstaffcount", MStaffCount); - } - PalEntry GetBlend () - { - if (paletteflash & PF_HEXENWEAPONS) - { - if (MStaffCount == 3) - return PalEntry(128, 100, 73, 0); - else if (MStaffCount == 2) - return PalEntry(128, 125, 92, 0); - else if (MStaffCount == 1) - return PalEntry(128, 150, 110, 0); - else - return PalEntry(0, 0, 0, 0); - } - else - { - return PalEntry (MStaffCount * 128 / 3, 151, 110, 0); - } - } - BYTE MStaffCount; -}; - -IMPLEMENT_CLASS(AMWeapBloodscourge, false, false) - -// Mage Staff FX2 (Bloodscourge) -------------------------------------------- - -class AMageStaffFX2 : public AActor -{ - DECLARE_CLASS(AMageStaffFX2, AActor) -public: - bool SpecialBlastHandling (AActor *source, double strength); -}; - -IMPLEMENT_CLASS(AMageStaffFX2, false, false) - -bool AMageStaffFX2::SpecialBlastHandling (AActor *source, double strength) -{ - // Reflect to originator - tracer = target; - target = source; - return true; -} - -//============================================================================ - -//============================================================================ -// -// MStaffSpawn -// -//============================================================================ - -void MStaffSpawn (AActor *pmo, DAngle angle, AActor *alttarget) -{ - AActor *mo; - FTranslatedLineTarget t; - - mo = P_SpawnPlayerMissile (pmo, 0, 0, 8, RUNTIME_CLASS(AMageStaffFX2), angle, &t); - if (mo) - { - mo->target = pmo; - if (t.linetarget && !t.unlinked) - mo->tracer = t.linetarget; - else - mo->tracer = alttarget; - } -} - -//============================================================================ -// -// A_MStaffAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MStaffAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - player_t *player; - FTranslatedLineTarget t; - - if (NULL == (player = self->player)) - { - return 0; - } - - AMWeapBloodscourge *weapon = static_cast (self->player->ReadyWeapon); - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - angle = self->Angles.Yaw; - - // [RH] Let's try and actually track what the player aimed at - P_AimLineAttack (self, angle, PLAYERMISSILERANGE, &t, 32.); - if (t.linetarget == NULL) - { - BlockCheckLine.x = self->X(); - BlockCheckLine.y = self->Y(); - BlockCheckLine.dx = -angle.Sin(); - BlockCheckLine.dy = -angle.Cos(); - t.linetarget = P_BlockmapSearch (self, 10, FrontBlockCheck); - } - MStaffSpawn (self, angle, t.linetarget); - MStaffSpawn (self, angle-5, t.linetarget); - MStaffSpawn (self, angle+5, t.linetarget); - S_Sound (self, CHAN_WEAPON, "MageStaffFire", 1, ATTN_NORM); - weapon->MStaffCount = 3; - return 0; -} - -//============================================================================ -// -// A_MStaffPalette -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MStaffPalette) -{ - PARAM_ACTION_PROLOGUE(AActor); - - if (self->player != NULL) - { - AMWeapBloodscourge *weapon = static_cast (self->player->ReadyWeapon); - if (weapon != NULL && weapon->MStaffCount != 0) - { - weapon->MStaffCount--; - } - } - return 0; -} - -//============================================================================ -// -// A_MStaffTrack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MStaffTrack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if ((self->tracer == 0) && (pr_mstafftrack()<50)) - { - self->tracer = P_RoughMonsterSearch (self, 10, true); - } - P_SeekerMissile(self, 2, 10); - return 0; -} - -//============================================================================ -// -// FrontBlockCheck -// -// [RH] Like RoughBlockCheck, but it won't return anything behind a line. -// -//============================================================================ - -static AActor *FrontBlockCheck (AActor *mo, int index, void *) -{ - FBlockNode *link; - - for (link = blocklinks[index]; link != NULL; link = link->NextActor) - { - if (link->Me != mo) - { - if (P_PointOnDivlineSide(link->Me->X(), link->Me->Y(), &BlockCheckLine) == 0 && - mo->IsOkayToAttack (link->Me)) - { - return link->Me; - } - } - } - return NULL; -} - -//============================================================================ -// -// MStaffSpawn2 - for use by mage class boss -// -//============================================================================ - -void MStaffSpawn2 (AActor *actor, DAngle angle) -{ - AActor *mo; - - mo = P_SpawnMissileAngleZ (actor, actor->Z()+40, RUNTIME_CLASS(AMageStaffFX2), angle, 0.); - if (mo) - { - mo->target = actor; - mo->tracer = P_BlockmapSearch (mo, 10, FrontBlockCheck); - } -} - -//============================================================================ -// -// A_MStaffAttack2 - for use by mage class boss -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MageAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - { - return 0; - } - DAngle angle = self->Angles.Yaw; - MStaffSpawn2(self, angle); - MStaffSpawn2(self, angle - 5); - MStaffSpawn2(self, angle + 5); - S_Sound(self, CHAN_WEAPON, "MageStaffFire", 1, ATTN_NORM); - return 0; -} diff --git a/src/g_hexen/a_serpent.cpp b/src/g_hexen/a_serpent.cpp deleted file mode 100644 index 6f435747ed..0000000000 --- a/src/g_hexen/a_serpent.cpp +++ /dev/null @@ -1,311 +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 "p_terrain.h" -#include "vm.h" -*/ - -static FRandom pr_serpentchase ("SerpentChase"); -static FRandom pr_serpenthump ("SerpentHump"); -static FRandom pr_serpentattack ("SerpentAttack"); -static FRandom pr_serpentmeattack ("SerpentMeAttack"); -static FRandom pr_serpentgibs ("SerpentGibs"); -static FRandom pr_delaygib ("DelayGib"); - -//============================================================================ -// -// A_SerpentUnHide -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentUnHide) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->renderflags &= ~RF_INVISIBLE; - self->Floorclip = 24; - return 0; -} - -//============================================================================ -// -// A_SerpentHide -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentHide) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->renderflags |= RF_INVISIBLE; - self->Floorclip = 0; - return 0; -} - -//============================================================================ -// -// A_SerpentRaiseHump -// -// Raises the hump above the surface by raising the floorclip level -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentRaiseHump) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Floorclip -= 4; - return 0; -} - -//============================================================================ -// -// A_SerpentLowerHump -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentLowerHump) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Floorclip += 4; - return 0; -} - -//============================================================================ -// -// A_SerpentHumpDecide -// -// Decided whether to hump up, or if the mobj is a serpent leader, -// to missile attack -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentHumpDecide) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->MissileState != NULL) - { - if (pr_serpenthump() > 30) - { - return 0; - } - else if (pr_serpenthump() < 40) - { // Missile attack - self->SetState (self->MeleeState); - return 0; - } - } - else if (pr_serpenthump() > 3) - { - return 0; - } - if (!self->CheckMeleeRange ()) - { // The hump shouldn't occur when within melee range - if (self->MissileState != NULL && pr_serpenthump() < 128) - { - self->SetState (self->MeleeState); - } - else - { - self->SetState (self->FindState ("Hump")); - S_Sound (self, CHAN_BODY, "SerpentActive", 1, ATTN_NORM); - } - } - return 0; -} - -//============================================================================ -// -// A_SerpentCheckForAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentCheckForAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->target) - { - return 0; - } - if (self->MissileState != NULL) - { - if (!self->CheckMeleeRange ()) - { - self->SetState (self->FindState ("Attack")); - return 0; - } - } - if (P_CheckMeleeRange2 (self)) - { - self->SetState (self->FindState ("Walk")); - } - else if (self->CheckMeleeRange ()) - { - if (pr_serpentattack() < 32) - { - self->SetState (self->FindState ("Walk")); - } - else - { - self->SetState (self->FindState ("Attack")); - } - } - return 0; -} - -//============================================================================ -// -// A_SerpentChooseAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentChooseAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->target || self->CheckMeleeRange()) - { - return 0; - } - if (self->MissileState != NULL) - { - self->SetState (self->MissileState); - } - return 0; -} - -//============================================================================ -// -// A_SerpentMeleeAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentMeleeAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->target) - { - return 0; - } - if (self->CheckMeleeRange ()) - { - int damage = pr_serpentmeattack.HitDice (5); - 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, "SerpentMeleeHit", 1, ATTN_NORM); - } - if (pr_serpentmeattack() < 96) - { - CALL_ACTION(A_SerpentCheckForAttack, self); - } - return 0; -} - -//============================================================================ -// -// A_SerpentSpawnGibs -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentSpawnGibs) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - static const char *GibTypes[] = - { - "SerpentGib3", - "SerpentGib2", - "SerpentGib1" - }; - - for (int i = countof(GibTypes)-1; i >= 0; --i) - { - double x = (pr_serpentgibs() - 128) / 16.; - double y = (pr_serpentgibs() - 128) / 16.; - - mo = Spawn (GibTypes[i], self->Vec2OffsetZ(x, y, self->floorz + 1), ALLOW_REPLACE); - if (mo) - { - mo->Vel.X = (pr_serpentgibs() - 128) / 1024.f; - mo->Vel.Y = (pr_serpentgibs() - 128) / 1024.f; - mo->Floorclip = 6; - } - } - return 0; -} - -//============================================================================ -// -// A_FloatGib -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FloatGib) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Floorclip -= 1; - return 0; -} - -//============================================================================ -// -// A_SinkGib -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SinkGib) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Floorclip += 1;; - return 0; -} - -//============================================================================ -// -// A_DelayGib -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_DelayGib) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->tics -= pr_delaygib()>>2; - return 0; -} - -//============================================================================ -// -// A_SerpentHeadCheck -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SerpentHeadCheck) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->Z() <= self->floorz) - { - if (Terrains[P_GetThingFloorType(self)].IsLiquid) - { - P_HitFloor (self); - self->SetState (NULL); - } - else - { - self->SetState (self->FindState(NAME_Death)); - } - } - return 0; -} - diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index a4be4dd1b0..4f4920c6fb 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -365,6 +365,12 @@ bool P_CheckMeleeRange2 (AActor *actor) return true; } +DEFINE_ACTION_FUNCTION(AActor, CheckMeleeRange2) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(P_CheckMeleeRange2(self)); +} + //============================================================================= // diff --git a/src/p_local.h b/src/p_local.h index d759828dce..12b4a40a3c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -238,7 +238,7 @@ enum PCM AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params = NULL); -AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false); +AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false, bool frontonly = false); // // P_MAP diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 5bb3bea0f0..2d2472cbda 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -45,7 +45,6 @@ #include "templates.h" #include "po_man.h" -static AActor *RoughBlockCheck (AActor *mo, int index, void *); sector_t *P_PointInSectorBuggy(double x, double y); int P_VanillaPointOnDivlineSide(double x, double y, const divline_t* line); @@ -1685,19 +1684,6 @@ FPathTraverse::~FPathTraverse() // distance is in MAPBLOCKUNITS //=========================================================================== -AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable) -{ - return P_BlockmapSearch (mo, distance, RoughBlockCheck, (void *)onlyseekable); -} - -DEFINE_ACTION_FUNCTION(AActor, RoughMonsterSearch) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(distance); - PARAM_BOOL_DEF(onlyseekable); - ACTION_RETURN_OBJECT(P_RoughMonsterSearch(self, distance, onlyseekable)); -} - AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params) { int blockX; @@ -1787,6 +1773,13 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in return NULL; } +struct BlockCheckInfo +{ + bool onlyseekable; + bool frontonly; + divline_t frontline; +}; + //=========================================================================== // // RoughBlockCheck @@ -1795,14 +1788,19 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in static AActor *RoughBlockCheck (AActor *mo, int index, void *param) { - bool onlyseekable = param != NULL; + BlockCheckInfo *info = (BlockCheckInfo *)param; + FBlockNode *link; for (link = blocklinks[index]; link != NULL; link = link->NextActor) { if (link->Me != mo) { - if (onlyseekable && !mo->CanSeek(link->Me)) + if (info->onlyseekable && !mo->CanSeek(link->Me)) + { + continue; + } + if (info->frontonly && P_PointOnDivlineSide(link->Me->X(), link->Me->Y(), &info->frontline) != 0) { continue; } @@ -1815,6 +1813,30 @@ static AActor *RoughBlockCheck (AActor *mo, int index, void *param) return NULL; } +AActor *P_RoughMonsterSearch(AActor *mo, int distance, bool onlyseekable, bool frontonly) +{ + BlockCheckInfo info; + info.onlyseekable = onlyseekable; + if ((info.frontonly = frontonly)) + { + info.frontline.x = mo->X(); + info.frontline.y = mo->Y(); + info.frontline.dx = -mo->Angles.Yaw.Sin(); + info.frontline.dy = -mo->Angles.Yaw.Cos(); + } + + return P_BlockmapSearch(mo, distance, RoughBlockCheck, (void *)&info); +} + +DEFINE_ACTION_FUNCTION(AActor, RoughMonsterSearch) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(distance); + PARAM_BOOL_DEF(onlyseekable); + PARAM_BOOL_DEF(frontonly); + ACTION_RETURN_OBJECT(P_RoughMonsterSearch(self, distance, onlyseekable, frontonly)); +} + //========================================================================== // // [RH] LinkToWorldForMapThing diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 22b52d18b2..6268c93956 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5908,6 +5908,13 @@ int P_GetThingFloorType (AActor *thing) } } +DEFINE_ACTION_FUNCTION(AActor, GetFloorTerrain) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_POINTER(&Terrains[P_GetThingFloorType(self)]); +} + + //--------------------------------------------------------------------------- // // FUNC P_HitWater diff --git a/src/p_terrain.cpp b/src/p_terrain.cpp index 2504bad94e..3adc94876d 100644 --- a/src/p_terrain.cpp +++ b/src/p_terrain.cpp @@ -724,3 +724,18 @@ FName P_GetTerrainName(int terrainnum) } } +DEFINE_FIELD_NAMED(FTerrainDef, Name, TerrainName) +DEFINE_FIELD(FTerrainDef, Splash) +DEFINE_FIELD(FTerrainDef, DamageAmount) +DEFINE_FIELD(FTerrainDef, DamageMOD) +DEFINE_FIELD(FTerrainDef, DamageTimeMask) +DEFINE_FIELD(FTerrainDef, FootClip) +DEFINE_FIELD(FTerrainDef, StepVolume) +DEFINE_FIELD(FTerrainDef, WalkStepTics) +DEFINE_FIELD(FTerrainDef, RunStepTics) +DEFINE_FIELD(FTerrainDef, LeftStepSound) +DEFINE_FIELD(FTerrainDef, RightStepSound) +DEFINE_FIELD(FTerrainDef, IsLiquid) +DEFINE_FIELD(FTerrainDef, AllowProtection) +DEFINE_FIELD(FTerrainDef, Friction) +DEFINE_FIELD(FTerrainDef, MoveFactor) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 6f0cad099c..d17e10420b 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -45,6 +45,7 @@ #include "autosegs.h" #include "p_maputl.h" #include "gi.h" +#include "p_terrain.h" static TArray properties; static TArray AFTable; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index c7082ff763..fdee430e12 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1095,6 +1095,7 @@ void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *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_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_GENERIC); 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_VEC2(v) do { DVector2 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector2(u); return 1; } return 0; } while(0) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 94adbf227a..09b983843b 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -288,6 +288,7 @@ class Actor : Thinker native native void SetFriendPlayer(PlayerInfo player); native void NoiseAlert(Actor emitter, bool splash = false, double maxdist = 0); native void ClearBounce(); + native TerrainDef GetFloorTerrain(); native void ExplodeMissile(line lin = null, Actor target = null); native void RestoreDamage(); @@ -310,7 +311,7 @@ class Actor : Thinker native native Actor SpawnMissileAngleZSpeed (double z, class type, double angle, double vz, double speed, Actor owner = null, bool checkspawn = true); native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); - native Actor RoughMonsterSearch(int distance, bool onlyseekable = false); + native Actor RoughMonsterSearch(int distance, bool onlyseekable = false, bool frontonly = false); native int ApplyDamageFactor(Name damagetype, int damage); native int GetModifiedDamage(Name damagetype, int damage, bool passive); @@ -329,6 +330,7 @@ class Actor : Thinker native native void SetIdle(bool nofunction = false); native bool CheckMeleeRange(); + native bool CheckMeleeRange2(); 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); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index c0894eda86..08d655caf6 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -247,4 +247,23 @@ struct Wads } native static int CheckNumForName(string name, int ns, int wadnum = -1, bool exact = false); -} \ No newline at end of file +} + +struct TerrainDef native +{ + native Name TerrainName; + native int Splash; + native int DamageAmount; + native Name DamageMOD; + native int DamageTimeMask; + native double FootClip; + native float StepVolume; + native int WalkStepTics; + native int RunStepTics; + native Sound LeftStepSound; + native Sound RightStepSound; + native bool IsLiquid; + native bool AllowProtection; + native double Friction; + native double MoveFactor; +}; diff --git a/wadsrc/static/zscript/hexen/baseweapons.txt b/wadsrc/static/zscript/hexen/baseweapons.txt index b7e2bd398a..a1e1af9bd6 100644 --- a/wadsrc/static/zscript/hexen/baseweapons.txt +++ b/wadsrc/static/zscript/hexen/baseweapons.txt @@ -19,7 +19,7 @@ class ClericWeapon : Weapon } } -class MageWeapon : Weapon native +class MageWeapon : Weapon { Default { diff --git a/wadsrc/static/zscript/hexen/mageboss.txt b/wadsrc/static/zscript/hexen/mageboss.txt index f9637f8d17..0c081d786d 100644 --- a/wadsrc/static/zscript/hexen/mageboss.txt +++ b/wadsrc/static/zscript/hexen/mageboss.txt @@ -18,8 +18,6 @@ class MageBoss : Actor Obituary "$OB_MBOSS"; } - native void A_MageAttack(); - States { Spawn: @@ -83,4 +81,39 @@ class MageBoss : Actor FDTH V 4 Bright; Stop; } + + //============================================================================ + // + // MStaffSpawn2 - for use by mage class boss + // + //============================================================================ + + void MStaffSpawn2 (double angle) + { + Actor mo = SpawnMissileAngleZ (pos.z + 40, "MageStaffFX2", angle, 0.); + if (mo) + { + mo.target = self; + mo.tracer = RoughMonsterSearch(10, true, true); + } + } + + //============================================================================ + // + // A_MStaffAttack2 - for use by mage class boss + // + //============================================================================ + + void A_MageAttack() + { + if (target == NULL) + { + return; + } + MStaffSpawn2(angle); + MStaffSpawn2(angle - 5); + MStaffSpawn2(angle + 5); + A_PlaySound("MageStaffFire", CHAN_WEAPON); + } + } diff --git a/wadsrc/static/zscript/hexen/magestaff.txt b/wadsrc/static/zscript/hexen/magestaff.txt index d485a72fa9..e450952404 100644 --- a/wadsrc/static/zscript/hexen/magestaff.txt +++ b/wadsrc/static/zscript/hexen/magestaff.txt @@ -76,8 +76,10 @@ class BloodscourgeDrop : Actor // The Mages's Staff (Bloodscourge) ----------------------------------------- -class MWeapBloodscourge : MageWeapon native +class MWeapBloodscourge : MageWeapon { + int MStaffCount; + Default { Health 3; @@ -97,9 +99,6 @@ class MWeapBloodscourge : MageWeapon native Tag "$TAG_MWEAPBLOODSCOURGE"; } - action native void A_MStaffAttack(); - action native void A_MStaffPalette(); - States { Spawn: @@ -123,11 +122,104 @@ class MWeapBloodscourge : MageWeapon native MSTF J 5 Offset (0, 36); Goto Ready; } + + //============================================================================ + // + // + // + //============================================================================ + + override Color GetBlend () + { + if (paletteflash & PF_HEXENWEAPONS) + { + if (MStaffCount == 3) + return Color(128, 100, 73, 0); + else if (MStaffCount == 2) + return Color(128, 125, 92, 0); + else if (MStaffCount == 1) + return Color(128, 150, 110, 0); + else + return Color(0, 0, 0, 0); + } + else + { + return Color (MStaffCount * 128 / 3, 151, 110, 0); + } + } + + //============================================================================ + // + // MStaffSpawn + // + //============================================================================ + + private action void MStaffSpawn (double angle, Actor alttarget) + { + FTranslatedLineTarget t; + + Actor mo = SpawnPlayerMissile ("MageStaffFX2", angle, pLineTarget:t); + if (mo) + { + mo.target = self; + if (t.linetarget && !t.unlinked) + mo.tracer = t.linetarget; + else + mo.tracer = alttarget; + } + } + + //============================================================================ + // + // A_MStaffAttack + // + //============================================================================ + + action void A_MStaffAttack() + { + FTranslatedLineTarget t; + + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != NULL) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + + // [RH] Let's try and actually track what the player aimed at + AimLineAttack (angle, PLAYERMISSILERANGE, t, 32.); + if (t.linetarget == NULL) + { + t.linetarget = RoughMonsterSearch(10, true, true); + } + MStaffSpawn (angle, t.linetarget); + MStaffSpawn (angle-5, t.linetarget); + MStaffSpawn (angle+5, t.linetarget); + A_PlaySound ("MageStaffFire", CHAN_WEAPON); + invoker.MStaffCount = 3; + } + + //============================================================================ + // + // A_MStaffPalette + // + //============================================================================ + + action void A_MStaffPalette() + { + if (invoker.MStaffCount > 0) invoker.MStaffCount--; + } } + // Mage Staff FX2 (Bloodscourge) -------------------------------------------- -class MageStaffFX2 : Actor native +class MageStaffFX2 : Actor { Default { @@ -143,7 +235,6 @@ class MageStaffFX2 : Actor native Obituary "$OB_MPMWEAPBLOODSCOURGE"; } - native void A_MStaffTrack(); States { @@ -158,6 +249,12 @@ class MageStaffFX2 : Actor native Stop; } + //============================================================================ + // + // + // + //============================================================================ + override int SpecialMissileHit (Actor victim) { if (victim != target && !victim.player && !victim.bBoss) @@ -168,5 +265,26 @@ class MageStaffFX2 : Actor native return -1; } - + override bool SpecialBlastHandling (Actor source, double strength) + { + // Reflect to originator + tracer = target; + target = source; + return true; + } + + //============================================================================ + // + // A_MStaffTrack + // + //============================================================================ + + void A_MStaffTrack() + { + if (tracer == null && random[MStaffTrack]() < 50) + { + tracer = RoughMonsterSearch (10, true); + } + A_SeekerMissile(2, 10); + } } diff --git a/wadsrc/static/zscript/hexen/serpent.txt b/wadsrc/static/zscript/hexen/serpent.txt index 70fb2195a9..6eaafcfd1f 100644 --- a/wadsrc/static/zscript/hexen/serpent.txt +++ b/wadsrc/static/zscript/hexen/serpent.txt @@ -24,16 +24,6 @@ class Serpent : Actor 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: @@ -99,6 +89,203 @@ class Serpent : Actor SSPT N 5 A_SerpentMeleeAttack; Goto Dive; } + + //============================================================================ + // + // A_SerpentUnHide + // + //============================================================================ + + void A_SerpentUnHide() + { + bInvisible = false; + Floorclip = 24; + } + + //============================================================================ + // + // A_SerpentHide + // + //============================================================================ + + void A_SerpentHide() + { + bInvisible = true; + Floorclip = 0; + } + + //============================================================================ + // + // A_SerpentRaiseHump + // + // Raises the hump above the surface by raising the floorclip level + //============================================================================ + + void A_SerpentRaiseHump() + { + Floorclip -= 4; + } + + //============================================================================ + // + // A_SerpentLowerHump + // + //============================================================================ + + void A_SerpentLowerHump() + { + Floorclip += 4; + } + + //============================================================================ + // + // A_SerpentHumpDecide + // + // Decided whether to hump up, or if the mobj is a serpent leader, + // to missile attack + //============================================================================ + + void A_SerpentHumpDecide() + { + if (MissileState != NULL) + { + if (random[SerpentHump]() > 30) + { + return; + } + else if (random[SerpentHump]() < 40) + { // Missile attack + SetState (MeleeState); + return; + } + } + else if (random[SerpentHump]() > 3) + { + return; + } + if (!CheckMeleeRange ()) + { // The hump shouldn't occur when within melee range + if (MissileState != NULL && random[SerpentHump]() < 128) + { + SetState (MeleeState); + } + else + { + SetStateLabel("Hump"); + A_PlaySound ("SerpentActive", CHAN_BODY); + } + } + } + + //============================================================================ + // + // A_SerpentCheckForAttack + // + //============================================================================ + + void A_SerpentCheckForAttack() + { + if (!target) + { + return; + } + if (MissileState != NULL) + { + if (!CheckMeleeRange ()) + { + SetStateLabel ("Attack"); + return; + } + } + if (CheckMeleeRange2 ()) + { + SetStateLabel ("Walk"); + } + else if (CheckMeleeRange ()) + { + if (random[SerpentAttack]() < 32) + { + SetStateLabel ("Walk"); + } + else + { + SetStateLabel ("Attack"); + } + } + } + + //============================================================================ + // + // A_SerpentChooseAttack + // + //============================================================================ + + void A_SerpentChooseAttack() + { + if (!target || CheckMeleeRange()) + { + return; + } + if (MissileState != NULL) + { + SetState (MissileState); + } + } + + //============================================================================ + // + // A_SerpentMeleeAttack + // + //============================================================================ + + void A_SerpentMeleeAttack() + { + if (!target) + { + return; + } + if (CheckMeleeRange ()) + { + int damage = random[SerpentAttack](1, 8) * 5; + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + A_PlaySound ("SerpentMeleeHit", CHAN_BODY); + } + if (random[SerpentAttack]() < 96) + { + A_SerpentCheckForAttack(); + } + } + + //============================================================================ + // + // A_SerpentSpawnGibs + // + //============================================================================ + + void A_SerpentSpawnGibs() + { + static const class GibTypes[] = + { + "SerpentGib3", + "SerpentGib2", + "SerpentGib1" + }; + + for (int i = 2; i >= 0; --i) + { + double x = (random[SerpentGibs]() - 128) / 16.; + double y = (random[SerpentGibs]() - 128) / 16.; + + Actor mo = Spawn (GibTypes[i], Vec2OffsetZ(x, y, floorz + 1), ALLOW_REPLACE); + if (mo) + { + mo.Vel.X = (random[SerpentGibs]() - 128) / 1024.f; + mo.Vel.Y = (random[SerpentGibs]() - 128) / 1024.f; + mo.Floorclip = 6; + } + } + } } // Serpent Leader ----------------------------------------------------------- @@ -159,8 +346,6 @@ class SerpentHead : Actor +NOBLOCKMAP } - native void A_SerpentHeadCheck(); - States { Spawn: @@ -170,6 +355,28 @@ class SerpentHead : Actor SSXD S -1; Loop; } + + //============================================================================ + // + // A_SerpentHeadCheck + // + //============================================================================ + + void A_SerpentHeadCheck() + { + if (pos.z <= floorz) + { + if (GetFloorTerrain().IsLiquid) + { + HitFloor (); + Destroy(); + } + else + { + SetStateLabel ("NAME_Death"); + } + } + } } // Serpent Gib 1 ------------------------------------------------------------ @@ -183,10 +390,6 @@ class SerpentGib1 : Actor +NOBLOCKMAP +NOGRAVITY } - native void A_FloatGib(); - native void A_DelayGib(); - native void A_SinkGib(); - States { Spawn: @@ -199,6 +402,41 @@ class SerpentGib1 : Actor SSXD QQQ 8 A_SinkGib; Stop; } + + //============================================================================ + // + // A_FloatGib + // + //============================================================================ + + void A_FloatGib() + { + Floorclip -= 1; + } + + //============================================================================ + // + // A_SinkGib + // + //============================================================================ + + void A_SinkGib() + { + Floorclip += 1; + } + + //============================================================================ + // + // A_DelayGib + // + //============================================================================ + + void A_DelayGib() + { + tics -= random[DelayGib]() >> 2; + } + + } // Serpent Gib 2 ------------------------------------------------------------ From d4427e696d12efa08b0de90db9ff22640d4c0bc6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 01:30:36 +0100 Subject: [PATCH 389/471] - scriptified Hexen's Banishment Device. --- src/CMakeLists.txt | 1 - src/g_game.cpp | 19 +- src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_teleportother.cpp | 198 ------------------ wadsrc/static/zscript/base.txt | 6 + wadsrc/static/zscript/hexen/teleportother.txt | 134 +++++++++++- 6 files changed, 149 insertions(+), 210 deletions(-) delete mode 100644 src/g_hexen/a_teleportother.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40d227fa42..553a66c127 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_hexen/a_teleportother.cpp g_strife/a_acolyte.cpp g_strife/a_alienspectres.cpp g_strife/a_coin.cpp diff --git a/src/g_game.cpp b/src/g_game.cpp index 350669cfea..b5729283e9 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1540,15 +1540,28 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart) { PARAM_PROLOGUE; unsigned int selections = deathmatchstarts.Size(); - unsigned int i = pr_dmspawn() % selections; + DVector3 pos; + int angle; + if (selections == 0) + { + angle = INT_MAX; + pos = DVector3(0, 0, 0); + } + else + { + unsigned int i = pr_dmspawn() % selections; + angle = deathmatchstarts[i].angle; + pos = deathmatchstarts[i].pos; + } + if (numret > 1) { - ret[1].SetInt(deathmatchstarts[i].angle); + ret[1].SetInt(angle); numret = 2; } if (numret > 0) { - ret[0].SetVector(deathmatchstarts[i].pos); + ret[0].SetVector(pos); } return numret; } diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 4cfd359f8f..f871e82d9a 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -26,4 +26,3 @@ // Include all the Hexen stuff here to reduce compile time #include "a_heresiarch.cpp" #include "a_spike.cpp" -#include "a_teleportother.cpp" diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp deleted file mode 100644 index 0e7dd018d7..0000000000 --- a/src/g_hexen/a_teleportother.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "s_sound.h" -#include "p_lnspec.h" -#include "m_random.h" -#include "vm.h" -#include "g_level.h" -#include "doomstat.h" -*/ - -#define TELEPORT_LIFE 1 - -static FRandom pr_telestarts ("TeleStarts"); -static FRandom pr_teledm ("TeleDM"); - -void A_TeloSpawnA (AActor *); -void A_TeloSpawnB (AActor *); -void A_TeloSpawnC (AActor *); -void A_TeloSpawnD (AActor *); -void A_CheckTeleRing (AActor *); -void P_TeleportToPlayerStarts (AActor *victim); -void P_TeleportToDeathmatchStarts (AActor *victim); - -// Teleport Other Artifact -------------------------------------------------- - -class AArtiTeleportOther : public AInventory -{ - DECLARE_CLASS (AArtiTeleportOther, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiTeleportOther, false, false) - -// Teleport Other FX -------------------------------------------------------- - -class ATelOtherFX1 : public AActor -{ - DECLARE_CLASS (ATelOtherFX1, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(ATelOtherFX1, false, false) - -static void TeloSpawn (AActor *source, const char *type) -{ - AActor *fx; - - fx = Spawn (type, source->Pos(), ALLOW_REPLACE); - if (fx) - { - fx->special1 = TELEPORT_LIFE; // Lifetime countdown - fx->Angles.Yaw = source->Angles.Yaw; - fx->target = source->target; - fx->Vel = source->Vel / 2; - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnA) -{ - PARAM_SELF_PROLOGUE(AActor); - TeloSpawn (self, "TelOtherFX2"); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnB) -{ - PARAM_SELF_PROLOGUE(AActor); - TeloSpawn (self, "TelOtherFX3"); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnC) -{ - PARAM_SELF_PROLOGUE(AActor); - TeloSpawn (self, "TelOtherFX4"); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnD) -{ - PARAM_SELF_PROLOGUE(AActor); - TeloSpawn (self, "TelOtherFX5"); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CheckTeleRing) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->special1-- <= 0) - { - self->SetState (self->FindState(NAME_Death)); - } - return 0; -} - -//=========================================================================== -// -// Activate Teleport Other -// -//=========================================================================== - -bool AArtiTeleportOther::Use (bool pickup) -{ - AActor *mo; - - mo = P_SpawnPlayerMissile (Owner, RUNTIME_CLASS(ATelOtherFX1)); - if (mo) - { - mo->target = Owner; - } - return true; -} - -//=========================================================================== -// -// Perform Teleport Other -// -//=========================================================================== - -int ATelOtherFX1::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if ((target->flags3 & MF3_ISMONSTER || target->player != NULL) && - !(target->flags2 & MF2_BOSS) && - !(target->flags3 & MF3_NOTELEOTHER)) - { - if (target->player) - { - if (deathmatch) - P_TeleportToDeathmatchStarts (target); - else - P_TeleportToPlayerStarts (target); - } - else - { - // If death action, run it upon teleport - if (target->flags3 & MF3_ISMONSTER && target->special) - { - target->RemoveFromHash (); - P_ExecuteSpecial(target->special, NULL, level.flags & LEVEL_ACTOWNSPECIAL - ? target : (AActor *)(this->target), false, target->args[0], target->args[1], - target->args[2], target->args[3], target->args[4]); - target->special = 0; - } - - // Send all monsters to deathmatch spots - P_TeleportToDeathmatchStarts (target); - } - } - return -1; -} - -//=========================================================================== -// -// P_TeleportToPlayerStarts -// -//=========================================================================== - -void P_TeleportToPlayerStarts (AActor *victim) -{ - DVector3 dest; - - FPlayerStart *start = G_PickPlayerStart(0, PPS_FORCERANDOM | PPS_NOBLOCKINGCHECK); - dest = start->pos; - dest.Z = ONFLOORZ; - P_Teleport (victim, dest, (double)start->angle, TELF_SOURCEFOG | TELF_DESTFOG); -} - -//=========================================================================== -// -// P_TeleportToDeathmatchStarts -// -//=========================================================================== - -void P_TeleportToDeathmatchStarts (AActor *victim) -{ - unsigned int i, selections; - DVector3 dest; - - selections = deathmatchstarts.Size (); - if (selections > 0) - { - i = pr_teledm() % selections; - dest = deathmatchstarts[i].pos; - dest.Z = ONFLOORZ; - P_Teleport (victim, dest, (double)deathmatchstarts[i].angle, TELF_SOURCEFOG | TELF_DESTFOG); - } - else - { - P_TeleportToPlayerStarts (victim); - } -} diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 08d655caf6..3a96cbbcbf 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -267,3 +267,9 @@ struct TerrainDef native native double Friction; native double MoveFactor; }; + +enum EPickStart +{ + PPS_FORCERANDOM = 1, + PPS_NOBLOCKINGCHECK = 2, +} diff --git a/wadsrc/static/zscript/hexen/teleportother.txt b/wadsrc/static/zscript/hexen/teleportother.txt index 2de144d5fa..f7be0ebff7 100644 --- a/wadsrc/static/zscript/hexen/teleportother.txt +++ b/wadsrc/static/zscript/hexen/teleportother.txt @@ -1,7 +1,7 @@ // Teleport Other Artifact -------------------------------------------------- -class ArtiTeleportOther : Inventory native +class ArtiTeleportOther : Inventory { Default { @@ -22,13 +22,29 @@ class ArtiTeleportOther : Inventory native TELO ABCD 5; Loop; } + + //=========================================================================== + // + // Activate Teleport Other + // + //=========================================================================== + + override bool Use (bool pickup) + { + Owner.SpawnPlayerMissile ("TelOtherFX1"); + return true; + } + + } // Teleport Other FX -------------------------------------------------------- -class TelOtherFX1 : Actor native +class TelOtherFX1 : Actor { + const TELEPORT_LIFE = 1; + Default { Damage 10001; @@ -41,11 +57,6 @@ class TelOtherFX1 : Actor native Speed 20; } - native void A_TeloSpawnA(); - native void A_TeloSpawnB(); - native void A_TeloSpawnC(); - native void A_TeloSpawnD(); - native void A_CheckTeleRing (); States { @@ -63,6 +74,115 @@ class TelOtherFX1 : Actor native TRNG E 3 Bright; Stop; } + + private void TeloSpawn (class type) + { + Actor fx = Spawn (type, pos, ALLOW_REPLACE); + if (fx) + { + fx.special1 = TELEPORT_LIFE; // Lifetime countdown + fx.angle = angle; + fx.target = target; + fx.Vel = Vel / 2; + } + } + + void A_TeloSpawnA() + { + TeloSpawn ("TelOtherFX2"); + } + + void A_TeloSpawnB() + { + TeloSpawn ("TelOtherFX3"); + } + + void A_TeloSpawnC() + { + TeloSpawn ("TelOtherFX4"); + } + + void A_TeloSpawnD() + { + TeloSpawn ("TelOtherFX5"); + } + + void A_CheckTeleRing () + { + if (self.special1-- <= 0) + { + self.SetStateLabel("Death"); + } + } + + //=========================================================================== + // + // Perform Teleport Other + // + //=========================================================================== + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if ((target.bIsMonster || target.player != NULL) && + !target.bBoss && !target.bNoTeleOther) + { + if (target.player) + { + if (deathmatch) + P_TeleportToDeathmatchStarts (target); + else + P_TeleportToPlayerStarts (target); + } + else + { + // If death action, run it upon teleport + if (target.bIsMonster && target.special) + { + target.RemoveFromHash (); + Actor caller = level.ActOwnSpecial? target : self.target; + caller.A_CallSpecial(target.special, target.args[0], target.args[1], target.args[2], target.args[3], target.args[4]); + target.special = 0; + } + + // Send all monsters to deathmatch spots + P_TeleportToDeathmatchStarts (target); + } + } + return -1; + } + + //=========================================================================== + // + // P_TeleportToPlayerStarts + // + //=========================================================================== + + private static void P_TeleportToPlayerStarts (Actor victim) + { + Vector3 dest; + double destAngle; + + [dest, destAngle] = G_PickPlayerStart(0, PPS_FORCERANDOM | PPS_NOBLOCKINGCHECK); + dest.Z = ONFLOORZ; + victim.Teleport ((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG); + } + + //=========================================================================== + // + // P_TeleportToDeathmatchStarts + // + //=========================================================================== + + private void P_TeleportToDeathmatchStarts (Actor victim) + { + Vector3 dest; + double destAngle; + + [dest, destAngle] = G_PickDeathmatchStart(); + if (destAngle < 65536) victim.Teleport((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG); + else P_TeleportToPlayerStarts(victim); + } + } From 7ea9f60464cc065246be8b5862bff8b13f363141 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 10:41:36 +0100 Subject: [PATCH 390/471] - scriptified the Acolyte. --- src/CMakeLists.txt | 1 - src/g_level.cpp | 5 +- src/g_strife/a_acolyte.cpp | 86 ------------------------ src/g_strife/a_strifestuff.cpp | 1 - src/p_user.cpp | 16 +++++ wadsrc/static/zscript/shared/player.txt | 2 + wadsrc/static/zscript/strife/acolyte.txt | 70 +++++++++++++++++-- 7 files changed, 87 insertions(+), 94 deletions(-) delete mode 100644 src/g_strife/a_acolyte.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 553a66c127..269fd3bd79 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_acolyte.cpp g_strife/a_alienspectres.cpp g_strife/a_coin.cpp g_strife/a_crusader.cpp diff --git a/src/g_level.cpp b/src/g_level.cpp index ea34dc95c7..0e7820d93a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -478,7 +478,8 @@ void G_InitNew (const char *mapname, bool bTitleLevel) // Set the initial quest log text for Strife. for (i = 0; i < MAXPLAYERS; ++i) { - players[i].SetLogText ("Find help"); + if (playeringame[i]) + players[i].SetLogText ("Find help"); } } @@ -1092,7 +1093,7 @@ void G_WorldDone (void) if (strncmp (nextlevel, "enDSeQ", 6) == 0) { FName endsequence = ENamedName(strtol(nextlevel.GetChars()+6, NULL, 16)); - // Strife needs a special case here to choose between good and sad ending. Bad is handled elsewherw. + // Strife needs a special case here to choose between good and sad ending. Bad is handled elsewhere. if (endsequence == NAME_Inter_Strife) { if (players[0].mo->FindInventory (QuestItemClasses[24]) || diff --git a/src/g_strife/a_acolyte.cpp b/src/g_strife/a_acolyte.cpp deleted file mode 100644 index f0ed0c414c..0000000000 --- a/src/g_strife/a_acolyte.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "a_strifeglobal.h" -#include "doomdata.h" -#include "vm.h" -#include "doomstat.h" -*/ - -//============================================================================ -// -// A_HideDecepticon -// -// Hide the Acolyte-to-be -> -// Hide the guy transforming into an Acolyte -> -// Hide the transformer -> -// Transformers are Autobots and Decepticons, and -// Decepticons are the bad guys, so... -> -// -// Hide the Decepticon! -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_HideDecepticon) -{ - PARAM_SELF_PROLOGUE(AActor); - - EV_DoDoor (DDoor::doorClose, NULL, self, 999, 8., 0, 0, 0); - if (self->target != NULL && self->target->player != NULL) - { - P_NoiseAlert (self->target, self); - } - return 0; -} - -//============================================================================ -// -// A_AcolyteDie -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_AcolyteDie) -{ - PARAM_SELF_PROLOGUE(AActor); - - int i; - - // [RH] Disable translucency here. - self->RenderStyle = STYLE_Normal; - - // Only the Blue Acolyte does extra stuff on death. - if (self->GetClass()->TypeName != NAME_AcolyteBlue) - return 0; - - // Make sure somebody is still alive - for (i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i] && players[i].health > 0) - break; - } - if (i == MAXPLAYERS) - return 0; - - // Make sure all the other blue acolytes are dead. - TThinkerIterator iterator(NAME_AcolyteBlue); - AActor *other; - - while ( (other = iterator.Next ()) ) - { - if (other != self && other->health > 0) - { // Found a living one - return 0; - } - } - - players[i].mo->GiveInventoryType (QuestItemClasses[6]); - players[i].SetLogNumber (14); - S_StopSound (CHAN_VOICE); - S_Sound (CHAN_VOICE, "svox/voc14", 1, ATTN_NORM); - return 0; -} - diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 6815b1d49d..ed56407f5e 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -24,7 +24,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_acolyte.cpp" #include "a_spectral.cpp" #include "a_alienspectres.cpp" #include "a_coin.cpp" diff --git a/src/p_user.cpp b/src/p_user.cpp index ce78d04a83..5f2d19cb4d 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -486,6 +486,14 @@ void player_t::SetLogNumber (int num) } } +DEFINE_ACTION_FUNCTION(_PlayerInfo, SetLogNumber) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_INT(log); + self->SetLogNumber(log); + return 0; +} + void player_t::SetLogText (const char *text) { LogText = text; @@ -496,6 +504,14 @@ void player_t::SetLogText (const char *text) AddToConsole(-1, "\n"); } +DEFINE_ACTION_FUNCTION(_PlayerInfo, SetLogText) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_STRING(log); + self->SetLogText(log); + return 0; +} + int player_t::GetSpawnClass() { const PClass * type = PlayerClasses[CurrentPlayerClass].Type; diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index c7615e9c20..bcbc7db613 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -233,5 +233,7 @@ FWeaponSlots weapons; native void SetSafeFlash(Weapon weap, State flashstate, int index); native PSprite GetPSprite(int id); native PSprite FindPSprite(int id); + native void SetLogNumber (int text); + native void SetLogText (String text); } diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt index 9a6b0105ad..1c50b318c0 100644 --- a/wadsrc/static/zscript/strife/acolyte.txt +++ b/wadsrc/static/zscript/strife/acolyte.txt @@ -26,8 +26,6 @@ class Acolyte : StrifeHumanoid Obituary "$OB_ACOLYTE"; } - native void A_AcolyteDie (); - States { Spawn: @@ -75,6 +73,49 @@ class Acolyte : StrifeHumanoid Stop; } + //============================================================================ + // + // A_AcolyteDie + // + //============================================================================ + + void A_AcolyteDie () + { + // [RH] Disable translucency here. + A_SetRenderStyle(1, STYLE_Normal); + + // Only the Blue Acolyte does extra stuff on death. + if (self is "AcolyteBlue") + { + int i; + // Make sure somebody is still alive + for (i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i] && players[i].health > 0) + break; + } + if (i == MAXPLAYERS) + return; + + // Make sure all the other blue acolytes are dead. + ThinkerIterator it = ThinkerIterator.Create("AcolyteBlue"); + Actor other; + + while ( (other = Actor(it.Next ())) ) + { + if (other != self && other.health > 0) + { // Found a living one + return; + } + } + + players[i].mo.GiveInventoryType ("QuestItem7"); + players[i].SetLogNumber (14); + A_StopSound (CHAN_VOICE); + A_PlaySound ("svox/voc14", CHAN_VOICE); + } + } + //============================================================================ // // A_BeShadowyFoe @@ -238,8 +279,6 @@ class AcolyteToBe : Acolyte -ISMONSTER } - native void A_HideDecepticon (); - States { Spawn: @@ -251,4 +290,27 @@ class AcolyteToBe : Acolyte Death: Goto XDeath; } + + //============================================================================ + // + // A_HideDecepticon + // + // Hide the Acolyte-to-be -> + // Hide the guy transforming into an Acolyte -> + // Hide the transformer -> + // Transformers are Autobots and Decepticons, and + // Decepticons are the bad guys, so... -> + // + // Hide the Decepticon! + // + //============================================================================ + + void A_HideDecepticon () + { + Door_Close(999, 64); + if (target != null && target.player != null) + { + target.NoiseAlert (self); + } + } } From b171d6e21f22c7abf336aa11fc56074080e706ae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 11:52:03 +0100 Subject: [PATCH 391/471] - scriptified a_alienspectres.cpp. --- src/CMakeLists.txt | 1 - src/c_console.cpp | 15 ++ src/g_strife/a_alienspectres.cpp | 201 ------------------ src/g_strife/a_strifestuff.cpp | 1 - src/g_strife/a_strifeweapons.cpp | 34 --- src/p_enemy.cpp | 6 + src/p_interaction.cpp | 2 +- src/p_mobj.cpp | 42 ++++ src/s_sound.cpp | 10 + wadsrc/static/zscript/actor.txt | 4 +- wadsrc/static/zscript/base.txt | 2 + wadsrc/static/zscript/strife/acolyte.txt | 18 +- .../static/zscript/strife/alienspectres.txt | 112 +++++++++- wadsrc/static/zscript/strife/spectral.txt | 62 +++++- 14 files changed, 253 insertions(+), 257 deletions(-) delete mode 100644 src/g_strife/a_alienspectres.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 269fd3bd79..911fce1ed2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_alienspectres.cpp g_strife/a_coin.cpp g_strife/a_crusader.cpp g_strife/a_entityboss.cpp diff --git a/src/c_console.cpp b/src/c_console.cpp index 3064abb0d2..1016be9fd6 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -65,6 +65,7 @@ #include "g_level.h" #include "d_event.h" #include "d_player.h" +#include "gstrings.h" #include "c_consolebuffer.h" #include "gi.h" @@ -1729,6 +1730,20 @@ void C_MidPrintBold (FFont *font, const char *msg) } } +DEFINE_ACTION_FUNCTION(DObject, C_MidPrint) +{ + PARAM_PROLOGUE; + PARAM_STRING(font); + PARAM_STRING(text); + PARAM_BOOL_DEF(bold); + + FFont *fnt = FFont::FindFont(font); + const char *txt = GStrings(text); + if (!bold) C_MidPrint(fnt, txt); + else C_MidPrintBold(fnt, txt); + return 0; +} + /****** Tab completion code ******/ struct TabData diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp deleted file mode 100644 index 194bfd9e09..0000000000 --- a/src/g_strife/a_alienspectres.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "m_random.h" -#include "a_strifeglobal.h" -#include "c_console.h" -#include "gstrings.h" -#include "vm.h" -#include "doomstat.h" -*/ - -static FRandom pr_spectrespawn ("AlienSpectreSpawn"); -static FRandom pr_spectrechunk ("212e4"); - -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SpectreChunkSmall) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *foo = Spawn("AlienChunkSmall", self->PosPlusZ(10.), ALLOW_REPLACE); - - if (foo != NULL) - { - int t; - - t = pr_spectrechunk() & 15; - foo->Vel.X = (t - (pr_spectrechunk() & 7)); - - t = pr_spectrechunk() & 15; - foo->Vel.Y = (t - (pr_spectrechunk() & 7)); - - foo->Vel.Z = (pr_spectrechunk() & 15); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_SpectreChunkLarge) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *foo = Spawn("AlienChunkLarge", self->PosPlusZ(10.), ALLOW_REPLACE); - - if (foo != NULL) - { - int t; - - t = pr_spectrechunk() & 7; - foo->Vel.X = (t - (pr_spectrechunk() & 15)); - - t = pr_spectrechunk() & 7; - foo->Vel.Y = (t - (pr_spectrechunk() & 15)); - - foo->Vel.Z = (pr_spectrechunk() & 7); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_Spectre3Attack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - - AActor *foo = Spawn("SpectralLightningV2", self->PosPlusZ(32.), ALLOW_REPLACE); - - foo->Vel.Z = -12; - foo->target = self; - foo->FriendPlayer = 0; - foo->tracer = self->target; - - self->Angles.Yaw -= 90.; - for (int i = 0; i < 20; ++i) - { - self->Angles.Yaw += 9.; - P_SpawnSubMissile (self, PClass::FindActor("SpectralLightningBall2"), self); - } - self->Angles.Yaw -= 90.; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *player; - char voc[32]; - int log; - int i; - - A_Unblock(self, true); // [RH] Need this for Sigil rewarding - if (!CheckBossDeath (self)) - { - return 0; - } - for (i = 0, player = NULL; i < MAXPLAYERS; ++i) - { - if (playeringame[i] && players[i].health > 0) - { - player = players[i].mo; - break; - } - } - if (player == NULL) - { - return 0; - } - - switch (self->GetClass()->TypeName) - { - case NAME_AlienSpectre1: - EV_DoFloor (DFloor::floorLowerToLowest, NULL, 999, 1., 0., -1, 0, false); - log = 95; - break; - - case NAME_AlienSpectre2: - C_MidPrint(SmallFont, GStrings("TXT_KILLED_BISHOP")); - log = 74; - player->GiveInventoryType (QuestItemClasses[20]); - break; - - case NAME_AlienSpectre3: - { - C_MidPrint(SmallFont, GStrings("TXT_KILLED_ORACLE")); - // If there are any Oracles still alive, kill them. - TThinkerIterator it(NAME_Oracle); - AActor *oracle; - - while ( (oracle = it.Next()) != NULL) - { - if (oracle->health > 0) - { - oracle->health = 0; - oracle->CallDie (self, self); - } - } - player->GiveInventoryType (QuestItemClasses[22]); - if (player->FindInventory (QuestItemClasses[20])) - { // If the Bishop is dead, set quest item 22 - player->GiveInventoryType (QuestItemClasses[21]); - } - if (player->FindInventory (QuestItemClasses[23]) == NULL) - { // Macil is calling us back... - log = 87; - } - else - { // You wield the power of the complete Sigil. - log = 85; - } - EV_DoDoor (DDoor::doorOpen, NULL, NULL, 222, 8., 0, 0, 0); - break; - } - - case NAME_AlienSpectre4: - C_MidPrint(SmallFont, GStrings("TXT_KILLED_MACIL")); - player->GiveInventoryType (QuestItemClasses[23]); - if (player->FindInventory (QuestItemClasses[24]) == NULL) - { // Richter has taken over. Macil is a snake. - log = 79; - } - else - { // Back to the factory for another Sigil! - log = 106; - } - break; - - case NAME_AlienSpectre5: - C_MidPrint(SmallFont, GStrings("TXT_KILLED_LOREMASTER")); - ASigil *sigil; - - player->GiveInventoryType (QuestItemClasses[25]); - if (!multiplayer) - { - player->GiveInventoryType (RUNTIME_CLASS(AUpgradeStamina)); - player->GiveInventoryType (RUNTIME_CLASS(AUpgradeAccuracy)); - } - sigil = player->FindInventory(); - if (sigil != NULL && sigil->NumPieces == 5) - { // You wield the power of the complete Sigil. - log = 85; - } - else - { // Another Sigil piece. Woohoo! - log = 83; - } - EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, 1., 0., -1, 0, false); - break; - - default: - return 0; - } - mysnprintf (voc, countof(voc), "svox/voc%d", log); - S_Sound (CHAN_VOICE, voc, 1, ATTN_NORM); - player->player->SetLogNumber (log); - return 0; -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index ed56407f5e..bf1379d3a3 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -25,7 +25,6 @@ // Include all the other Strife stuff here to reduce compile time #include "a_spectral.cpp" -#include "a_alienspectres.cpp" #include "a_coin.cpp" #include "a_crusader.cpp" #include "a_entityboss.cpp" diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 1909ec7816..0630089d69 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -566,40 +566,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaulerTorpedoWave) return 0; } -AActor *P_SpawnSubMissile (AActor *source, PClassActor *type, AActor *target) -{ - AActor *other = Spawn (type, source->Pos(), ALLOW_REPLACE); - - if (other == NULL) - { - return NULL; - } - - other->target = target; - other->Angles.Yaw = source->Angles.Yaw; - other->VelFromAngle(); - - if (other->flags4 & MF4_SPECTRAL) - { - if (source->flags & MF_MISSILE && source->flags4 & MF4_SPECTRAL) - { - other->FriendPlayer = source->FriendPlayer; - } - else - { - other->SetFriendPlayer(target->player); - } - } - - if (P_CheckMissileSpawn (other, source->radius)) - { - DAngle pitch = P_AimLineAttack (source, source->Angles.Yaw, 1024.); - other->Vel.Z = -other->Speed * pitch.Sin(); - return other; - } - return NULL; -} - class APhosphorousFire : public AActor { DECLARE_CLASS (APhosphorousFire, AActor) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 4f4920c6fb..fcd8f9ceee 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3339,6 +3339,12 @@ bool CheckBossDeath (AActor *actor) return true; } +DEFINE_ACTION_FUNCTION(AActor, CheckBossDeath) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(CheckBossDeath(self)); +} + // // A_BossDeath // Possibly trigger special effects if on a boss level diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index c2d958050e..3c3347ec1a 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -767,7 +767,7 @@ DEFINE_ACTION_FUNCTION(AActor, Die) PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(source, AActor); PARAM_OBJECT(inflictor, AActor); - PARAM_INT(dmgflags); + PARAM_INT_DEF(dmgflags); self->Die(source, inflictor, dmgflags); return 0; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 6268c93956..a52ee49769 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6554,6 +6554,48 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissileAngleZSpeed) ACTION_RETURN_OBJECT(P_SpawnMissileAngleZSpeed(self, z, type, angle, vz, speed, owner, checkspawn)); } + +AActor *P_SpawnSubMissile(AActor *source, PClassActor *type, AActor *target) +{ + AActor *other = Spawn(type, source->Pos(), ALLOW_REPLACE); + + if (other == NULL) + { + return NULL; + } + + other->target = target; + other->Angles.Yaw = source->Angles.Yaw; + other->VelFromAngle(); + + if (other->flags4 & MF4_SPECTRAL) + { + if (source->flags & MF_MISSILE && source->flags4 & MF4_SPECTRAL) + { + other->FriendPlayer = source->FriendPlayer; + } + else + { + other->SetFriendPlayer(target->player); + } + } + + if (P_CheckMissileSpawn(other, source->radius)) + { + DAngle pitch = P_AimLineAttack(source, source->Angles.Yaw, 1024.); + other->Vel.Z = -other->Speed * pitch.Sin(); + return other; + } + return NULL; +} + +DEFINE_ACTION_FUNCTION(AActor, SpawnSubMissile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(cls, AActor); + PARAM_OBJECT(target, AActor); + ACTION_RETURN_OBJECT(P_SpawnSubMissile(self, cls, target)); +} /* ================ = diff --git a/src/s_sound.cpp b/src/s_sound.cpp index a51a7101be..81b94b0f22 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1232,6 +1232,16 @@ void S_Sound (int channel, FSoundID sound_id, float volume, float attenuation) S_StartSound (NULL, NULL, NULL, NULL, channel, sound_id, volume, attenuation); } +DEFINE_ACTION_FUNCTION(DObject, S_Sound) +{ + PARAM_PROLOGUE; + PARAM_SOUND(id); + PARAM_INT(channel); + PARAM_FLOAT_DEF(volume); + PARAM_FLOAT_DEF(attn); + return 0; +} + //========================================================================== // // S_Sound - An actor is source diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 09b983843b..dd1bec839c 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -264,7 +264,7 @@ class Actor : Thinker native virtual native void Activate(Actor activator); virtual native void Deactivate(Actor activator); virtual native int DoSpecialDamage (Actor target, int damage, Name damagetype); - virtual native void Die(Actor source, Actor inflictor, int dmgflags); + virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0); virtual native bool Slam(Actor victim); virtual native bool UseInventory(Inventory item); virtual native bool SpecialBlastHandling (Actor source, double strength); @@ -309,11 +309,13 @@ class Actor : Thinker native native Actor SpawnMissileXYZ(Vector3 pos, Actor dest, Class type, bool checkspawn = true, Actor owner = null); native Actor SpawnMissileZ (double z, Actor dest, class type); native Actor SpawnMissileAngleZSpeed (double z, class type, double angle, double vz, double speed, Actor owner = null, bool checkspawn = true); + native Actor SpawnSubMissile(Class type, Actor target); native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); native Actor RoughMonsterSearch(int distance, bool onlyseekable = false, bool frontonly = false); native int ApplyDamageFactor(Name damagetype, int damage); native int GetModifiedDamage(Name damagetype, int damage, bool passive); + native bool CheckBossDeath(); void A_Light(int extralight) { if (player) player.extralight = clamp(extralight, -20, 20); } void A_Light0() { if (player) player.extralight = 0; } diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 3a96cbbcbf..c76e4590ec 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -8,6 +8,8 @@ class Object native native static vector3, int G_PickDeathmatchStart(); native static vector3, int G_PickPlayerStart(int pnum, int flags = 0); native static int GameType(); + native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM); + native static void C_MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable. /*virtual*/ native void Destroy(); } diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt index 1c50b318c0..45f075d6b7 100644 --- a/wadsrc/static/zscript/strife/acolyte.txt +++ b/wadsrc/static/zscript/strife/acolyte.txt @@ -98,21 +98,13 @@ class Acolyte : StrifeHumanoid return; // Make sure all the other blue acolytes are dead. - ThinkerIterator it = ThinkerIterator.Create("AcolyteBlue"); - Actor other; - - while ( (other = Actor(it.Next ())) ) + if (CheckBossDeath()) { - if (other != self && other.health > 0) - { // Found a living one - return; - } + players[i].mo.GiveInventoryType ("QuestItem7"); + players[i].SetLogNumber (14); + A_StopSound (CHAN_VOICE); + A_PlaySound ("svox/voc14", CHAN_VOICE); } - - players[i].mo.GiveInventoryType ("QuestItem7"); - players[i].SetLogNumber (14); - A_StopSound (CHAN_VOICE); - A_PlaySound ("svox/voc14", CHAN_VOICE); } } diff --git a/wadsrc/static/zscript/strife/alienspectres.txt b/wadsrc/static/zscript/strife/alienspectres.txt index 0fe9826f00..2beee63ea4 100644 --- a/wadsrc/static/zscript/strife/alienspectres.txt +++ b/wadsrc/static/zscript/strife/alienspectres.txt @@ -32,8 +32,6 @@ class AlienSpectre1 : SpectralMonster +NOICEDEATH } - native void A_AlienSpectreDeath (); - States { Spawn: @@ -76,6 +74,116 @@ class AlienSpectre1 : SpectralMonster AL1P R 5 Bright A_AlienSpectreDeath; Stop; } + + //============================================================================ + + void A_AlienSpectreDeath () + { + PlayerPawn player = null; + int log = 0; + + A_NoBlocking(); // [RH] Need this for Sigil rewarding + if (!CheckBossDeath ()) + { + return; + } + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i] && players[i].health > 0) + { + player = players[i].mo; + break; + } + } + if (player == null) + { + return; + } + + class cls = GetClass(); + if (cls == "AlienSpectre1") + { + Floor_LowerToLowest(999, 8); + log = 95; + } + else if (cls == "AlienSpectre2") + { + C_MidPrint("SmallFont", "TXT_KILLED_BISHOP"); + log = 74; + player.GiveInventoryType ("QuestItem21"); + } + else if (cls == "AlienSpectre3") + { + C_MidPrint("SmallFont", "TXT_KILLED_ORACLE"); + // If there are any Oracles still alive, kill them. + ThinkerIterator it = ThinkerIterator.Create("Oracle"); + Actor oracle; + + while ( (oracle = Actor(it.Next())) != null) + { + if (oracle.health > 0) + { + oracle.health = 0; + oracle.Die (self, self); + } + } + player.GiveInventoryType ("QuestItem23"); + if (player.FindInventory ("QuestItem21")) + { // If the Bishop is dead, set quest item 22 + player.GiveInventoryType ("QuestItem22"); + } + if (player.FindInventory ("QuestItem24") == null) + { // Macil is calling us back... + log = 87; + } + else + { // You wield the power of the complete Sigil. + log = 85; + } + Door_Open(222, 64); + } + else if (cls == "AlienSpectre4") + { + C_MidPrint("SmallFont", "TXT_KILLED_MACIL"); + player.GiveInventoryType ("QuestItem24"); + if (player.FindInventory ("QuestItem25") == null) + { // Richter has taken over. Macil is a snake. + log = 79; + } + else + { // Back to the factory for another Sigil! + log = 106; + } + } + else if (cls == "AlienSpectre5") + { + C_MidPrint("SmallFont", "TXT_KILLED_LOREMASTER"); + + player.GiveInventoryType ("QuestItem26"); + if (!multiplayer) + { + player.GiveInventoryType ("UpgradeStamina"); + player.GiveInventoryType ("UpgradeAccuracy"); + } + Sigil sigl = Sigil(player.FindInventory("Sigil")); + if (sigl != null /*&& sigl.NumPieces == 5*/) + { // You wield the power of the complete Sigil. + log = 85; + } + else + { // Another Sigil piece. Woohoo! + log = 83; + } + Floor_LowerToLowest(666, 8); + } + if (log > 0) + { + String voc = "svox/voc" .. log; + A_PlaySound(voc, CHAN_VOICE); + player.player.SetLogNumber (log); + } + } + } diff --git a/wadsrc/static/zscript/strife/spectral.txt b/wadsrc/static/zscript/strife/spectral.txt index d6a2349048..9ea95ba1d5 100644 --- a/wadsrc/static/zscript/strife/spectral.txt +++ b/wadsrc/static/zscript/strife/spectral.txt @@ -11,10 +11,66 @@ class SpectralMonster : Actor native +SPECTRAL +NOICEDEATH } + + //============================================================================ + + void A_SpectreChunkSmall () + { + Actor foo = Spawn("AlienChunkSmall", pos + (0, 0, 10), ALLOW_REPLACE); + + if (foo != null) + { + int t; + + t = random[SpectreChunk]() & 15; + foo.Vel.X = (t - (random[SpectreChunk]() & 7)); + + t = random[SpectreChunk]() & 15; + foo.Vel.Y = (t - (random[SpectreChunk]() & 7)); + + foo.Vel.Z = (random[SpectreChunk]() & 15); + } + } + + void A_SpectreChunkLarge () + { + Actor foo = Spawn("AlienChunkLarge", pos + (0, 0, 10), ALLOW_REPLACE); + + if (foo != null) + { + int t; + + t = random[SpectreChunk]() & 7; + foo.Vel.X = (t - (random[SpectreChunk]() & 15)); + + t = random[SpectreChunk]() & 7; + foo.Vel.Y = (t - (random[SpectreChunk]() & 15)); + + foo.Vel.Z = (random[SpectreChunk]() & 7); + } + } + + void A_Spectre3Attack () + { + if (target == null) + return; + + Actor foo = Spawn("SpectralLightningV2", Pos + (0, 0, 32), ALLOW_REPLACE); + + foo.Vel.Z = -12; + foo.target = self; + foo.FriendPlayer = 0; + foo.tracer = target; + + Angle -= 90.; + for (int i = 0; i < 20; ++i) + { + Angle += 9.; + SpawnSubMissile ("SpectralLightningBall2", self); + } + Angle -= 90.; + } - native void A_SpectreChunkSmall (); - native void A_SpectreChunkLarge (); - native void A_Spectre3Attack (); native void A_SpotLightning (); } From dc9ee0727a31beae12862a8453b80515aff3890c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 12:55:33 +0100 Subject: [PATCH 392/471] - scriptified a_spectral.cpp. - consolidated A_Tracer and A_Tracer2. Note that this commit temporarily disables a few features in order to make it compile. --- src/CMakeLists.txt | 1 - src/actor.h | 1 + src/g_strife/a_entityboss.cpp | 5 +- src/g_strife/a_programmer.cpp | 26 ---- src/g_strife/a_spectral.cpp | 144 -------------------- src/g_strife/a_strifestuff.cpp | 1 - src/p_interaction.cpp | 3 +- src/p_mobj.cpp | 19 +++ src/p_user.cpp | 11 +- wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/doom/revenant.txt | 55 ++++---- wadsrc/static/zscript/strife/programmer.txt | 22 ++- wadsrc/static/zscript/strife/spectral.txt | 90 ++++++++++-- 13 files changed, 160 insertions(+), 220 deletions(-) delete mode 100644 src/g_strife/a_spectral.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 911fce1ed2..21637c59b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -871,7 +871,6 @@ set( NOT_COMPILED_SOURCE_FILES g_strife/a_reaver.cpp g_strife/a_rebels.cpp g_strife/a_sentinel.cpp - g_strife/a_spectral.cpp g_strife/a_stalker.cpp g_strife/a_strifeitems.cpp g_strife/a_strifeweapons.cpp diff --git a/src/actor.h b/src/actor.h index 578b094ed6..06a5e9f118 100644 --- a/src/actor.h +++ b/src/actor.h @@ -674,6 +674,7 @@ public: // Something just touched this actor. virtual void Touch (AActor *toucher); + void CallTouch(AActor *toucher); // Adds the item to this actor's inventory and sets its Owner. virtual void AddInventory (AInventory *item); diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp index 5350229015..7a6b6f0277 100644 --- a/src/g_strife/a_entityboss.cpp +++ b/src/g_strife/a_entityboss.cpp @@ -36,7 +36,6 @@ void A_SpectralMissile (AActor *self, const char *missilename) } } -DECLARE_ACTION(A_SpotLightning) DECLARE_ACTION(A_Spectre3Attack) @@ -49,7 +48,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityAttack) switch (pr_entity() % 5) { case 0: - CALL_ACTION(A_SpotLightning, self); + //CALL_ACTION(A_SpotLightning, self); break; case 2: @@ -57,7 +56,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityAttack) break; case 3: - CALL_ACTION(A_Spectre3Attack, self); + //CALL_ACTION(A_Spectre3Attack, self); break; case 4: diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp index 07f6a6c4ca..a02848dd2b 100644 --- a/src/g_strife/a_programmer.cpp +++ b/src/g_strife/a_programmer.cpp @@ -94,32 +94,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerMelee) return 0; } -//============================================================================ -// -// A_SpotLightning -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SpotLightning) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *spot; - - if (self->target == NULL) - return 0; - - spot = Spawn("SpectralLightningSpot", self->target->PosAtZ(self->target->floorz), ALLOW_REPLACE); - if (spot != NULL) - { - spot->threshold = 25; - spot->target = self; - spot->FriendPlayer = 0; - spot->tracer = self->target; - } - return 0; -} - //============================================================================ // // A_SpawnProgrammerBase diff --git a/src/g_strife/a_spectral.cpp b/src/g_strife/a_spectral.cpp deleted file mode 100644 index 4bd24bac7d..0000000000 --- a/src/g_strife/a_spectral.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "s_sound.h" -#include "m_random.h" -#include "a_strifeglobal.h" -#include "vm.h" -*/ - -class ASpectralMonster : public AActor -{ - DECLARE_CLASS (ASpectralMonster, AActor) -public: - void Touch (AActor *toucher); -}; - -IMPLEMENT_CLASS(ASpectralMonster, false, false) - -void ASpectralMonster::Touch (AActor *toucher) -{ - P_DamageMobj (toucher, this, this, 5, NAME_Melee); -} - - -DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightningTail) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *foo = Spawn("SpectralLightningHTail", self->Vec3Offset(-self->Vel.X, -self->Vel.Y, 0.), ALLOW_REPLACE); - - foo->Angles.Yaw = self->Angles.Yaw; - foo->FriendPlayer = self->FriendPlayer; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_SpectralBigBallLightning) -{ - PARAM_SELF_PROLOGUE(AActor); - - PClassActor *cls = PClass::FindActor("SpectralLightningH3"); - if (cls) - { - self->Angles.Yaw += 90.; - P_SpawnSubMissile (self, cls, self->target); - self->Angles.Yaw += 180.; - P_SpawnSubMissile (self, cls, self->target); - self->Angles.Yaw -= 270.; - P_SpawnSubMissile (self, cls, self->target); - } - return 0; -} - -static FRandom pr_zap5 ("Zap5"); - -DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightning) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *flash; - - if (self->threshold != 0) - --self->threshold; - - self->Vel.X += pr_zap5.Random2(3); - self->Vel.Y += pr_zap5.Random2(3); - - double xo = pr_zap5.Random2(3) * 50.; - double yo = pr_zap5.Random2(3) * 50.; - - flash = Spawn (self->threshold > 25 ? PClass::FindActor(NAME_SpectralLightningV2) : - PClass::FindActor(NAME_SpectralLightningV1), self->Vec2OffsetZ(xo, yo, ONCEILINGZ), ALLOW_REPLACE); - - flash->target = self->target; - flash->Vel.Z = -18; - flash->FriendPlayer = self->FriendPlayer; - - flash = Spawn(NAME_SpectralLightningV2, self->PosAtZ(ONCEILINGZ), ALLOW_REPLACE); - - flash->target = self->target; - flash->Vel.Z = -18; - flash->FriendPlayer = self->FriendPlayer; - return 0; -} - -// In Strife, this number is stored in the data segment, but it doesn't seem to be -// altered anywhere. -#define TRACEANGLE (19.6875) - -DEFINE_ACTION_FUNCTION(AActor, A_Tracer2) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *dest; - double dist; - double slope; - - dest = self->tracer; - - if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest)) - return 0; - - 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; -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index bf1379d3a3..ad6afce608 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -24,7 +24,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_spectral.cpp" #include "a_coin.cpp" #include "a_crusader.cpp" #include "a_entityboss.cpp" diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 3c3347ec1a..41994c38e7 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -105,8 +105,7 @@ void P_TouchSpecialThing (AActor *special, AActor *toucher) toucher->player->Bot->prev = toucher->player->Bot->dest; toucher->player->Bot->dest = NULL; } - - special->Touch (toucher); + special->CallTouch (toucher); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a52ee49769..6f0754a8fa 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1440,6 +1440,25 @@ void AActor::Touch (AActor *toucher) { } +DEFINE_ACTION_FUNCTION(AActor, Touch) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(toucher, AActor); + self->Touch(toucher); + return 0; +} + +void AActor::CallTouch(AActor *toucher) +{ + IFVIRTUAL(AActor, Touch) + { + VMValue params[2] = { (DObject*)this, toucher }; + VMFrameStack stack; + stack.Call(func, params, 2, nullptr, 0, nullptr); + } + else Touch(toucher); +} + //============================================================================ // // AActor :: Grind diff --git a/src/p_user.cpp b/src/p_user.cpp index 5f2d19cb4d..1033299e63 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -498,10 +498,13 @@ void player_t::SetLogText (const char *text) { LogText = text; - // Print log text to console - AddToConsole(-1, TEXTCOLOR_GOLD); - AddToConsole(-1, LogText); - AddToConsole(-1, "\n"); + if (mo->CheckLocalView(consoleplayer)) + { + // Print log text to console + AddToConsole(-1, TEXTCOLOR_GOLD); + AddToConsole(-1, LogText); + AddToConsole(-1, "\n"); + } } DEFINE_ACTION_FUNCTION(_PlayerInfo, SetLogText) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index dd1bec839c..cdcc630b5e 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -268,6 +268,7 @@ class Actor : Thinker native virtual native bool Slam(Actor victim); virtual native bool UseInventory(Inventory item); virtual native bool SpecialBlastHandling (Actor source, double strength); + virtual native void Touch(Actor toucher); virtual int SpecialMissileHit (Actor victim) // for this no native version exists { @@ -617,7 +618,6 @@ class Actor : Thinker native 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(); diff --git a/wadsrc/static/zscript/doom/revenant.txt b/wadsrc/static/zscript/doom/revenant.txt index 2fc35c60f2..2fa335a2df 100644 --- a/wadsrc/static/zscript/doom/revenant.txt +++ b/wadsrc/static/zscript/doom/revenant.txt @@ -129,8 +129,6 @@ class RevenantTracerSmoke : Actor extend class Actor { - const TRACEANGLE = (16.875); - void A_SkelMissile() { if (target == null) return; @@ -166,33 +164,12 @@ extend class Actor } } - void A_Tracer() + void A_Tracer2(double traceang = 19.6875) { 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; @@ -205,13 +182,13 @@ extend class Actor if (diff < 0) { - angle -= TRACEANGLE; + angle -= traceang; if (deltaangle(angle, exact) > 0) angle = exact; } else if (diff > 0) { - angle += TRACEANGLE; + angle += traceang; if (deltaangle(angle, exact) < 0.) angle = exact; } @@ -238,5 +215,31 @@ extend class Actor Vel.Z += 1. / 8; } } + + void A_Tracer() + { + // 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); + Actor 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; + + // The rest of this function was identical with Strife's version, except for the angle being used. + A_Tracer2(16.875); + } } diff --git a/wadsrc/static/zscript/strife/programmer.txt b/wadsrc/static/zscript/strife/programmer.txt index dc88a790f4..9ef9bdeb02 100644 --- a/wadsrc/static/zscript/strife/programmer.txt +++ b/wadsrc/static/zscript/strife/programmer.txt @@ -36,7 +36,6 @@ class Programmer : Actor native void A_ProgrammerMelee (); native void A_SpawnProgrammerBase (); native void A_ProgrammerDeath (); - native void A_SpotLightning(); States { @@ -80,6 +79,27 @@ class Programmer : Actor PRGR X -1 Bright A_ProgrammerDeath; Stop; } + + //============================================================================ + // + // A_SpotLightning + // + //============================================================================ + + void A_SpotLightning() + { + if (target == NULL) return; + + Actor spot = Spawn("SpectralLightningSpot", (target.pos.xy, target.floorz), ALLOW_REPLACE); + if (spot != NULL) + { + spot.threshold = 25; + spot.target = self; + spot.FriendPlayer = 0; + spot.tracer = target; + } + } + } diff --git a/wadsrc/static/zscript/strife/spectral.txt b/wadsrc/static/zscript/strife/spectral.txt index 9ea95ba1d5..0878cff948 100644 --- a/wadsrc/static/zscript/strife/spectral.txt +++ b/wadsrc/static/zscript/strife/spectral.txt @@ -2,7 +2,7 @@ // base for all spectral monsters which hurt when being touched-------------- -class SpectralMonster : Actor native +class SpectralMonster : Actor { Default { @@ -11,6 +11,12 @@ class SpectralMonster : Actor native +SPECTRAL +NOICEDEATH } + + override void Touch (Actor toucher) + { + toucher.DamageMobj (self, self, 5, 'Melee'); + } + //============================================================================ @@ -71,7 +77,26 @@ class SpectralMonster : Actor native Angle -= 90.; } - native void A_SpotLightning (); + //============================================================================ + // + // A_SpotLightning + // + //============================================================================ + + void A_SpotLightning() + { + if (target == null) return; + + Actor spot = Spawn("SpectralLightningSpot", (target.pos.xy, target.floorz), ALLOW_REPLACE); + if (spot != null) + { + spot.threshold = 25; + spot.target = self; + spot.FriendPlayer = 0; + spot.tracer = target; + } + } + } @@ -180,7 +205,6 @@ class SpectralLightningH1 : SpectralLightningBase +SPECTRAL } - native void A_SpectralLightningTail (); States { @@ -189,6 +213,14 @@ class SpectralLightningH1 : SpectralLightningBase ZAP6 BC 4 Bright A_SpectralLightningTail; Loop; } + + void A_SpectralLightningTail () + { + Actor foo = Spawn("SpectralLightningHTail", Vec3Offset(-Vel.X, -Vel.Y, 0.), ALLOW_REPLACE); + + foo.Angle = Angle; + foo.FriendPlayer = FriendPlayer; + } } @@ -245,8 +277,6 @@ class SpectralLightningBigBall1 : SpectralLightningDeath2 +SPECTRAL } - native void A_SpectralBigBallLightning (); - States { Spawn: @@ -254,6 +284,21 @@ class SpectralLightningBigBall1 : SpectralLightningDeath2 ZAP7 CDE 6 Bright A_SpectralBigBallLightning; Loop; } + + void A_SpectralBigBallLightning () + { + Class cls = "SpectralLightningH3"; + if (cls) + { + angle += 90.; + SpawnSubMissile (cls, target); + angle += 180.; + SpawnSubMissile (cls, target); + angle -= 270.; + SpawnSubMissile (cls, target); + } + } + } @@ -315,8 +360,6 @@ class SpectralLightningSpot : SpectralLightningDeath1 Alpha 0.6; } - native void A_SpectralLightning (); - States { Spawn: @@ -325,6 +368,35 @@ class SpectralLightningSpot : SpectralLightningDeath1 ZAP5 CD 4 Bright A_Countdown; Loop; } + + void A_SpectralLightning () + { + if (threshold != 0) + --threshold; + + Vel.X += random2[Zap5](3); + Vel.Y += random2[Zap5](3); + + double xo = random2[Zap5](3) * 50.; + double yo = random2[Zap5](3) * 50.; + + class cls; + if (threshold > 25) cls = "SpectralLightningV2"; + else cls = "SpectralLightningV1"; + + Actor flash = Spawn (cls, Vec2OffsetZ(xo, yo, ONCEILINGZ), ALLOW_REPLACE); + + flash.target = target; + flash.Vel.Z = -18; + flash.FriendPlayer = FriendPlayer; + + flash = Spawn("SpectralLightningV2", (pos.xy, ONCEILINGZ), ALLOW_REPLACE); + + flash.target = target; + flash.Vel.Z = -18; + flash.FriendPlayer = FriendPlayer; + } + } // Sigil Lightning (Big Vertical #1) ---------------------------------------- @@ -357,7 +429,3 @@ class SpectralLightningBigV2 : SpectralLightningBigV1 Damage 60; } } - - - - From c9a4087c18fe35d82a2d6891c780590da80d6b28 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 13:11:27 +0100 Subject: [PATCH 393/471] - scriptified a_entityboss.cpp. --- src/CMakeLists.txt | 1 - src/g_strife/a_entityboss.cpp | 114 -------------------- src/g_strife/a_strifestuff.cpp | 1 - wadsrc/static/zscript/strife/entityboss.txt | 101 +++++++++++++++-- 4 files changed, 94 insertions(+), 123 deletions(-) delete mode 100644 src/g_strife/a_entityboss.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21637c59b8..211411f20a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -863,7 +863,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_spike.cpp g_strife/a_coin.cpp g_strife/a_crusader.cpp - g_strife/a_entityboss.cpp g_strife/a_inquisitor.cpp g_strife/a_loremaster.cpp g_strife/a_oracle.cpp diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp deleted file mode 100644 index 7a6b6f0277..0000000000 --- a/src/g_strife/a_entityboss.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "a_strifeglobal.h" -#include "vm.h" -#include "g_level.h" -*/ - -static FRandom pr_entity ("Entity"); - -DEFINE_ACTION_FUNCTION(AActor, A_SubEntityDeath) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (CheckBossDeath (self)) - { - G_ExitLevel (0, false); - } - return 0; -} - -void A_SpectralMissile (AActor *self, const char *missilename) -{ - if (self->target != NULL) - { - AActor *missile = P_SpawnMissileXYZ (self->PosPlusZ(32.), self, self->target, PClass::FindActor(missilename), false); - if (missile != NULL) - { - missile->tracer = self->target; - P_CheckMissileSpawn(missile, self->radius); - } - } -} - -DECLARE_ACTION(A_Spectre3Attack) - - -DEFINE_ACTION_FUNCTION(AActor, A_EntityAttack) -{ - 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. - switch (pr_entity() % 5) - { - case 0: - //CALL_ACTION(A_SpotLightning, self); - break; - - case 2: - A_SpectralMissile (self, "SpectralLightningH3"); - break; - - case 3: - //CALL_ACTION(A_Spectre3Attack, self); - break; - - case 4: - A_SpectralMissile (self, "SpectralLightningBigV2"); - break; - - case 1: - case 5: - A_SpectralMissile (self, "SpectralLightningBigBall2"); - break; - } - return 0; -} - - -DEFINE_ACTION_FUNCTION(AActor, A_SpawnEntity) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *entity = Spawn("EntityBoss", self->PosPlusZ(70.), ALLOW_REPLACE); - if (entity != NULL) - { - entity->Angles.Yaw = self->Angles.Yaw; - entity->CopyFriendliness(self, true); - entity->Vel.Z = 5; - entity->tracer = self; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_EntityDeath) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *second; - double secondRadius = GetDefaultByName("EntitySecond")->radius * 2; - - static const double turns[3] = { 0, 90, -90 }; - const double velmul[3] = { 4.8828125f, secondRadius*4, secondRadius*4 }; - - AActor *spot = self->tracer; - if (spot == NULL) spot = self; - - for (int i = 0; i < 3; i++) - { - DAngle an = self->Angles.Yaw + turns[i]; - DVector3 pos = spot->Vec3Angle(secondRadius, an, self->tracer ? 70. : 0.); - - second = Spawn("EntitySecond", pos, ALLOW_REPLACE); - second->CopyFriendliness(self, true); - A_FaceTarget(second); - second->VelFromAngle(velmul[i], an); - } - return 0; -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index ad6afce608..df89e614ab 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -26,7 +26,6 @@ // Include all the other Strife stuff here to reduce compile time #include "a_coin.cpp" #include "a_crusader.cpp" -#include "a_entityboss.cpp" #include "a_inquisitor.cpp" #include "a_loremaster.cpp" //#include "a_macil.cpp" diff --git a/wadsrc/static/zscript/strife/entityboss.txt b/wadsrc/static/zscript/strife/entityboss.txt index 8ccdbbd02f..daf1a78ee2 100644 --- a/wadsrc/static/zscript/strife/entityboss.txt +++ b/wadsrc/static/zscript/strife/entityboss.txt @@ -32,7 +32,6 @@ class EntityPod : Actor SeeSound "misc/gibbed"; } - native void A_SpawnEntity (); States { @@ -47,10 +46,23 @@ class EntityPod : Actor PODD E -1; Stop; } + + void A_SpawnEntity () + { + Actor entity = Spawn("EntityBoss", pos + (0,0,70), ALLOW_REPLACE); + if (entity != null) + { + entity.Angle = self.Angle; + entity.CopyFriendliness(self, true); + entity.Vel.Z = 5; + entity.tracer = self; + } + } + } -// Entity Boss -------------------------------------------------------------- +// -------------------------------------------------------------- class EntityBoss : SpectralMonster { @@ -87,9 +99,6 @@ class EntityBoss : SpectralMonster Obituary "$OB_ENTITY"; } - native void A_EntityAttack(); - native void A_EntityDeath(); - States { Spawn: @@ -129,6 +138,76 @@ class EntityBoss : SpectralMonster MNAL Q 6 Bright A_EntityDeath; Stop; } + + // -------------------------------------------------------------- + + private void A_SpectralMissile (class missilename) + { + if (target != null) + { + Actor missile = SpawnMissileXYZ (Pos + (0,0,32), target, missilename, false); + if (missile != null) + { + missile.tracer = target; + missile.CheckMissileSpawn(radius); + } + } + } + + // -------------------------------------------------------------- + + void A_EntityAttack() + { + // 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. + switch (random[Entity]() % 5) + { + case 0: + A_SpotLightning(); + break; + + case 2: + A_SpectralMissile ("SpectralLightningH3"); + break; + + case 3: + A_Spectre3Attack(); + break; + + case 4: + A_SpectralMissile ("SpectralLightningBigV2"); + break; + + default: + A_SpectralMissile ("SpectralLightningBigBall2"); + break; + } + } + + // -------------------------------------------------------------- + + void A_EntityDeath() + { + Actor second; + double secondRadius = GetDefaultByType("EntitySecond").radius * 2; + + static const double turns[] = { 0, 90, -90 }; + + Actor spot = tracer; + if (spot == null) spot = self; + + for (int i = 0; i < 3; i++) + { + double an = Angle + turns[i]; + Vector3 pos = spot.Vec3Angle(secondRadius, an, tracer ? 70. : 0.); + + second = Spawn("EntitySecond", pos, ALLOW_REPLACE); + second.CopyFriendliness(self, true); + second.A_FaceTarget(); + second.VelFromAngle(i == 0? 4.8828125 : secondRadius * 4., an); + } + } + } // Second Entity Boss ------------------------------------------------------- @@ -167,8 +246,6 @@ class EntitySecond : SpectralMonster Obituary "$OB_ENTITY"; } - native void A_SubEntityDeath (); - States { Spawn: @@ -202,6 +279,16 @@ class EntitySecond : SpectralMonster MDTH O 3 Bright A_SubEntityDeath; Stop; } + + // -------------------------------------------------------------- + + void A_SubEntityDeath () + { + if (CheckBossDeath ()) + { + Exit_Normal(0); + } + } } From 8551a4f6e123596812feca20c4622e9b9c22eda8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 14:39:25 +0100 Subject: [PATCH 394/471] - scriptified the Sigil. This isn't fully tested yet. --- src/dobjtype.cpp | 10 + src/dobjtype.h | 1 + src/g_shared/a_pickups.cpp | 22 ++ src/g_shared/a_pickups.h | 1 + src/g_shared/sbarinfo_commands.cpp | 2 +- src/g_strife/a_strifeglobal.h | 14 - src/g_strife/a_strifeweapons.cpp | 432 --------------------- src/g_strife/strife_sbar.cpp | 2 +- src/m_cheat.cpp | 30 +- src/namedef.h | 5 + src/p_acs.cpp | 30 +- src/p_conversation.cpp | 2 +- src/p_enemy.cpp | 2 +- src/p_pspr.cpp | 9 + src/scripting/zscript/zcc_compile.cpp | 8 +- src/scripting/zscript/zcc_compile.h | 2 +- wadsrc/static/zscript/shared/inventory.txt | 1 + wadsrc/static/zscript/shared/player.txt | 3 + wadsrc/static/zscript/strife/sigil.txt | 368 +++++++++++++++++- 19 files changed, 450 insertions(+), 494 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 88c31d0078..62a6a2b2d2 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3545,6 +3545,16 @@ const PClass *PClass::NativeClass() const return cls; } +VMFunction *PClass::FindFunction(FName clsname, FName funcname) +{ + auto cls = PClass::FindActor(clsname); + if (!cls) return nullptr; + auto func = dyn_cast(cls->Symbols.FindSymbol(funcname, true)); + if (!func) return nullptr; + return func->Variants[0].Implementation; +} + + /* FTypeTable **************************************************************/ //========================================================================== diff --git a/src/dobjtype.h b/src/dobjtype.h index b952a3c232..89d3091564 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -859,6 +859,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); + static VMFunction *FindFunction(FName cls, FName func); PClass *FindClassTentative(FName name); static TArray AllClasses; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 2172d2a0cc..cb5f4dd121 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -589,6 +589,28 @@ bool AInventory::SpecialDropAction (AActor *dropper) return false; } +DEFINE_ACTION_FUNCTION(AInventory, SpecialDropAction) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_OBJECT(dropper, AActor); + ACTION_RETURN_BOOL(self->SpecialDropAction(dropper)); +} + +bool AInventory::CallSpecialDropAction(AActor *dropper) +{ + IFVIRTUAL(AInventory, SpecialDropAction) + { + VMValue params[2] = { (DObject*)this, (DObject*)dropper }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + return !!retval; + } + return SpecialDropAction(dropper); +} + //=========================================================================== // // AInventory :: ShouldRespawn diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 429b2ab905..e15f0724c9 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -168,6 +168,7 @@ public: bool CallTryPickup (AActor *toucher, AActor **toucher_return = NULL); virtual void DoPickupSpecial (AActor *toucher); virtual bool SpecialDropAction (AActor *dropper); + bool CallSpecialDropAction(AActor *dropper); virtual bool DrawPowerup (int x, int y); virtual void DoEffect (); virtual bool Grind(bool items); diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index b3aecb0b54..f78c610404 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -268,7 +268,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl } else if(type == SIGIL) { - AInventory *item = statusBar->CPlayer->mo->FindInventory(); + AInventory *item = statusBar->CPlayer->mo->FindInventory(PClass::FindActor(NAME_Sigil)); if (item != NULL) texture = TexMan(item->Icon); } diff --git a/src/g_strife/a_strifeglobal.h b/src/g_strife/a_strifeglobal.h index 9e7f9148e0..c07bce63c3 100644 --- a/src/g_strife/a_strifeglobal.h +++ b/src/g_strife/a_strifeglobal.h @@ -49,20 +49,6 @@ public: bool TryPickup (AActor *&toucher); }; -class ASigil : public AWeapon -{ - DECLARE_CLASS (ASigil, AWeapon) -public: - bool HandlePickup (AInventory *item); - AInventory *CreateCopy (AActor *other); - - void Serialize(FSerializer &arc); - bool SpecialDropAction (AActor *dropper); - static int GiveSigilPiece (AActor *daPlayer); - void BeginPlay(); - - int NumPieces, DownPieces; -}; extern PClassActor *QuestItemClasses[31]; diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 0630089d69..34862f943d 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -698,435 +698,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireGrenade) return 0; } -// The Almighty Sigil! ------------------------------------------------------ - -IMPLEMENT_CLASS(ASigil, false, false) - -//============================================================================ -// -// ASigil :: Serialize -// -//============================================================================ - -void ASigil::BeginPlay() -{ - NumPieces = health; -} - -//============================================================================ -// -// ASigil :: Serialize -// -//============================================================================ - -void ASigil::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - arc("numpieces", NumPieces) - ("downpieces", DownPieces); -} - -//============================================================================ -// -// ASigil :: HandlePickup -// -//============================================================================ - -bool ASigil::HandlePickup (AInventory *item) -{ - if (item->IsKindOf (RUNTIME_CLASS(ASigil))) - { - int otherPieces = static_cast(item)->NumPieces; - if (otherPieces > NumPieces) - { - item->ItemFlags |= IF_PICKUPGOOD; - Icon = item->Icon; - // If the player is holding the Sigil right now, drop it and bring - // it back with the new piece(s) in view. - if (Owner->player != NULL && Owner->player->ReadyWeapon == this) - { - DownPieces = NumPieces; - Owner->player->PendingWeapon = this; - } - NumPieces = otherPieces; - } - return true; - } - return false; -} - -//============================================================================ -// -// ASigil :: CreateCopy -// -//============================================================================ - -AInventory *ASigil::CreateCopy (AActor *other) -{ - ASigil *copy = Spawn (); - copy->Amount = Amount; - copy->MaxAmount = MaxAmount; - copy->NumPieces = NumPieces; - copy->Icon = Icon; - GoAwayAndDie (); - return copy; -} - -//============================================================================ -// -// A_SelectPiece -// -// Decide which sprite frame this Sigil should use as an item, based on how -// many pieces it represents. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SelectPiece) -{ - PARAM_ACTION_PROLOGUE(AActor); - - int pieces = MIN (static_cast(self)->NumPieces, 5); - - if (pieces > 1) - { - self->SetState (self->FindState("Spawn")+pieces); - } - return 0; -} - -//============================================================================ -// -// A_SelectSigilView -// -// Decide which first-person frame this Sigil should show, based on how many -// pieces it represents. Strife did this by selecting a flash that looked like -// the Sigil whenever you switched to it and at the end of an attack. I have -// chosen to make the weapon sprite choose the correct frame and let the flash -// be a regular flash. It means I need to use more states, but I think it's -// worth it. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilView) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DPSprite *pspr; - int pieces; - - if (self->player == nullptr) - { - return 0; - } - pieces = static_cast(self->player->ReadyWeapon)->NumPieces; - pspr = self->player->GetPSprite(PSP_WEAPON); - pspr->SetState(pspr->GetState() + pieces); - return 0; -} - -//============================================================================ -// -// A_SelectSigilDown -// -// Same as A_SelectSigilView, except it uses DownPieces. This is so that when -// you pick up a Sigil, the old one will drop and *then* change to the new -// one. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilDown) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DPSprite *pspr; - int pieces; - - if (self->player == nullptr) - { - return 0; - } - pieces = static_cast(self->player->ReadyWeapon)->DownPieces; - static_cast(self->player->ReadyWeapon)->DownPieces = 0; - if (pieces == 0) - { - pieces = static_cast(self->player->ReadyWeapon)->NumPieces; - } - pspr = self->player->GetPSprite(PSP_WEAPON); - pspr->SetState(pspr->GetState() + pieces); - return 0; -} - -//============================================================================ -// -// A_SelectSigilAttack -// -// Same as A_SelectSigilView, but used just before attacking. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilAttack) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DPSprite *pspr; - int pieces; - - if (self->player == nullptr) - { - return 0; - } - pieces = static_cast(self->player->ReadyWeapon)->NumPieces; - pspr = self->player->GetPSprite(PSP_WEAPON); - pspr->SetState(pspr->GetState() + 4*pieces - 3); - return 0; -} - -//============================================================================ -// -// A_SigilCharge -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SigilCharge) -{ - PARAM_ACTION_PROLOGUE(AActor); - - S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); - if (self->player != NULL) - { - self->player->extralight = 2; - } - return 0; -} - -//============================================================================ -// -// A_FireSigil1 -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *spot; - player_t *player = self->player; - FTranslatedLineTarget t; - - if (player == NULL || player->ReadyWeapon == NULL) - return 0; - - P_DamageMobj (self, self, NULL, 1*4, 0, DMG_NO_ARMOR); - S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); - - P_BulletSlope (self, &t, ALF_PORTALRESTRICT); - if (t.linetarget != NULL) - { - spot = Spawn("SpectralLightningSpot", t.linetarget->PosAtZ(t.linetarget->floorz), ALLOW_REPLACE); - if (spot != NULL) - { - spot->tracer = t.linetarget; - } - } - else - { - spot = Spawn("SpectralLightningSpot", self->Pos(), ALLOW_REPLACE); - if (spot != NULL) - { - spot->VelFromAngle(28., self->Angles.Yaw); - } - } - if (spot != NULL) - { - spot->SetFriendPlayer(player); - spot->target = self; - } - return 0; -} - -//============================================================================ -// -// A_FireSigil2 -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireSigil2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player = self->player; - - if (player == NULL || player->ReadyWeapon == NULL) - return 0; - - P_DamageMobj (self, self, NULL, 2*4, 0, DMG_NO_ARMOR); - S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); - - P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningH1")); - return 0; -} - -//============================================================================ -// -// A_FireSigil3 -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireSigil3) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *spot; - player_t *player = self->player; - int i; - - if (player == NULL || player->ReadyWeapon == NULL) - return 0; - - P_DamageMobj (self, self, NULL, 3*4, 0, DMG_NO_ARMOR); - S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); - - self->Angles.Yaw -= 90.; - for (i = 0; i < 20; ++i) - { - self->Angles.Yaw += 9.; - spot = P_SpawnSubMissile (self, PClass::FindActor("SpectralLightningBall1"), self); - if (spot != NULL) - { - spot->SetZ(self->Z() + 32); - } - } - self->Angles.Yaw -= 90.; - return 0; -} - -//============================================================================ -// -// A_FireSigil4 -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4) -{ - PARAM_ACTION_PROLOGUE(AActor); - - AActor *spot; - player_t *player = self->player; - FTranslatedLineTarget t; - - if (player == NULL || player->ReadyWeapon == NULL) - return 0; - - P_DamageMobj (self, self, NULL, 4*4, 0, DMG_NO_ARMOR); - S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); - - P_BulletSlope (self, &t, ALF_PORTALRESTRICT); - if (t.linetarget != NULL) - { - spot = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("SpectralLightningBigV1"), self->Angles.Yaw, &t, NULL, false, false, ALF_PORTALRESTRICT); - if (spot != NULL) - { - spot->tracer = t.linetarget; - } - } - else - { - spot = P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningBigV1")); - if (spot != NULL) - { - spot->VelFromAngle(spot->Speed, self->Angles.Yaw); - } - } - return 0; -} - -//============================================================================ -// -// A_FireSigil5 -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireSigil5) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player = self->player; - - if (player == NULL || player->ReadyWeapon == NULL) - return 0; - - P_DamageMobj (self, self, NULL, 5*4, 0, DMG_NO_ARMOR); - S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); - - P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningBigBall1")); - return 0; -} - -//============================================================================ -// -// ASigil :: SpecialDropAction -// -// Monsters don't drop Sigil pieces. The Sigil pieces grab hold of the person -// who killed the dropper and automatically enter their inventory. That's the -// way it works if you believe Macil, anyway... -// -//============================================================================ - -bool ASigil::SpecialDropAction (AActor *dropper) -{ - // Give a Sigil piece to every player in the game - for (int i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i] && players[i].mo != NULL) - { - GiveSigilPiece (players[i].mo); - Destroy (); - } - } - return true; -} - -//============================================================================ -// -// ASigil :: GiveSigilPiece -// -// Gives the actor another Sigil piece, up to 5. Returns the number of Sigil -// pieces the actor previously held. -// -//============================================================================ - -int ASigil::GiveSigilPiece (AActor *receiver) -{ - ASigil *sigil; - - sigil = receiver->FindInventory (); - if (sigil == NULL) - { - sigil = static_cast(Spawn("Sigil1")); - if (!sigil->CallTryPickup (receiver)) - { - sigil->Destroy (); - } - return 0; - } - else if (sigil->NumPieces < 5) - { - ++sigil->NumPieces; - static const char* sigils[5] = - { - "Sigil1", "Sigil2", "Sigil3", "Sigil4", "Sigil5" - }; - sigil->Icon = ((AInventory*)GetDefaultByName (sigils[MAX(0,sigil->NumPieces-1)]))->Icon; - // If the player has the Sigil out, drop it and bring it back up. - if (sigil->Owner->player != NULL && sigil->Owner->player->ReadyWeapon == sigil) - { - sigil->Owner->player->PendingWeapon = sigil; - sigil->DownPieces = sigil->NumPieces - 1; - } - return sigil->NumPieces - 1; - } - else - { - return 5; - } -} diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 39f92d0762..79a363d1c7 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -439,7 +439,7 @@ private: } // Sigil - item = CPlayer->mo->FindInventory(); + item = CPlayer->mo->FindInventory(PClass::FindActor(NAME_Sigil)); if (item != NULL) { DrawImage (TexMan(item->Icon), 253, 7); diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 7ba40f957e..33a90c85f5 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -483,18 +483,28 @@ void cht_DoCheat (player_t *player, int cheat) case CHT_LEGO: if (player->mo != NULL && player->health >= 0) { - int oldpieces = ASigil::GiveSigilPiece (player->mo); - item = player->mo->FindInventory (RUNTIME_CLASS(ASigil)); - - if (item != NULL) + static VMFunction *gsp = nullptr; + if (gsp == nullptr) gsp = PClass::FindFunction(NAME_Sigil, NAME_GiveSigilPiece); + if (gsp) { - if (oldpieces == 5) + VMValue params[1] = { player->mo }; + VMFrameStack stack; + VMReturn ret; + int oldpieces = 1; + ret.IntAt(&oldpieces); + stack.Call(gsp, params, 1, &ret, 1, nullptr); + item = player->mo->FindInventory(PClass::FindActor(NAME_Sigil)); + + if (item != NULL) { - item->Destroy (); - } - else - { - player->PendingWeapon = static_cast (item); + if (oldpieces == 5) + { + item->Destroy(); + } + else + { + player->PendingWeapon = static_cast (item); + } } } } diff --git a/src/namedef.h b/src/namedef.h index 3a4a1c1800..9cb4e8d231 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -120,6 +120,11 @@ xx(ArtiPoisonBag3) // Strife quests xx(QuestItem) +xx(Sigil) +xx(ScriptedMarine) +xx(GiveSigilPiece) +xx(SetWeapon) +xx(SetSprite) // Armor xx(BasicArmor) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index a5b8b977d4..97f6602464 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -6112,29 +6112,25 @@ static bool CharArrayParms(int &capacity, int &offset, int &a, int *Stack, int & static void SetMarineWeapon(AActor *marine, int weapon) { static VMFunction *smw = nullptr; - if (smw == nullptr) + if (smw == nullptr) smw = PClass::FindFunction(NAME_ScriptedMarine, NAME_SetWeapon); + if (smw) { - auto cls = PClass::FindActor("ScriptedMarine"); - auto func = dyn_cast(cls->Symbols.FindSymbol("SetWeapon", true)); - smw = func->Variants[0].Implementation; + VMValue params[2] = { marine, weapon }; + VMFrameStack stack; + stack.Call(smw, params, 2, nullptr, 0, nullptr); } - VMValue params[2] = { marine, weapon }; - VMFrameStack stack; - stack.Call(smw, params, 2, nullptr, 0, nullptr); } static void SetMarineSprite(AActor *marine, PClassActor *source) { static VMFunction *sms = nullptr; - if (sms == nullptr) + if (sms == nullptr) sms = PClass::FindFunction(NAME_ScriptedMarine, NAME_SetSprite); + if (sms) { - auto cls = PClass::FindActor("ScriptedMarine"); - auto func = dyn_cast(cls->Symbols.FindSymbol("SetSprite", true)); - sms = func->Variants[0].Implementation; + VMValue params[2] = { marine, source }; + VMFrameStack stack; + stack.Call(sms, params, 2, nullptr, 0, nullptr); } - VMValue params[2] = { marine, source }; - VMFrameStack stack; - stack.Call(sms, params, 2, nullptr, 0, nullptr); } int DLevelScript::RunScript () @@ -8577,15 +8573,15 @@ scriptwait: case PCD_GETSIGILPIECES: { - ASigil *sigil; + AInventory *sigil; - if (activator == NULL || (sigil = activator->FindInventory()) == NULL) + if (activator == NULL || (sigil = activator->FindInventory(PClass::FindActor(NAME_Sigil))) == NULL) { PushToStack (0); } else { - PushToStack (sigil->NumPieces); + PushToStack (sigil->health); } } break; diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 404b2f2bc0..95aabe44b8 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -646,7 +646,7 @@ static void TakeStrifeItem (player_t *player, PClassActor *itemtype, int amount) return; // Don't take the sigil. - if (itemtype == RUNTIME_CLASS(ASigil)) + if (itemtype->GetClass()->TypeName == NAME_Sigil) return; player->mo->TakeInventory(itemtype, amount); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index fcd8f9ceee..3712ac86c9 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3209,7 +3209,7 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c AInventory *inv = static_cast(mo); ModifyDropAmount(inv, dropamount); inv->ItemFlags |= IF_TOSSED; - if (inv->SpecialDropAction (source)) + if (inv->CallSpecialDropAction (source)) { // The special action indicates that the item should not spawn inv->Destroy(); diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index e2ea3084db..610ade35a2 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -439,6 +439,15 @@ void DPSprite::SetState(FState *newstate, bool pending) return; } +DEFINE_ACTION_FUNCTION(DPSprite, SetState) +{ + PARAM_SELF_PROLOGUE(DPSprite); + PARAM_POINTER(state, FState); + PARAM_BOOL_DEF(pending); + self->SetState(state, pending); + return 0; +} + //--------------------------------------------------------------------------- // // PROC P_BringUpWeapon diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 56f991287e..c454ced835 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2408,7 +2408,7 @@ static bool CheckRandom(ZCC_Expression *duration) // Sets up the action function call // //========================================================================== -FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) +FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af, int StateFlags) { // We have 3 cases to consider here: // 1. A function without parameters. This can be called directly @@ -2436,7 +2436,9 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af) // We can use this function directly without wrapping it in a caller. auto selfclass = dyn_cast(afd->Variants[0].SelfClass); assert(selfclass != nullptr); // non classes are not supposed to get here. - if ((afd->Variants[0].Flags & VARF_Action) || !cls->IsDescendantOf(RUNTIME_CLASS(AStateProvider)) || !selfclass->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) + + int comboflags = afd->Variants[0].UseFlags & StateFlags; + if (comboflags == StateFlags) // the function must satisfy all the flags the state requires { return new FxVMFunctionCall(new FxSelf(*af), afd, argumentlist, *af, false); } @@ -2627,7 +2629,7 @@ void ZCCCompiler::CompileStates() if (sl->Action != nullptr) { - auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); + auto code = SetupActionFunction(static_cast(c->Type()), sl->Action, state.UseFlags); if (code != nullptr) { auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, state.UseFlags); diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 9599b4b968..8b3a9f5f12 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -108,7 +108,7 @@ private: void InitFunctions(); void CompileStates(); - FxExpression *SetupActionFunction(PClass *cls, ZCC_TreeNode *sl); + FxExpression *SetupActionFunction(PClass *cls, ZCC_TreeNode *sl, int stateflags); bool SimplifyingConstant; TArray Constants; diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 25c94cb87a..1bc695339d 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -29,6 +29,7 @@ class Inventory : Actor native virtual native color GetBlend (); virtual native bool HandlePickup(Inventory item); virtual native Inventory CreateCopy(Actor other); + virtual native bool SpecialDropAction (Actor dropper); native void GoAwayAndDie(); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index bcbc7db613..6d1b8abfcb 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -133,6 +133,9 @@ class PSprite : Object native native bool bPowDouble; native bool bCVarFast; native bool bFlip; + + native void SetState(State newstate, bool pending = false); + } struct PlayerInfo native // this is what internally is known as player_t diff --git a/wadsrc/static/zscript/strife/sigil.txt b/wadsrc/static/zscript/strife/sigil.txt index d8b1f80f8a..a9f8020094 100644 --- a/wadsrc/static/zscript/strife/sigil.txt +++ b/wadsrc/static/zscript/strife/sigil.txt @@ -1,8 +1,11 @@ // The Almighty Sigil! ------------------------------------------------------ -class Sigil : Weapon native +class Sigil : Weapon { + // NUmPieces gets stored in 'health', so that it can be quickly accessed by ACS's GetSigilPieces function. + int downpieces; + Default { Weapon.Kickback 100; @@ -16,18 +19,7 @@ class Sigil : Weapon native 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 + States(Actor) { Spawn: SIGL A 1; @@ -41,6 +33,9 @@ class Sigil : Weapon native Stop; SIGL E -1; Stop; + } + States(Weapon) + { Ready: SIGH A 0 Bright A_SelectSigilView; Wait; @@ -120,6 +115,353 @@ class Sigil : Weapon native SIGF C 0 Bright A_Light0; Stop; } + + + //============================================================================ + // + // ASigil :: HandlePickup + // + //============================================================================ + + override bool HandlePickup (Inventory item) + { + if (item is "Sigil") + { + int otherPieces = item.health; + if (otherPieces > health) + { + item.bPickupGood = true; + Icon = item.Icon; + // If the player is holding the Sigil right now, drop it and bring + // it back with the new piece(s) in view. + if (Owner.player != null && Owner.player.ReadyWeapon == self) + { + DownPieces = health; + Owner.player.PendingWeapon = self; + } + health = otherPieces; + } + return true; + } + return false; + } + + //============================================================================ + // + // ASigil :: CreateCopy + // + //============================================================================ + + override Inventory CreateCopy (Actor other) + { + Sigil copy = Sigil(Spawn("Sigil")); + copy.Amount = Amount; + copy.MaxAmount = MaxAmount; + copy.health = health; + copy.Icon = Icon; + GoAwayAndDie (); + return copy; + } + + //============================================================================ + // + // A_SelectPiece + // + // Decide which sprite frame self Sigil should use as an item, based on how + // many pieces it represents. + // + //============================================================================ + + void A_SelectPiece () + { + int pieces = min (health, 5); + + if (pieces > 1) + { + SetState (FindState("Spawn") + pieces); + } + } + + //============================================================================ + // + // A_SelectSigilView + // + // Decide which first-person frame self Sigil should show, based on how many + // pieces it represents. Strife did self by selecting a flash that looked like + // the Sigil whenever you switched to it and at the end of an attack. I have + // chosen to make the weapon sprite choose the correct frame and let the flash + // be a regular flash. It means I need to use more states, but I think it's + // worth it. + // + //============================================================================ + + action void A_SelectSigilView () + { + if (player == null) + { + return; + } + PSprite pspr = player.GetPSprite(PSP_WEAPON); + pspr.SetState(pspr.CurState + invoker.health); + } + + //============================================================================ + // + // A_SelectSigilDown + // + // Same as A_SelectSigilView, except it uses DownPieces. self is so that when + // you pick up a Sigil, the old one will drop and *then* change to the new + // one. + // + //============================================================================ + + action void A_SelectSigilDown () + { + if (player == null) + { + return; + } + PSprite pspr = player.GetPSprite(PSP_WEAPON); + int pieces = invoker.downpieces; + if (pieces < 1 || pieces > 5) pieces = invoker.health; + pspr.SetState(pspr.CurState + pieces); + } + + //============================================================================ + // + // A_SelectSigilAttack + // + // Same as A_SelectSigilView, but used just before attacking. + // + //============================================================================ + + action void A_SelectSigilAttack () + { + if (player == null) + { + return; + } + PSprite pspr = player.GetPSprite(PSP_WEAPON); + pspr.SetState(pspr.CurState + (4 * invoker.health - 3)); + } + + //============================================================================ + // + // A_SigilCharge + // + //============================================================================ + + action void A_SigilCharge () + { + A_PlaySound ("weapons/sigilcharge", CHAN_WEAPON); + if (player != null) + { + player.extralight = 2; + } + } + + //============================================================================ + // + // A_FireSigil1 + // + //============================================================================ + + action void A_FireSigil1 () + { + Actor spot; + FTranslatedLineTarget t; + + if (player == null || player.ReadyWeapon == null) + return; + + DamageMobj (self, null, 1*4, 'Sigil', DMG_NO_ARMOR); + A_PlaySound ("weapons/sigilcharge", CHAN_WEAPON); + + BulletSlope (t, ALF_PORTALRESTRICT); + if (t.linetarget != null) + { + spot = Spawn("SpectralLightningSpot", (t.linetarget.pos.xy, t.linetarget.floorz), ALLOW_REPLACE); + if (spot != null) + { + spot.tracer = t.linetarget; + } + } + else + { + spot = Spawn("SpectralLightningSpot", Pos, ALLOW_REPLACE); + if (spot != null) + { + spot.VelFromAngle(28., angle); + } + } + if (spot != null) + { + spot.SetFriendPlayer(player); + spot.target = self; + } + } + + //============================================================================ + // + // A_FireSigil2 + // + //============================================================================ + + action void A_FireSigil2 () + { + if (player == null || player.ReadyWeapon == null) + return; + + DamageMobj (self, null, 2*4, 'Sigil', DMG_NO_ARMOR); + A_PlaySound ("weapons/sigilcharge", CHAN_WEAPON); + SpawnPlayerMissile ("SpectralLightningH1"); + } + + //============================================================================ + // + // A_FireSigil3 + // + //============================================================================ + + action void A_FireSigil3 () + { + if (player == null || player.ReadyWeapon == null) + return; + + DamageMobj (self, null, 3*4, 'Sigil', DMG_NO_ARMOR); + A_PlaySound ("weapons/sigilcharge", CHAN_WEAPON); + + angle -= 90.; + for (int i = 0; i < 20; ++i) + { + angle += 9.; + Actor spot = SpawnSubMissile ("SpectralLightningBall1", self); + if (spot != null) + { + spot.SetZ(pos.z + 32); + } + } + angle -= 90.; + } + + //============================================================================ + // + // A_FireSigil4 + // + //============================================================================ + + action void A_FireSigil4 () + { + FTranslatedLineTarget t; + + if (player == null || player.ReadyWeapon == null) + return; + + DamageMobj (self, null, 4*4, 'Sigil', DMG_NO_ARMOR); + A_PlaySound ("weapons/sigilcharge", CHAN_WEAPON); + + BulletSlope (t, ALF_PORTALRESTRICT); + if (t.linetarget != null) + { + Actor spot = SpawnPlayerMissile ("SpectralLightningBigV1", angle, pLineTarget: t, aimFlags: ALF_PORTALRESTRICT); + if (spot != null) + { + spot.tracer = t.linetarget; + } + } + else + { + Actor spot = SpawnPlayerMissile ("SpectralLightningBigV1"); + if (spot != null) + { + spot.VelFromAngle(spot.Speed, angle); + } + } + } + + //============================================================================ + // + // A_FireSigil5 + // + //============================================================================ + + action void A_FireSigil5 () + { + if (player == null || player.ReadyWeapon == null) + return; + + DamageMobj (self, null, 5*4, 'Sigil', DMG_NO_ARMOR); + A_PlaySound ("weapons/sigilcharge", CHAN_WEAPON); + + SpawnPlayerMissile ("SpectralLightningBigBall1"); + } + + //============================================================================ + // + // ASigil :: SpecialDropAction + // + // Monsters don't drop Sigil pieces. The Sigil pieces grab hold of the person + // who killed the dropper and automatically enter their inventory. That's the + // way it works if you believe Macil, anyway... + // + //============================================================================ + + override bool SpecialDropAction (Actor dropper) + { + // Give a Sigil piece to every player in the game + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i] && players[i].mo != null) + { + GiveSigilPiece (players[i].mo); + Destroy (); + } + } + return true; + } + + //============================================================================ + // + // ASigil :: GiveSigilPiece + // + // Gives the actor another Sigil piece, up to 5. Returns the number of Sigil + // pieces the actor previously held. + // + //============================================================================ + + static int GiveSigilPiece (Actor receiver) + { + Sigil sigl = Sigil(receiver.FindInventory("Sigil")); + if (sigl == null) + { + sigl = Sigil(Spawn("Sigil1")); + if (!sigl.CallTryPickup (receiver)) + { + sigl.Destroy (); + } + return 0; + } + else if (sigl.health < 5) + { + ++sigl.health; + static const class sigils[] = + { + "Sigil1", "Sigil2", "Sigil3", "Sigil4", "Sigil5" + }; + sigl.Icon = GetDefaultByType(sigils[clamp(sigl.health, 1, 5)]).Icon; + // If the player has the Sigil out, drop it and bring it back up. + if (sigl.Owner.player != null && sigl.Owner.player.ReadyWeapon == sigl) + { + sigl.Owner.player.PendingWeapon = sigl; + sigl.DownPieces = sigl.health - 1; + } + return sigl.health - 1; + } + else + { + return 5; + } + } } // Sigil 1 ------------------------------------------------------------------ From 53318f4bdef9ce89a0495510b3cd44481319eafe Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 15:51:07 +0100 Subject: [PATCH 395/471] - scriptified Reaver and Templar. --- src/CMakeLists.txt | 2 -- src/g_strife/a_reaver.cpp | 36 --------------------- src/g_strife/a_strifestuff.cpp | 2 -- src/g_strife/a_templar.cpp | 36 --------------------- wadsrc/static/zscript/strife/inquisitor.txt | 1 - wadsrc/static/zscript/strife/reaver.txt | 27 ++++++++++++++-- wadsrc/static/zscript/strife/sigil.txt | 2 +- wadsrc/static/zscript/strife/templar.txt | 18 ++++++++++- 8 files changed, 42 insertions(+), 82 deletions(-) delete mode 100644 src/g_strife/a_reaver.cpp delete mode 100644 src/g_strife/a_templar.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 211411f20a..c5156cbf46 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -867,13 +867,11 @@ set( NOT_COMPILED_SOURCE_FILES g_strife/a_loremaster.cpp g_strife/a_oracle.cpp g_strife/a_programmer.cpp - g_strife/a_reaver.cpp g_strife/a_rebels.cpp g_strife/a_sentinel.cpp g_strife/a_stalker.cpp g_strife/a_strifeitems.cpp g_strife/a_strifeweapons.cpp - g_strife/a_templar.cpp g_strife/a_thingstoblowup.cpp g_shared/sbarinfo_commands.cpp xlat/xlat_parser.y diff --git a/src/g_strife/a_reaver.cpp b/src/g_strife/a_reaver.cpp deleted file mode 100644 index 9c6e9f6b93..0000000000 --- a/src/g_strife/a_reaver.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -#include "actor.h" -#include "p_enemy.h" -#include "a_action.h" -#include "s_sound.h" -#include "m_random.h" -#include "p_local.h" -#include "a_strifeglobal.h" -#include "vm.h" -*/ - -static FRandom pr_reaverattack ("ReaverAttack"); - -DEFINE_ACTION_FUNCTION(AActor, A_ReaverRanged) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target != NULL) - { - DAngle bangle; - DAngle pitch; - - A_FaceTarget (self); - S_Sound (self, CHAN_WEAPON, "reaver/attack", 1, ATTN_NORM); - bangle = self->Angles.Yaw; - pitch = P_AimLineAttack (self, bangle, MISSILERANGE); - - for (int i = 0; i < 3; ++i) - { - DAngle angle = bangle + pr_reaverattack.Random2() * (22.5 / 256); - int damage = ((pr_reaverattack() & 7) + 1) * 3; - P_LineAttack (self, angle, MISSILERANGE, pitch, damage, NAME_Hitscan, NAME_StrifePuff); - } - } - return 0; -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index df89e614ab..78ceaa0971 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -31,13 +31,11 @@ //#include "a_macil.cpp" #include "a_oracle.cpp" #include "a_programmer.cpp" -#include "a_reaver.cpp" #include "a_rebels.cpp" #include "a_sentinel.cpp" #include "a_stalker.cpp" #include "a_strifeitems.cpp" #include "a_strifeweapons.cpp" -#include "a_templar.cpp" #include "a_thingstoblowup.cpp" // Notes so I don't forget them: diff --git a/src/g_strife/a_templar.cpp b/src/g_strife/a_templar.cpp deleted file mode 100644 index 0bfa00b24e..0000000000 --- a/src/g_strife/a_templar.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "a_strifeglobal.h" -#include "vm.h" -*/ - -static FRandom pr_templar ("Templar"); - -DEFINE_ACTION_FUNCTION(AActor, A_TemplarAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - int damage; - DAngle angle; - DAngle pitch; - - if (self->target == NULL) - return 0; - - S_Sound (self, CHAN_WEAPON, "templar/shoot", 1, ATTN_NORM); - A_FaceTarget (self); - pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE); - - for (int i = 0; i < 10; ++i) - { - damage = (pr_templar() & 4) * 2; - angle = self->Angles.Yaw + pr_templar.Random2() * (11.25 / 256); - P_LineAttack (self, angle, MISSILERANGE+64., pitch + pr_templar.Random2() * (7.097 / 256), damage, NAME_Hitscan, NAME_MaulerPuff); - } - return 0; -} diff --git a/wadsrc/static/zscript/strife/inquisitor.txt b/wadsrc/static/zscript/strife/inquisitor.txt index b27818a61a..e7da303bef 100644 --- a/wadsrc/static/zscript/strife/inquisitor.txt +++ b/wadsrc/static/zscript/strife/inquisitor.txt @@ -31,7 +31,6 @@ class Inquisitor : Actor native void A_InquisitorJump (); native void A_InquisitorCheckLand (); native void A_TossArm (); - native void A_ReaverRanged (); States { diff --git a/wadsrc/static/zscript/strife/reaver.txt b/wadsrc/static/zscript/strife/reaver.txt index 7656a37a93..d1c206b731 100644 --- a/wadsrc/static/zscript/strife/reaver.txt +++ b/wadsrc/static/zscript/strife/reaver.txt @@ -22,8 +22,6 @@ class Reaver : Actor Obituary "$OB_REAVER"; } - native void A_ReaverRanged (); - States { Spawn: @@ -64,4 +62,27 @@ class Reaver : Actor } } - \ No newline at end of file + +extend class Actor +{ + // The Inquisitor also uses this function + + void A_ReaverRanged () + { + if (target != null) + { + A_FaceTarget (); + A_PlaySound ("reaver/attack", CHAN_WEAPON); + double bangle = Angle; + double pitch = AimLineAttack (bangle, MISSILERANGE); + + for (int i = 0; i < 3; ++i) + { + double ang = bangle + Random2[ReaverAttack]() * (22.5 / 256); + int damage = ((random[ReaverAttack]() & 7) + 1) * 3; + LineAttack (ang, MISSILERANGE, pitch, damage, 'Hitscan', "StrifePuff"); + } + } + } + +} \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/sigil.txt b/wadsrc/static/zscript/strife/sigil.txt index a9f8020094..096915ccf2 100644 --- a/wadsrc/static/zscript/strife/sigil.txt +++ b/wadsrc/static/zscript/strife/sigil.txt @@ -448,7 +448,7 @@ class Sigil : Weapon { "Sigil1", "Sigil2", "Sigil3", "Sigil4", "Sigil5" }; - sigl.Icon = GetDefaultByType(sigils[clamp(sigl.health, 1, 5)]).Icon; + sigl.Icon = GetDefaultByType(sigils[clamp(sigl.health, 1, 5)-1]).Icon; // If the player has the Sigil out, drop it and bring it back up. if (sigl.Owner.player != null && sigl.Owner.player.ReadyWeapon == sigl) { diff --git a/wadsrc/static/zscript/strife/templar.txt b/wadsrc/static/zscript/strife/templar.txt index 5b1605cf42..23290011c9 100644 --- a/wadsrc/static/zscript/strife/templar.txt +++ b/wadsrc/static/zscript/strife/templar.txt @@ -25,7 +25,6 @@ class Templar : Actor Obituary "$OB_TEMPLAR"; DropItem "EnergyPod"; } - native void A_TemplarAttack(); States { @@ -64,5 +63,22 @@ class Templar : Actor PGRD \ -1; Stop; } + + void A_TemplarAttack() + { + if (target != null) + { + A_PlaySound ("templar/shoot", CHAN_WEAPON); + A_FaceTarget (); + double pitch = AimLineAttack (angle, MISSILERANGE); + + for (int i = 0; i < 10; ++i) + { + int damage = (random[Templar]() & 4) * 2; + double ang = angle + random2[Templar]() * (11.25 / 256); + LineAttack (ang, MISSILERANGE+64., pitch + random2[Templar]() * (7.097 / 256), damage, 'Hitscan', "MaulerPuff"); + } + } + } } From d2ce78fae7da67b8df0023cb66125fcc9bb0965e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 16:19:01 +0100 Subject: [PATCH 396/471] - changed the return value of PickupMessage to an FString so that it can interface with scripts. - use standard convention of prefacing localizable strings with "$" for C_MidPrint. --- src/c_console.cpp | 2 +- src/d_dehacked.cpp | 2 +- src/d_dehacked.h | 2 +- src/g_shared/a_pickups.cpp | 33 +++++++++++++++---- src/g_shared/a_pickups.h | 7 ++-- src/g_shared/a_weaponpiece.cpp | 2 +- src/g_shared/a_weaponpiece.h | 2 +- src/g_strife/a_coin.cpp | 2 ++ src/g_strife/a_strifeglobal.h | 2 +- wadsrc/static/zscript/shared/inventory.txt | 1 + .../static/zscript/strife/alienspectres.txt | 8 ++--- 11 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 1016be9fd6..691c4a3ca7 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1738,7 +1738,7 @@ DEFINE_ACTION_FUNCTION(DObject, C_MidPrint) PARAM_BOOL_DEF(bold); FFont *fnt = FFont::FindFont(font); - const char *txt = GStrings(text); + const char *txt = text[0] == '$'? GStrings(&text[1]) : text.GetChars(); if (!bold) C_MidPrint(fnt, txt); else C_MidPrintBold(fnt, txt); return 0; diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 624116e06f..e9e5a58d0d 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3144,7 +3144,7 @@ bool ADehackedPickup::TryPickup (AActor *&toucher) return false; } -const char *ADehackedPickup::PickupMessage () +FString ADehackedPickup::PickupMessage () { if (RealPickup != nullptr) return RealPickup->PickupMessage (); diff --git a/src/d_dehacked.h b/src/d_dehacked.h index a622707a3a..434853bf22 100644 --- a/src/d_dehacked.h +++ b/src/d_dehacked.h @@ -42,7 +42,7 @@ class ADehackedPickup : public AInventory HAS_OBJECT_POINTERS public: void Destroy() override; - const char *PickupMessage (); + FString PickupMessage (); bool ShouldRespawn (); bool ShouldStay (); bool TryPickup (AActor *&toucher); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index cb5f4dd121..ad9fb70ce3 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -475,7 +475,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) } int AInventory::StaticLastMessageTic; -const char *AInventory::StaticLastMessage; +FString AInventory::StaticLastMessage; IMPLEMENT_CLASS(AInventory, false, true) @@ -1205,10 +1205,10 @@ void AInventory::Touch (AActor *toucher) if (!(ItemFlags & IF_QUIET)) { - const char * message = PickupMessage (); + FString message = GetPickupMessage (); - if (message != NULL && *message != 0 && localview - && (StaticLastMessageTic != gametic || StaticLastMessage != message)) + if (message.IsNotEmpty() && localview + && (StaticLastMessageTic != gametic || StaticLastMessage.Compare(message))) { StaticLastMessageTic = gametic; StaticLastMessage = message; @@ -1283,11 +1283,32 @@ void AInventory::DoPickupSpecial (AActor *toucher) // //=========================================================================== -const char *AInventory::PickupMessage () +FString AInventory::PickupMessage () { return GetClass()->PickupMessage; } +DEFINE_ACTION_FUNCTION(AInventory, PickupMessage) +{ + PARAM_SELF_PROLOGUE(AInventory); + ACTION_RETURN_STRING(self->PickupMessage()); +} + +FString AInventory::GetPickupMessage() +{ + IFVIRTUAL(AInventory, PickupMessage) + { + VMValue params[1] = { (DObject*)this }; + VMReturn ret; + VMFrameStack stack; + FString retval; + ret.StringAt(&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + return retval; + } + else return PickupMessage(); +} + //=========================================================================== // // AInventory :: PlayPickupSound @@ -1884,7 +1905,7 @@ DEFINE_FIELD(AHealth, PrevHealth) // AHealth :: PickupMessage // //=========================================================================== -const char *AHealth::PickupMessage () +FString AHealth::PickupMessage () { int threshold = GetClass()->LowHealth; diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index e15f0724c9..76a3262549 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -173,7 +173,8 @@ public: virtual void DoEffect (); virtual bool Grind(bool items); - virtual const char *PickupMessage (); + virtual FString PickupMessage (); + FString GetPickupMessage(); virtual void PlayPickupSound (AActor *toucher); bool DoRespawn (); @@ -228,7 +229,7 @@ protected: private: static int StaticLastMessageTic; - static const char *StaticLastMessage; + static FString StaticLastMessage; }; class AStateProvider : public AInventory @@ -438,7 +439,7 @@ class AHealth : public AInventory public: int PrevHealth; virtual bool TryPickup (AActor *&other); - virtual const char *PickupMessage (); + virtual FString PickupMessage (); }; // HealthPickup is some item that gives the player health when used. diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp index 52c9a9e388..bb98415fca 100644 --- a/src/g_shared/a_weaponpiece.cpp +++ b/src/g_shared/a_weaponpiece.cpp @@ -177,7 +177,7 @@ bool AWeaponPiece::PrivateShouldStay () // //=========================================================================== -const char *AWeaponPiece::PickupMessage () +FString AWeaponPiece::PickupMessage () { if (FullWeapon) { diff --git a/src/g_shared/a_weaponpiece.h b/src/g_shared/a_weaponpiece.h index 3a6fbcbd7c..e293637cf9 100644 --- a/src/g_shared/a_weaponpiece.h +++ b/src/g_shared/a_weaponpiece.h @@ -22,7 +22,7 @@ public: bool TryPickup (AActor *&toucher); bool TryPickupRestricted (AActor *&toucher); bool ShouldStay (); - virtual const char *PickupMessage (); + virtual FString PickupMessage (); virtual void PlayPickupSound (AActor *toucher); int PieceValue; diff --git a/src/g_strife/a_coin.cpp b/src/g_strife/a_coin.cpp index f74d92e552..a94b1375d6 100644 --- a/src/g_strife/a_coin.cpp +++ b/src/g_strife/a_coin.cpp @@ -8,6 +8,7 @@ IMPLEMENT_CLASS(ACoin, false, false) +/* const char *ACoin::PickupMessage () { if (Amount == 1) @@ -22,6 +23,7 @@ const char *ACoin::PickupMessage () return msg; } } +*/ bool ACoin::HandlePickup (AInventory *item) { diff --git a/src/g_strife/a_strifeglobal.h b/src/g_strife/a_strifeglobal.h index c07bce63c3..2561d961e5 100644 --- a/src/g_strife/a_strifeglobal.h +++ b/src/g_strife/a_strifeglobal.h @@ -17,7 +17,7 @@ class ACoin : public AInventory { DECLARE_CLASS (ACoin, AInventory) public: - const char *PickupMessage (); + //const char *PickupMessage (); bool HandlePickup (AInventory *item); AInventory *CreateTossable (); AInventory *CreateCopy (AActor *other); diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 1bc695339d..d1164f2c4d 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -30,6 +30,7 @@ class Inventory : Actor native virtual native bool HandlePickup(Inventory item); virtual native Inventory CreateCopy(Actor other); virtual native bool SpecialDropAction (Actor dropper); + virtual native String PickupMessage(); native void GoAwayAndDie(); diff --git a/wadsrc/static/zscript/strife/alienspectres.txt b/wadsrc/static/zscript/strife/alienspectres.txt index 2beee63ea4..39cbc83315 100644 --- a/wadsrc/static/zscript/strife/alienspectres.txt +++ b/wadsrc/static/zscript/strife/alienspectres.txt @@ -108,13 +108,13 @@ class AlienSpectre1 : SpectralMonster } else if (cls == "AlienSpectre2") { - C_MidPrint("SmallFont", "TXT_KILLED_BISHOP"); + C_MidPrint("SmallFont", "$TXT_KILLED_BISHOP"); log = 74; player.GiveInventoryType ("QuestItem21"); } else if (cls == "AlienSpectre3") { - C_MidPrint("SmallFont", "TXT_KILLED_ORACLE"); + C_MidPrint("SmallFont", "$TXT_KILLED_ORACLE"); // If there are any Oracles still alive, kill them. ThinkerIterator it = ThinkerIterator.Create("Oracle"); Actor oracle; @@ -144,7 +144,7 @@ class AlienSpectre1 : SpectralMonster } else if (cls == "AlienSpectre4") { - C_MidPrint("SmallFont", "TXT_KILLED_MACIL"); + C_MidPrint("SmallFont", "$TXT_KILLED_MACIL"); player.GiveInventoryType ("QuestItem24"); if (player.FindInventory ("QuestItem25") == null) { // Richter has taken over. Macil is a snake. @@ -157,7 +157,7 @@ class AlienSpectre1 : SpectralMonster } else if (cls == "AlienSpectre5") { - C_MidPrint("SmallFont", "TXT_KILLED_LOREMASTER"); + C_MidPrint("SmallFont", "$TXT_KILLED_LOREMASTER"); player.GiveInventoryType ("QuestItem26"); if (!multiplayer) From 9064a5b0ac0c11a86a1e6da5559e2682f29bce00 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 18:15:18 +0100 Subject: [PATCH 397/471] - scriptified Strife's coins. - added a String class to allow attaching methods to the builtin string type. This works by checking if the left side of the member accessor is a string and just replacing the tyoe in this one place, all the rest is automatic. --- src/dobjtype.cpp | 4 +- src/dobjtype.h | 1 + src/g_shared/a_artifacts.h | 1 + src/g_shared/a_pickups.cpp | 35 +++++++ src/g_shared/a_pickups.h | 5 +- src/g_shared/a_weapons.cpp | 2 +- src/g_strife/a_coin.cpp | 4 +- src/g_strife/a_strifeglobal.h | 10 -- src/g_strife/a_strifeitems.cpp | 2 +- src/p_conversation.cpp | 26 +++--- src/p_mobj.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 22 ++++- src/scripting/thingdef_data.cpp | 18 ++++ src/scripting/vm/vmdisasm.cpp | 4 + wadsrc/static/zscript/base.txt | 11 +++ wadsrc/static/zscript/shared/inventory.txt | 3 + wadsrc/static/zscript/strife/coin.txt | 104 ++++++++++++++++++++- 17 files changed, 221 insertions(+), 33 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 62a6a2b2d2..7377af56b7 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -89,6 +89,7 @@ PStateLabel *TypeStateLabel; PStruct *TypeVector2; PStruct *TypeVector3; PStruct *TypeColorStruct; +PStruct *TypeStringStruct; PPointer *TypeNullPtr; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -587,7 +588,8 @@ void PType::StaticInit() TypeTable.AddType(TypeSpriteID = new PSpriteID); TypeTable.AddType(TypeTextureID = new PTextureID); - TypeColorStruct = new PStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. + TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. + TypeStringStruct = NewNativeStruct(NAME_String, nullptr); #ifdef __BIG_ENDIAN__ TypeColorStruct->AddField(NAME_a, TypeUInt8); TypeColorStruct->AddField(NAME_r, TypeUInt8); diff --git a/src/dobjtype.h b/src/dobjtype.h index 89d3091564..ad626ee8bb 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -945,6 +945,7 @@ extern PSpriteID *TypeSpriteID; extern PStruct *TypeVector2; extern PStruct *TypeVector3; extern PStruct *TypeColorStruct; +extern PStruct *TypeStringStruct; extern PStatePointer *TypeState; extern PStateLabel *TypeStateLabel; extern PPointer *TypeNullPtr; diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index 95de950867..c3a0f31f08 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -16,6 +16,7 @@ public: virtual bool HandlePickup (AInventory *item); virtual AInventory *CreateCopy (AActor *other); virtual AInventory *CreateTossable (); + virtual void Serialize(FSerializer &arc); virtual void OwnerDied (); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index ad9fb70ce3..df434baae4 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -919,6 +919,27 @@ AInventory *AInventory::CreateTossable () return copy; } +DEFINE_ACTION_FUNCTION(AInventory, CreateTossable) +{ + PARAM_SELF_PROLOGUE(AInventory); + ACTION_RETURN_OBJECT(self->CreateTossable()); +} + +AInventory *AInventory::CallCreateTossable() +{ + IFVIRTUAL(AInventory, CreateTossable) + { + VMValue params[1] = { (DObject*)this }; + VMReturn ret; + VMFrameStack stack; + AInventory *retval; + ret.PointerAt((void**)&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + return retval; + } + else return CreateTossable(); +} + //=========================================================================== // // AInventory :: BecomeItem @@ -946,6 +967,13 @@ void AInventory::BecomeItem () SetState (FindState("Held")); } +DEFINE_ACTION_FUNCTION(AInventory, BecomeItem) +{ + PARAM_SELF_PROLOGUE(AInventory); + self->BecomeItem(); + return 0; +} + //=========================================================================== // // AInventory :: BecomePickup @@ -973,6 +1001,13 @@ void AInventory::BecomePickup () SetState (SpawnState); } +DEFINE_ACTION_FUNCTION(AInventory, BecomePickup) +{ + PARAM_SELF_PROLOGUE(AInventory); + self->BecomePickup(); + return 0; +} + //=========================================================================== // // AInventory :: AbsorbDamage diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 76a3262549..8fc96cd57f 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -196,13 +196,14 @@ public: FSoundIDNoInit PickupSound; - virtual void BecomeItem (); - virtual void BecomePickup (); + void BecomeItem (); + void BecomePickup (); virtual void AttachToOwner (AActor *other); virtual void DetachFromOwner (); virtual AInventory *CreateCopy (AActor *other); AInventory *CallCreateCopy(AActor *other); virtual AInventory *CreateTossable (); + AInventory *CallCreateTossable(); virtual bool GoAway (); virtual void GoAwayAndDie (); virtual bool HandlePickup (AInventory *item); diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index c2feebec67..4f49ecd6f6 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -424,7 +424,7 @@ AInventory *AWeapon::CreateTossable () (((AWeapon*)SisterWeapon->GetDefault())->AmmoGive1 > 0 || ((AWeapon*)SisterWeapon->GetDefault())->AmmoGive2 > 0)) { - return SisterWeapon->CreateTossable (); + return SisterWeapon->CallCreateTossable (); } AWeapon *copy = static_cast (Super::CreateTossable ()); diff --git a/src/g_strife/a_coin.cpp b/src/g_strife/a_coin.cpp index a94b1375d6..dcbbecf10b 100644 --- a/src/g_strife/a_coin.cpp +++ b/src/g_strife/a_coin.cpp @@ -6,9 +6,9 @@ // Coin --------------------------------------------------------------------- +/* IMPLEMENT_CLASS(ACoin, false, false) -/* const char *ACoin::PickupMessage () { if (Amount == 1) @@ -23,7 +23,6 @@ const char *ACoin::PickupMessage () return msg; } } -*/ bool ACoin::HandlePickup (AInventory *item) { @@ -108,3 +107,4 @@ AInventory *ACoin::CreateTossable () } return tossed; } +*/ diff --git a/src/g_strife/a_strifeglobal.h b/src/g_strife/a_strifeglobal.h index 2561d961e5..adf8d59bf8 100644 --- a/src/g_strife/a_strifeglobal.h +++ b/src/g_strife/a_strifeglobal.h @@ -13,16 +13,6 @@ public: bool Use (bool pickup); }; -class ACoin : public AInventory -{ - DECLARE_CLASS (ACoin, AInventory) -public: - //const char *PickupMessage (); - bool HandlePickup (AInventory *item); - AInventory *CreateTossable (); - AInventory *CreateCopy (AActor *other); -}; - class ADummyStrifeItem : public AInventory { DECLARE_CLASS (ADummyStrifeItem, AInventory) diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index 0586583ff5..0f1132cbd5 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -82,7 +82,7 @@ bool AHealthTraining::TryPickup (AActor *&toucher) if (Super::TryPickup (toucher)) { toucher->GiveInventoryType (PClass::FindActor("GunTraining")); - AInventory *coin = Spawn (); + AInventory *coin = (AInventory*)Spawn("Coin"); if (coin != NULL) { coin->Amount = toucher->player->mo->accuracy*5 + 300; diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 95aabe44b8..bf1c392aef 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -1053,18 +1053,22 @@ public: if (ShowGold) { - AInventory *coin = cp->ConversationPC->FindInventory (RUNTIME_CLASS(ACoin)); - char goldstr[32]; + auto cointype = PClass::FindActor("Coin"); + if (cointype) + { + AInventory *coin = cp->ConversationPC->FindInventory(cointype); + char goldstr[32]; - mysnprintf (goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0); - screen->DrawText (SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true, - DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE); - screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon), - 3, 190, DTA_320x200, true, - DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE); - screen->DrawText (SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE); - screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon), - 2, 189, DTA_320x200, true, TAG_DONE); + mysnprintf(goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0); + screen->DrawText(SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true, + DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE); + screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon), + 3, 190, DTA_320x200, true, + DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE); + screen->DrawText(SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE); + screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon), + 2, 189, DTA_320x200, true, TAG_DONE); + } } y = mYpos; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 6f0754a8fa..0f58b600c4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1002,7 +1002,7 @@ bool AActor::UseInventory(AInventory *item) AInventory *AActor::DropInventory (AInventory *item) { - AInventory *drop = item->CreateTossable (); + AInventory *drop = item->CallCreateTossable (); if (drop == NULL) { diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f63629bb52..5277ad70e1 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5766,9 +5766,11 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) // allow accessing the color channels by mapping the type to a matching struct which defines them. if (Object->ValueType == TypeColor) + { Object->ValueType = TypeColorStruct; + } - if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { auto ptype = static_cast(Object->ValueType)->PointedType; if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) @@ -7306,6 +7308,12 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } } + if (Self->ValueType == TypeString) + { + // same for String methods. It also uses a hidden struct type to define them. + Self->ValueType = TypeStringStruct; + } + if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { auto ptype = static_cast(Self->ValueType)->PointedType; @@ -7876,8 +7884,16 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { assert(Self != nullptr); selfemit = Self->Emit(build); - assert(selfemit.RegType == REGT_POINTER); - build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); + assert((selfemit.RegType == REGT_POINTER) || (selfemit.Fixed && selfemit.Target)); + if (selfemit.Fixed && selfemit.Target) + { + // Address of a local variable. + build->Emit(OP_PARAM, 0, selfemit.RegType | REGT_ADDROF, selfemit.RegNum); + } + else + { + build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); + } count += 1; if (Function->Variants[0].Flags & VARF_Action) { diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index d17e10420b..a1542a8a50 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -46,6 +46,8 @@ #include "p_maputl.h" #include "gi.h" #include "p_terrain.h" +#include "gstrings.h" +#include "zstring.h" static TArray properties; static TArray AFTable; @@ -826,3 +828,19 @@ DEFINE_ACTION_FUNCTION(DObject, GameType) PARAM_PROLOGUE; ACTION_RETURN_INT(gameinfo.gametype); } + +DEFINE_ACTION_FUNCTION(FStringTable, Localize) +{ + PARAM_PROLOGUE; + PARAM_STRING(label); + ACTION_RETURN_STRING(GStrings(label)); +} + +DEFINE_ACTION_FUNCTION(FString, Replace) +{ + PARAM_SELF_STRUCT_PROLOGUE(FString); + PARAM_STRING(s1); + PARAM_STRING(s2); + self->Substitute(*s1, *s2); + return 0; +} \ No newline at end of file diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 88962bf680..2158139abb 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -289,6 +289,10 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction a &= CMP_CHECK | CMP_APPROX; cmp = true; } + if (code[i].op == OP_PARAM && code[i].b & REGT_ADDROF) + { + name = "parama"; + } if (cmp) { // Comparison instruction. Modify name for inverted test. if (!(a & CMP_CHECK)) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index c76e4590ec..8d2e7a71bc 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -98,6 +98,11 @@ struct LevelLocals native // level_info_t *info cannot be done yet. } +struct StringTable native +{ + native static String Localize(String val); +} + // a few values of this need to be readable by the play code. // Most are handled at load time and are omitted here. struct DehInfo native @@ -275,3 +280,9 @@ enum EPickStart PPS_FORCERANDOM = 1, PPS_NOBLOCKINGCHECK = 2, } + +// Although String is a builtin type, this is a convenient way to attach methods to it. +struct String native +{ + native void Replace(String pattern, String replacement); +} diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index d1164f2c4d..d3e50d1981 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -29,10 +29,13 @@ class Inventory : Actor native virtual native color GetBlend (); virtual native bool HandlePickup(Inventory item); virtual native Inventory CreateCopy(Actor other); + virtual native Inventory CreateTossable(); virtual native bool SpecialDropAction (Actor dropper); virtual native String PickupMessage(); native void GoAwayAndDie(); + native void BecomeItem(); + native void BecomePickup(); // These are regular functions for the item itself. private native void A_RestoreSpecialDoomThing(); diff --git a/wadsrc/static/zscript/strife/coin.txt b/wadsrc/static/zscript/strife/coin.txt index a930cb0ba9..b94a3f1d13 100644 --- a/wadsrc/static/zscript/strife/coin.txt +++ b/wadsrc/static/zscript/strife/coin.txt @@ -1,7 +1,7 @@ // Coin --------------------------------------------------------------------- -class Coin : Inventory native +class Coin : Inventory { Default { @@ -20,6 +20,108 @@ class Coin : Inventory native COIN A -1; Stop; } + + // Coin --------------------------------------------------------------------- + + override String PickupMessage () + { + if (Amount == 1) + { + return Super.PickupMessage(); + } + else + { + String msg = StringTable.Localize("TXT_XGOLD"); + msg.Replace("%d", "" .. Amount); + return msg; + } + } + + override bool HandlePickup (Inventory item) + { + if (item is "Coin") + { + if (Amount < MaxAmount) + { + if (MaxAmount - Amount < item.Amount) + { + Amount = MaxAmount; + } + else + { + Amount += item.Amount; + } + item.bPickupGood = true; + } + return true; + } + return false; + } + + override Inventory CreateCopy (Actor other) + { + if (GetClass() == "Coin") + { + return Super.CreateCopy (other); + } + Inventory copy = Inventory(Spawn("Coin")); + copy.Amount = Amount; + copy.BecomeItem (); + GoAwayAndDie (); + return copy; + } + + //=========================================================================== + // + // ACoin :: CreateTossable + // + // Gold drops in increments of 50 if you have that much, less if you don't. + // + //=========================================================================== + + override Inventory CreateTossable () + { + Coin tossed; + + if (bUndroppable || Owner == NULL || Amount <= 0) + { + return NULL; + } + if (Amount >= 50) + { + Amount -= 50; + tossed = Coin(Spawn("Gold50")); + } + else if (Amount >= 25) + { + Amount -= 25; + tossed = Coin(Spawn("Gold25")); + } + else if (Amount >= 10) + { + Amount -= 10; + tossed = Coin(Spawn("Gold10")); + } + else if (Amount > 1 || bKeepDepleted) + { + Amount -= 1; + tossed = Coin(Spawn("Coin")); + } + else // Amount == 1 && !(ItemFlags & IF_KEEPDEPLETED) + { + BecomePickup (); + tossed = self; + } + tossed.bSpecial = false; + tossed.bSolid = false; + tossed.DropTime = 30; + if (tossed != self && Amount <= 0) + { + Destroy (); + } + return tossed; + } + } From b8cf377d9e7a6825a5c2ec48399be122d5290e85 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 18:36:13 +0100 Subject: [PATCH 398/471] - scriptified the Crusader. --- src/CMakeLists.txt | 1 - src/g_strife/a_coin.cpp | 110 ---------------------- src/g_strife/a_crusader.cpp | 100 -------------------- src/g_strife/a_strifestuff.cpp | 2 - src/p_mobj.cpp | 9 ++ wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/strife/crusader.txt | 85 +++++++++++++++-- 7 files changed, 88 insertions(+), 220 deletions(-) delete mode 100644 src/g_strife/a_coin.cpp delete mode 100644 src/g_strife/a_crusader.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5156cbf46..c8d560c2be 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_coin.cpp g_strife/a_crusader.cpp g_strife/a_inquisitor.cpp g_strife/a_loremaster.cpp diff --git a/src/g_strife/a_coin.cpp b/src/g_strife/a_coin.cpp deleted file mode 100644 index dcbbecf10b..0000000000 --- a/src/g_strife/a_coin.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* -#include "a_pickups.h" -#include "a_strifeglobal.h" -#include "gstrings.h" -*/ - -// Coin --------------------------------------------------------------------- - -/* -IMPLEMENT_CLASS(ACoin, false, false) - -const char *ACoin::PickupMessage () -{ - if (Amount == 1) - { - return Super::PickupMessage(); - } - else - { - static char msg[64]; - - mysnprintf (msg, countof(msg), GStrings("TXT_XGOLD"), Amount); - return msg; - } -} - -bool ACoin::HandlePickup (AInventory *item) -{ - if (item->IsKindOf (RUNTIME_CLASS(ACoin))) - { - if (Amount < MaxAmount) - { - if (MaxAmount - Amount < item->Amount) - { - Amount = MaxAmount; - } - else - { - Amount += item->Amount; - } - item->ItemFlags |= IF_PICKUPGOOD; - } - return true; - } - return false; -} - -AInventory *ACoin::CreateCopy (AActor *other) -{ - if (GetClass() == RUNTIME_CLASS(ACoin)) - { - return Super::CreateCopy (other); - } - AInventory *copy = Spawn (); - copy->Amount = Amount; - copy->BecomeItem (); - GoAwayAndDie (); - return copy; -} - -//=========================================================================== -// -// ACoin :: CreateTossable -// -// Gold drops in increments of 50 if you have that much, less if you don't. -// -//=========================================================================== - -AInventory *ACoin::CreateTossable () -{ - ACoin *tossed; - - if ((ItemFlags & IF_UNDROPPABLE) || Owner == NULL || Amount <= 0) - { - return NULL; - } - if (Amount >= 50) - { - Amount -= 50; - tossed = static_cast(Spawn("Gold50", Owner->Pos(), NO_REPLACE)); - } - else if (Amount >= 25) - { - Amount -= 25; - tossed = static_cast(Spawn("Gold25", Owner->Pos(), NO_REPLACE)); - } - else if (Amount >= 10) - { - Amount -= 10; - tossed = static_cast(Spawn("Gold10", Owner->Pos(), NO_REPLACE)); - } - else if (Amount > 1 || (ItemFlags & IF_KEEPDEPLETED)) - { - Amount -= 1; - tossed = static_cast(Spawn("Coin", Owner->Pos(), NO_REPLACE)); - } - else // Amount == 1 && !(ItemFlags & IF_KEEPDEPLETED) - { - BecomePickup (); - tossed = this; - } - tossed->flags &= ~(MF_SPECIAL|MF_SOLID); - tossed->DropTime = 30; - if (tossed != this && Amount <= 0) - { - Destroy (); - } - return tossed; -} -*/ diff --git a/src/g_strife/a_crusader.cpp b/src/g_strife/a_crusader.cpp deleted file mode 100644 index 05835a5f98..0000000000 --- a/src/g_strife/a_crusader.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "a_strifeglobal.h" -#include "vm.h" -*/ - -static bool CrusaderCheckRange (AActor *self) -{ - if (self->reactiontime == 0 && P_CheckSight (self, self->target)) - { - return self->Distance2D (self->target) < 264.; - } - return false; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CrusaderChoose) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - - if (CrusaderCheckRange (self)) - { - A_FaceTarget (self); - self->Angles.Yaw -= 180./16; - P_SpawnMissileZAimed (self, self->Z() + 40, self->target, PClass::FindActor("FastFlameMissile")); - } - else - { - if (P_CheckMissileRange (self)) - { - A_FaceTarget (self); - P_SpawnMissileZAimed (self, self->Z() + 56, self->target, PClass::FindActor("CrusaderMissile")); - self->Angles.Yaw -= 45./32; - P_SpawnMissileZAimed (self, self->Z() + 40, self->target, PClass::FindActor("CrusaderMissile")); - self->Angles.Yaw += 45./16; - P_SpawnMissileZAimed (self, self->Z() + 40, self->target, PClass::FindActor("CrusaderMissile")); - self->Angles.Yaw -= 45./16; - self->reactiontime += 15; - } - self->SetState (self->SeeState); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepLeft) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Angles.Yaw += 90./16; - AActor *misl = P_SpawnMissileZAimed (self, self->Z() + 48, self->target, PClass::FindActor("FastFlameMissile")); - if (misl != NULL) - { - misl->Vel.Z += 1; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepRight) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Angles.Yaw -= 90./16; - AActor *misl = P_SpawnMissileZAimed (self, self->Z() + 48, self->target, PClass::FindActor("FastFlameMissile")); - if (misl != NULL) - { - misl->Vel.Z += 1; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CrusaderRefire) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL || - self->target->health <= 0 || - !P_CheckSight (self, self->target)) - { - self->SetState (self->SeeState); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CrusaderDeath) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (CheckBossDeath (self)) - { - EV_DoFloor (DFloor::floorLowerToLowest, NULL, 667, 1., 0., -1, 0, false); - } - return 0; -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 78ceaa0971..d38e4130bb 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -24,8 +24,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_coin.cpp" -#include "a_crusader.cpp" #include "a_inquisitor.cpp" #include "a_loremaster.cpp" //#include "a_macil.cpp" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 0f58b600c4..93c9b80f35 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6520,6 +6520,15 @@ AActor *P_SpawnMissileZAimed (AActor *source, double z, AActor *dest, PClassActo return P_SpawnMissileAngleZSpeed (source, z, type, an, vz, speed); } +DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZAimed) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(z); + PARAM_OBJECT(dest, AActor); + PARAM_CLASS(type, AActor); + ACTION_RETURN_OBJECT(P_SpawnMissileZAimed(self, z, dest, type)); +} + //--------------------------------------------------------------------------- // // FUNC P_SpawnMissileAngleZSpeed diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index cdcc630b5e..3b49e3e3c3 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -310,6 +310,7 @@ class Actor : Thinker native native Actor SpawnMissileXYZ(Vector3 pos, Actor dest, Class type, bool checkspawn = true, Actor owner = null); native Actor SpawnMissileZ (double z, Actor dest, class type); native Actor SpawnMissileAngleZSpeed (double z, class type, double angle, double vz, double speed, Actor owner = null, bool checkspawn = true); + native Actor SpawnMissileZAimed (double z, Actor dest, Class type); native Actor SpawnSubMissile(Class type, Actor target); native Actor, Actor SpawnPlayerMissile(class type, double angle = 0, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); diff --git a/wadsrc/static/zscript/strife/crusader.txt b/wadsrc/static/zscript/strife/crusader.txt index 02b08fc937..834464e063 100644 --- a/wadsrc/static/zscript/strife/crusader.txt +++ b/wadsrc/static/zscript/strife/crusader.txt @@ -28,12 +28,6 @@ class Crusader : Actor 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: @@ -66,6 +60,83 @@ class Crusader : Actor ROB2 P -1 A_CrusaderDeath; Stop; } + +// Crusader ----------------------------------------------------------------- + + private bool CrusaderCheckRange () + { + if (reactiontime == 0 && CheckSight (target)) + { + return Distance2D (target) < 264.; + } + return false; + } + + void A_CrusaderChoose () + { + if (target == null) + return; + + if (CrusaderCheckRange ()) + { + A_FaceTarget (); + angle -= 180./16; + SpawnMissileZAimed (pos.z + 40, target, "FastFlameMissile"); + } + else + { + if (CheckMissileRange ()) + { + A_FaceTarget (); + SpawnMissileZAimed (pos.z + 56, target, "CrusaderMissile"); + angle -= 45./32; + SpawnMissileZAimed (pos.z + 40, target, "CrusaderMissile"); + angle += 45./16; + SpawnMissileZAimed (pos.z + 40, target, "CrusaderMissile"); + angle -= 45./16; + reactiontime += 15; + } + SetState (SeeState); + } + } + + void A_CrusaderSweepLeft () + { + angle += 90./16; + Actor misl = SpawnMissileZAimed (pos.z + 48, target, "FastFlameMissile"); + if (misl != null) + { + misl.Vel.Z += 1; + } + } + + void A_CrusaderSweepRight () + { + angle -= 90./16; + Actor misl = SpawnMissileZAimed (pos.z + 48, target, "FastFlameMissile"); + if (misl != null) + { + misl.Vel.Z += 1; + } + } + + void A_CrusaderRefire () + { + if (target == null || + target.health <= 0 || + !CheckSight (target)) + { + SetState (SeeState); + } + } + + void A_CrusaderDeath () + { + if (CheckBossDeath ()) + { + Floor_LowerToLowest(667, 8); + } + } } @@ -105,7 +176,7 @@ class CrusaderMissile : Actor MICR A 6 Bright A_RocketInFlight; Loop; Death: - SMIS A 0 Bright A_SetTranslucent(1,1); + SMIS A 0 Bright A_SetRenderStyle(1, STYLE_Normal); SMIS A 5 Bright; SMIS B 5 Bright; SMIS C 4 Bright; From bf1c2a7e51d1e0688adc215539635635ed76d9b8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 18:49:25 +0100 Subject: [PATCH 399/471] - scriptified the Inquisitor. --- src/CMakeLists.txt | 2 - src/g_strife/a_inquisitor.cpp | 136 -------------------- src/g_strife/a_strifestuff.cpp | 2 - wadsrc/static/zscript/strife/inquisitor.txt | 112 ++++++++++++++-- 4 files changed, 104 insertions(+), 148 deletions(-) delete mode 100644 src/g_strife/a_inquisitor.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c8d560c2be..74760f138a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,8 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_crusader.cpp - g_strife/a_inquisitor.cpp g_strife/a_loremaster.cpp g_strife/a_oracle.cpp g_strife/a_programmer.cpp diff --git a/src/g_strife/a_inquisitor.cpp b/src/g_strife/a_inquisitor.cpp deleted file mode 100644 index a4c2d72f4f..0000000000 --- a/src/g_strife/a_inquisitor.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "vm.h" -*/ - -static FRandom pr_inq ("Inquisitor"); - -DEFINE_ACTION_FUNCTION(AActor, A_InquisitorWalk) -{ - PARAM_SELF_PROLOGUE(AActor); - - S_Sound (self, CHAN_BODY, "inquisitor/walk", 1, ATTN_NORM); - A_Chase (stack, self); - return 0; -} - -bool InquisitorCheckDistance (AActor *self) -{ - if (self->reactiontime == 0 && P_CheckSight (self, self->target)) - { - return self->Distance2D (self->target) < 264.; - } - return false; -} - -DEFINE_ACTION_FUNCTION(AActor, A_InquisitorDecide) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - - A_FaceTarget (self); - if (!InquisitorCheckDistance (self)) - { - self->SetState (self->FindState("Grenade")); - } - if (self->target->Z() != self->Z()) - { - if (self->Top() + 54 < self->ceilingz) - { - self->SetState (self->FindState("Jump")); - } - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_InquisitorAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *proj; - - if (self->target == NULL) - return 0; - - A_FaceTarget (self); - - self->AddZ(32); - self->Angles.Yaw -= 45./32; - proj = P_SpawnMissileZAimed (self, self->Z(), self->target, PClass::FindActor("InquisitorShot")); - if (proj != NULL) - { - proj->Vel.Z += 9; - } - self->Angles.Yaw += 45./16; - proj = P_SpawnMissileZAimed (self, self->Z(), self->target, PClass::FindActor("InquisitorShot")); - if (proj != NULL) - { - proj->Vel.Z += 16; - } - self->AddZ(-32); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_InquisitorJump) -{ - PARAM_SELF_PROLOGUE(AActor); - - double dist; - double speed; - - if (self->target == NULL) - return 0; - - S_Sound (self, CHAN_ITEM|CHAN_LOOP, "inquisitor/jump", 1, ATTN_NORM); - self->AddZ(64); - A_FaceTarget (self); - speed = self->Speed * (2./3); - self->VelFromAngle(speed); - dist = self->DistanceBySpeed(self->target, speed); - self->Vel.Z = (self->target->Z() - self->Z()) / dist; - self->reactiontime = 60; - self->flags |= MF_NOGRAVITY; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_InquisitorCheckLand) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->reactiontime--; - if (self->reactiontime < 0 || - self->Vel.X == 0 || - self->Vel.Y == 0 || - self->Z() <= self->floorz) - { - self->SetState (self->SeeState); - self->reactiontime = 0; - self->flags &= ~MF_NOGRAVITY; - S_StopSound (self, CHAN_ITEM); - return 0; - } - if (!S_IsActorPlayingSomething (self, CHAN_ITEM, -1)) - { - S_Sound (self, CHAN_ITEM|CHAN_LOOP, "inquisitor/jump", 1, ATTN_NORM); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_TossArm) -{ - 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.); - foo->VelFromAngle(foo->Speed / 8); - foo->Vel.Z = pr_inq() / 64.; - return 0; -} - diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index d38e4130bb..ba316175d6 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -24,9 +24,7 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_inquisitor.cpp" #include "a_loremaster.cpp" -//#include "a_macil.cpp" #include "a_oracle.cpp" #include "a_programmer.cpp" #include "a_rebels.cpp" diff --git a/wadsrc/static/zscript/strife/inquisitor.txt b/wadsrc/static/zscript/strife/inquisitor.txt index e7da303bef..ef73ade1ed 100644 --- a/wadsrc/static/zscript/strife/inquisitor.txt +++ b/wadsrc/static/zscript/strife/inquisitor.txt @@ -25,13 +25,6 @@ class Inquisitor : Actor 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 (); - States { Spawn: @@ -81,6 +74,109 @@ class Inquisitor : Actor RBB3 E -1; Stop; } + + + // Inquisitor --------------------------------------------------------------- + + void A_InquisitorWalk () + { + A_PlaySound ("inquisitor/walk", CHAN_BODY); + A_Chase (); + } + + private bool InquisitorCheckDistance () + { + if (reactiontime == 0 && CheckSight (target)) + { + return Distance2D (target) < 264.; + } + return false; + } + + void A_InquisitorDecide () + { + if (target == null) + return; + + A_FaceTarget (); + if (!InquisitorCheckDistance ()) + { + SetStateLabel("Grenade"); + } + if (target.pos.z != pos.z) + { + if (pos.z + height + 54 < ceilingz) + { + SetStateLabel("Jump"); + } + } + } + + void A_InquisitorAttack () + { + if (target == null) + return; + + A_FaceTarget (); + + AddZ(32); + angle -= 45./32; + Actor proj = SpawnMissileZAimed (pos.z, target, "InquisitorShot"); + if (proj != null) + { + proj.Vel.Z += 9; + } + angle += 45./16; + proj = SpawnMissileZAimed (pos.z, target, "InquisitorShot"); + if (proj != null) + { + proj.Vel.Z += 16; + } + AddZ(-32); + } + + void A_InquisitorJump () + { + if (target == null) + return; + + A_PlaySound ("inquisitor/jump", CHAN_ITEM, 1, true); + AddZ(64); + A_FaceTarget (); + speed = Speed * (2./3); + VelFromAngle(speed); + double dist = DistanceBySpeed(target, speed); + Vel.Z = (target.pos.z - pos.z) / dist; + reactiontime = 60; + bNoGravity = true; + } + + void A_InquisitorCheckLand () + { + reactiontime--; + if (reactiontime < 0 || + Vel.X == 0 || + Vel.Y == 0 || + pos.z <= floorz) + { + SetState (SeeState); + reactiontime = 0; + bNoGravity = false; + A_StopSound (CHAN_ITEM); + return; + } + A_PlaySound ("inquisitor/jump", CHAN_ITEM, 1, true); + } + + void A_TossArm () + { + Actor foo = Spawn("InquisitorArm", Pos + (0,0,24), ALLOW_REPLACE); + foo.angle = angle - 90. + Random2[Inquisitor]() * (360./1024.); + foo.VelFromAngle(foo.Speed / 8); + foo.Vel.Z = random[Inquisitor]() / 64.; + } + + } // Inquisitor Shot ---------------------------------------------------------- @@ -109,7 +205,7 @@ class InquisitorShot : Actor UBAM AB 3 A_Countdown; Loop; Death: - BNG2 A 0 Bright A_SetTranslucent(1,1); + BNG2 A 0 Bright A_SetRenderStyle(1, STYLE_Normal); BNG2 A 4 Bright A_Explode(192, 192, 1, 1); BNG2 B 4 Bright; BNG2 C 4 Bright; From 119bcb924d134db5befa459d89ee5b6664081508 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 18:59:57 +0100 Subject: [PATCH 400/471] - scriptified the Loremaster. --- src/CMakeLists.txt | 1 - src/g_strife/a_loremaster.cpp | 43 --------------------- src/g_strife/a_strifestuff.cpp | 1 - src/p_mobj.cpp | 11 +++++- wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/strife/loremaster.txt | 24 ++++++++++-- 6 files changed, 31 insertions(+), 50 deletions(-) delete mode 100644 src/g_strife/a_loremaster.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 74760f138a..eddf2d9e94 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_loremaster.cpp g_strife/a_oracle.cpp g_strife/a_programmer.cpp g_strife/a_rebels.cpp diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp deleted file mode 100644 index 747ba326af..0000000000 --- a/src/g_strife/a_loremaster.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* -#include "actor.h" -#include "a_action.h" -#include "a_strifeglobal.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "vm.h" -*/ - -// Loremaster (aka Priest) -------------------------------------------------- - -class ALoreShot : public AActor -{ - DECLARE_CLASS (ALoreShot, AActor) -public: - int DoSpecialDamage (AActor *victim, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(ALoreShot, false, false) - -int ALoreShot::DoSpecialDamage (AActor *victim, int damage, FName damagetype) -{ - - if (victim != NULL && target != NULL && !(victim->flags7 & MF7_DONTTHRUST)) - { - DVector3 thrust = victim->Vec3To(target); - thrust.MakeResize(255. * 50 / MAX(victim->Mass, 1)); - victim->Vel += thrust; - } - return damage; -} - -DEFINE_ACTION_FUNCTION(AActor, A_LoremasterChain) -{ - PARAM_SELF_PROLOGUE(AActor); - - S_Sound (self, CHAN_BODY, "loremaster/active", 1, ATTN_NORM); - Spawn("LoreShot2", self->Pos(), ALLOW_REPLACE); - Spawn("LoreShot2", self->Vec3Offset(-self->Vel/2.), ALLOW_REPLACE); - Spawn("LoreShot2", self->Vec3Offset(-self->Vel), ALLOW_REPLACE); - return 0; -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index ba316175d6..e8ae59c182 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -24,7 +24,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_loremaster.cpp" #include "a_oracle.cpp" #include "a_programmer.cpp" #include "a_rebels.cpp" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 93c9b80f35..8424caee82 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7509,13 +7509,20 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2Angle) } +DEFINE_ACTION_FUNCTION(AActor, Vec3To) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(t, AActor) + ACTION_RETURN_VEC3(self->Vec3To(t)); +} + DEFINE_ACTION_FUNCTION(AActor, Vec3Angle) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(length) - PARAM_ANGLE(angle); + PARAM_ANGLE(angle); PARAM_FLOAT(z); - PARAM_BOOL_DEF(absolute); + PARAM_BOOL_DEF(absolute); ACTION_RETURN_VEC3(self->Vec3Angle(length, angle, z, absolute)); } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 3b49e3e3c3..2d2725d1e6 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -354,6 +354,7 @@ class Actor : Thinker native native double AngleTo(Actor target, bool absolute = false); native void AddZ(double zadd, bool moving = true); native void SetZ(double z); + native vector3 Vec3To(Actor other); native vector3 Vec3Offset(double x, double y, double z, bool absolute = false); native vector3 Vec3Angle(double length, double angle, double z = 0, bool absolute = false); native vector2 Vec2Angle(double length, double angle, bool absolute = false); diff --git a/wadsrc/static/zscript/strife/loremaster.txt b/wadsrc/static/zscript/strife/loremaster.txt index 4a48cf4d30..14571f91c8 100644 --- a/wadsrc/static/zscript/strife/loremaster.txt +++ b/wadsrc/static/zscript/strife/loremaster.txt @@ -76,7 +76,7 @@ class Loremaster : Actor // Loremaster Projectile ---------------------------------------------------- -class LoreShot : Actor native +class LoreShot : Actor { Default { @@ -91,8 +91,6 @@ class LoreShot : Actor native ActiveSound "loremaster/swish"; } - native void A_LoremasterChain (); - States { Spawn: @@ -102,6 +100,26 @@ class LoreShot : Actor native OCLW A 6; Stop; } + + override int DoSpecialDamage (Actor victim, int damage, Name damagetype) + { + + if (victim != NULL && target != NULL && !victim.bDontThrust) + { + Vector3 thrust = victim.Vec3To(target); + victim.Vel += thrust.Unit() * (255. * 50 / max(victim.Mass, 1)); + } + return damage; + } + + void A_LoremasterChain () + { + A_PlaySound ("loremaster/active", CHAN_BODY); + Spawn("LoreShot2", Pos, ALLOW_REPLACE); + Spawn("LoreShot2", Vec3Offset(-Vel.x/2., -Vel.y/2., -Vel.z/2.), ALLOW_REPLACE); + Spawn("LoreShot2", Vec3Offset(-Vel.x, -Vel.y, -Vel.z), ALLOW_REPLACE); + } + } // Loremaster Subprojectile ------------------------------------------------- From 360cbfba2a843e5e828cf17706816dc2f8743d37 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 19:42:26 +0100 Subject: [PATCH 401/471] - scriptified Oracle, Programmer and Rebels. --- src/CMakeLists.txt | 3 - src/actor.h | 2 +- src/g_strife/a_oracle.cpp | 26 ---- src/g_strife/a_programmer.cpp | 141 ------------------ src/g_strife/a_rebels.cpp | 124 --------------- src/g_strife/a_strifeitems.cpp | 14 +- src/g_strife/a_strifestuff.cpp | 3 - src/p_mobj.cpp | 7 + wadsrc/static/zscript/actor.txt | 4 +- wadsrc/static/zscript/strife/oracle.txt | 17 ++- wadsrc/static/zscript/strife/programmer.txt | 115 +++++++++++++- wadsrc/static/zscript/strife/rebels.txt | 73 ++++++++- .../static/zscript/strife/strifehumanoid.txt | 18 +++ 13 files changed, 233 insertions(+), 314 deletions(-) delete mode 100644 src/g_strife/a_oracle.cpp delete mode 100644 src/g_strife/a_programmer.cpp delete mode 100644 src/g_strife/a_rebels.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eddf2d9e94..885b9fd916 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,9 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_oracle.cpp - g_strife/a_programmer.cpp - g_strife/a_rebels.cpp g_strife/a_sentinel.cpp g_strife/a_stalker.cpp g_strife/a_strifeitems.cpp diff --git a/src/actor.h b/src/actor.h index 06a5e9f118..8e1b167398 100644 --- a/src/actor.h +++ b/src/actor.h @@ -696,7 +696,7 @@ public: bool UseInventory(AInventory *item); // Tosses an item out of the inventory. - virtual AInventory *DropInventory (AInventory *item); + AInventory *DropInventory (AInventory *item); // Removes all items from the inventory. void ClearInventory(); diff --git a/src/g_strife/a_oracle.cpp b/src/g_strife/a_oracle.cpp deleted file mode 100644 index f498499226..0000000000 --- a/src/g_strife/a_oracle.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* -#include "actor.h" -#include "a_action.h" -#include "a_strifeglobal.h" -#include "p_enemy.h" -#include "r_defs.h" -#include "vm.h" -*/ - - -DEFINE_ACTION_FUNCTION(AActor, A_WakeOracleSpectre) -{ - PARAM_SELF_PROLOGUE(AActor); - - TThinkerIterator it(NAME_AlienSpectre3); - AActor *spectre = it.Next(); - - if (spectre != NULL && spectre->health > 0 && self->target != spectre) - { - spectre->Sector->SoundTarget = spectre->LastHeard = self->LastHeard; - spectre->target = self->target; - spectre->SetState (spectre->SeeState); - } - return 0; -} - diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp deleted file mode 100644 index a02848dd2b..0000000000 --- a/src/g_strife/a_programmer.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "a_strifeglobal.h" -#include "vm.h" -#include "g_level.h" -#include "doomstat.h" -*/ -static FRandom pr_prog ("Programmer"); - -// The Programmer level ending thing ---------------------------------------- -// [RH] I took some liberties to make this "cooler" than it was in Strife. - -class AProgLevelEnder : public AInventory -{ - DECLARE_CLASS (AProgLevelEnder, AInventory) -public: - void Tick (); - PalEntry GetBlend (); -}; - -IMPLEMENT_CLASS(AProgLevelEnder, false, false) - -//============================================================================ -// -// AProgLevelEnder :: Tick -// -// Fade to black, end the level, then unfade. -// -//============================================================================ - -void AProgLevelEnder::Tick () -{ - if (special2 == 0) - { // fade out over .66 second - special1 += 255 / (TICRATE*2/3); - if (++special1 >= 255) - { - special1 = 255; - special2 = 1; - G_ExitLevel (0, false); - } - } - else - { // fade in over two seconds - special1 -= 255 / (TICRATE*2); - if (special1 <= 0) - { - Destroy (); - } - } -} - -//============================================================================ -// -// AProgLevelEnder :: GetBlend -// -//============================================================================ - -PalEntry AProgLevelEnder::GetBlend () -{ - return PalEntry ((BYTE)special1, 0, 0, 0); -} - -//============================================================================ -// -// A_ProgrammerMelee -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerMelee) -{ - PARAM_SELF_PROLOGUE(AActor); - - int damage; - - if (self->target == NULL) - return 0; - - A_FaceTarget (self); - - if (!self->CheckMeleeRange ()) - return 0; - - S_Sound (self, CHAN_WEAPON, "programmer/clank", 1, ATTN_NORM); - - damage = ((pr_prog() % 10) + 1) * 6; - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; -} - -//============================================================================ -// -// A_SpawnProgrammerBase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SpawnProgrammerBase) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *foo = Spawn("ProgrammerBase", self->PosPlusZ(24.), ALLOW_REPLACE); - if (foo != NULL) - { - foo->Angles.Yaw = self->Angles.Yaw + 180. + pr_prog.Random2() * (360. / 1024.); - foo->VelFromAngle(); - foo->Vel.Z = pr_prog() / 128.; - } - return 0; -} - -//============================================================================ -// -// A_ProgrammerDeath -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerDeath) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!CheckBossDeath (self)) - return 0; - - for (int i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i] && players[i].health > 0) - { - players[i].mo->GiveInventoryType (RUNTIME_CLASS(AProgLevelEnder)); - break; - } - } - // the sky change scripts are now done as special actions in MAPINFO - A_BossDeath(self); - return 0; -} diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp deleted file mode 100644 index d3d68153f3..0000000000 --- a/src/g_strife/a_rebels.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "gi.h" -#include "a_sharedglobal.h" -#include "a_strifeglobal.h" -#include "vm.h" -#include "doomstat.h" -*/ - -static FRandom pr_shootgun ("ShootGun"); - -//============================================================================ -// -// A_ShootGun -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ShootGun) -{ - PARAM_SELF_PROLOGUE(AActor); - - DAngle pitch; - - if (self->target == NULL) - return 0; - - S_Sound (self, CHAN_WEAPON, "monsters/rifle", 1, ATTN_NORM); - A_FaceTarget (self); - pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE); - P_LineAttack (self, self->Angles.Yaw + pr_shootgun.Random2() * (11.25 / 256), - MISSILERANGE, pitch, - 3*(pr_shootgun() % 5 + 1), NAME_Hitscan, NAME_StrifePuff); - return 0; -} - -// Teleporter Beacon -------------------------------------------------------- - -class ATeleporterBeacon : public AInventory -{ - DECLARE_CLASS (ATeleporterBeacon, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(ATeleporterBeacon, false, false) - -bool ATeleporterBeacon::Use (bool pickup) -{ - AInventory *drop; - - // Increase the amount by one so that when DropInventory decrements it, - // the actor will have the same number of beacons that he started with. - // When we return to UseInventory, it will take care of decrementing - // Amount again and disposing of this item if there are no more. - Amount++; - drop = Owner->DropInventory (this); - if (drop == NULL) - { - Amount--; - return false; - } - else - { - drop->SetState(drop->FindState(NAME_Drop)); - drop->target = Owner; - return true; - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_Beacon) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *owner = self->target; - AActor *rebel; - - rebel = Spawn("Rebel1", self->PosAtZ(self->floorz), ALLOW_REPLACE); - if (!P_TryMove (rebel, rebel->Pos(), true)) - { - rebel->Destroy (); - return 0; - } - // Once the rebels start teleporting in, you can't pick up the beacon anymore. - self->flags &= ~MF_SPECIAL; - static_cast(self)->DropTime = 0; - // Set up the new rebel. - rebel->threshold = rebel->DefThreshold; - rebel->target = NULL; - rebel->flags4 |= MF4_INCOMBAT; - rebel->LastHeard = owner; // Make sure the rebels look for targets - if (deathmatch) - { - rebel->health *= 2; - } - if (owner != NULL) - { - // Rebels are the same color as their owner (but only in multiplayer) - if (multiplayer) - { - rebel->Translation = owner->Translation; - } - rebel->SetFriendPlayer(owner->player); - // Set the rebel's target to whatever last hurt the player, so long as it's not - // one of the player's other rebels. - if (owner->target != NULL && !rebel->IsFriend (owner->target)) - { - rebel->target = owner->target; - } - } - - rebel->SetState (rebel->SeeState); - rebel->Angles.Yaw = self->Angles.Yaw; - P_SpawnTeleportFog(rebel, rebel->Vec3Angle(20., self->Angles.Yaw, 0), false, true); - if (--self->health < 0) - { - self->SetState(self->FindState(NAME_Death)); - } - return 0; -} diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index 0f1132cbd5..aa48d98399 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -180,8 +180,18 @@ IMPLEMENT_CLASS(ARaiseAlarm, false, false) bool ARaiseAlarm::TryPickup (AActor *&toucher) { P_NoiseAlert (toucher, toucher); - VMFrameStack stack1, *stack = &stack1; - CALL_ACTION(A_WakeOracleSpectre, toucher); + /* + ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3"); + Actor spectre = Actor(it.Next()); + + if (spectre != NULL && spectre.health > 0 && toucher != spectre) + { + spectre.CurSector.SoundTarget = spectre.LastHeard = toucher; + spectre.target = toucher; + spectre.SetState (spectre.SeeState); + } + + */ GoAwayAndDie (); return true; } diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index e8ae59c182..0a2f5c5fdd 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -24,9 +24,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_oracle.cpp" -#include "a_programmer.cpp" -#include "a_rebels.cpp" #include "a_sentinel.cpp" #include "a_stalker.cpp" #include "a_strifeitems.cpp" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 8424caee82..c85b8bbbc8 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1018,6 +1018,13 @@ AInventory *AActor::DropInventory (AInventory *item) return drop; } +DEFINE_ACTION_FUNCTION(AActor, DropInventory) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(item, AInventory); + ACTION_RETURN_OBJECT(self->DropInventory(item)); +} + //============================================================================ // // AActor :: FindInventory diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2d2725d1e6..35dee8fba2 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -372,12 +372,13 @@ class Actor : Thinker native native void PlayActiveSound(); native void Howl(); - // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native Inventory FindInventory(class itemtype, bool subclass = false); native Inventory GiveInventoryType(class itemtype); + native Inventory DropInventory (Inventory item); native bool GiveAmmo (Class type, int amount); + // DECORATE compatible functions native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); native double GetDistance(bool checkz, int ptr = AAPTR_TARGET); native double GetAngle(int flags, int ptr = AAPTR_DEFAULT); @@ -701,7 +702,6 @@ class Actor : Thinker native native void A_ClearLastHeard(); native bool A_SelectWeapon(class whichweapon, int flags = 0); native void A_ClassBossHealth(); - native void A_ShootGun(); native void A_RocketInFlight(); native void A_Bang4Cloud(); native void A_DropFire(); diff --git a/wadsrc/static/zscript/strife/oracle.txt b/wadsrc/static/zscript/strife/oracle.txt index 6023629c28..740a7b69a3 100644 --- a/wadsrc/static/zscript/strife/oracle.txt +++ b/wadsrc/static/zscript/strife/oracle.txt @@ -19,8 +19,6 @@ class Oracle : Actor DropItem "Meat"; } - native void A_WakeOracleSpectre (); - States { Spawn: @@ -35,4 +33,19 @@ class Oracle : Actor ORCL Q -1; Stop; } + + void A_WakeOracleSpectre () + { + ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3"); + Actor spectre = Actor(it.Next()); + + if (spectre != NULL && spectre.health > 0 && self.target != spectre) + { + spectre.CurSector.SoundTarget = spectre.LastHeard = self.LastHeard; + spectre.target = self.target; + spectre.SetState (spectre.SeeState); + } + } + + } diff --git a/wadsrc/static/zscript/strife/programmer.txt b/wadsrc/static/zscript/strife/programmer.txt index 9ef9bdeb02..3fa34b6595 100644 --- a/wadsrc/static/zscript/strife/programmer.txt +++ b/wadsrc/static/zscript/strife/programmer.txt @@ -33,10 +33,6 @@ class Programmer : Actor DropItem "Sigil1"; } - native void A_ProgrammerMelee (); - native void A_SpawnProgrammerBase (); - native void A_ProgrammerDeath (); - States { Spawn: @@ -80,6 +76,69 @@ class Programmer : Actor Stop; } + //============================================================================ + // + // A_ProgrammerMelee + // + //============================================================================ + + void A_ProgrammerMelee () + { + if (target == null) + return; + + A_FaceTarget (); + + if (!CheckMeleeRange ()) + return; + + A_PlaySound("programmer/clank", CHAN_WEAPON); + + int damage = ((random[Programmer]() % 10) + 1) * 6; + int newdam = DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + + //============================================================================ + // + // A_SpawnProgrammerBase + // + //============================================================================ + + void A_SpawnProgrammerBase () + { + Actor foo = Spawn("ProgrammerBase", Pos + (0,0,24), ALLOW_REPLACE); + if (foo != null) + { + foo.Angle = Angle + 180. + Random2[Programmer]() * (360. / 1024.); + foo.VelFromAngle(); + foo.Vel.Z = random[Programmer]() / 128.; + } + } + + //============================================================================ + // + // A_ProgrammerDeath + // + //============================================================================ + + void A_ProgrammerDeath () + { + if (!CheckBossDeath ()) + return; + + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i] && players[i].health > 0) + { + players[i].mo.GiveInventoryType ("ProgLevelEnder"); + break; + } + } + // the sky change scripts are now done as special actions in MAPINFO + A_BossDeath(); + } + //============================================================================ // // A_SpotLightning @@ -88,10 +147,10 @@ class Programmer : Actor void A_SpotLightning() { - if (target == NULL) return; + if (target == null) return; Actor spot = Spawn("SpectralLightningSpot", (target.pos.xy, target.floorz), ALLOW_REPLACE); - if (spot != NULL) + if (spot != null) { spot.threshold = 25; spot.target = self; @@ -127,10 +186,52 @@ class ProgrammerBase : Actor // The Programmer level ending thing ---------------------------------------- -class ProgLevelEnder : Inventory native +class ProgLevelEnder : Inventory { Default { +INVENTORY.UNDROPPABLE } + + + //============================================================================ + // + // AProgLevelEnder :: Tick + // + // Fade to black, end the level, then unfade. + // + //============================================================================ + + override void Tick () + { + if (special2 == 0) + { // fade out over .66 second + special1 += 255 / (TICRATE*2/3); + if (++special1 >= 255) + { + special1 = 255; + special2 = 1; + Exit_Normal(0); + } + } + else + { // fade in over two seconds + special1 -= 255 / (TICRATE*2); + if (special1 <= 0) + { + Destroy (); + } + } + } + + //============================================================================ + // + // AProgLevelEnder :: GetBlend + // + //============================================================================ + + override Color GetBlend () + { + return Color(special1, 0, 0, 0); + } } diff --git a/wadsrc/static/zscript/strife/rebels.txt b/wadsrc/static/zscript/strife/rebels.txt index d9e65560fe..24deea25b1 100644 --- a/wadsrc/static/zscript/strife/rebels.txt +++ b/wadsrc/static/zscript/strife/rebels.txt @@ -107,7 +107,7 @@ class Rebel6 : Rebel // Teleporter Beacon -------------------------------------------------------- -class TeleporterBeacon : Inventory native +class TeleporterBeacon : Inventory { Default { @@ -122,8 +122,6 @@ class TeleporterBeacon : Inventory native Inventory.PickupMessage "$TXT_BEACON"; } - native void A_Beacon (); - States { Spawn: @@ -137,4 +135,73 @@ class TeleporterBeacon : Inventory native BEAC A 1 A_FadeOut(0.015); Loop; } + + // Teleporter Beacon -------------------------------------------------------- + + override bool Use (bool pickup) + { + // Increase the amount by one so that when DropInventory decrements it, + // the actor will have the same number of beacons that he started with. + // When we return to UseInventory, it will take care of decrementing + // Amount again and disposing of self item if there are no more. + Amount++; + Inventory drop = Owner.DropInventory (self); + if (drop == null) + { + Amount--; + return false; + } + else + { + drop.SetStateLabel("Drop"); + drop.target = Owner; + return true; + } + } + + void A_Beacon() + { + Actor owner = target; + Actor rebel = Spawn("Rebel1", (pos.xy, floorz), ALLOW_REPLACE); + if (!rebel.TryMove (rebel.Pos.xy, true)) + { + rebel.Destroy (); + return; + } + // Once the rebels start teleporting in, you can't pick up the beacon anymore. + bSpecial = false; + Inventory(self).DropTime = 0; + // Set up the new rebel. + rebel.threshold = rebel.DefThreshold; + rebel.target = null; + rebel.bInCombat = true; + rebel.LastHeard = owner; // Make sure the rebels look for targets + if (deathmatch) + { + rebel.health *= 2; + } + if (owner != null) + { + // Rebels are the same color as their owner (but only in multiplayer) + if (multiplayer) + { + rebel.Translation = owner.Translation; + } + rebel.SetFriendPlayer(owner.player); + // Set the rebel's target to whatever last hurt the player, so long as it's not + // one of the player's other rebels. + if (owner.target != null && !rebel.IsFriend (owner.target)) + { + rebel.target = owner.target; + } + } + + rebel.SetState (rebel.SeeState); + rebel.Angle = Angle; + rebel.SpawnTeleportFog(rebel.Vec3Angle(20., Angle, 0), false, true); + if (--health < 0) + { + SetStateLabel("Death"); + } + } } \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/strifehumanoid.txt b/wadsrc/static/zscript/strife/strifehumanoid.txt index 7ac776026c..7cec969ea0 100644 --- a/wadsrc/static/zscript/strife/strifehumanoid.txt +++ b/wadsrc/static/zscript/strife/strifehumanoid.txt @@ -56,3 +56,21 @@ class FireDroplet : Actor } +extend class Actor +{ + //============================================================================ + // + // A_ShootGun + // + //============================================================================ + + void A_ShootGun() + { + if (!target) return; + A_PlaySound ("monsters/rifle", CHAN_WEAPON); + A_FaceTarget (); + double pitch = AimLineAttack (angle, MISSILERANGE); + LineAttack (Angle + Random2[ShootGun]() * (11.25 / 256), MISSILERANGE, pitch, 3*(random[ShootGun]() % 5 + 1), 'Hitscan', "StrifePuff"); + } + +} \ No newline at end of file From dd5494d848f0ca07dd77ecc1e624b0a419d56fca Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 19:56:16 +0100 Subject: [PATCH 402/471] - scriptified Stalker and Sentinel. --- src/CMakeLists.txt | 2 - src/g_strife/a_sentinel.cpp | 95 ----------------------- src/g_strife/a_stalker.cpp | 88 --------------------- src/g_strife/a_strifestuff.cpp | 2 - wadsrc/static/zscript/actor.txt | 2 - wadsrc/static/zscript/strife/sentinel.txt | 79 ++++++++++++++++++- wadsrc/static/zscript/strife/stalker.txt | 68 ++++++++++++++-- 7 files changed, 139 insertions(+), 197 deletions(-) delete mode 100644 src/g_strife/a_sentinel.cpp delete mode 100644 src/g_strife/a_stalker.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 885b9fd916..8415218027 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,8 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_sentinel.cpp - g_strife/a_stalker.cpp g_strife/a_strifeitems.cpp g_strife/a_strifeweapons.cpp g_strife/a_thingstoblowup.cpp diff --git a/src/g_strife/a_sentinel.cpp b/src/g_strife/a_sentinel.cpp deleted file mode 100644 index 44946c84ac..0000000000 --- a/src/g_strife/a_sentinel.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -#include "actor.h" -#include "p_enemy.h" -#include "a_action.h" -#include "p_local.h" -#include "m_random.h" -#include "vm.h" -*/ - -static FRandom pr_sentinelrefire ("SentinelRefire"); - -DEFINE_ACTION_FUNCTION(AActor, A_SentinelBob) -{ - PARAM_SELF_PROLOGUE(AActor); - - double minz, maxz; - - if (self->flags & MF_INFLOAT) - { - self->Vel.Z = 0; - return 0; - } - if (self->threshold != 0) - return 0; - - maxz = self->ceilingz - self->Height - 16; - minz = self->floorz + 96; - if (minz > maxz) - { - minz = maxz; - } - if (minz < self->Z()) - { - self->Vel.Z -= 1; - } - else - { - self->Vel.Z += 1; - } - self->reactiontime = (minz >= self->Z()) ? 4 : 0; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_SentinelAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *missile, *trail; - - // [BB] Without a target the P_SpawnMissileZAimed call will crash. - if (!self->target) - { - return 0; - } - - missile = P_SpawnMissileZAimed (self, self->Z() + 32, self->target, PClass::FindActor("SentinelFX2")); - - if (missile != NULL && (missile->Vel.X != 0 || missile->Vel.Y != 0)) - { - for (int i = 8; i > 1; --i) - { - trail = Spawn("SentinelFX1", - self->Vec3Angle(missile->radius*i, missile->Angles.Yaw, 32 + missile->Vel.Z / 4 * i), ALLOW_REPLACE); - if (trail != NULL) - { - trail->target = self; - trail->Vel = missile->Vel; - P_CheckMissileSpawn (trail, self->radius); - } - } - missile->AddZ(missile->Vel.Z / 4); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_SentinelRefire) -{ - PARAM_SELF_PROLOGUE(AActor); - - A_FaceTarget (self); - - if (pr_sentinelrefire() >= 30) - { - if (self->target == NULL || - self->target->health <= 0 || - !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES) || - P_HitFriend(self) || - (self->MissileState == NULL && !self->CheckMeleeRange()) || - pr_sentinelrefire() < 40) - { - self->SetState (self->SeeState); - } - } - return 0; -} diff --git a/src/g_strife/a_stalker.cpp b/src/g_strife/a_stalker.cpp deleted file mode 100644 index 9189ef8de6..0000000000 --- a/src/g_strife/a_stalker.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "vm.h" -*/ - -static FRandom pr_stalker ("Stalker"); - - -DEFINE_ACTION_FUNCTION(AActor, A_StalkerChaseDecide) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!(self->flags & MF_NOGRAVITY)) - { - self->SetState (self->FindState("SeeFloor")); - } - else if (self->ceilingz > self->Top()) - { - self->SetState (self->FindState("Drop")); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_StalkerLookInit) -{ - PARAM_SELF_PROLOGUE(AActor); - - FState *state; - if (self->flags & MF_NOGRAVITY) - { - state = self->FindState("LookCeiling"); - } - else - { - state = self->FindState("LookFloor"); - } - if (self->state->NextState != state) - { - self->SetState (state); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_StalkerDrop) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags5 &= ~MF5_NOVERTICALMELEERANGE; - self->flags &= ~MF_NOGRAVITY; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_StalkerAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->flags & MF_NOGRAVITY) - { - self->SetState (self->FindState("Drop")); - } - else if (self->target != NULL) - { - A_FaceTarget (self); - if (self->CheckMeleeRange ()) - { - int damage = (pr_stalker() & 7) * 2 + 2; - - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - } - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_StalkerWalk) -{ - PARAM_SELF_PROLOGUE(AActor); - - S_Sound (self, CHAN_BODY, "stalker/walk", 1, ATTN_NORM); - A_Chase (stack, self); - return 0; -} - diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 0a2f5c5fdd..3d475a58bb 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -24,8 +24,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_sentinel.cpp" -#include "a_stalker.cpp" #include "a_strifeitems.cpp" #include "a_strifeweapons.cpp" #include "a_thingstoblowup.cpp" diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 35dee8fba2..2d716f4443 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -619,8 +619,6 @@ class Actor : Thinker native 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_SetShadow(); native void A_ClearShadow(); native void A_GetHurt(); diff --git a/wadsrc/static/zscript/strife/sentinel.txt b/wadsrc/static/zscript/strife/sentinel.txt index 946a99ea24..e9e6255d4d 100644 --- a/wadsrc/static/zscript/strife/sentinel.txt +++ b/wadsrc/static/zscript/strife/sentinel.txt @@ -28,8 +28,6 @@ class Sentinel : Actor Obituary "$OB_SENTINEL"; } - native void A_SentinelAttack (); - States { Spawn: @@ -56,6 +54,34 @@ class Sentinel : Actor SEWR J 5; Stop; } + + void A_SentinelAttack () + { + // [BB] Without a target the P_SpawnMissileZAimed call will crash. + if (!target) + { + return; + } + + Actor missile = SpawnMissileZAimed (pos.z + 32, target, "SentinelFX2"); + + if (missile != NULL && (missile.Vel.X != 0 || missile.Vel.Y != 0)) + { + for (int i = 8; i > 1; --i) + { + Actor trail = Spawn("SentinelFX1", Vec3Angle(missile.radius*i, missile.angle, 32 + missile.Vel.Z / 4 * i), ALLOW_REPLACE); + if (trail != NULL) + { + trail.target = self; + trail.Vel = missile.Vel; + trail.CheckMissileSpawn (radius); + } + } + missile.AddZ(missile.Vel.Z / 4); + } + } + + } // Sentinel FX 1 ------------------------------------------------------------ @@ -102,3 +128,52 @@ class SentinelFX2 : SentinelFX1 } } + +extend class Actor +{ + // These are used elsewhere, too. + void A_SentinelBob() + { + if (bInFloat) + { + Vel.Z = 0; + return; + } + if (threshold != 0) + return; + + double maxz = ceilingz - Height - 16; + double minz = floorz + 96; + if (minz > maxz) + { + minz = maxz; + } + if (minz < pos.z) + { + Vel.Z -= 1; + } + else + { + Vel.Z += 1; + } + reactiontime = (minz >= pos.z) ? 4 : 0; + } + + void A_SentinelRefire() + { + A_FaceTarget (); + + if (random[SentinelRefire]() >= 30) + { + if (target == NULL || + target.health <= 0 || + !CheckSight (target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES) || + HitFriend() || + (MissileState == NULL && !CheckMeleeRange()) || + random[SentinelRefire]() < 40) + { + SetState (SeeState); + } + } + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/stalker.txt b/wadsrc/static/zscript/strife/stalker.txt index 51a9190415..cede9cae12 100644 --- a/wadsrc/static/zscript/strife/stalker.txt +++ b/wadsrc/static/zscript/strife/stalker.txt @@ -28,12 +28,6 @@ class Stalker : Actor 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: @@ -76,4 +70,66 @@ class Stalker : Actor STLK "XYZ[" 4 Bright; Stop; } + + void A_StalkerChaseDecide () + { + if (!bNoGravity) + { + SetStateLabel("SeeFloor"); + } + else if (ceilingz > pos.z + height) + { + SetStateLabel("Drop"); + } + } + + void A_StalkerLookInit () + { + State st; + if (!bNoGravity) + { + st = FindState("LookCeiling"); + } + else + { + st = FindState("LookFloor"); + } + if (st.NextState != st) + { + SetState (st); + } + } + + void A_StalkerDrop () + { + bNoVerticalMeleeRange = false; + bNoGravity = false; + } + + void A_StalkerAttack () + { + if (bNoGravity) + { + SetStateLabel("Drop"); + } + else if (target != null) + { + A_FaceTarget (); + if (CheckMeleeRange ()) + { + int damage = (random[Stalker]() & 7) * 2 + 2; + + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + } + } + + void A_StalkerWalk () + { + A_PlaySound ("stalker/walk", CHAN_BODY); + A_Chase (); + } + + } From caef5344b0304b07dcb14eba1424a0934c47934f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 21:33:14 +0100 Subject: [PATCH 403/471] - scriptified a_thingstoblowup.cpp. - changed the power crystal floor movement to use DFloor instead of an incomplete in-place hack to ensure that everything is processed properly. --- src/CMakeLists.txt | 1 - src/g_strife/a_strifestuff.cpp | 42 ------ src/g_strife/a_thingstoblowup.cpp | 121 ------------------ src/p_floor.cpp | 15 +++ src/scripting/codegeneration/codegen.cpp | 3 +- wadsrc/static/zscript/actor.txt | 5 - wadsrc/static/zscript/base.txt | 68 ++++++++++ .../static/zscript/strife/strifehumanoid.txt | 27 ++++ .../static/zscript/strife/thingstoblowup.txt | 86 ++++++++++++- 9 files changed, 194 insertions(+), 174 deletions(-) delete mode 100644 src/g_strife/a_thingstoblowup.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8415218027..3ca87affa1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -863,7 +863,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_spike.cpp g_strife/a_strifeitems.cpp g_strife/a_strifeweapons.cpp - g_strife/a_thingstoblowup.cpp g_shared/sbarinfo_commands.cpp xlat/xlat_parser.y xlat_parser.c diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 3d475a58bb..18a758e2e1 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -26,7 +26,6 @@ // Include all the other Strife stuff here to reduce compile time #include "a_strifeitems.cpp" #include "a_strifeweapons.cpp" -#include "a_thingstoblowup.cpp" // Notes so I don't forget them: // Strife does some extra stuff in A_Explode if a player caused the explosion. (probably NoiseAlert) @@ -67,47 +66,6 @@ int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int return health; } -// Kneeling Guy ------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_SetShadow) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags |= MF_STRIFEx8000000|MF_SHADOW; - self->RenderStyle = STYLE_Translucent; - self->Alpha = HR_SHADOW; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_ClearShadow) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags &= ~(MF_STRIFEx8000000|MF_SHADOW); - self->RenderStyle = STYLE_Normal; - self->Alpha = 1.; - return 0; -} - -static FRandom pr_gethurt ("HurtMe!"); - -DEFINE_ACTION_FUNCTION(AActor, A_GetHurt) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags4 |= MF4_INCOMBAT; - if ((pr_gethurt() % 5) == 0) - { - S_Sound (self, CHAN_VOICE, self->PainSound, 1, ATTN_NORM); - self->health--; - } - if (self->health <= 0) - { - self->CallDie (self->target, self->target); - } - return 0; -} - // Klaxon Warning Light ----------------------------------------------------- DEFINE_ACTION_FUNCTION(AActor, A_TurretLook) diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp deleted file mode 100644 index 08670d484e..0000000000 --- a/src/g_strife/a_thingstoblowup.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "p_local.h" -#include "c_console.h" -#include "p_enemy.h" -#include "a_action.h" -#include "gstrings.h" -#include "vm.h" -#include "vm.h" -#include "doomstat.h" -*/ - -static FRandom pr_bang4cloud ("Bang4Cloud"); -static FRandom pr_lightout ("LightOut"); - -DEFINE_ACTION_FUNCTION(AActor, A_Bang4Cloud) -{ - PARAM_SELF_PROLOGUE(AActor); - - double xo = (pr_bang4cloud.Random2() & 3) * (10. / 64); - double yo = (pr_bang4cloud.Random2() & 3) * (10. / 64); - Spawn("Bang4Cloud", self->Vec3Offset(xo, yo, 0.), ALLOW_REPLACE); - return 0; -} - -// ------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_GiveQuestItem) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(questitem); - - // Give one of these quest items to every player in the game - if (questitem >= 0 && questitem < (int)countof(QuestItemClasses)) - { - for (int i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i]) - { - AInventory *item = static_cast(Spawn (QuestItemClasses[questitem - 1])); - if (!item->CallTryPickup (players[i].mo)) - { - item->Destroy (); - } - } - } - } - - char messageid[64]; - - mysnprintf(messageid, countof(messageid), "TXT_QUEST_%d", questitem); - const char * name = GStrings[messageid]; - - if (name != NULL) - { - C_MidPrint (SmallFont, name); - } - return 0; -} - -// PowerCrystal ------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_ExtraLightOff) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target != NULL && self->target->player != NULL) - { - self->target->player->extralight = 0; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_Explode512) -{ - PARAM_SELF_PROLOGUE(AActor); - - P_RadiusAttack (self, self->target, 512, 512, NAME_None, RADF_HURTSOURCE); - if (self->target != NULL && self->target->player != NULL) - { - self->target->player->extralight = 5; - } - P_CheckSplash(self, 512); - - // Strife didn't do this next part, but it looks good - self->RenderStyle = STYLE_Add; - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_LightGoesOut) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *foo; - sector_t *sec = self->Sector; - vertex_t *spot; - double newheight; - - sec->SetLightLevel(0); - - double oldtheight = sec->floorplane.fD(); - newheight = sec->FindLowestFloorSurrounding(&spot); - sec->floorplane.setD(sec->floorplane.PointToDist (spot, newheight)); - double newtheight = sec->floorplane.fD(); - sec->ChangePlaneTexZ(sector_t::floor, newtheight - oldtheight); - sec->CheckPortalPlane(sector_t::floor); - - for (int i = 0; i < 8; ++i) - { - foo = Spawn("Rubble1", self->Pos(), ALLOW_REPLACE); - if (foo != NULL) - { - int t = pr_lightout() & 15; - foo->Vel.X = t - (pr_lightout() & 7); - foo->Vel.Y = pr_lightout.Random2() & 7; - foo->Vel.Z = 7 + (pr_lightout() & 3); - } - } - return 0; -} diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 0431fa808b..8fd5ad038c 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -492,6 +492,21 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line, return true; } +DEFINE_ACTION_FUNCTION(DFloor, CreateFloor) +{ + PARAM_PROLOGUE; + PARAM_POINTER(sec, sector_t); + PARAM_INT(floortype); + PARAM_POINTER(ln, line_t); + PARAM_FLOAT(speed); + PARAM_FLOAT_DEF(height); + PARAM_INT_DEF(crush); + PARAM_INT_DEF(change); + PARAM_BOOL_DEF(hereticlower); + PARAM_BOOL_DEF(hexencrush); + ACTION_RETURN_BOOL(P_CreateFloor(sec, (DFloor::EFloor)floortype, ln, speed, height, crush, change, hexencrush, hereticlower)); +} + //========================================================================== // // HANDLE FLOOR TYPES diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 5277ad70e1..6912755b46 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -9512,7 +9512,8 @@ int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray &def if (!cls->IsDescendantOf(desttype)) { - Printf("class '%s' is not compatible with '%s'\n", clsname.GetChars(), desttype->TypeName.GetChars()); + // Let the caller check this. The message can be enabled for diagnostic purposes. + DPrintf(DMSG_SPAMMY, "class '%s' is not compatible with '%s'\n", clsname.GetChars(), desttype->TypeName.GetChars()); cls = nullptr; } ret->SetPointer(const_cast(cls), ATAG_OBJECT); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2d716f4443..90cffb81a2 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -619,9 +619,6 @@ class Actor : Thinker native native void A_Wander(int flags = 0); native void A_Look2(); native void A_TossGib(); - native void A_SetShadow(); - native void A_ClearShadow(); - native void A_GetHurt(); native void A_TurretLook(); native void A_KlaxonBlare(); native void A_Countdown(); @@ -701,9 +698,7 @@ class Actor : Thinker native native bool A_SelectWeapon(class whichweapon, int flags = 0); native void A_ClassBossHealth(); 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_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 8d2e7a71bc..6f9b2dfe1d 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -212,6 +212,28 @@ struct Sector native native uint16 ZoneNumber; native uint16 MoreFlags; + + enum ESectorFlags + { + SECF_SILENT = 1, // actors in sector make no noise + SECF_NOFALLINGDAMAGE= 2, // No falling damage in this sector + SECF_FLOORDROP = 4, // all actors standing on this floor will remain on it when it lowers very fast. + SECF_NORESPAWN = 8, // players can not respawn in this sector + SECF_FRICTION = 16, // sector has friction enabled + SECF_PUSH = 32, // pushers enabled + SECF_SILENTMOVE = 64, // Sector movement makes mo sound (Eternity got this so this may be useful for an extended cross-port standard.) + SECF_DMGTERRAINFX = 128, // spawns terrain splash when inflicting damage + SECF_ENDGODMODE = 256, // getting damaged by this sector ends god mode + SECF_ENDLEVEL = 512, // ends level when health goes below 10 + SECF_HAZARD = 1024, // Change to Strife's delayed damage handling. + + SECF_WASSECRET = 1 << 30, // a secret that was discovered + SECF_SECRET = 1 << 31, // a secret sector + + SECF_DAMAGEFLAGS = SECF_ENDGODMODE|SECF_ENDLEVEL|SECF_DMGTERRAINFX|SECF_HAZARD, + SECF_NOMODIFY = SECF_SECRET|SECF_WASSECRET, // not modifiable by Sector_ChangeFlags + SECF_SPECIALFLAGS = SECF_DAMAGEFLAGS|SECF_FRICTION|SECF_PUSH, // these flags originate from 'special and must be transferrable by floor thinkers + } native uint Flags; native SectorAction SecActTarget; @@ -286,3 +308,49 @@ struct String native { native void Replace(String pattern, String replacement); } + +class Floor : Thinker native +{ + // only here so that some constants and functions can be added. Not directly usable yet. + enum EFloor + { + floorLowerToLowest, + floorLowerToNearest, + floorLowerToHighest, + floorLowerByValue, + floorRaiseByValue, + floorRaiseToHighest, + floorRaiseToNearest, + floorRaiseAndCrush, + floorRaiseAndCrushDoom, + floorCrushStop, + floorLowerInstant, + floorRaiseInstant, + floorMoveToValue, + floorRaiseToLowestCeiling, + floorRaiseByTexture, + + floorLowerAndChange, + floorRaiseAndChange, + + floorRaiseToLowest, + floorRaiseToCeiling, + floorLowerToLowestCeiling, + floorLowerByTexture, + floorLowerToCeiling, + + donutRaise, + + buildStair, + waitStair, + resetStair, + + // Not to be used as parameters to EV_DoFloor() + genFloorChg0, + genFloorChgT, + genFloorChg + }; + + native static bool CreateFloor(sector sec, EFloor floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool hexencrush = false, bool hereticlower = false); + +} \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/strifehumanoid.txt b/wadsrc/static/zscript/strife/strifehumanoid.txt index 7cec969ea0..0686ec098f 100644 --- a/wadsrc/static/zscript/strife/strifehumanoid.txt +++ b/wadsrc/static/zscript/strife/strifehumanoid.txt @@ -72,5 +72,32 @@ extend class Actor double pitch = AimLineAttack (angle, MISSILERANGE); LineAttack (Angle + Random2[ShootGun]() * (11.25 / 256), MISSILERANGE, pitch, 3*(random[ShootGun]() % 5 + 1), 'Hitscan', "StrifePuff"); } + + // Kneeling Guy ------------------------------------------------------------- + void A_SetShadow() + { + bShadow = true; + A_SetRenderStyle(HR_SHADOW, STYLE_Translucent); + } + + void A_ClearShadow() + { + bShadow = false; + A_SetRenderStyle(1, STYLE_Normal); + } + + void A_GetHurt() + { + bInCombat = true; + if ((random[HurtMe]() % 5) == 0) + { + A_PlaySound (PainSound, CHAN_VOICE); + health--; + } + if (health <= 0) + { + Die (target, target); + } + } } \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/thingstoblowup.txt b/wadsrc/static/zscript/strife/thingstoblowup.txt index dbbad8ed60..5e5bfac210 100644 --- a/wadsrc/static/zscript/strife/thingstoblowup.txt +++ b/wadsrc/static/zscript/strife/thingstoblowup.txt @@ -1,4 +1,42 @@ +extend class Actor +{ + void A_Bang4Cloud() + { + double xo = (random[Bang4Cloud]() & 3) * (10. / 64); + double yo = (random[Bang4Cloud]() & 3) * (10. / 64); + Spawn("Bang4Cloud", Vec3Offset(xo, yo, 0.), ALLOW_REPLACE); + } + + void A_GiveQuestItem(int questitem) + { + // Give one of these quest items to every player in the game + if (questitem >= 0) + { + String itemname = "QuestItem" .. questitem; + class item = itemname; + if (item != null) + { + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i]) + { + players[i].mo.GiveInventoryType(item); + } + } + } + } + + String msgid = "TXT_QUEST_" .. questitem; + String msg = StringTable.Localize(msgid); + + if (msg != msgid) // if both are identical there was no message of this name in the stringtable. + { + C_MidPrint ("SmallFont", msg); + } + } + +} // A Cloud used for varius explosions --------------------------------------- // This actor has no direct equivalent in strife. To create this, Strife @@ -121,10 +159,6 @@ class PowerCrystal : Actor ActiveSound "misc/reactor"; } - native void A_ExtraLightOff (); - native void A_Explode512 (); - native void A_LightGoesOut (); - States { Spawn: @@ -150,4 +184,48 @@ class PowerCrystal : Actor BOOM VWXY 3 Bright; Stop; } + + // PowerCrystal ------------------------------------------------------------------- + + void A_ExtraLightOff() + { + if (target != NULL && target.player != NULL) + { + target.player.extralight = 0; + } + } + + void A_Explode512() + { + A_Explode(512, 512); + if (target != NULL && target.player != NULL) + { + target.player.extralight = 5; + } + A_SetRenderStyle(1, STYLE_Add); + } + + void A_LightGoesOut() + { + sector sec = CurSector; + + sec.Flags |= Sector.SECF_SILENTMOVE; + sec.lightlevel = 0; + // Do this right with proper checks instead of just hacking the floor height. + Floor.CreateFloor(sec, Floor.floorLowerToLowest, null, 65536.); + + + for (int i = 0; i < 8; ++i) + { + Actor foo = Spawn("Rubble1", Pos, ALLOW_REPLACE); + if (foo != NULL) + { + int t = random[LightOut]() & 15; + foo.Vel.X = t - (random[LightOut]() & 7); + foo.Vel.Y = random2[LightOut]() & 7; + foo.Vel.Z = 7 + (random[LightOut]() & 3); + } + } + } + } From edd8e51a691a5ad1a79cb9dcaedafaf27895c965 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 23:30:14 +0100 Subject: [PATCH 404/471] - scriptified most of a_strifestuff.cpp. --- src/g_strife/a_strifestuff.cpp | 246 ------------------ src/p_actionfunctions.cpp | 29 +++ src/p_enemy.cpp | 5 +- src/p_states.cpp | 13 + src/scripting/thingdef_data.cpp | 6 + wadsrc/static/zscript.txt | 2 + wadsrc/static/zscript/actor.txt | 12 +- wadsrc/static/zscript/base.txt | 2 + wadsrc/static/zscript/shared/player.txt | 9 + wadsrc/static/zscript/strife/acolyte.txt | 2 +- wadsrc/static/zscript/strife/klaxon.txt | 125 +++++++++ .../static/zscript/strife/strifefunctions.txt | 120 +++++++++ .../static/zscript/strife/strifehumanoid.txt | 47 ---- wadsrc/static/zscript/strife/strifeplayer.txt | 68 ++++- wadsrc/static/zscript/strife/strifestuff.txt | 73 ------ 15 files changed, 376 insertions(+), 383 deletions(-) create mode 100644 wadsrc/static/zscript/strife/klaxon.txt create mode 100644 wadsrc/static/zscript/strife/strifefunctions.txt diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 18a758e2e1..20fe55de32 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -66,70 +66,6 @@ int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int return health; } -// Klaxon Warning Light ----------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_TurretLook) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *target; - - if (self->flags5 & MF5_INCONVERSATION) - return 0; - - self->threshold = 0; - target = self->LastHeard; - if (target != NULL && - target->health > 0 && - target->flags & MF_SHOOTABLE && - (self->flags & MF_FRIENDLY) != (target->flags & MF_FRIENDLY)) - { - self->target = target; - if ((self->flags & MF_AMBUSH) && !P_CheckSight (self, target)) - { - return 0; - } - if (self->SeeSound != 0) - { - S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM); - } - self->LastHeard = NULL; - self->threshold = 10; - self->SetState (self->SeeState); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_KlaxonBlare) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (--self->reactiontime < 0) - { - self->target = NULL; - self->reactiontime = self->GetDefault()->reactiontime; - CALL_ACTION(A_TurretLook, self); - if (self->target == NULL) - { - self->SetIdle(); - } - else - { - self->reactiontime = 50; - } - } - if (self->reactiontime == 2) - { - // [RH] Unalert monsters near the alarm and not just those in the same sector as it. - P_NoiseAlert (NULL, self, false); - } - else if (self->reactiontime > 50) - { - S_Sound (self, CHAN_VOICE, "misc/alarm", 1, ATTN_NORM); - } - return 0; -} - // Power Coupling ----------------------------------------------------------- class APowerCoupling : public AActor @@ -183,185 +119,3 @@ public: IMPLEMENT_CLASS(AMeat, false, false) -//========================================================================== -// -// A_TossGib -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_TossGib) -{ - PARAM_SELF_PROLOGUE(AActor); - - const char *gibtype = (self->flags & MF_NOBLOOD) ? "Junk" : "Meat"; - AActor *gib = Spawn (gibtype, self->PosPlusZ(24.), ALLOW_REPLACE); - - if (gib == NULL) - { - return 0; - } - - gib->Angles.Yaw = pr_gibtosser() * (360 / 256.f); - gib->VelFromAngle(pr_gibtosser() & 15); - gib->Vel.Z = pr_gibtosser() & 15; - return 0; -} - -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FLoopActiveSound) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->ActiveSound != 0 && !(level.time & 7)) - { - S_Sound (self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_Countdown) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (--self->reactiontime <= 0) - { - P_ExplodeMissile (self, NULL, NULL); - self->flags &= ~MF_SKULLFLY; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_LoopActiveSound) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->ActiveSound != 0 && !S_IsActorPlayingSomething (self, CHAN_VOICE, -1)) - { - S_Sound (self, CHAN_VOICE|CHAN_LOOP, self->ActiveSound, 1, ATTN_NORM); - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain) -{ - PARAM_SELF_PROLOGUE(AActor); - - sector_t *sec = self->Sector; - - if (self->Z() == sec->floorplane.ZatPoint(self) && sec->PortalBlocksMovement(sector_t::floor)) - { - if (sec->special == Damage_InstantDeath) - { - P_DamageMobj (self, NULL, NULL, 999, NAME_InstantDeath); - } - else if (sec->special == Scroll_StrifeCurrent) - { - int anglespeed = tagManager.GetFirstSectorTag(sec) - 100; - double speed = (anglespeed % 10) / 16.; - DAngle an = (anglespeed / 10) * (360 / 8.); - self->Thrust(an, speed); - } - } - return 0; -} - -//============================================================================ -// -// A_ClearSoundTarget -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ClearSoundTarget) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *actor; - - self->Sector->SoundTarget = NULL; - for (actor = self->Sector->thinglist; actor != NULL; actor = actor->snext) - { - actor->LastHeard = NULL; - } - return 0; -} - - -DEFINE_ACTION_FUNCTION(AActor, A_ItBurnsItBurns) -{ - PARAM_SELF_PROLOGUE(AActor); - - S_Sound (self, CHAN_VOICE, "human/imonfire", 1, ATTN_NORM); - - if (self->player != nullptr && self->player->mo == self) - { - P_SetPsprite(self->player, PSP_STRIFEHANDS, self->FindState("FireHands")); - - self->player->ReadyWeapon = nullptr; - self->player->PendingWeapon = WP_NOCHANGE; - self->player->playerstate = PST_LIVE; - self->player->extralight = 3; - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_DropFire) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *drop = Spawn("FireDroplet", self->PosPlusZ(24.), ALLOW_REPLACE); - drop->Vel.Z = -1.; - P_RadiusAttack (self, self, 64, 64, NAME_Fire, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CrispyPlayer) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->player != nullptr && self->player->mo == self) - { - DPSprite *psp; - psp = self->player->GetPSprite(PSP_STRIFEHANDS); - - FState *firehandslower = self->FindState("FireHandsLower"); - FState *firehands = self->FindState("FireHands"); - FState *state = psp->GetState(); - - if (state != nullptr && firehandslower != nullptr && firehands != nullptr && firehands < firehandslower) - { - self->player->playerstate = PST_DEAD; - psp->SetState(state + (firehandslower - firehands)); - } - else if (state == nullptr) - { - psp->SetState(nullptr); - } - } - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_HandLower) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->player != nullptr) - { - DPSprite *psp = self->player->GetPSprite(PSP_STRIFEHANDS); - - if (psp->GetState() == nullptr) - { - psp->SetState(nullptr); - return 0; - } - - psp->y += 9; - if (psp->y > WEAPONBOTTOM*2) - { - psp->SetState(nullptr); - } - - if (self->player->extralight > 0) self->player->extralight--; - } - return 0; -} diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index d33695a1b8..a23e9943a6 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -6807,3 +6807,32 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetTranslation) self->SetTranslation(trname); return 0; } + +//========================================================================== +// +// +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain) +{ + PARAM_SELF_PROLOGUE(AActor); + + sector_t *sec = self->Sector; + + if (self->Z() == sec->floorplane.ZatPoint(self) && sec->PortalBlocksMovement(sector_t::floor)) + { + if (sec->special == Damage_InstantDeath) + { + P_DamageMobj(self, NULL, NULL, 999, NAME_InstantDeath); + } + else if (sec->special == Scroll_StrifeCurrent) + { + int anglespeed = tagManager.GetFirstSectorTag(sec) - 100; + double speed = (anglespeed % 10) / 16.; + DAngle an = (anglespeed / 10) * (360 / 8.); + self->Thrust(an, speed); + } + } + return 0; +} diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 3712ac86c9..4d93931522 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -265,10 +265,11 @@ void P_NoiseAlert (AActor *target, AActor *emitter, bool splash, double maxdist) DEFINE_ACTION_FUNCTION(AActor, NoiseAlert) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(emitter, AActor); + PARAM_OBJECT(target, AActor); PARAM_BOOL_DEF(splash); PARAM_FLOAT_DEF(maxdist); - P_NoiseAlert(self, emitter, splash, maxdist); + // Note that the emitter is self, not the target of the alert! Target can be NULL. + P_NoiseAlert(target, self, splash, maxdist); return 0; } diff --git a/src/p_states.cpp b/src/p_states.cpp index f141cb550a..7daaa5e41c 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -1078,3 +1078,16 @@ DEFINE_FIELD_BIT(FState, StateFlags, bNoDelay, STF_NODELAY) DEFINE_FIELD_BIT(FState, StateFlags, bSameFrame, STF_SAMEFRAME) DEFINE_FIELD_BIT(FState, StateFlags, bCanRaise, STF_CANRAISE) DEFINE_FIELD_BIT(FState, StateFlags, bDehacked, STF_DEHACKED) + +DEFINE_ACTION_FUNCTION(FState, DistanceTo) +{ + PARAM_SELF_STRUCT_PROLOGUE(FState); + PARAM_POINTER(other, FState); + + // Safely calculate the distance between two states. + auto o1 = FState::StaticFindStateOwner(self); + int retv; + if (other < o1->OwnedStates || other >= o1->OwnedStates + o1->NumOwnedStates) retv = INT_MIN; + else retv = int(other - self); + ACTION_RETURN_INT(retv); +} diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index a1542a8a50..ee7cae76c0 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -743,6 +743,12 @@ void InitThingdef() playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); GlobalSymbols.AddSymbol(playerf); + // Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag. + // It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution' + // is to create a static variable from it and reference that in the script. Yuck!!! + static AWeapon *wpnochg = WP_NOCHANGE; + playerf = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg); + GlobalSymbols.AddSymbol(playerf); // this needs to be done manually until it can be given a proper type. RUNTIME_CLASS(AActor)->AddNativeField("DecalGenerator", NewPointer(TypeVoid), myoffsetof(AActor, DecalGenerator)); diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index fa0cebd965..d3ed13d7ef 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -166,6 +166,7 @@ zscript/strife/coin.txt zscript/strife/crusader.txt zscript/strife/entityboss.txt zscript/strife/inquisitor.txt +zscript/strife/klaxon.txt zscript/strife/loremaster.txt zscript/strife/macil.txt zscript/strife/merchants.txt @@ -181,6 +182,7 @@ zscript/strife/sentinel.txt zscript/strife/stalker.txt zscript/strife/strifeammo.txt zscript/strife/strifearmor.txt +zscript/strife/strifefunctions.txt zscript/strife/strifeitems.txt zscript/strife/strifekeys.txt zscript/strife/strifestuff.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 90cffb81a2..7dbb5ee552 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -287,7 +287,7 @@ class Actor : Thinker native native bool isTeammate(Actor other); native int PlayerNumber(); native void SetFriendPlayer(PlayerInfo player); - native void NoiseAlert(Actor emitter, bool splash = false, double maxdist = 0); + native void NoiseAlert(Actor target, bool splash = false, double maxdist = 0); native void ClearBounce(); native TerrainDef GetFloorTerrain(); @@ -615,16 +615,11 @@ class Actor : Thinker native native void A_PlayerScream(); native void A_SkullPop(class skulltype = "BloodySkull"); native void A_CheckPlayerDone(); + native void A_CheckTerrain(); native void A_Wander(int flags = 0); native void A_Look2(); - native void A_TossGib(); - native void A_TurretLook(); - native void A_KlaxonBlare(); - native void A_Countdown(); native void A_AlertMonsters(double maxdist = 0, int flags = 0); - native void A_ClearSoundTarget(); - native void A_CheckTerrain(); deprecated native void A_MissileAttack(); deprecated native void A_MeleeAttack(); @@ -633,8 +628,6 @@ class Actor : Thinker native native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class pufftype = "BulletPuff"); native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double 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); @@ -698,7 +691,6 @@ class Actor : Thinker native native bool A_SelectWeapon(class whichweapon, int flags = 0); native void A_ClassBossHealth(); native void A_RocketInFlight(); - native void A_DropFire(); native void A_RemoveForcefield(); native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 6f9b2dfe1d..0f9c4f23d2 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -131,6 +131,8 @@ struct State native native bool bSameFrame; native bool bCanRaise; native bool bDehacked; + + native int DistanceTo(state other); } struct F3DFloor native diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 6d1b8abfcb..aa9b4a0669 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -138,6 +138,15 @@ class PSprite : Object native } +enum EPlayerState +{ + PST_LIVE, // Playing or camping. + PST_DEAD, // Dead on the ground, view follows killer. + PST_REBORN, // Ready to restart/respawn??? + PST_ENTER, // [BC] Entered the game + PST_GONE // Player has left the game +} + struct PlayerInfo native // this is what internally is known as player_t { native readonly PlayerPawn mo; diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt index 45f075d6b7..6ae44f7f4c 100644 --- a/wadsrc/static/zscript/strife/acolyte.txt +++ b/wadsrc/static/zscript/strife/acolyte.txt @@ -302,7 +302,7 @@ class AcolyteToBe : Acolyte Door_Close(999, 64); if (target != null && target.player != null) { - target.NoiseAlert (self); + NoiseAlert (target); } } } diff --git a/wadsrc/static/zscript/strife/klaxon.txt b/wadsrc/static/zscript/strife/klaxon.txt new file mode 100644 index 0000000000..51c4d7df2d --- /dev/null +++ b/wadsrc/static/zscript/strife/klaxon.txt @@ -0,0 +1,125 @@ +// 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; + } +} + + +extend class Actor +{ + void A_TurretLook() + { + if (bInConversation) + return; + + threshold = 0; + Actor targ = LastHeard; + if (targ != NULL && targ.health > 0 && targ.bShootable && !IsFriend(targ)) + { + target = targ; + if (bAmbush && !CheckSight (targ)) + { + return; + } + if (SeeSound != 0) + { + A_PlaySound (SeeSound, CHAN_VOICE); + } + LastHeard = NULL; + threshold = 10; + SetState (SeeState); + } + } + + void A_KlaxonBlare() + { + if (--reactiontime < 0) + { + target = NULL; + reactiontime = Default.reactiontime; + A_TurretLook(); + if (target == NULL) + { + SetIdle(); + } + else + { + reactiontime = 50; + } + } + if (reactiontime == 2) + { + // [RH] Unalert monsters near the alarm and not just those in the same sector as it. + NoiseAlert (NULL, false); + } + else if (reactiontime > 50) + { + A_PlaySound ("misc/alarm", CHAN_VOICE); + } + } + +} \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/strifefunctions.txt b/wadsrc/static/zscript/strife/strifefunctions.txt new file mode 100644 index 0000000000..ed7db24d3c --- /dev/null +++ b/wadsrc/static/zscript/strife/strifefunctions.txt @@ -0,0 +1,120 @@ +// common Strife action functions. + +extend class Actor +{ + + //============================================================================ + + void A_FLoopActiveSound() + { + if (ActiveSound != 0 && !(level.time & 7)) + { + A_PlaySound (ActiveSound, CHAN_VOICE); + } + } + + void A_LoopActiveSound() + { + A_PlaySound(ActiveSound, CHAN_VOICE, 1, true); + } + + //============================================================================ + // + // + // + //============================================================================ + + void A_Countdown() + { + if (--reactiontime <= 0) + { + ExplodeMissile (); + bSkullFly = false; + } + } + + //============================================================================ + // + // A_ClearSoundTarget + // + //============================================================================ + + void A_ClearSoundTarget() + { + CurSector.SoundTarget = null; + for (Actor mo = CurSector.thinglist; mo != null; mo = mo.snext) + { + mo.LastHeard = null; + } + } + + //========================================================================== + // + // A_TossGib + // + //========================================================================== + + void A_TossGib() + { + class gibtype; + if (bNoBlood) gibtype = "Junk"; + else gibtype = "Meat"; + Actor gib = Spawn (gibtype, pos + (0,0,24), ALLOW_REPLACE); + + if (gib == null) + { + return; + } + + gib.Angle = random[GibTosser]() * (360 / 256.f); + gib.VelFromAngle(random[GibTosser]() & 15); + gib.Vel.Z = random[GibTosser]() & 15; + } + + // A_ShootGun ------------------------------------------------------------- + + void A_ShootGun() + { + if (!target) return; + A_PlaySound ("monsters/rifle", CHAN_WEAPON); + A_FaceTarget (); + double pitch = AimLineAttack (angle, MISSILERANGE); + LineAttack (Angle + Random2[ShootGun]() * (11.25 / 256), MISSILERANGE, pitch, 3*(random[ShootGun]() % 5 + 1), 'Hitscan', "StrifePuff"); + } + + // Kneeling Guy ------------------------------------------------------------- + + void A_SetShadow() + { + bShadow = true; + A_SetRenderStyle(HR_SHADOW, STYLE_Translucent); + } + + void A_ClearShadow() + { + bShadow = false; + A_SetRenderStyle(1, STYLE_Normal); + } + + void A_GetHurt() + { + bInCombat = true; + if ((random[HurtMe]() % 5) == 0) + { + A_PlaySound (PainSound, CHAN_VOICE); + health--; + } + if (health <= 0) + { + Die (target, target); + } + } + + void A_DropFire() + { + Actor drop = Spawn("FireDroplet", pos + (0,0,24), ALLOW_REPLACE); + drop.Vel.Z = -1.; + A_Explode(64, 64, XF_NOSPLASH, damagetype: 'Fire'); + } + +} diff --git a/wadsrc/static/zscript/strife/strifehumanoid.txt b/wadsrc/static/zscript/strife/strifehumanoid.txt index 0686ec098f..26709cd936 100644 --- a/wadsrc/static/zscript/strife/strifehumanoid.txt +++ b/wadsrc/static/zscript/strife/strifehumanoid.txt @@ -54,50 +54,3 @@ class FireDroplet : Actor Stop; } } - - -extend class Actor -{ - //============================================================================ - // - // A_ShootGun - // - //============================================================================ - - void A_ShootGun() - { - if (!target) return; - A_PlaySound ("monsters/rifle", CHAN_WEAPON); - A_FaceTarget (); - double pitch = AimLineAttack (angle, MISSILERANGE); - LineAttack (Angle + Random2[ShootGun]() * (11.25 / 256), MISSILERANGE, pitch, 3*(random[ShootGun]() % 5 + 1), 'Hitscan', "StrifePuff"); - } - - // Kneeling Guy ------------------------------------------------------------- - - void A_SetShadow() - { - bShadow = true; - A_SetRenderStyle(HR_SHADOW, STYLE_Translucent); - } - - void A_ClearShadow() - { - bShadow = false; - A_SetRenderStyle(1, STYLE_Normal); - } - - void A_GetHurt() - { - bInCombat = true; - if ((random[HurtMe]() % 5) == 0) - { - A_PlaySound (PainSound, CHAN_VOICE); - health--; - } - if (health <= 0) - { - Die (target, target); - } - } -} \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/strifeplayer.txt b/wadsrc/static/zscript/strife/strifeplayer.txt index 0b61e3122a..2033fdb5e9 100644 --- a/wadsrc/static/zscript/strife/strifeplayer.txt +++ b/wadsrc/static/zscript/strife/strifeplayer.txt @@ -36,10 +36,6 @@ class StrifePlayer : PlayerPawn 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: @@ -101,5 +97,69 @@ class StrifePlayer : PlayerPawn WAVE ABCD 3 A_HandLower; Loop; } + + void A_ItBurnsItBurns() + { + A_PlaySound ("human/imonfire", CHAN_VOICE); + + if (player != null && player.mo == self) + { + player.SetPsprite(PSP_STRIFEHANDS, FindState("FireHands")); + + player.ReadyWeapon = null; + player.PendingWeapon = WP_NOCHANGE; + player.playerstate = PST_LIVE; + player.extralight = 3; + } + } + + void A_CrispyPlayer() + { + if (player != null && player.mo == self) + { + PSprite psp = player.GetPSprite(PSP_STRIFEHANDS); + + State firehandslower = FindState("FireHandsLower"); + State firehands = FindState("FireHands"); + + if (psp.CurState != null && firehandslower != null && firehands != null) + { + // Calculate state to go to. + int dist = firehands.DistanceTo(psp.curState); + if (dist > 0) + { + player.playerstate = PST_DEAD; + psp.SetState(firehandslower + dist); + return; + } + } + player.playerstate = PST_DEAD; + psp.SetState(null); + } + } + + void A_HandLower() + { + if (player != null) + { + PSprite psp = player.GetPSprite(PSP_STRIFEHANDS); + + if (psp.CurState == null) + { + psp.SetState(null); + return; + } + + psp.y += 9; + if (psp.y > WEAPONBOTTOM*2) + { + psp.SetState(null); + } + + if (player.extralight > 0) player.extralight--; + } + return; + } + } diff --git a/wadsrc/static/zscript/strife/strifestuff.txt b/wadsrc/static/zscript/strife/strifestuff.txt index e72e8d9243..38a27889f1 100644 --- a/wadsrc/static/zscript/strife/strifestuff.txt +++ b/wadsrc/static/zscript/strife/strifestuff.txt @@ -1796,81 +1796,8 @@ class KneelingGuy : Actor 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 From 55b549c0c63476abe5b8f448ecece0e56d4c363a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 00:16:30 +0100 Subject: [PATCH 405/471] - converted the rest of a_strifestuff.cpp. - changed some very old A_Explode calls which passed all values as integer literals. --- src/actor.h | 1 + src/g_strife/a_strifeitems.cpp | 20 ----- src/g_strife/a_strifestuff.cpp | 84 ------------------- src/p_enemy.cpp | 9 ++ src/p_interaction.cpp | 2 +- src/p_lnspec.cpp | 14 +--- src/p_mobj.cpp | 26 ++++++ src/p_sectors.cpp | 28 +++++++ src/p_spec.cpp | 1 + src/r_defs.h | 1 + wadsrc/static/zscript/actor.txt | 3 +- wadsrc/static/zscript/base.txt | 1 + wadsrc/static/zscript/strife/crusader.txt | 6 +- wadsrc/static/zscript/strife/inquisitor.txt | 8 +- wadsrc/static/zscript/strife/reaver.txt | 2 +- wadsrc/static/zscript/strife/strifebishop.txt | 6 +- .../static/zscript/strife/strifefunctions.txt | 5 ++ wadsrc/static/zscript/strife/strifeitems.txt | 4 +- wadsrc/static/zscript/strife/strifestuff.txt | 53 +++++++++++- .../static/zscript/strife/strifeweapons.txt | 8 +- 20 files changed, 143 insertions(+), 139 deletions(-) diff --git a/src/actor.h b/src/actor.h index 8e1b167398..b627bac661 100644 --- a/src/actor.h +++ b/src/actor.h @@ -638,6 +638,7 @@ public: // Like DoSpecialDamage, but called on the actor receiving the damage. virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); + int CallTakeSpecialDamage(AActor *inflictor, AActor *source, int damage, FName damagetype); // Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed // Made a metadata property so no longer virtual diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index aa48d98399..b9f3f288ed 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -21,26 +21,6 @@ IMPLEMENT_CLASS(ADegninOre, false, false) -DEFINE_ACTION_FUNCTION(AActor, A_RemoveForceField) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags &= ~MF_SPECIAL; - - for (int i = 0; i < self->Sector->linecount; ++i) - { - line_t *line = self->Sector->lines[i]; - if (line->backsector != NULL && line->special == ForceField) - { - line->flags &= ~(ML_BLOCKING|ML_BLOCKEVERYTHING); - line->special = 0; - line->sidedef[0]->SetTexture(side_t::mid, FNullTextureID()); - line->sidedef[1]->SetTexture(side_t::mid, FNullTextureID()); - } - } - return 0; -} - bool ADegninOre::Use (bool pickup) { if (pickup) diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 20fe55de32..6537f180e7 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -28,13 +28,6 @@ #include "a_strifeweapons.cpp" // Notes so I don't forget them: -// Strife does some extra stuff in A_Explode if a player caused the explosion. (probably NoiseAlert) -// See the instructions @ 21249. -// -// Strife's FLOATSPEED is 5 and not 4. -// -// In P_CheckMissileRange, mobjtypes 53,54,55,56,57,58 shift the distance right 4 bits (some, but not all the acolytes) -// mobjtypes 61,63,91 shift it right 1 bit // // When shooting missiles at something, if MF_SHADOW is set, the angle is adjusted with the formula: // angle += pr_spawnmissile.Random2() << 21 @@ -42,80 +35,3 @@ // angle += pr_spawnmissile.Random2() << 22 // Note that these numbers are different from those used by all the other Doom engine games. -static FRandom pr_gibtosser ("GibTosser"); - -// Force Field Guard -------------------------------------------------------- - -void A_RemoveForceField (AActor *); - -class AForceFieldGuard : public AActor -{ - DECLARE_CLASS (AForceFieldGuard, AActor) -public: - int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(AForceFieldGuard, false, false) - -int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) -{ - if (inflictor == NULL || !inflictor->IsKindOf (RUNTIME_CLASS(ADegninOre))) - { - return -1; - } - return health; -} - -// Power Coupling ----------------------------------------------------------- - -class APowerCoupling : public AActor -{ - DECLARE_CLASS (APowerCoupling, AActor) -public: - void Die (AActor *source, AActor *inflictor, int dmgflags); -}; - -IMPLEMENT_CLASS(APowerCoupling, false, false) - -void APowerCoupling::Die (AActor *source, AActor *inflictor, int dmgflags) -{ - Super::Die (source, inflictor, dmgflags); - - int i; - - for (i = 0; i < MAXPLAYERS; ++i) - if (playeringame[i] && players[i].health > 0) - break; - - if (i == MAXPLAYERS) - return; - - // [RH] In case the player broke it with the dagger, alert the guards now. - if (LastHeard != source) - { - P_NoiseAlert (source, this); - } - EV_DoDoor (DDoor::doorClose, NULL, players[i].mo, 225, 2., 0, 0, 0); - EV_DoFloor (DFloor::floorLowerToHighest, NULL, 44, 1., 0., -1, 0, false); - players[i].mo->GiveInventoryType (QuestItemClasses[5]); - S_Sound (CHAN_VOICE, "svox/voc13", 1, ATTN_NORM); - players[i].SetLogNumber (13); - P_DropItem (this, PClass::FindActor("BrokenPowerCoupling"), -1, 256); - Destroy (); -} - -// Gibs for things that bleed ----------------------------------------------- - -class AMeat : public AActor -{ - DECLARE_CLASS (AMeat, AActor) -public: - void BeginPlay () - { - // Strife used mod 19, but there are 20 states. Hmm. - SetState (SpawnState + pr_gibtosser() % 20); - } -}; - -IMPLEMENT_CLASS(AMeat, false, false) - diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 4d93931522..6a59986c03 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3224,6 +3224,15 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c return NULL; } +DEFINE_ACTION_FUNCTION(AActor, DoDropItem) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(cls, AActor); + PARAM_INT(amt); + PARAM_INT(chance); + ACTION_RETURN_OBJECT(P_DropItem(self, cls, amt, chance)); +} + //============================================================================ // // P_TossItem diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 41994c38e7..a5fcc2dda5 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1121,7 +1121,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, if (damage >= 0) { - damage = target->TakeSpecialDamage(inflictor, source, damage, mod); + damage = target->CallTakeSpecialDamage(inflictor, source, damage, mod); } // '<0' is handled below. This only handles the case where damage gets reduced to 0. diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index e41912e239..1f318f5594 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -347,7 +347,7 @@ FUNC(LS_Floor_LowerToHighest) } FUNC(LS_Floor_LowerToHighestEE) -// Floor_LowerToHighest (tag, speed, change) +// Floor_LowerToHighestEE (tag, speed, change) { return EV_DoFloor (DFloor::floorLowerToHighest, ln, arg0, SPEED(arg1), 0, -1, CHANGE(arg2), false); } @@ -3152,17 +3152,7 @@ FUNC(LS_ClearForceField) sector_t *sec = §ors[secnum]; rtn = true; - for (int i = 0; i < sec->linecount; ++i) - { - line_t *line = sec->lines[i]; - if (line->backsector != NULL && line->special == ForceField) - { - line->flags &= ~(ML_BLOCKING|ML_BLOCKEVERYTHING); - line->special = 0; - line->sidedef[0]->SetTexture(side_t::mid, FNullTextureID()); - line->sidedef[1]->SetTexture(side_t::mid, FNullTextureID()); - } - } + sec->RemoveForceField(); } return rtn; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index c85b8bbbc8..7257eff95f 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7018,6 +7018,32 @@ int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FN return (death == NULL) ? -1 : damage; } +DEFINE_ACTION_FUNCTION(AActor, TakeSpecialDamage) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(inflictor, AActor); + PARAM_OBJECT(source, AActor); + PARAM_INT(damage); + PARAM_NAME(damagetype); + ACTION_RETURN_INT(self->TakeSpecialDamage(inflictor, source, damage, damagetype)); +} + +int AActor::CallTakeSpecialDamage(AActor *inflictor, AActor *source, int damage, FName damagetype) +{ + IFVIRTUAL(AActor, TakeSpecialDamage) + { + VMValue params[5] = { (DObject*)this, inflictor, source, damage, damagetype.GetIndex() }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 5, &ret, 1, nullptr); + return retval; + } + else return TakeSpecialDamage(inflictor, source, damage, damagetype); + +} + void AActor::Crash() { // [RC] Weird that this forces the Crash state regardless of flag. diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 585c60f4bb..e6302199b1 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -22,6 +22,7 @@ //----------------------------------------------------------------------------- #include "p_spec.h" +#include "p_lnspec.h" #include "c_cvars.h" #include "doomstat.h" #include "g_level.h" @@ -1075,6 +1076,33 @@ double sector_t::NextLowestFloorAt(double x, double y, double z, int flags, doub } } + //=========================================================================== + // + // + // + //=========================================================================== + + void sector_t::RemoveForceField() + { + for (int i = 0; i < linecount; ++i) + { + line_t *line = lines[i]; + if (line->backsector != NULL && line->special == ForceField) + { + line->flags &= ~(ML_BLOCKING | ML_BLOCKEVERYTHING); + line->special = 0; + line->sidedef[0]->SetTexture(side_t::mid, FNullTextureID()); + line->sidedef[1]->SetTexture(side_t::mid, FNullTextureID()); + } + } + } + + DEFINE_ACTION_FUNCTION(_Sector, RemoveForceField) + { + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + self->RemoveForceField(); + return 0; + } //=========================================================================== // // diff --git a/src/p_spec.cpp b/src/p_spec.cpp index c9a8294b59..eb6b9bea7e 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -1591,3 +1591,4 @@ void sector_t::AdjustFloorClip () const } } } + diff --git a/src/r_defs.h b/src/r_defs.h index 9c2a822f21..a7de16c597 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -625,6 +625,7 @@ public: sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH] double FindLowestCeilingPoint(vertex_t **v) const; double FindHighestFloorPoint(vertex_t **v) const; + void RemoveForceField(); void AdjustFloorClip () const; void SetColor(int r, int g, int b, int desat); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 7dbb5ee552..c5052ab798 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -264,6 +264,7 @@ class Actor : Thinker native virtual native void Activate(Actor activator); virtual native void Deactivate(Actor activator); virtual native int DoSpecialDamage (Actor target, int damage, Name damagetype); + virtual native int TakeSpecialDamage (Actor inflictor, Actor source, int damage, Name damagetype); virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0); virtual native bool Slam(Actor victim); virtual native bool UseInventory(Inventory item); @@ -290,6 +291,7 @@ class Actor : Thinker native native void NoiseAlert(Actor target, bool splash = false, double maxdist = 0); native void ClearBounce(); native TerrainDef GetFloorTerrain(); + native Inventory DoDropItem(Class type, int dropamount, int chance); native void ExplodeMissile(line lin = null, Actor target = null); native void RestoreDamage(); @@ -691,7 +693,6 @@ class Actor : Thinker native native bool A_SelectWeapon(class whichweapon, int flags = 0); native void A_ClassBossHealth(); native void A_RocketInFlight(); - native void A_RemoveForcefield(); native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 0f9c4f23d2..b0abc73eca 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -247,6 +247,7 @@ struct Sector native native double, Sector, F3DFloor NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0); + native void RemoveForceField(); } struct Wads diff --git a/wadsrc/static/zscript/strife/crusader.txt b/wadsrc/static/zscript/strife/crusader.txt index 834464e063..ce2ba6ef8b 100644 --- a/wadsrc/static/zscript/strife/crusader.txt +++ b/wadsrc/static/zscript/strife/crusader.txt @@ -52,11 +52,11 @@ class Crusader : Actor 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 J 4 Bright A_Explode(64, 64, alert:true); ROB2 K 4 Bright A_Fall; - ROB2 L 4 A_Explode(64,64,1,1); + ROB2 L 4 A_Explode(64, 64, alert:true); ROB2 MN 4 A_TossGib; - ROB2 O 4 A_Explode(64,64,1,1); + ROB2 O 4 A_Explode(64, 64, alert:true); ROB2 P -1 A_CrusaderDeath; Stop; } diff --git a/wadsrc/static/zscript/strife/inquisitor.txt b/wadsrc/static/zscript/strife/inquisitor.txt index ef73ade1ed..6d3c5bc7f7 100644 --- a/wadsrc/static/zscript/strife/inquisitor.txt +++ b/wadsrc/static/zscript/strife/inquisitor.txt @@ -58,16 +58,16 @@ class Inquisitor : Actor 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 O 4 Bright A_Explode(128, 128, alert:true); 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 W 4 Bright A_Explode(128, 128, alert:true); 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); + ROB3 ] 3 Bright A_Explode(128, 128, alert:true); RBB3 A 3 Bright A_TossArm; RBB3 B 3 Bright A_TossGib; RBB3 CD 3 A_TossGib; @@ -206,7 +206,7 @@ class InquisitorShot : Actor Loop; Death: BNG2 A 0 Bright A_SetRenderStyle(1, STYLE_Normal); - BNG2 A 4 Bright A_Explode(192, 192, 1, 1); + BNG2 A 4 Bright A_Explode(192, 192, alert:true); BNG2 B 4 Bright; BNG2 C 4 Bright; BNG2 D 4 Bright; diff --git a/wadsrc/static/zscript/strife/reaver.txt b/wadsrc/static/zscript/strife/reaver.txt index d1c206b731..6ebcd47e23 100644 --- a/wadsrc/static/zscript/strife/reaver.txt +++ b/wadsrc/static/zscript/strife/reaver.txt @@ -49,7 +49,7 @@ class Reaver : Actor ROB1 L 5; ROB1 M 5 A_NoBlocking; ROB1 NOP 5; - ROB1 Q 6 A_Explode(32,32,1,1); + ROB1 Q 6 A_Explode(32, 32, alert:true); ROB1 R -1; Stop; XDeath: diff --git a/wadsrc/static/zscript/strife/strifebishop.txt b/wadsrc/static/zscript/strife/strifebishop.txt index 98b09eceed..b7de186a27 100644 --- a/wadsrc/static/zscript/strife/strifebishop.txt +++ b/wadsrc/static/zscript/strife/strifebishop.txt @@ -47,7 +47,7 @@ class StrifeBishop : Actor 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 J 4 Bright A_Explode(64, 64, alert:true); MLDR KL 3 Bright; MLDR M 4 Bright A_NoBlocking; MLDR N 4 Bright; @@ -88,8 +88,8 @@ class BishopMissile : Actor 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 A 0 Bright A_SetRenderStyle(1, STYLE_Normal); + SMIS A 5 Bright A_Explode(64, 64, alert:true); SMIS B 5 Bright; SMIS C 4 Bright; SMIS DEFG 2 Bright; diff --git a/wadsrc/static/zscript/strife/strifefunctions.txt b/wadsrc/static/zscript/strife/strifefunctions.txt index ed7db24d3c..febb2fdcb1 100644 --- a/wadsrc/static/zscript/strife/strifefunctions.txt +++ b/wadsrc/static/zscript/strife/strifefunctions.txt @@ -117,4 +117,9 @@ extend class Actor A_Explode(64, 64, XF_NOSPLASH, damagetype: 'Fire'); } + void A_RemoveForceField() + { + bSpecial = false; + CurSector.RemoveForceField(); + } } diff --git a/wadsrc/static/zscript/strife/strifeitems.txt b/wadsrc/static/zscript/strife/strifeitems.txt index cfc9394137..4d8e3d5e46 100644 --- a/wadsrc/static/zscript/strife/strifeitems.txt +++ b/wadsrc/static/zscript/strife/strifeitems.txt @@ -415,9 +415,9 @@ class DegninOre : Inventory native Stop; Death: XPRK A 1 A_RemoveForceField; - BNG3 A 0 A_SetTranslucent(1,1); + BNG3 A 0 A_SetRenderStyle(1, STYLE_Normal); BNG3 A 0 A_Scream; - BNG3 A 3 Bright A_Explode(192,192,1,1); + BNG3 A 3 Bright A_Explode(192, 192, alert:true); BNG3 BCDEFGH 3 Bright; Stop; } diff --git a/wadsrc/static/zscript/strife/strifestuff.txt b/wadsrc/static/zscript/strife/strifestuff.txt index 38a27889f1..12502ad0da 100644 --- a/wadsrc/static/zscript/strife/strifestuff.txt +++ b/wadsrc/static/zscript/strife/strifestuff.txt @@ -192,7 +192,7 @@ class ExplosiveBarrel2 : Actor 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 F 2 Bright A_Explode(64, 64, alert:true); BART GHIJ 2 Bright; BART K 3 Bright; BART L -1; @@ -1726,7 +1726,7 @@ class TargetPractice : Actor // Force Field Guard -------------------------------------------------------- -class ForceFieldGuard : Actor native +class ForceFieldGuard : Actor { Default { @@ -1748,6 +1748,16 @@ class ForceFieldGuard : Actor native TNT1 A 1 A_RemoveForceField; Stop; } + + override int TakeSpecialDamage (Actor inflictor, Actor source, int damage, Name damagetype) + { + if (inflictor == NULL || !(inflictor is "DegninOre")) + { + return -1; + } + return health; + } + } // Kneeling Guy ------------------------------------------------------------- @@ -1800,7 +1810,7 @@ class KneelingGuy : Actor // Power Coupling ----------------------------------------------------------- -class PowerCoupling : Actor native +class PowerCoupling : Actor { Default { @@ -1821,11 +1831,39 @@ class PowerCoupling : Actor native COUP AB 5; Loop; } + + override void Die (Actor source, Actor inflictor, int dmgflags) + { + Super.Die (source, inflictor, dmgflags); + + int i; + + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].health > 0) + break; + + if (i == MAXPLAYERS) + return; + + // [RH] In case the player broke it with the dagger, alert the guards now. + if (LastHeard != source) + { + NoiseAlert (source); + } + Door_Close(225, 16); + Floor_LowerToHighestEE(44, 8); + players[i].mo.GiveInventoryType ("QuestItem6"); + S_Sound ("svox/voc13", CHAN_VOICE); + players[i].SetLogNumber (13); + DoDropItem ("BrokenPowerCoupling", -1, 256); + Destroy (); + } + } // Gibs for things that bleed ----------------------------------------------- -class Meat : Actor native +class Meat : Actor { Default { @@ -1875,6 +1913,13 @@ class Meat : Actor native MEAT T 700; Stop; } + + override void BeginPlay () + { + // Strife used mod 19, but there are 20 states. Hmm. + SetState (SpawnState + random[GibTosser]() % 20); + } + } // Gibs for things that don't bleed ----------------------------------------- diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index 968e4c4c54..0180ea4451 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -418,8 +418,8 @@ class MiniMissile : Actor 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 A 0 Bright A_SetRenderStyle(1, STYLE_Normal); + SMIS A 5 Bright A_Explode(64, 64, alert:true); SMIS B 5 Bright; SMIS C 4 Bright; SMIS DEFG 2 Bright; @@ -715,8 +715,8 @@ class HEGrenade : Actor 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 A 0 Bright A_SetRenderStyle(1, STYLE_Normal); + BNG4 A 2 Bright A_Explode(192, 192, alert:true); BNG4 BCDEFGHIJKLMN 3 Bright; Stop; } From 3af9232fca01dbcd30abf0242cf67bf57c80a216 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 12:17:05 +0100 Subject: [PATCH 406/471] - scriptified a_strifeitems.cpp and a_debris.cpp. - Changed the glass shards so that they do not have to override FloorBounceMissile. It was the only place where this was virtually overridden and provided little usefulness. - made 'out' variables work. - fixed virtual call handling for HandlePickup. --- src/CMakeLists.txt | 2 - src/actor.h | 7 +- src/d_player.h | 2 +- src/g_level.cpp | 1 - src/g_shared/a_debris.cpp | 27 -- src/g_shared/a_pickups.cpp | 25 +- src/g_shared/a_pickups.h | 4 +- src/g_shared/sbarinfo.cpp | 1 - src/g_strife/a_strifeglobal.h | 38 -- src/g_strife/a_strifeitems.cpp | 377 ------------------ src/g_strife/a_strifestuff.cpp | 2 - src/g_strife/strife_sbar.cpp | 1 - src/m_cheat.cpp | 1 - src/p_acs.cpp | 1 - src/p_conversation.cpp | 3 +- src/p_lnspec.cpp | 5 +- src/p_mobj.cpp | 27 +- src/p_user.cpp | 4 +- src/scripting/codegeneration/codegen.cpp | 39 +- src/scripting/thingdef_data.cpp | 7 + src/scripting/zscript/zcc_compile.cpp | 19 +- src/virtual.h | 7 +- wadsrc/static/zscript/actor.txt | 3 +- wadsrc/static/zscript/constants.txt | 22 + wadsrc/static/zscript/doom/scriptedmarine.txt | 2 +- wadsrc/static/zscript/shared/debris.txt | 12 +- wadsrc/static/zscript/shared/inventory.txt | 3 +- wadsrc/static/zscript/strife/acolyte.txt | 4 +- wadsrc/static/zscript/strife/strifeitems.txt | 256 +++++++++++- 29 files changed, 374 insertions(+), 528 deletions(-) delete mode 100644 src/g_shared/a_debris.cpp delete mode 100644 src/g_strife/a_strifeitems.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ca87affa1..923d545e08 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_strifeitems.cpp g_strife/a_strifeweapons.cpp g_shared/sbarinfo_commands.cpp xlat/xlat_parser.y @@ -1119,7 +1118,6 @@ set (PCH_SOURCES g_shared/a_artifacts.cpp g_shared/a_bridge.cpp g_shared/a_camera.cpp - g_shared/a_debris.cpp g_shared/a_decals.cpp g_shared/a_fastprojectile.cpp g_shared/a_flashfader.cpp diff --git a/src/actor.h b/src/actor.h index b627bac661..0b6c58c19a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -648,7 +648,7 @@ public: void PlayBounceSound(bool onfloor); // Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor - virtual bool FloorBounceMissile (secplane_t &plane); + bool FloorBounceMissile (secplane_t &plane); // Called when an actor is to be reflected by a disc of repulsion. // Returns true to continue normal blast processing. @@ -682,7 +682,7 @@ public: // Give an item to the actor and pick it up. // Returns true if the item pickup succeeded. - virtual bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false); + bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false); // Removes the item from the inventory list. virtual void RemoveInventory (AInventory *item); @@ -693,8 +693,7 @@ public: virtual bool TakeInventory (PClassActor *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false); // Uses an item and removes it from the inventory. - virtual bool DoUseInventory (AInventory *item); - bool UseInventory(AInventory *item); + virtual bool UseInventory (AInventory *item); // Tosses an item out of the inventory. AInventory *DropInventory (AInventory *item); diff --git a/src/d_player.h b/src/d_player.h index af06e97301..d1678b6199 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -109,7 +109,7 @@ public: virtual void Tick(); virtual void AddInventory (AInventory *item); virtual void RemoveInventory (AInventory *item); - virtual bool DoUseInventory (AInventory *item); + virtual bool UseInventory (AInventory *item); virtual void MarkPrecacheSounds () const; virtual void PlayIdle (); diff --git a/src/g_level.cpp b/src/g_level.cpp index 0e7820d93a..4bb78461af 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -79,7 +79,6 @@ #include "v_palette.h" #include "menu/menu.h" #include "a_sharedglobal.h" -#include "a_strifeglobal.h" #include "r_data/colormaps.h" #include "r_renderer.h" #include "r_utility.h" diff --git a/src/g_shared/a_debris.cpp b/src/g_shared/a_debris.cpp deleted file mode 100644 index 0932088c2d..0000000000 --- a/src/g_shared/a_debris.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "m_fixed.h" - -// Stained glass ------------------------------------------------------------ - -class AGlassShard : public AActor -{ - DECLARE_CLASS (AGlassShard, AActor) -public: - bool FloorBounceMissile (secplane_t &plane) - { - if (!Super::FloorBounceMissile (plane)) - { - if (fabs (Vel.Z) < 0.5) - { - Destroy (); - } - return false; - } - return true; - } -}; - -IMPLEMENT_CLASS(AGlassShard, false, false) - diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index df434baae4..38d068bd78 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -11,7 +11,6 @@ #include "c_dispatch.h" #include "gstrings.h" #include "templates.h" -#include "a_strifeglobal.h" #include "a_morph.h" #include "a_specialspot.h" #include "g_level.h" @@ -751,7 +750,7 @@ bool AInventory::CallHandlePickup(AInventory *item) auto self = this; while (self != nullptr) { - IFVIRTUAL(AInventory, HandlePickup) + IFVIRTUALPTR(self, AInventory, HandlePickup) { // Without the type cast this picks the 'void *' assignment... VMValue params[2] = { (DObject*)self, (DObject*)item }; @@ -1684,6 +1683,13 @@ bool AInventory::TryPickup (AActor *&toucher) return true; } +DEFINE_ACTION_FUNCTION(AInventory, TryPickup) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_POINTER(toucher, AActor*); + ACTION_RETURN_BOOL(self->TryPickup(*toucher)); +} + //=========================================================================== // // AInventory :: TryPickupRestricted @@ -1710,7 +1716,20 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) bool res; if (CanPickup(toucher)) - res = TryPickup(toucher); + { + bool res; + IFVIRTUAL(AInventory, TryPickup) + { + VMValue params[2] = { (DObject*)this, (void*)&toucher }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + res = !!retval; + } + else res = TryPickup(toucher); + } else if (!(ItemFlags & IF_RESTRICTABSOLUTELY)) res = TryPickupRestricted(toucher); // let an item decide for itself how it will handle this else diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 8fc96cd57f..48afac2268 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -222,9 +222,9 @@ public: virtual PalEntry GetBlend (); PalEntry CallGetBlend(); -protected: virtual bool TryPickup (AActor *&toucher); virtual bool TryPickupRestricted (AActor *&toucher); +protected: bool CanPickup(AActor * toucher); void GiveQuest(AActor * toucher); @@ -600,5 +600,7 @@ public: bool TryPickup(AActor *&toucher); }; +extern PClassActor *QuestItemClasses[31]; + #endif //__A_PICKUPS_H__ diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index ed91be4c73..4bb9d5b81b 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -52,7 +52,6 @@ #include "r_data/r_translate.h" #include "a_artifacts.h" #include "a_weaponpiece.h" -#include "a_strifeglobal.h" #include "g_level.h" #include "v_palette.h" #include "p_acs.h" diff --git a/src/g_strife/a_strifeglobal.h b/src/g_strife/a_strifeglobal.h index adf8d59bf8..9206dd08cc 100644 --- a/src/g_strife/a_strifeglobal.h +++ b/src/g_strife/a_strifeglobal.h @@ -4,42 +4,4 @@ #include "info.h" #include "a_pickups.h" -// Base class for every humanoid in Strife that can go into -// a fire or electric death. -class ADegninOre : public AInventory -{ - DECLARE_CLASS (ADegninOre, AInventory) -public: - bool Use (bool pickup); -}; - -class ADummyStrifeItem : public AInventory -{ - DECLARE_CLASS (ADummyStrifeItem, AInventory) -}; - -class AUpgradeStamina : public ADummyStrifeItem -{ - DECLARE_CLASS (AUpgradeStamina, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -class AUpgradeAccuracy : public ADummyStrifeItem -{ - DECLARE_CLASS (AUpgradeAccuracy, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -class ASlideshowStarter : public ADummyStrifeItem -{ - DECLARE_CLASS (ASlideshowStarter, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - - -extern PClassActor *QuestItemClasses[31]; - #endif diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp deleted file mode 100644 index b9f3f288ed..0000000000 --- a/src/g_strife/a_strifeitems.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "d_player.h" -#include "gstrings.h" -#include "p_local.h" -#include "p_spec.h" -#include "a_strifeglobal.h" -#include "p_lnspec.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "d_event.h" -#include "a_keys.h" -#include "c_console.h" -#include "templates.h" -#include "vm.h" -#include "g_level.h" -#include "doomstat.h" -*/ -// Degnin Ore --------------------------------------------------------------- - -IMPLEMENT_CLASS(ADegninOre, false, false) - -bool ADegninOre::Use (bool pickup) -{ - if (pickup) - { - return false; - } - else - { - AInventory *drop; - - // Increase the amount by one so that when DropInventory decrements it, - // the actor will have the same number of beacons that he started with. - // When we return to UseInventory, it will take care of decrementing - // Amount again and disposing of this item if there are no more. - Amount++; - drop = Owner->DropInventory (this); - if (drop == NULL) - { - Amount--; - return false; - } - return true; - } -} - -// Health Training ---------------------------------------------------------- - -class AHealthTraining : public AInventory -{ - DECLARE_CLASS (AHealthTraining, AInventory) -public: - bool TryPickup (AActor *&toucher); -}; - -IMPLEMENT_CLASS(AHealthTraining, false, false) - -bool AHealthTraining::TryPickup (AActor *&toucher) -{ - if (Super::TryPickup (toucher)) - { - toucher->GiveInventoryType (PClass::FindActor("GunTraining")); - AInventory *coin = (AInventory*)Spawn("Coin"); - if (coin != NULL) - { - coin->Amount = toucher->player->mo->accuracy*5 + 300; - if (!coin->CallTryPickup (toucher)) - { - coin->Destroy (); - } - } - return true; - } - return false; -} - -// Scanner ------------------------------------------------------------------ - -class AScanner : public APowerupGiver -{ - DECLARE_CLASS (AScanner, APowerupGiver) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AScanner, false, false) - -bool AScanner::Use (bool pickup) -{ - if (!(level.flags2 & LEVEL2_ALLMAP)) - { - if (Owner->CheckLocalView (consoleplayer)) - { - C_MidPrint(SmallFont, GStrings("TXT_NEEDMAP")); - } - return false; - } - return Super::Use (pickup); -} - -// Prison Pass -------------------------------------------------------------- - -class APrisonPass : public AKey -{ - DECLARE_CLASS (APrisonPass, AKey) -public: - bool TryPickup (AActor *&toucher); - bool SpecialDropAction (AActor *dropper); -}; - -IMPLEMENT_CLASS(APrisonPass, false, false) - -bool APrisonPass::TryPickup (AActor *&toucher) -{ - Super::TryPickup (toucher); - EV_DoDoor (DDoor::doorOpen, NULL, toucher, 223, 2., 0, 0, 0); - toucher->GiveInventoryType (QuestItemClasses[9]); - return true; -} - -//============================================================================ -// -// APrisonPass :: SpecialDropAction -// -// Trying to make a monster that drops a prison pass turns it into an -// OpenDoor223 item instead. That means the only way to get it in Strife -// is through dialog, which is why it doesn't have its own sprite. -// -//============================================================================ - -bool APrisonPass::SpecialDropAction (AActor *dropper) -{ - EV_DoDoor (DDoor::doorOpen, NULL, dropper, 223, 2., 0, 0, 0); - Destroy (); - return true; -} - - -//--------------------------------------------------------------------------- -// Dummy items. They are just used by Strife to perform --------------------- -// actions and cannot be held. ---------------------------------------------- -//--------------------------------------------------------------------------- - -IMPLEMENT_CLASS(ADummyStrifeItem, false, false) - -// Sound the alarm! --------------------------------------------------------- - -class ARaiseAlarm : public ADummyStrifeItem -{ - DECLARE_CLASS (ARaiseAlarm, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); - bool SpecialDropAction (AActor *dropper); -}; - -IMPLEMENT_CLASS(ARaiseAlarm, false, false) - -bool ARaiseAlarm::TryPickup (AActor *&toucher) -{ - P_NoiseAlert (toucher, toucher); - /* - ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3"); - Actor spectre = Actor(it.Next()); - - if (spectre != NULL && spectre.health > 0 && toucher != spectre) - { - spectre.CurSector.SoundTarget = spectre.LastHeard = toucher; - spectre.target = toucher; - spectre.SetState (spectre.SeeState); - } - - */ - GoAwayAndDie (); - return true; -} - -bool ARaiseAlarm::SpecialDropAction (AActor *dropper) -{ - if (dropper->target != nullptr) - { - P_NoiseAlert(dropper->target, dropper->target); - if (dropper->target->CheckLocalView(consoleplayer)) - { - Printf("You Fool! You've set off the alarm.\n"); - } - } - Destroy (); - return true; -} - -// Open door tag 222 -------------------------------------------------------- - -class AOpenDoor222 : public ADummyStrifeItem -{ - DECLARE_CLASS (AOpenDoor222, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -IMPLEMENT_CLASS(AOpenDoor222, false, false) - -bool AOpenDoor222::TryPickup (AActor *&toucher) -{ - EV_DoDoor (DDoor::doorOpen, NULL, toucher, 222, 2., 0, 0, 0); - GoAwayAndDie (); - return true; -} - -// Close door tag 222 ------------------------------------------------------- - -class ACloseDoor222 : public ADummyStrifeItem -{ - DECLARE_CLASS (ACloseDoor222, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); - bool SpecialDropAction (AActor *dropper); -}; - -IMPLEMENT_CLASS(ACloseDoor222, false, false) - -bool ACloseDoor222::TryPickup (AActor *&toucher) -{ - EV_DoDoor (DDoor::doorClose, NULL, toucher, 222, 2., 0, 0, 0); - GoAwayAndDie (); - return true; -} - -bool ACloseDoor222::SpecialDropAction (AActor *dropper) -{ - EV_DoDoor (DDoor::doorClose, NULL, dropper, 222, 2., 0, 0, 0); - if (dropper->target != nullptr) - { - if (dropper->target->CheckLocalView(consoleplayer)) - { - Printf("You're dead! You set off the alarm.\n"); - } - P_NoiseAlert(dropper->target, dropper->target); - } - Destroy (); - return true; -} - -// Open door tag 224 -------------------------------------------------------- - -class AOpenDoor224 : public ADummyStrifeItem -{ - DECLARE_CLASS (AOpenDoor224, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); - bool SpecialDropAction (AActor *dropper); -}; - -IMPLEMENT_CLASS(AOpenDoor224, false, false) - -bool AOpenDoor224::TryPickup (AActor *&toucher) -{ - EV_DoDoor (DDoor::doorOpen, NULL, toucher, 224, 2., 0, 0, 0); - GoAwayAndDie (); - return true; -} - -bool AOpenDoor224::SpecialDropAction (AActor *dropper) -{ - EV_DoDoor (DDoor::doorOpen, NULL, dropper, 224, 2., 0, 0, 0); - Destroy (); - return true; -} - -// Ammo --------------------------------------------------------------------- - -class AAmmoFillup : public ADummyStrifeItem -{ - DECLARE_CLASS (AAmmoFillup, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -IMPLEMENT_CLASS(AAmmoFillup, false, false) - -bool AAmmoFillup::TryPickup (AActor *&toucher) -{ - PClassActor *clip = PClass::FindActor(NAME_ClipOfBullets); - if (clip != NULL) - { - AInventory *item = toucher->FindInventory(clip); - if (item == NULL) - { - item = toucher->GiveInventoryType (clip); - if (item != NULL) - { - item->Amount = 50; - } - } - else if (item->Amount < 50) - { - item->Amount = 50; - } - else - { - return false; - } - GoAwayAndDie (); - } - return true; -} - -// Health ------------------------------------------------------------------- - -class AHealthFillup : public ADummyStrifeItem -{ - DECLARE_CLASS (AHealthFillup, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -IMPLEMENT_CLASS(AHealthFillup, false, false) - -bool AHealthFillup::TryPickup (AActor *&toucher) -{ - static const int skillhealths[5] = { -100, -75, -50, -50, -100 }; - - int index = clamp(gameskill, 0,4); - if (!P_GiveBody (toucher, skillhealths[index])) - { - return false; - } - GoAwayAndDie (); - return true; -} - -// Upgrade Stamina ---------------------------------------------------------- - -IMPLEMENT_CLASS(AUpgradeStamina, false, false) - -bool AUpgradeStamina::TryPickup (AActor *&toucher) -{ - if (toucher->player == NULL) - return false; - - toucher->player->mo->stamina += Amount; - if (toucher->player->mo->stamina >= MaxAmount) - toucher->player->mo->stamina = MaxAmount; - - P_GiveBody (toucher, -100); - GoAwayAndDie (); - return true; -} - -// Upgrade Accuracy --------------------------------------------------------- - -IMPLEMENT_CLASS(AUpgradeAccuracy, false, false) - -bool AUpgradeAccuracy::TryPickup (AActor *&toucher) -{ - if (toucher->player == NULL || toucher->player->mo->accuracy >= 100) - return false; - toucher->player->mo->accuracy += 10; - GoAwayAndDie (); - return true; -} - -// Start a slideshow -------------------------------------------------------- - -IMPLEMENT_CLASS(ASlideshowStarter, false, false) - -bool ASlideshowStarter::TryPickup (AActor *&toucher) -{ - gameaction = ga_slideshow; - if (level.levelnum == 10) - { - toucher->GiveInventoryType (QuestItemClasses[16]); - } - GoAwayAndDie (); - return true; -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 6537f180e7..e93c13600d 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -6,7 +6,6 @@ #include "d_player.h" #include "a_action.h" #include "p_local.h" -#include "a_strifeglobal.h" #include "p_enemy.h" #include "p_lnspec.h" #include "c_console.h" @@ -24,7 +23,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_strifeitems.cpp" #include "a_strifeweapons.cpp" // Notes so I don't forget them: diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 79a363d1c7..c12c7a7237 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -12,7 +12,6 @@ #include "m_swap.h" #include "templates.h" #include "a_keys.h" -#include "a_strifeglobal.h" #include "gi.h" #include "g_level.h" #include "colormatcher.h" diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 33a90c85f5..f5cd568482 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -30,7 +30,6 @@ #include "doomstat.h" #include "gstrings.h" #include "p_local.h" -#include "a_strifeglobal.h" #include "gi.h" #include "p_enemy.h" #include "sbar.h" diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 97f6602464..a711106742 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -58,7 +58,6 @@ #include "sbar.h" #include "m_swap.h" #include "a_sharedglobal.h" -#include "a_strifeglobal.h" #include "v_video.h" #include "w_wad.h" #include "r_sky.h" diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index bf1c392aef..5fd21e73b3 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -44,7 +44,6 @@ #include "m_random.h" #include "gi.h" #include "templates.h" -#include "a_strifeglobal.h" #include "a_keys.h" #include "p_enemy.h" #include "gstrings.h" @@ -1357,7 +1356,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply } } - if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(ASlideshowStarter))) + if (reply->GiveType->IsDescendantOf(PClass::FindActor("SlideshowStarter"))) gameaction = ga_slideshow; } else diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 1f318f5594..179e057b34 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -50,7 +50,6 @@ #include "gi.h" #include "m_random.h" #include "p_conversation.h" -#include "a_strifeglobal.h" #include "r_data/r_translate.h" #include "p_3dmidtex.h" #include "d_net.h" @@ -3220,8 +3219,8 @@ FUNC(LS_GlassBreak) if (it != NULL) { it->GiveInventoryType (QuestItemClasses[28]); - it->GiveInventoryType (RUNTIME_CLASS(AUpgradeAccuracy)); - it->GiveInventoryType (RUNTIME_CLASS(AUpgradeStamina)); + it->GiveInventoryType (PClass::FindActor("UpgradeAccuracy")); + it->GiveInventoryType (PClass::FindActor("UpgradeStamina")); } } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7257eff95f..d76832c59e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -942,7 +942,7 @@ AInventory *AActor::FirstInv () // //============================================================================ -bool AActor::DoUseInventory (AInventory *item) +bool AActor::UseInventory (AInventory *item) { // No using items if you're dead. if (health <= 0) @@ -973,23 +973,7 @@ DEFINE_ACTION_FUNCTION(AActor, UseInventory) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(item, AInventory); - ACTION_RETURN_BOOL(self->DoUseInventory(item)); -} - -bool AActor::UseInventory(AInventory *item) -{ - IFVIRTUAL(AActor, UseInventory) - { - // Without the type cast this picks the 'void *' assignment... - VMValue params[2] = { (DObject*)this, (DObject*)item }; - VMReturn ret; - VMFrameStack stack; - int retval; - ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); - return !!retval; - } - else return DoUseInventory(item); + ACTION_RETURN_BOOL(self->UseInventory(item)); } //=========================================================================== @@ -1304,6 +1288,13 @@ bool AActor::CheckLocalView (int playernum) const return false; } +DEFINE_ACTION_FUNCTION(AActor, CheckLocalView) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(cp); + ACTION_RETURN_BOOL(self->CheckLocalView(cp)); +} + //============================================================================ // // AActor :: IsInsideVisibleAngles diff --git a/src/p_user.cpp b/src/p_user.cpp index 1033299e63..1ac60ba351 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -901,7 +901,7 @@ void APlayerPawn::RemoveInventory (AInventory *item) // //=========================================================================== -bool APlayerPawn::DoUseInventory (AInventory *item) +bool APlayerPawn::UseInventory (AInventory *item) { const PClass *itemtype = item->GetClass(); @@ -915,7 +915,7 @@ bool APlayerPawn::DoUseInventory (AInventory *item) return false; } - if (!Super::DoUseInventory (item)) + if (!Super::UseInventory (item)) { // Heretic and Hexen advance the inventory cursor if the use failed. // Should this behavior be retained? diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 6912755b46..2eb6cfec67 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5822,10 +5822,30 @@ bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable) 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; + // 'Out' variables are actually pointers but this fact must be hidden to the script. + if (Variable->VarFlags & VARF_Out) + { + if (!AddressRequested) + { + ExpEmit reg(build, ValueType->GetRegType(), ValueType->GetRegCount()); + build->Emit(ValueType->GetLoadOp(), reg.RegNum, Variable->RegNum, build->GetConstantInt(RegOffset)); + return reg; + } + else + { + if (RegOffset == 0) return ExpEmit(Variable->RegNum, REGT_POINTER, false, true); + ExpEmit reg(build, REGT_POINTER); + build->Emit(OP_ADDA_RK, reg.RegNum, Variable->RegNum, build->GetConstantInt(RegOffset)); + return reg; + } + } + else + { + ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); + ret.RegCount = ValueType->GetRegCount(); + if (AddressRequested) ret.Target = true; + return ret; + } } @@ -7781,7 +7801,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } FxExpression *x; - if (!(flag & VARF_Ref)) + if (!(flag & (VARF_Ref|VARF_Out))) { x = new FxTypeCast(ArgList[i], type, false); x = x->Resolve(ctx); @@ -7793,7 +7813,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr) { ArgList[i]->RequestAddress(ctx, &writable); - ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType); + if (flag & VARF_Ref) ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType); // For a reference argument the types must match 100%. if (type != ArgList[i]->ValueType) { @@ -9917,10 +9937,15 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) { if (Init == nullptr) { - if (RegNum == -1) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); + if (RegNum == -1) + { + if (!(VarFlags & VARF_Out)) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); + else RegNum = build->Registers[REGT_POINTER].Get(1); + } } else { + assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters. ExpEmit emitval = Init->Emit(build); int regtype = emitval.RegType; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index ee7cae76c0..65a979edd6 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -48,6 +48,7 @@ #include "p_terrain.h" #include "gstrings.h" #include "zstring.h" +#include "d_event.h" static TArray properties; static TArray AFTable; @@ -743,6 +744,12 @@ void InitThingdef() playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); GlobalSymbols.AddSymbol(playerf); + playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction); + GlobalSymbols.AddSymbol(playerf); + + playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer); + GlobalSymbols.AddSymbol(playerf); + // Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag. // It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution' // is to create a static variable from it and reference that in the script. Yuck!!! diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index c454ced835..4eab47c1b9 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2169,17 +2169,16 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { 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)) + if (type->IsA(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) { - // 'out' parameters and all structs except vectors are passed by reference - if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3)) - { - type = NewPointer(type); - flags |= VARF_Ref; - } - else if (type == TypeVector2) + // Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly. + type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/); + flags |= VARF_Ref; + } + else if (type->GetRegType() != REGT_NIL) + { + if (p->Flags & ZCC_Out) flags |= VARF_Out; + if (type == TypeVector2) { elementcount = 2; } diff --git a/src/virtual.h b/src/virtual.h index 8485dec078..844c51d381 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -7,15 +7,14 @@ inline unsigned GetVirtualIndex(PClass *cls, const char *funcname) return VIndex; } -#define IFVIRTUAL(cls, funcname) \ +#define IFVIRTUALPTR(self, cls, funcname) \ static unsigned VIndex = ~0u; \ if (VIndex == ~0u) { \ VIndex = GetVirtualIndex(RUNTIME_CLASS(cls), #funcname); \ assert(VIndex != ~0u); \ } \ - auto clss = GetClass(); \ + auto clss = self->GetClass(); \ VMFunction *func = clss->Virtuals.Size() > VIndex? clss->Virtuals[VIndex] : nullptr; \ if (func != nullptr) - - +#define IFVIRTUAL(cls, funcname) IFVIRTUALPTR(this, cls, funcname) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c5052ab798..25d164d294 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -267,7 +267,6 @@ class Actor : Thinker native virtual native int TakeSpecialDamage (Actor inflictor, Actor source, int damage, Name damagetype); virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0); virtual native bool Slam(Actor victim); - virtual native bool UseInventory(Inventory item); virtual native bool SpecialBlastHandling (Actor source, double strength); virtual native void Touch(Actor toucher); @@ -292,6 +291,7 @@ class Actor : Thinker native native void ClearBounce(); native TerrainDef GetFloorTerrain(); native Inventory DoDropItem(Class type, int dropamount, int chance); + native bool CheckLocalView(int consoleplayer); native void ExplodeMissile(line lin = null, Actor target = null); native void RestoreDamage(); @@ -378,6 +378,7 @@ class Actor : Thinker native native Inventory FindInventory(class itemtype, bool subclass = false); native Inventory GiveInventoryType(class itemtype); native Inventory DropInventory (Inventory item); + native bool UseInventory(Inventory item); native bool GiveAmmo (Class type, int amount); // DECORATE compatible functions diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 5f86282a89..8180e67105 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1015,3 +1015,25 @@ enum PaletteFlashFlags PF_ICE = 4, PF_HAZARD = 8, }; + +enum EGameAction +{ + ga_nothing, + ga_loadlevel, + ga_newgame, + ga_newgame2, + ga_recordgame, + ga_loadgame, + ga_loadgamehidecon, + ga_loadgameplaydemo, + ga_autoloadgame, + ga_savegame, + ga_autosave, + ga_playdemo, + ga_completed, + ga_slideshow, + ga_worlddone, + ga_screenshot, + ga_togglemap, + ga_fullconsole, +}; diff --git a/wadsrc/static/zscript/doom/scriptedmarine.txt b/wadsrc/static/zscript/doom/scriptedmarine.txt index 3987bc795f..22766ac909 100644 --- a/wadsrc/static/zscript/doom/scriptedmarine.txt +++ b/wadsrc/static/zscript/doom/scriptedmarine.txt @@ -175,7 +175,7 @@ class ScriptedMarine : Actor // //============================================================================ - private bool GetWeaponStates(int weap, WeaponStates wstates) + private bool GetWeaponStates(int weap, out WeaponStates wstates) { static const statelabel MeleeNames[] = { diff --git a/wadsrc/static/zscript/shared/debris.txt b/wadsrc/static/zscript/shared/debris.txt index 24eae25be5..3ffcea057a 100644 --- a/wadsrc/static/zscript/shared/debris.txt +++ b/wadsrc/static/zscript/shared/debris.txt @@ -187,7 +187,7 @@ class Dirt6 : Actor // Stained glass ------------------------------------------------------------ -class GlassShard : Actor native +class GlassShard : Actor { Default { @@ -199,6 +199,16 @@ class GlassShard : Actor native BounceType "HexenCompat"; BounceFactor 0.3; } + + override void Tick() + { + Super.Tick(); + if (Vel.Z > 0 && Vel.Z < 0.5 && pos.z < floorz + 1) + { + Destroy (); + } + } + } class SGShard1 : GlassShard diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index d3e50d1981..dbede839f3 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -41,7 +41,8 @@ class Inventory : Actor native private native void A_RestoreSpecialDoomThing(); private native void A_RestoreSpecialThing1(); private native void A_RestoreSpecialThing2(); - + + virtual native bool TryPickup(in out Actor toucher); native bool, Actor CallTryPickup(Actor toucher); States(Actor, Overlay, Weapon, Item) diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt index 6ae44f7f4c..e5a019ea8c 100644 --- a/wadsrc/static/zscript/strife/acolyte.txt +++ b/wadsrc/static/zscript/strife/acolyte.txt @@ -97,8 +97,8 @@ class Acolyte : StrifeHumanoid if (i == MAXPLAYERS) return; - // Make sure all the other blue acolytes are dead. - if (CheckBossDeath()) + // Make sure all the other blue acolytes are dead, but do this only once in case of simultaneous kills. + if (CheckBossDeath() && !players[i].mo.FindInventory("QuestItem7")) { players[i].mo.GiveInventoryType ("QuestItem7"); players[i].SetLogNumber (14); diff --git a/wadsrc/static/zscript/strife/strifeitems.txt b/wadsrc/static/zscript/strife/strifeitems.txt index 4d8e3d5e46..6d80377714 100644 --- a/wadsrc/static/zscript/strife/strifeitems.txt +++ b/wadsrc/static/zscript/strife/strifeitems.txt @@ -389,7 +389,7 @@ class Communicator : Inventory // Degnin Ore --------------------------------------------------------------- -class DegninOre : Inventory native +class DegninOre : Inventory { Default { @@ -421,6 +421,32 @@ class DegninOre : Inventory native BNG3 BCDEFGH 3 Bright; Stop; } + + override bool Use (bool pickup) + { + if (pickup) + { + return false; + } + else + { + Inventory drop; + + // Increase the amount by one so that when DropInventory decrements it, + // the actor will have the same number of beacons that he started with. + // When we return to UseInventory, it will take care of decrementing + // Amount again and disposing of this item if there are no more. + Amount++; + drop = Owner.DropInventory (self); + if (drop == NULL) + { + Amount--; + return false; + } + return true; + } + } + } // Gun Training ------------------------------------------------------------- @@ -446,7 +472,7 @@ class GunTraining : Inventory // Health Training ---------------------------------------------------------- -class HealthTraining : Inventory native +class HealthTraining : Inventory { Default { @@ -463,13 +489,23 @@ class HealthTraining : Inventory native HELT A -1; Stop; } + + override bool TryPickup (in out Actor toucher) + { + if (Super.TryPickup(toucher)) + { + toucher.GiveInventoryType ("GunTraining"); + toucher.A_GiveInventory("Coin", toucher.player.mo.accuracy*5 + 300); + return true; + } + return false; + } + } - - // Scanner ------------------------------------------------------------------ -class Scanner : PowerupGiver native +class Scanner : PowerupGiver { Default { @@ -488,11 +524,25 @@ class Scanner : PowerupGiver native PMUP AB 6; Loop; } + + override bool Use (bool pickup) + { + if (!level.AllMap) + { + if (Owner.CheckLocalView (consoleplayer)) + { + C_MidPrint("SmallFont", "$TXT_NEEDMAP"); + } + return false; + } + return Super.Use (pickup); + } + } // Prison Pass -------------------------------------------------------------- -class PrisonPass : Key native +class PrisonPass : Key { Default { @@ -506,6 +556,32 @@ class PrisonPass : Key native TOKN A -1; Stop; } + + override bool TryPickup (in out Actor toucher) + { + Super.TryPickup (toucher); + Door_Open(223, 16); + toucher.GiveInventoryType ("QuestItem10"); + return true; + } + + //============================================================================ + // + // APrisonPass :: SpecialDropAction + // + // Trying to make a monster that drops a prison pass turns it into an + // OpenDoor223 item instead. That means the only way to get it in Strife + // is through dialog, which is why it doesn't have its own sprite. + // + //============================================================================ + + override bool SpecialDropAction (Actor dropper) + { + Door_Open(223, 16); + Destroy (); + return true; + } + } //--------------------------------------------------------------------------- @@ -513,7 +589,7 @@ class PrisonPass : Key native // actions and cannot be held. ---------------------------------------------- //--------------------------------------------------------------------------- -class DummyStrifeItem : Inventory native +class DummyStrifeItem : Inventory { States { @@ -525,73 +601,221 @@ class DummyStrifeItem : Inventory native // Sound the alarm! --------------------------------------------------------- -class RaiseAlarm : DummyStrifeItem native +class RaiseAlarm : DummyStrifeItem { Default { Tag "$TAG_ALARM"; } + + override bool TryPickup (in out Actor toucher) + { + toucher.NoiseAlert (toucher); + + ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3"); + Actor spectre = Actor(it.Next()); + + if (spectre != NULL && spectre.health > 0 && toucher != spectre) + { + spectre.CurSector.SoundTarget = spectre.LastHeard = toucher; + spectre.target = toucher; + spectre.SetState (spectre.SeeState); + } + GoAwayAndDie (); + return true; + } + + override bool SpecialDropAction (Actor dropper) + { + if (dropper.target != null) + { + dropper.target.NoiseAlert(dropper.target); + if (dropper.target.CheckLocalView(consoleplayer)) + { + A_Log("You Fool! You've set off the alarm."); + } + } + Destroy (); + return true; + } + } // Open door tag 222 -------------------------------------------------------- -class OpenDoor222 : DummyStrifeItem native +class OpenDoor222 : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + Door_Open(222, 16); + GoAwayAndDie (); + return true; + } + } // Close door tag 222 ------------------------------------------------------- -class CloseDoor222 : DummyStrifeItem native +class CloseDoor222 : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + Door_Close(222, 16); + GoAwayAndDie (); + return true; + } + + override bool SpecialDropAction (Actor dropper) + { + Door_Close(222, 16); + if (dropper.target != null) + { + if (dropper.target.CheckLocalView(consoleplayer)) + { + A_Log("You're dead! You set off the alarm."); + } + dropper.target.NoiseAlert(dropper.target); + } + Destroy (); + return true; + } + } // Open door tag 224 -------------------------------------------------------- -class OpenDoor224 : DummyStrifeItem native +class OpenDoor224 : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + Door_Open(224, 16); + GoAwayAndDie (); + return true; + } + + override bool SpecialDropAction (Actor dropper) + { + Door_Open(224, 16); + Destroy (); + return true; + } + } // Ammo --------------------------------------------------------------------- -class AmmoFillup : DummyStrifeItem native +class AmmoFillup : DummyStrifeItem { Default { Tag "$TAG_AMMOFILLUP"; } + + override bool TryPickup (in out Actor toucher) + { + Inventory item = toucher.FindInventory("ClipOfBullets"); + if (item == NULL) + { + item = toucher.GiveInventoryType ("ClipOfBullets"); + if (item != NULL) + { + item.Amount = 50; + } + } + else if (item.Amount < 50) + { + item.Amount = 50; + } + else + { + return false; + } + GoAwayAndDie (); + return true; + } + } // Health ------------------------------------------------------------------- -class HealthFillup : DummyStrifeItem native +class HealthFillup : DummyStrifeItem { Default { Tag "$TAG_HEALTHFILLUP"; } + + override bool TryPickup (in out Actor toucher) + { + static const int skillhealths[] = { -100, -75, -50, -50, -100 }; + + int index = clamp(skill, 0,4); + if (!toucher.GiveBody (skillhealths[index])) + { + return false; + } + GoAwayAndDie (); + return true; + } + } // Upgrade Stamina ---------------------------------------------------------- -class UpgradeStamina : DummyStrifeItem native +class UpgradeStamina : DummyStrifeItem { Default { Inventory.Amount 10; Inventory.MaxAmount 100; } + + override bool TryPickup (in out Actor toucher) + { + if (toucher.player == NULL) + return false; + + toucher.player.mo.stamina += Amount; + if (toucher.player.mo.stamina >= MaxAmount) + toucher.player.mo.stamina = MaxAmount; + + toucher.GiveBody (-100); + GoAwayAndDie (); + return true; + } + } // Upgrade Accuracy --------------------------------------------------------- -class UpgradeAccuracy : DummyStrifeItem native +class UpgradeAccuracy : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + if (toucher.player == NULL || toucher.player.mo.accuracy >= 100) + return false; + toucher.player.mo.accuracy += 10; + GoAwayAndDie (); + return true; + } + } // Start a slideshow -------------------------------------------------------- -class SlideshowStarter : DummyStrifeItem native +class SlideshowStarter : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + gameaction = ga_slideshow; + if (level.levelnum == 10) + { + toucher.GiveInventoryType ("QuestItem17"); + } + GoAwayAndDie (); + return true; + } + } From be5ba70ed245064a62f6f8204cbb934525a3e739 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 13:00:07 +0100 Subject: [PATCH 407/471] - scriptified Strife's dagger and crossbow. --- src/g_strife/a_strifeweapons.cpp | 247 ------------------ src/p_enemy.cpp | 64 +++++ src/p_mobj.cpp | 5 + src/scripting/zscript/zcc-parse.lemon | 2 +- wadsrc/static/zscript.txt | 2 + wadsrc/static/zscript/actor.txt | 3 +- .../static/zscript/strife/strifefunctions.txt | 60 ++++- .../static/zscript/strife/strifeweapons.txt | 206 --------------- .../static/zscript/strife/weaponcrossbow.txt | 227 ++++++++++++++++ wadsrc/static/zscript/strife/weapondagger.txt | 69 +++++ 10 files changed, 428 insertions(+), 457 deletions(-) create mode 100644 wadsrc/static/zscript/strife/weaponcrossbow.txt create mode 100644 wadsrc/static/zscript/strife/weapondagger.txt diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 34862f943d..67c8c8c17f 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -16,7 +16,6 @@ // hacking more stuff in the executable, be sure to give // all Strife missiles the MF4_STRIFEDAMAGE flag. -static FRandom pr_jabdagger ("JabDagger"); static FRandom pr_electric ("FireElectric"); static FRandom pr_sgunshot ("StrifeGunShot"); static FRandom pr_minimissile ("MiniMissile"); @@ -29,252 +28,6 @@ static FRandom pr_phburn ("PhBurn"); void A_LoopActiveSound (AActor *); void A_Countdown (AActor *); -// Punch Dagger ------------------------------------------------------------- - -//============================================================================ -// -// P_DaggerAlert -// -//============================================================================ - -void P_DaggerAlert (AActor *target, AActor *emitter) -{ - AActor *looker; - sector_t *sec = emitter->Sector; - - if (emitter->LastHeard != NULL) - return; - if (emitter->health <= 0) - return; - if (!(emitter->flags3 & MF3_ISMONSTER)) - return; - if (emitter->flags4 & MF4_INCOMBAT) - return; - emitter->flags4 |= MF4_INCOMBAT; - - emitter->target = target; - FState *painstate = emitter->FindState(NAME_Pain, NAME_Dagger); - if (painstate != NULL) - { - emitter->SetState (painstate); - } - - for (looker = sec->thinglist; looker != NULL; looker = looker->snext) - { - if (looker == emitter || looker == target) - continue; - - if (looker->health <= 0) - continue; - - if (!(looker->flags4 & MF4_SEESDAGGERS)) - continue; - - if (!(looker->flags4 & MF4_INCOMBAT)) - { - if (!P_CheckSight (looker, target) && !P_CheckSight (looker, emitter)) - continue; - - looker->target = target; - if (looker->SeeSound) - { - S_Sound (looker, CHAN_VOICE, looker->SeeSound, 1, ATTN_NORM); - } - looker->SetState (looker->SeeState); - looker->flags4 |= MF4_INCOMBAT; - } - } -} - -//============================================================================ -// -// A_JabDagger -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_JabDagger) -{ - PARAM_ACTION_PROLOGUE(AActor); - - DAngle angle; - int damage; - DAngle pitch; - int power; - FTranslatedLineTarget t; - - power = MIN(10, self->player->mo->stamina / 10); - damage = (pr_jabdagger() % (power + 8)) * (power + 2); - - if (self->FindInventory()) - { - damage *= 10; - } - - angle = self->Angles.Yaw + pr_jabdagger.Random2() * (5.625 / 256); - pitch = P_AimLineAttack (self, angle, 80.); - P_LineAttack (self, angle, 80., pitch, damage, NAME_Melee, "StrifeSpark", true, &t); - - // turn to face target - if (t.linetarget) - { - S_Sound (self, CHAN_WEAPON, - t.linetarget->flags & MF_NOBLOOD ? "misc/metalhit" : "misc/meathit", - 1, ATTN_NORM); - self->Angles.Yaw = t.angleFromSource; - self->flags |= MF_JUSTATTACKED; - P_DaggerAlert (self, t.linetarget); - } - else - { - S_Sound (self, CHAN_WEAPON, "misc/swish", 1, ATTN_NORM); - } - return 0; -} - -//============================================================================ -// -// A_AlertMonsters -// -//============================================================================ - -enum -{ - AMF_TARGETEMITTER = 1, - AMF_TARGETNONPLAYER = 2, - AMF_EMITFROMTARGET = 4, -}; - -DEFINE_ACTION_FUNCTION(AActor, A_AlertMonsters) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT_DEF(maxdist); - PARAM_INT_DEF(Flags); - - AActor * target = NULL; - AActor * emitter = self; - - if (self->player != NULL || (Flags & AMF_TARGETEMITTER)) - { - target = self; - } - else if (self->target != NULL && (Flags & AMF_TARGETNONPLAYER)) - { - target = self->target; - } - else if (self->target != NULL && self->target->player != NULL) - { - target = self->target; - } - - if (Flags & AMF_EMITFROMTARGET) emitter = target; - - if (target != NULL && emitter != NULL) - { - P_NoiseAlert(target, emitter, false, maxdist); - } - return 0; -} - -// Poison Bolt -------------------------------------------------------------- - -class APoisonBolt : public AActor -{ - DECLARE_CLASS (APoisonBolt, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(APoisonBolt, false, false) - -int APoisonBolt::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->flags & MF_NOBLOOD) - { - return -1; - } - if (target->health < 1000000) - { - if (!(target->flags2 & MF2_BOSS)) - return target->health + 10; - else - return 50; - } - return 1; -} - -// Strife's Crossbow -------------------------------------------------------- - -//============================================================================ -// -// A_ClearFlash -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ClearFlash) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player = self->player; - - if (player == nullptr) - return 0; - - P_SetPsprite (player, PSP_FLASH, nullptr); - return 0; -} - -//============================================================================ -// -// A_ShowElectricFlash -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ShowElectricFlash) -{ - PARAM_ACTION_PROLOGUE(AActor); - - if (self->player != nullptr) - { - P_SetPsprite (self->player, PSP_FLASH, self->player->ReadyWeapon->FindState(NAME_Flash)); - } - return 0; -} - -//============================================================================ -// -// A_FireElectric -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireArrow) -{ - PARAM_ACTION_PROLOGUE(AActor); - PARAM_CLASS(ti, AActor); - - DAngle savedangle; - - if (self->player == NULL) - return 0; - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - - if (ti) - { - savedangle = self->Angles.Yaw; - self->Angles.Yaw += pr_electric.Random2() * (5.625/256) * self->player->mo->AccuracyFactor(); - self->player->mo->PlayAttacking2 (); - P_SpawnPlayerMissile (self, ti); - self->Angles.Yaw = savedangle; - S_Sound (self, CHAN_WEAPON, "weapons/xbowshoot", 1, ATTN_NORM); - } - return 0; -} - // Assault Gun -------------------------------------------------------------- //============================================================================ diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 6a59986c03..3d9122930e 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -273,6 +273,70 @@ DEFINE_ACTION_FUNCTION(AActor, NoiseAlert) return 0; } +//============================================================================ +// +// P_DaggerAlert +// +//============================================================================ + +void P_DaggerAlert(AActor *target, AActor *emitter) +{ + AActor *looker; + sector_t *sec = emitter->Sector; + + if (emitter->LastHeard != NULL) + return; + if (emitter->health <= 0) + return; + if (!(emitter->flags3 & MF3_ISMONSTER)) + return; + if (emitter->flags4 & MF4_INCOMBAT) + return; + emitter->flags4 |= MF4_INCOMBAT; + + emitter->target = target; + FState *painstate = emitter->FindState(NAME_Pain, NAME_Dagger); + if (painstate != NULL) + { + emitter->SetState(painstate); + } + + for (looker = sec->thinglist; looker != NULL; looker = looker->snext) + { + if (looker == emitter || looker == target) + continue; + + if (looker->health <= 0) + continue; + + if (!(looker->flags4 & MF4_SEESDAGGERS)) + continue; + + if (!(looker->flags4 & MF4_INCOMBAT)) + { + if (!P_CheckSight(looker, target) && !P_CheckSight(looker, emitter)) + continue; + + looker->target = target; + if (looker->SeeSound) + { + S_Sound(looker, CHAN_VOICE, looker->SeeSound, 1, ATTN_NORM); + } + looker->SetState(looker->SeeState); + looker->flags4 |= MF4_INCOMBAT; + } + } +} + +DEFINE_ACTION_FUNCTION(AActor, DaggerAlert) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(target, AActor); + // Note that the emitter is self, not the target of the alert! Target can be NULL. + P_DaggerAlert(target, self); + return 0; +} + //---------------------------------------------------------------------------- // diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d76832c59e..04a9e9433a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7598,6 +7598,11 @@ DEFINE_ACTION_FUNCTION(AActor, ClearBounce) return 0; } +DEFINE_ACTION_FUNCTION(AActor, AccuracyFactor) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_FLOAT(self->AccuracyFactor()); +} //---------------------------------------------------------------------------- // diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index ccd7e6e845..685c401e78 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -740,7 +740,7 @@ type_name(X) ::= DOT dottable_id(A). /* 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 VECTOR2 VECTOR3 NAME MAP ARRAY VOID STATE COLOR UINT8 INT8 UINT16 INT16. + SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 NAME MAP ARRAY VOID STATE COLOR SOUND UINT8 INT8 UINT16 INT16. /* Aggregate types */ %type aggregate_type {ZCC_Type *} diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index d3ed13d7ef..4b646be4a9 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -189,6 +189,8 @@ zscript/strife/strifestuff.txt zscript/strife/thingstoblowup.txt zscript/strife/templar.txt zscript/strife/zombie.txt +zscript/strife/weapondagger.txt +zscript/strife/weaponcrossbow.txt zscript/strife/sigil.txt zscript/chex/chexmonsters.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 25d164d294..a5e0db1534 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -288,6 +288,7 @@ class Actor : Thinker native native int PlayerNumber(); native void SetFriendPlayer(PlayerInfo player); native void NoiseAlert(Actor target, bool splash = false, double maxdist = 0); + native void DaggerAlert(Actor target); native void ClearBounce(); native TerrainDef GetFloorTerrain(); native Inventory DoDropItem(Class type, int dropamount, int chance); @@ -380,6 +381,7 @@ class Actor : Thinker native native Inventory DropInventory (Inventory item); native bool UseInventory(Inventory item); native bool GiveAmmo (Class type, int amount); + native float AccuracyFactor(); // DECORATE compatible functions native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); @@ -622,7 +624,6 @@ class Actor : Thinker native native void A_Wander(int flags = 0); native void A_Look2(); - native void A_AlertMonsters(double maxdist = 0, int flags = 0); deprecated native void A_MissileAttack(); deprecated native void A_MeleeAttack(); diff --git a/wadsrc/static/zscript/strife/strifefunctions.txt b/wadsrc/static/zscript/strife/strifefunctions.txt index febb2fdcb1..f95ebcfcc9 100644 --- a/wadsrc/static/zscript/strife/strifefunctions.txt +++ b/wadsrc/static/zscript/strife/strifefunctions.txt @@ -71,7 +71,11 @@ extend class Actor gib.Vel.Z = random[GibTosser]() & 15; } - // A_ShootGun ------------------------------------------------------------- + //========================================================================== + // + // + // + //========================================================================== void A_ShootGun() { @@ -82,7 +86,11 @@ extend class Actor LineAttack (Angle + Random2[ShootGun]() * (11.25 / 256), MISSILERANGE, pitch, 3*(random[ShootGun]() % 5 + 1), 'Hitscan', "StrifePuff"); } - // Kneeling Guy ------------------------------------------------------------- + //========================================================================== + // + // + // + //========================================================================== void A_SetShadow() { @@ -96,6 +104,12 @@ extend class Actor A_SetRenderStyle(1, STYLE_Normal); } + //========================================================================== + // + // + // + //========================================================================== + void A_GetHurt() { bInCombat = true; @@ -110,6 +124,12 @@ extend class Actor } } + //========================================================================== + // + // + // + //========================================================================== + void A_DropFire() { Actor drop = Spawn("FireDroplet", pos + (0,0,24), ALLOW_REPLACE); @@ -117,9 +137,45 @@ extend class Actor A_Explode(64, 64, XF_NOSPLASH, damagetype: 'Fire'); } + //========================================================================== + // + // + // + //========================================================================== + void A_RemoveForceField() { bSpecial = false; CurSector.RemoveForceField(); } + + //========================================================================== + // + // + // + //========================================================================== + + void A_AlertMonsters(double maxdist = 0, int flags = 0) + { + Actor target = null; + Actor emitter = self; + + if (player != null || (Flags & AMF_TARGETEMITTER)) + { + target = self; + } + else if (target != null && (self.target.player != null || (Flags & AMF_TARGETNONPLAYER))) + { + target = self.target; + } + + if (Flags & AMF_EMITFROMTARGET) emitter = target; + + if (target != null && emitter != null) + { + emitter.NoiseAlert(target, false, maxdist); + } + } + + } diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index 0180ea4451..a2475397dd 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -50,212 +50,6 @@ class StrifeSpark : StrifePuff } } -// 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 diff --git a/wadsrc/static/zscript/strife/weaponcrossbow.txt b/wadsrc/static/zscript/strife/weaponcrossbow.txt new file mode 100644 index 0000000000..1617fbfcdb --- /dev/null +++ b/wadsrc/static/zscript/strife/weaponcrossbow.txt @@ -0,0 +1,227 @@ +// 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"; + } + + 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; + } + + //============================================================================ + // + // A_ClearFlash + // + //============================================================================ + + action void A_ClearFlash () + { + if (player == null) + return; + + player.SetPsprite (PSP_FLASH, null); + } + + //============================================================================ + // + // A_ShowElectricFlash + // + //============================================================================ + + action void A_ShowElectricFlash () + { + if (player != null) + { + player.SetPsprite (PSP_FLASH, player.ReadyWeapon.FindState('Flash')); + } + } + + //============================================================================ + // + // A_FireElectric + // + //============================================================================ + + action void A_FireArrow (class proj) + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + if (proj) + { + double savedangle = angle; + angle += Random2[Electric]() * (5.625/256) * AccuracyFactor(); + player.mo.PlayAttacking2 (); + SpawnPlayerMissile (proj); + angle = savedangle; + A_PlaySound ("weapons/xbowshoot", CHAN_WEAPON); + } + } +} + + +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; + } +} + +// Electric Bolt ------------------------------------------------------------ + +class ElectricBolt : Actor +{ + Default + { + Speed 30; + Radius 10; + Height 10; + Damage 10; + Projectile; + +STRIFEDAMAGE + +NOBLOCKMAP + +NOGRAVITY + +DROPOFF + MaxStepHeight 4; + SeeSound "misc/swish"; + ActiveSound "misc/swish"; + DeathSound "weapons/xbowhit"; + Obituary "$OB_MPELECTRICBOLT"; + } + States + { + Spawn: + AROW A 10 A_LoopActiveSound; + Loop; + Death: + ZAP1 A 3 A_AlertMonsters; + ZAP1 BCDEFE 3; + ZAP1 DCB 2; + ZAP1 A 1; + Stop; + } +} + + +// Poison Bolt -------------------------------------------------------------- + +class PoisonBolt : Actor +{ + 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; + } + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if (target.bNoBlood) + { + return -1; + } + if (target.health < 1000000) + { + if (!target.bBoss) + return target.health + 10; + else + return 50; + } + return 1; + } + + +} + + diff --git a/wadsrc/static/zscript/strife/weapondagger.txt b/wadsrc/static/zscript/strife/weapondagger.txt new file mode 100644 index 0000000000..24aef209b3 --- /dev/null +++ b/wadsrc/static/zscript/strife/weapondagger.txt @@ -0,0 +1,69 @@ + +// Punch Dagger ------------------------------------------------------------- + +class PunchDagger : StrifeWeapon +{ + Default + { + Weapon.SelectionOrder 3900; + +WEAPON.NOALERT + Obituary "$OB_MPPUNCHDAGGER"; + Tag "$TAG_PUNCHDAGGER"; + } + + 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; + } + + //============================================================================ + // + // A_JabDagger + // + //============================================================================ + + action void A_JabDagger () + { + FTranslatedLineTarget t; + + int power = MIN(10, stamina / 10); + int damage = (random[JabDagger]() % (power + 8)) * (power + 2); + + if (FindInventory("PowerStrength")) + { + damage *= 10; + } + + double angle = angle + random2[JabDagger]() * (5.625 / 256); + double pitch = AimLineAttack (angle, 80.); + LineAttack (angle, 80., pitch, damage, 'Melee', "StrifeSpark", true, t); + + // turn to face target + if (t.linetarget) + { + S_Sound (t.linetarget.bNoBlood ? sound("misc/metalhit") : sound("misc/meathit"), CHAN_WEAPON); + angle = t.angleFromSource; + bJustAttacked = true; + t.linetarget.DaggerAlert (self); + } + else + { + A_PlaySound ("misc/swish", CHAN_WEAPON); + } + } +} From 5beebb83b741b0ef43cb4ef6e65e7d2c24ba4302 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 13:28:43 +0100 Subject: [PATCH 408/471] - scriptified Strife's assault gun and missile launcher. --- src/g_shared/a_pickups.cpp | 1 - src/g_strife/a_strifeweapons.cpp | 109 ----------- wadsrc/static/zscript.txt | 2 + wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/constants.txt | 9 + wadsrc/static/zscript/shared/inventory.txt | 1 - .../static/zscript/strife/strifefunctions.txt | 19 +- .../static/zscript/strife/strifeweapons.txt | 171 ------------------ .../static/zscript/strife/weaponassault.txt | 94 ++++++++++ .../static/zscript/strife/weaponmissile.txt | 137 ++++++++++++++ 10 files changed, 260 insertions(+), 284 deletions(-) create mode 100644 wadsrc/static/zscript/strife/weaponassault.txt create mode 100644 wadsrc/static/zscript/strife/weaponmissile.txt diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 38d068bd78..ad843667a5 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1717,7 +1717,6 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) bool res; if (CanPickup(toucher)) { - bool res; IFVIRTUAL(AInventory, TryPickup) { VMValue params[2] = { (DObject*)this, (void*)&toucher }; diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 67c8c8c17f..8492789db1 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -30,117 +30,8 @@ void A_Countdown (AActor *); // Assault Gun -------------------------------------------------------------- -//============================================================================ -// -// P_StrifeGunShot -// -//============================================================================ - -void P_StrifeGunShot (AActor *mo, bool accurate, DAngle pitch) -{ - DAngle angle; - int damage; - - damage = 4*(pr_sgunshot()%3+1); - angle = mo->Angles.Yaw; - - if (mo->player != NULL && !accurate) - { - angle += pr_sgunshot.Random2() * (22.5 / 256) * mo->player->mo->AccuracyFactor(); - } - - P_LineAttack (mo, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, NAME_StrifePuff); -} - -//============================================================================ -// -// A_FireAssaultGun -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireAssaultGun) -{ - PARAM_ACTION_PROLOGUE(AActor); - - bool accurate; - - S_Sound (self, CHAN_WEAPON, "weapons/assaultgun", 1, ATTN_NORM); - - if (self->player != NULL) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - self->player->mo->PlayAttacking2 (); - accurate = !self->player->refire; - } - else - { - accurate = true; - } - - P_StrifeGunShot (self, accurate, P_BulletSlope (self)); - return 0; -} - // Mini-Missile Launcher ---------------------------------------------------- -//============================================================================ -// -// A_FireMiniMissile -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player = self->player; - DAngle savedangle; - - if (self->player == NULL) - return 0; - - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - - savedangle = self->Angles.Yaw; - self->Angles.Yaw += pr_minimissile.Random2() * (11.25 / 256) * player->mo->AccuracyFactor(); - player->mo->PlayAttacking2 (); - P_SpawnPlayerMissile (self, PClass::FindActor("MiniMissile")); - self->Angles.Yaw = savedangle; - return 0; -} - -//============================================================================ -// -// A_RocketInFlight -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_RocketInFlight) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *trail; - - S_Sound (self, CHAN_VOICE, "misc/missileinflight", 1, ATTN_NORM); - P_SpawnPuff (self, PClass::FindActor("MiniMissilePuff"), self->Pos(), self->Angles.Yaw - 180, self->Angles.Yaw - 180, 2, PF_HITTHING); - trail = Spawn("RocketTrail", self->Vec3Offset(-self->Vel.X, -self->Vel.Y, 0.), ALLOW_REPLACE); - if (trail != NULL) - { - trail->Vel.Z = 1; - } - return 0; -} - // Flame Thrower ------------------------------------------------------------ //============================================================================ diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 4b646be4a9..eb6e30dcba 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -191,6 +191,8 @@ zscript/strife/templar.txt zscript/strife/zombie.txt zscript/strife/weapondagger.txt zscript/strife/weaponcrossbow.txt +zscript/strife/weaponassault.txt +zscript/strife/weaponmissile.txt zscript/strife/sigil.txt zscript/chex/chexmonsters.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index a5e0db1534..5279372fd1 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -694,7 +694,6 @@ class Actor : Thinker native native void A_ClearLastHeard(); native bool A_SelectWeapon(class whichweapon, int flags = 0); native void A_ClassBossHealth(); - native void A_RocketInFlight(); native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 8180e67105..2ccfb70481 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1037,3 +1037,12 @@ enum EGameAction ga_togglemap, ga_fullconsole, }; + +enum EPuffFlags +{ + PF_HITTHING = 1, + PF_MELEERANGE = 2, + PF_TEMPORARY = 4, + PF_HITTHINGBLEED = 8, + PF_NORANDOMZ = 16 +}; diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index dbede839f3..5192b4c93b 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -83,7 +83,6 @@ class StateProvider : Inventory native 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 state A_CheckForReload(int counter, statelabel label, bool dontincrement = false); action native void A_ResetReloadCounter(); } diff --git a/wadsrc/static/zscript/strife/strifefunctions.txt b/wadsrc/static/zscript/strife/strifefunctions.txt index f95ebcfcc9..7cfdf39746 100644 --- a/wadsrc/static/zscript/strife/strifefunctions.txt +++ b/wadsrc/static/zscript/strife/strifefunctions.txt @@ -1,4 +1,4 @@ -// common Strife action functions. +// common Strife action functions that are used by multiple different actors extend class Actor { @@ -177,5 +177,22 @@ extend class Actor } } + //============================================================================ + // + // A_RocketInFlight + // + //============================================================================ + + void A_RocketInFlight() + { + A_PlaySound ("misc/missileinflight", CHAN_VOICE); + SpawnPuff ("MiniMissilePuff", Pos, Angle - 180, Angle - 180, 2, PF_HITTHING); + Actor trail = Spawn("RocketTrail", Vec3Offset(-Vel.X, -Vel.Y, 0.), ALLOW_REPLACE); + if (trail != null) + { + trail.Vel.Z = 1; + } + } + } diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index a2475397dd..ae0bc1284e 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -50,177 +50,6 @@ class StrifeSpark : StrifePuff } } -// 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_SetRenderStyle(1, STYLE_Normal); - SMIS A 5 Bright A_Explode(64, 64, alert:true); - SMIS B 5 Bright; - SMIS C 4 Bright; - SMIS DEFG 2 Bright; - Stop; - } -} - // Flame Thrower ------------------------------------------------------------ class FlameThrower : StrifeWeapon diff --git a/wadsrc/static/zscript/strife/weaponassault.txt b/wadsrc/static/zscript/strife/weaponassault.txt new file mode 100644 index 0000000000..c382d8e848 --- /dev/null +++ b/wadsrc/static/zscript/strife/weaponassault.txt @@ -0,0 +1,94 @@ +// 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; + } +} + +extend class StateProvider +{ + //============================================================================ + // + // A_FireAssaultGun + // + //============================================================================ + + void A_FireAssaultGun() + { + if (player == null) + { + return; + } + + A_PlaySound ("weapons/assaultgun", CHAN_WEAPON); + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + player.mo.PlayAttacking2 (); + + int damage = 4*(random[StrifeGun]() % 3 + 1); + double ang = angle; + + if (player.refire) + { + ang += Random2[StrifeGun]() * (22.5 / 256) * AccuracyFactor(); + } + LineAttack (ang, PLAYERMISSILERANGE, BulletSlope (), damage, 'Hitscan', "StrifePuff"); + } +} + + +// Standing variant of the assault gun -------------------------------------- + +class AssaultGunStanding : WeaponGiver +{ + Default + { + DropItem "AssaultGun"; + Inventory.PickupMessage "$TXT_ASSAULTGUN"; + } + States + { + Spawn: + RIFL B -1; + Stop; + } +} + + diff --git a/wadsrc/static/zscript/strife/weaponmissile.txt b/wadsrc/static/zscript/strife/weaponmissile.txt new file mode 100644 index 0000000000..589f754939 --- /dev/null +++ b/wadsrc/static/zscript/strife/weaponmissile.txt @@ -0,0 +1,137 @@ +// 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"; + } + + 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; + } + + //============================================================================ + // + // A_FireMiniMissile + // + //============================================================================ + + action void A_FireMiniMissile () + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + + double savedangle = angle; + angle += Random2[MiniMissile]() * (11.25 / 256) * AccuracyFactor(); + player.mo.PlayAttacking2 (); + SpawnPlayerMissile ("MiniMissile"); + angle = savedangle; + } +} + + +// 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_SetRenderStyle(1, STYLE_Normal); + SMIS A 5 Bright A_Explode(64, 64, alert:true); + SMIS B 5 Bright; + SMIS C 4 Bright; + SMIS DEFG 2 Bright; + Stop; + } +} + From b625156df63dd2434cef8b0ec5dc42983ed344e3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 14:12:39 +0100 Subject: [PATCH 409/471] - scriptified Strife's flamethrower and grenade launcher. --- src/g_strife/a_strifeweapons.cpp | 179 ---------- src/p_glnodes.cpp | 1 - src/p_maputl.cpp | 1 - src/p_mobj.cpp | 9 + src/p_sectors.cpp | 39 +++ wadsrc/static/zscript.txt | 2 + wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/base.txt | 3 + .../static/zscript/strife/strifeweapons.txt | 288 ---------------- wadsrc/static/zscript/strife/weaponflamer.txt | 118 +++++++ .../static/zscript/strife/weapongrenade.txt | 315 ++++++++++++++++++ 11 files changed, 487 insertions(+), 469 deletions(-) create mode 100644 wadsrc/static/zscript/strife/weaponflamer.txt create mode 100644 wadsrc/static/zscript/strife/weapongrenade.txt diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 8492789db1..bcedd14298 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -34,53 +34,6 @@ void A_Countdown (AActor *); // Flame Thrower ------------------------------------------------------------ -//============================================================================ -// -// A_FlameDie -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FlameDie) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags |= MF_NOGRAVITY; - self->Vel.Z = pr_flamedie() & 3; - return 0; -} - -//============================================================================ -// -// A_FireFlamer -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player = self->player; - - if (player != NULL) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - player->mo->PlayAttacking2 (); - } - - self->Angles.Yaw += pr_flamethrower.Random2() * (5.625/256.); - self = P_SpawnPlayerMissile (self, PClass::FindActor("FlameMissile")); - if (self != NULL) - { - self->Vel.Z += 5; - } - return 0; -} - // Mauler ------------------------------------------------------------------- //============================================================================ @@ -210,135 +163,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaulerTorpedoWave) return 0; } -class APhosphorousFire : public AActor -{ - DECLARE_CLASS (APhosphorousFire, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(APhosphorousFire, false, false) - -int APhosphorousFire::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->flags & MF_NOBLOOD) - { - return damage / 2; - } - return Super::DoSpecialDamage (target, damage, damagetype); -} - -DEFINE_ACTION_FUNCTION(AActor, A_BurnArea) -{ - PARAM_SELF_PROLOGUE(AActor); - - P_RadiusAttack (self, self->target, 128, 128, self->DamageType, RADF_HURTSOURCE); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_Burnination) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Vel.Z -= 8; - self->Vel.X += (pr_phburn.Random2 (3)); - self->Vel.Y += (pr_phburn.Random2 (3)); - S_Sound (self, CHAN_VOICE, "world/largefire", 1, ATTN_NORM); - - // Only the main fire spawns more. - if (!(self->flags & MF_DROPPED)) - { - // Original x and y offsets seemed to be like this: - // x + (((pr_phburn() + 12) & 31) << F.RACBITS); - // - // But that creates a lop-sided burn because it won't use negative offsets. - int xofs, xrand = pr_phburn(); - int yofs, yrand = pr_phburn(); - - // Adding 12 is pointless if you're going to mask it afterward. - xofs = xrand & 31; - if (xrand & 128) - { - xofs = -xofs; - } - - yofs = yrand & 31; - if (yrand & 128) - { - yofs = -yofs; - } - - DVector2 pos = self->Vec2Offset((double)xofs, (double)yofs); - sector_t * sector = P_PointInSector(pos); - - // The sector's floor is too high so spawn the flame elsewhere. - if (sector->floorplane.ZatPoint(pos) > self->Z() + self->MaxStepHeight) - { - pos = self->Pos(); - } - - AActor *drop = Spawn (DVector3(pos, self->Z() + 4.), ALLOW_REPLACE); - if (drop != NULL) - { - drop->Vel.X = self->Vel.X + pr_phburn.Random2 (7); - drop->Vel.Y = self->Vel.Y + pr_phburn.Random2 (7); - drop->Vel.Z = self->Vel.Z - 1; - drop->reactiontime = (pr_phburn() & 3) + 2; - drop->flags |= MF_DROPPED; - } - } - return 0; -} - -//============================================================================ -// -// A_FireGrenade -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireGrenade) -{ - PARAM_ACTION_PROLOGUE(AActor); - PARAM_CLASS(grenadetype, AActor); - PARAM_ANGLE(angleofs); - PARAM_STATE(flash) - - player_t *player = self->player; - AActor *grenade; - DAngle an; - AWeapon *weapon; - - if (player == nullptr || grenadetype == nullptr) - return 0; - - if ((weapon = player->ReadyWeapon) == nullptr) - return 0; - - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - - P_SetPsprite (player, PSP_FLASH, flash, true); - - if (grenadetype != nullptr) - { - self->AddZ(32); - grenade = P_SpawnSubMissile (self, grenadetype, self); - self->AddZ(-32); - if (grenade == nullptr) - return 0; - - if (grenade->SeeSound != 0) - { - S_Sound (grenade, CHAN_VOICE, grenade->SeeSound, 1, ATTN_NORM); - } - - grenade->Vel.Z = (-self->Angles.Pitch.TanClamped()) * grenade->Speed + 8; - - DVector2 offset = self->Angles.Yaw.ToVector(self->radius + grenade->radius); - DAngle an = self->Angles.Yaw + angleofs; - offset += an.ToVector(15); - grenade->SetOrigin(grenade->Vec3Offset(offset.X, offset.Y, 0.), false); - } - return 0; -} - diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 39c8f8e0dc..26e341aab7 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -1356,7 +1356,6 @@ subsector_t *P_PointInSubsector (double x, double y) return (subsector_t *)((BYTE *)node - 1); } - //========================================================================== // // PointOnLine diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 2d2472cbda..16fc790c05 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1971,4 +1971,3 @@ sector_t *P_PointInSectorBuggy(double x, double y) subsector_t *ssec = (subsector_t *)((BYTE *)node - 1); return ssec->sector; } - diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 04a9e9433a..5e2a9f0394 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7560,6 +7560,15 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2OffsetZ) ACTION_RETURN_VEC3(self->Vec2OffsetZ(x, y, z, absolute)); } +DEFINE_ACTION_FUNCTION(AActor, Vec2Offset) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_VEC2(self->Vec2Offset(x, y, absolute)); +} + DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index e6302199b1..2b8097e554 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -1050,6 +1050,35 @@ double sector_t::NextLowestFloorAt(double x, double y, double z, int flags, doub } } +DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt) +{ + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_INT_DEF(flags); + PARAM_FLOAT_DEF(steph); + sector_t *resultsec; + F3DFloor *resultff; + double resultheight = self->NextLowestFloorAt(x, y, z, flags, steph, &resultsec, &resultff); + + if (numret > 2) + { + ret[2].SetPointer(resultff, ATAG_GENERIC); + numret = 3; + } + if (numret > 1) + { + ret[1].SetPointer(resultsec, ATAG_GENERIC); + } + if (numret > 0) + { + ret[0].SetFloat(resultheight); + } + return numret; +} + + //=========================================================================== // // @@ -1103,6 +1132,16 @@ double sector_t::NextLowestFloorAt(double x, double y, double z, int flags, doub self->RemoveForceField(); return 0; } + + + DEFINE_ACTION_FUNCTION(_Sector, PointInSector) + { + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + ACTION_RETURN_POINTER(P_PointInSector(x, y)); + } + //=========================================================================== // // diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index eb6e30dcba..cbba151f5c 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -193,6 +193,8 @@ zscript/strife/weapondagger.txt zscript/strife/weaponcrossbow.txt zscript/strife/weaponassault.txt zscript/strife/weaponmissile.txt +zscript/strife/weaponflamer.txt +zscript/strife/weapongrenade.txt zscript/strife/sigil.txt zscript/chex/chexmonsters.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5279372fd1..37306db39a 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -361,6 +361,7 @@ class Actor : Thinker native native vector3 Vec3Offset(double x, double y, double z, bool absolute = false); native vector3 Vec3Angle(double length, double angle, double z = 0, bool absolute = false); native vector2 Vec2Angle(double length, double angle, bool absolute = false); + native vector2 Vec2Offset(double x, double y, bool absolute = false); native vector3 Vec2OffsetZ(double x, double y, double atz, bool absolute = false); native void VelFromAngle(double speed = 0, double angle = 0); native void Thrust(double speed = 0, double angle = 0); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index b0abc73eca..08125952d2 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -247,7 +247,10 @@ struct Sector native native double, Sector, F3DFloor NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0); + native double, Sector, F3DFloor NextLowestFloorAt(double x, double y, double z, int flags = 0, double steph = 0); + native void RemoveForceField(); + native static Sector PointInSector(Vector2 pt); } struct Wads diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index ae0bc1284e..9e2f2c84f1 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -50,88 +50,6 @@ class StrifeSpark : StrifePuff } } -// 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 @@ -306,209 +224,3 @@ class MaulerTorpedoWave : Actor } -// 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_SetRenderStyle(1, STYLE_Normal); - BNG4 A 2 Bright A_Explode(192, 192, alert:true); - 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, double 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/weaponflamer.txt b/wadsrc/static/zscript/strife/weaponflamer.txt new file mode 100644 index 0000000000..9a47bc2422 --- /dev/null +++ b/wadsrc/static/zscript/strife/weaponflamer.txt @@ -0,0 +1,118 @@ +// 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"; + } + + 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; + } + + //============================================================================ + // + // A_FireFlamer + // + //============================================================================ + + action void A_FireFlamer () + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + + player.mo.PlayAttacking2 (); + + Angle += Random2[Flamethrower]() * (5.625/256.); + Actor mo = SpawnPlayerMissile ("FlameMissile"); + if (mo != NULL) + { + mo.Vel.Z += 5; + } + } +} + + +// 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"; + } + + 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; + } + + //============================================================================ + // + // A_FlameDie + // + //============================================================================ + + void A_FlameDie () + { + bNoGravity = true; + Vel.Z = random[FlameDie]() & 3; + } +} + diff --git a/wadsrc/static/zscript/strife/weapongrenade.txt b/wadsrc/static/zscript/strife/weapongrenade.txt new file mode 100644 index 0000000000..7a775c57ba --- /dev/null +++ b/wadsrc/static/zscript/strife/weapongrenade.txt @@ -0,0 +1,315 @@ +// 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"; + } + + 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; + } + + //============================================================================ + // + // A_FireGrenade + // + //============================================================================ + + action void A_FireGrenade (class grenadetype, double angleofs, statelabel flash) + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + + player.SetPsprite (PSP_FLASH, weapon.FindState(flash), true); + } + + if (grenadetype != null) + { + AddZ(32); + Actor grenade = SpawnSubMissile (grenadetype, self); + AddZ(-32); + if (grenade == null) + return; + + if (grenade.SeeSound != 0) + { + grenade.A_PlaySound (grenade.SeeSound, CHAN_VOICE); + } + + grenade.Vel.Z = (-clamp(tan(Pitch), -5, 5)) * grenade.Speed + 8; + + Vector2 offset = AngleToVector(angle, radius + grenade.radius); + double an = Angle + angleofs; + offset += AngleToVector(an, 15); + grenade.SetOrigin(grenade.Vec3Offset(offset.X, offset.Y, 0.), false); + } + } +} + +// 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; + } +} + +// 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_SetRenderStyle(1, STYLE_Normal); + BNG4 A 2 Bright A_Explode(192, 192, alert:true); + 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 +{ + Default + { + Reactiontime 120; + DamageType "Fire"; + +NOBLOCKMAP + +FLOORCLIP + +NOTELEPORT + +NODAMAGETHRUST + +DONTSPLASH + RenderStyle "Add"; + Obituary "$OB_MPPHOSPHOROUSGRENADE"; + } + + 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; + } + + int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if (target.bNoBlood) + { + return damage / 2; + } + return Super.DoSpecialDamage (target, damage, damagetype); + } + + // This function is mostly redundant and only kept in case some mod references it. + void A_Burnarea () + { + A_Explode(128, 128); + } + + void A_Burnination () + { + Vel.Z -= 8; + Vel.X += (random2[PHBurn] (3)); + Vel.Y += (random2[PHBurn] (3)); + A_PlaySound ("world/largefire", CHAN_VOICE); + + // Only the main fire spawns more. + if (!bDropped) + { + // Original x and y offsets seemed to be like this: + // x + (((pr_phburn() + 12) & 31) << F.RACBITS); + // + // But that creates a lop-sided burn because it won't use negative offsets. + int xofs, xrand = random[PHBurn](); + int yofs, yrand = random[PHBurn](); + + // Adding 12 is pointless if you're going to mask it afterward. + xofs = xrand & 31; + if (xrand & 128) + { + xofs = -xofs; + } + + yofs = yrand & 31; + if (yrand & 128) + { + yofs = -yofs; + } + + Vector2 newpos = Vec2Offset(xofs, yofs); + + Sector sec = Sector.PointInSector(newpos); + // Consider portals and 3D floors instead of just using the current sector's z. + double floorh = sec.NextLowestFloorAt(newpos.x, newpos.y, pos.z+4, 0, MaxStepHeight); + + // The sector's floor is too high so spawn the flame elsewhere. + if (floorh + MaxStepHeight) + { + newpos = Pos.xy; + } + + Actor drop = Spawn("PhosphorousFire", (newpos, pos.z + 4.), ALLOW_REPLACE); + if (drop != NULL) + { + drop.Vel.X = Vel.X + random2[PHBurn] (7); + drop.Vel.Y = Vel.Y + random2[PHBurn] (7); + drop.Vel.Z = Vel.Z - 1; + drop.reactiontime = (random[PHBurn]() & 3) + 2; + drop.bDropped = true; + } + } + } + + +} + From e01f680b72393f0332f8a1e7a7b224cfd6a9ea2d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 14:32:49 +0100 Subject: [PATCH 410/471] - scriptified the Mauler, completing Strife. --- src/CMakeLists.txt | 2 - src/g_strife/a_strifeglobal.h | 7 - src/g_strife/a_strifestuff.cpp | 35 --- src/g_strife/a_strifeweapons.cpp | 165 ---------- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/strife/strifestuff.txt | 9 + .../static/zscript/strife/strifeweapons.txt | 174 ----------- wadsrc/static/zscript/strife/weaponmauler.txt | 286 ++++++++++++++++++ 8 files changed, 296 insertions(+), 383 deletions(-) delete mode 100644 src/g_strife/a_strifeglobal.h delete mode 100644 src/g_strife/a_strifestuff.cpp delete mode 100644 src/g_strife/a_strifeweapons.cpp create mode 100644 wadsrc/static/zscript/strife/weaponmauler.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 923d545e08..2d04747948 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_strifeweapons.cpp g_shared/sbarinfo_commands.cpp xlat/xlat_parser.y xlat_parser.c @@ -1111,7 +1110,6 @@ set (PCH_SOURCES wi_stuff.cpp zstrformat.cpp g_hexen/a_hexenmisc.cpp - g_strife/a_strifestuff.cpp g_strife/strife_sbar.cpp g_shared/a_action.cpp g_shared/a_armor.cpp diff --git a/src/g_strife/a_strifeglobal.h b/src/g_strife/a_strifeglobal.h deleted file mode 100644 index 9206dd08cc..0000000000 --- a/src/g_strife/a_strifeglobal.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __A_STRIFEGLOBAL_H__ -#define __A_STRIFEGLOBAL_H__ - -#include "info.h" -#include "a_pickups.h" - -#endif diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp deleted file mode 100644 index e93c13600d..0000000000 --- a/src/g_strife/a_strifestuff.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "actor.h" -#include "g_level.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "p_lnspec.h" -#include "c_console.h" -#include "vm.h" -#include "doomstat.h" -#include "gstrings.h" -#include "a_keys.h" -#include "a_sharedglobal.h" -#include "templates.h" -#include "d_event.h" -#include "v_font.h" -#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_strifeweapons.cpp" - -// Notes so I don't forget them: -// -// When shooting missiles at something, if MF_SHADOW is set, the angle is adjusted with the formula: -// angle += pr_spawnmissile.Random2() << 21 -// When MF_STRIFEx4000000 is set, the angle is adjusted similarly: -// angle += pr_spawnmissile.Random2() << 22 -// Note that these numbers are different from those used by all the other Doom engine games. - diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp deleted file mode 100644 index bcedd14298..0000000000 --- a/src/g_strife/a_strifeweapons.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* -#include "a_pickups.h" -#include "p_local.h" -#include "m_random.h" -#include "a_strifeglobal.h" -#include "s_sound.h" -#include "p_enemy.h" -#include "templates.h" -#include "vm.h" -#include "doomstat.h" -*/ - -// Note: Strife missiles do 1-4 times their damage amount. -// Doom missiles do 1-8 times their damage amount, so to -// make the strife missiles do proper damage without -// hacking more stuff in the executable, be sure to give -// all Strife missiles the MF4_STRIFEDAMAGE flag. - -static FRandom pr_electric ("FireElectric"); -static FRandom pr_sgunshot ("StrifeGunShot"); -static FRandom pr_minimissile ("MiniMissile"); -static FRandom pr_flamethrower ("FlameThrower"); -static FRandom pr_flamedie ("FlameDie"); -static FRandom pr_mauler1 ("Mauler1"); -static FRandom pr_mauler2 ("Mauler2"); -static FRandom pr_phburn ("PhBurn"); - -void A_LoopActiveSound (AActor *); -void A_Countdown (AActor *); - -// Assault Gun -------------------------------------------------------------- - -// Mini-Missile Launcher ---------------------------------------------------- - -// Flame Thrower ------------------------------------------------------------ - -// Mauler ------------------------------------------------------------------- - -//============================================================================ -// -// A_FireMauler1 -// -// Hey! This is exactly the same as a super shotgun except for the sound -// and the bullet puffs and the disintegration death. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireMauler1) -{ - PARAM_ACTION_PROLOGUE(AActor); - - if (self->player != NULL) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - // Strife apparently didn't show the player shooting. Let's fix that. - self->player->mo->PlayAttacking2 (); - } - - S_Sound (self, CHAN_WEAPON, "weapons/mauler1", 1, ATTN_NORM); - - - DAngle bpitch = P_BulletSlope (self); - - for (int i = 0; i < 20; ++i) - { - int damage = 5 * (pr_mauler1() % 3 + 1); - DAngle angle = self->Angles.Yaw + pr_mauler1.Random2() * (11.25 / 256); - DAngle pitch = bpitch + pr_mauler1.Random2() * (7.097 / 256); - - // Strife used a range of 2112 units for the mauler to signal that - // it should use a different puff. ZDoom's default range is longer - // than this, so let's not handicap it by being too faithful to the - // original. - P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, NAME_MaulerPuff); - } - return 0; -} - -//============================================================================ -// -// A_FireMauler2Pre -// -// Makes some noise and moves the psprite. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2Pre) -{ - PARAM_ACTION_PROLOGUE(AActor); - - S_Sound (self, CHAN_WEAPON, "weapons/mauler2charge", 1, ATTN_NORM); - - if (self->player != nullptr) - { - self->player->GetPSprite(PSP_WEAPON)->x += pr_mauler2.Random2() / 64.; - self->player->GetPSprite(PSP_WEAPON)->y += pr_mauler2.Random2() / 64.; - } - return 0; -} - -//============================================================================ -// -// A_FireMauler2Pre -// -// Fires the torpedo. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2) -{ - PARAM_ACTION_PROLOGUE(AActor); - - if (self->player != NULL) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - self->player->mo->PlayAttacking2 (); - } - P_SpawnPlayerMissile (self, PClass::FindActor("MaulerTorpedo")); - P_DamageMobj (self, self, NULL, 20, self->DamageType); - self->Thrust(self->Angles.Yaw+180., 7.8125); - return 0; -} - -//============================================================================ -// -// A_MaulerTorpedoWave -// -// Launches lots of balls when the torpedo hits something. -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MaulerTorpedoWave) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *wavedef = GetDefaultByName("MaulerTorpedoWave"); - double savedz; - self->Angles.Yaw += 180.; - - // If the torpedo hit the ceiling, it should still spawn the wave - savedz = self->Z(); - if (wavedef && self->ceilingz < self->Z() + wavedef->Height) - { - self->SetZ(self->ceilingz - wavedef->Height); - } - - for (int i = 0; i < 80; ++i) - { - self->Angles.Yaw += 4.5; - P_SpawnSubMissile (self, PClass::FindActor("MaulerTorpedoWave"), self->target); - } - self->SetZ(savedz); - return 0; -} - diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index cbba151f5c..82810185a3 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -195,6 +195,7 @@ zscript/strife/weaponassault.txt zscript/strife/weaponmissile.txt zscript/strife/weaponflamer.txt zscript/strife/weapongrenade.txt +zscript/strife/weaponmauler.txt zscript/strife/sigil.txt zscript/chex/chexmonsters.txt diff --git a/wadsrc/static/zscript/strife/strifestuff.txt b/wadsrc/static/zscript/strife/strifestuff.txt index 12502ad0da..20bee61d01 100644 --- a/wadsrc/static/zscript/strife/strifestuff.txt +++ b/wadsrc/static/zscript/strife/strifestuff.txt @@ -1,3 +1,12 @@ +// Notes so I don't forget them: +// +// When shooting missiles at something, if MF_SHADOW is set, the angle is adjusted with the formula: +// angle += pr_spawnmissile.Random2() << 21 +// When MF_STRIFEx4000000 is set, the angle is adjusted similarly: +// angle += pr_spawnmissile.Random2() << 22 +// Note that these numbers are different from those used by all the other Doom engine games. + + // Tank 1 Huge ------------------------------------------------------------ class Tank1 : Actor diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index 9e2f2c84f1..5cb01342e1 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -50,177 +50,3 @@ class StrifeSpark : StrifePuff } } -// 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; - } -} - - diff --git a/wadsrc/static/zscript/strife/weaponmauler.txt b/wadsrc/static/zscript/strife/weaponmauler.txt new file mode 100644 index 0000000000..80f3afcdec --- /dev/null +++ b/wadsrc/static/zscript/strife/weaponmauler.txt @@ -0,0 +1,286 @@ +// 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"; + } + + 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; + } + + //============================================================================ + // + // A_FireMauler1 + // + // Hey! This is exactly the same as a super shotgun except for the sound + // and the bullet puffs and the disintegration death. + // + //============================================================================ + + action void A_FireMauler1() + { + if (player == null) + { + return; + } + + A_PlaySound ("weapons/mauler1", CHAN_WEAPON); + Weapon weap = player.ReadyWeapon; + if (weap != null) + { + if (!weap.DepleteAmmo (weap.bAltFire, true, 2)) + return; + + } + player.mo.PlayAttacking2 (); + + double pitch = BulletSlope (); + + for (int i = 0 ; i < 20 ; i++) + { + int damage = 5 * random[Mauler1](1, 3); + double ang = angle + Random2[Mauler1]() * (11.25 / 256); + + // Strife used a range of 2112 units for the mauler to signal that + // it should use a different puff. ZDoom's default range is longer + // than this, so let's not handicap it by being too faithful to the + // original. + + LineAttack (ang, PLAYERMISSILERANGE, pitch + Random2[Mauler1]() * (7.097 / 256), damage, 'Hitscan', "MaulerPuff"); + } + } +} + + +// 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"; + } + + 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; + } + + //============================================================================ + // + // A_FireMauler2Pre + // + // Makes some noise and moves the psprite. + // + //============================================================================ + + action void A_FireMauler2Pre () + { + A_PlaySound ("weapons/mauler2charge", CHAN_WEAPON); + + if (player != null) + { + PSprite psp = player.GetPSprite(PSP_WEAPON); + psp.x += Random2[Mauler2]() / 64.; + psp.y += Random2[Mauler2]() / 64.; + } + } + + //============================================================================ + // + // A_FireMauler2Pre + // + // Fires the torpedo. + // + //============================================================================ + + action void A_FireMauler2 () + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + player.mo.PlayAttacking2 (); + + SpawnPlayerMissile ("MaulerTorpedo"); + DamageMobj (self, null, 20, 'Disintegrate'); + Thrust(7.8125, Angle+180.); + } +} + + +// 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"; + } + + States + { + Spawn: + TORP ABCD 4 Bright; + Loop; + Death: + THIT AB 8 Bright; + THIT C 8 Bright A_MaulerTorpedoWave; + THIT DE 8 Bright; + Stop; + } + + //============================================================================ + // + // A_MaulerTorpedoWave + // + // Launches lots of balls when the torpedo hits something. + // + //============================================================================ + + action void A_MaulerTorpedoWave() + { + readonly wavedef = GetDefaultByType("MaulerTorpedoWave"); + double savedz = pos.z; + angle += 180.; + + // If the torpedo hit the ceiling, it should still spawn the wave + if (wavedef && ceilingz < pos.z + wavedef.Height) + { + SetZ(ceilingz - wavedef.Height); + } + + for (int i = 0; i < 80; ++i) + { + Angle += 4.5; + SpawnSubMissile ("MaulerTorpedoWave", target); + } + SetZ(savedz); + } +} + + +// 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; + } + +} + + From f5b3429274b4ad232408bd32799ffb98be1a0d3a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 15:24:38 +0100 Subject: [PATCH 411/471] - partial scriptification of the Heresiarch --- src/g_hexen/a_heresiarch.cpp | 386 +------------------- wadsrc/static/zscript/doom/bossbrain.txt | 4 +- wadsrc/static/zscript/hexen/heresiarch.txt | 387 ++++++++++++++++++++- 3 files changed, 372 insertions(+), 405 deletions(-) diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index a53d9926de..38d9160943 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -11,23 +11,6 @@ #include "g_level.h" */ -//============================================================================ -// -// Sorcerer stuff -// -// Sorcerer Variables -// specialf1 Angle of ball 1 (all others relative to that) -// StopBall which ball to stop at in stop mode (MT_???) -// args[0] Defense time -// args[1] Number of full rotations since stopping mode -// args[2] Target orbit speed for acceleration/deceleration -// args[3] Movement mode (see SORC_ macros) -// args[4] Current ball orbit speed -// Sorcerer Ball Variables -// specialf1 Previous angle of ball (for woosh) -// special2 Countdown of rapid fire (FX4) -//============================================================================ - #define SORCBALL_INITIAL_SPEED 7 #define SORCBALL_TERMINAL_SPEED 25 #define SORCBALL_SPEED_ROTATIONS 5 @@ -209,42 +192,7 @@ void ASorcBall1::DoFireSpell () } } -//============================================================================ -// -// A_SorcSpinBalls -// -// Spawn spinning balls above head - actor is sorcerer -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SorcSpinBalls) -{ - PARAM_SELF_PROLOGUE(AHeresiarch); - - AActor *mo; - - self->SpawnState += 2; // [RH] Don't spawn balls again - A_SlowBalls(self); - self->args[0] = 0; // Currently no defense - self->args[3] = SORC_NORMAL; - self->args[4] = SORCBALL_INITIAL_SPEED; // Initial orbit speed - self->BallAngle = 1.; - - DVector3 pos = self->PosPlusZ(-self->Floorclip + self->Height); - - mo = Spawn("SorcBall1", pos, NO_REPLACE); - if (mo) - { - mo->target = self; - mo->special2 = SORCFX4_RAPIDFIRE_TIME; - } - mo = Spawn("SorcBall2", pos, NO_REPLACE); - if (mo) mo->target = self; - mo = Spawn("SorcBall3", pos, NO_REPLACE); - if (mo) mo->target = self; - return 0; -} - - +DEFINE_FIELD(AHeresiarch, BallAngle); //============================================================================ // // A_SorcBallOrbit @@ -370,38 +318,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcBallOrbit) return 0; } -//============================================================================ -// -// A_SpeedBalls -// -// Set balls to speed mode - self is sorcerer -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SpeedBalls) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->args[3] = SORC_ACCELERATE; // speed mode - self->args[2] = SORCBALL_TERMINAL_SPEED; // target speed - return 0; -} - - -//============================================================================ -// -// A_SlowBalls -// -// Set balls to slow mode - actor is sorcerer -// -//============================================================================ - -void A_SlowBalls(AActor *self) -{ - self->args[3] = SORC_DECELERATE; // slow mode - self->args[2] = SORCBALL_INITIAL_SPEED; // target speed -} - //============================================================================ // // A_StopBalls @@ -666,303 +582,3 @@ void A_SorcOffense2(AActor *self) } } -//============================================================================ -// -// A_SorcBossAttack -// -// Resume ball spinning -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SorcBossAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->args[3] = SORC_ACCELERATE; - self->args[2] = SORCBALL_INITIAL_SPEED; - return 0; -} - -//============================================================================ -// -// A_SpawnFizzle -// -// spell cast magic fizzle -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SpawnFizzle) -{ - PARAM_SELF_PROLOGUE(AActor); - int speed = (int)self->Speed; - DAngle rangle; - AActor *mo; - int ix; - - DVector3 pos = self->Vec3Angle(5., self->Angles.Yaw, -self->Floorclip + self->Height / 2. ); - for (ix=0; ix<5; ix++) - { - mo = Spawn("SorcSpark1", pos, ALLOW_REPLACE); - if (mo) - { - rangle = self->Angles.Yaw + (pr_heresiarch() % 5) * (4096 / 360.); - mo->Vel.X = (pr_heresiarch() % speed) * rangle.Cos(); - mo->Vel.Y = (pr_heresiarch() % speed) * rangle.Sin(); - mo->Vel.Z = 2; - } - } - return 0; -} - - -//============================================================================ -// -// A_SorcFX1Seek -// -// Yellow spell - offense -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SorcFX1Seek) -{ - PARAM_SELF_PROLOGUE(AActor); - - A_DoBounceCheck (self, "SorcererHeadScream"); - P_SeekerMissile(self, 2, 6); - return 0; -} - - -//============================================================================ -// -// A_SorcFX2Split -// -// Blue spell - defense -// -//============================================================================ -// -// FX2 Variables -// specialf1 current angle -// special2 -// args[0] 0 = CW, 1 = CCW -// args[1] -//============================================================================ - -// Split ball in two -DEFINE_ACTION_FUNCTION(AActor, A_SorcFX2Split) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - mo = Spawn(self->GetClass(), self->Pos(), NO_REPLACE); - if (mo) - { - mo->target = self->target; - mo->args[0] = 0; // CW - mo->specialf1 = self->Angles.Yaw.Degrees; // Set angle - mo->SetState (mo->FindState("Orbit")); - } - mo = Spawn(self->GetClass(), self->Pos(), NO_REPLACE); - if (mo) - { - mo->target = self->target; - mo->args[0] = 1; // CCW - mo->specialf1 = self->Angles.Yaw.Degrees; // Set angle - mo->SetState (mo->FindState("Orbit")); - } - self->Destroy (); - return 0; -} - -//============================================================================ -// -// A_SorcFX2Orbit -// -// Orbit FX2 about sorcerer -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SorcFX2Orbit) -{ - PARAM_SELF_PROLOGUE(AActor); - - DAngle angle; - DVector3 pos; - AActor *parent = self->target; - - // [RH] If no parent, then disappear - if (parent == NULL) - { - self->Destroy(); - return 0; - } - - double dist = parent->radius; - - if ((parent->health <= 0) || // Sorcerer is dead - (!parent->args[0])) // Time expired - { - self->SetState (self->FindState(NAME_Death)); - parent->args[0] = 0; - parent->flags2 &= ~MF2_REFLECTIVE; - parent->flags2 &= ~MF2_INVULNERABLE; - } - - if (self->args[0] && (parent->args[0]-- <= 0)) // Time expired - { - self->SetState (self->FindState(NAME_Death)); - parent->args[0] = 0; - parent->flags2 &= ~MF2_REFLECTIVE; - } - - // Move to new position based on angle - if (self->args[0]) // Counter clock-wise - { - self->specialf1 += 10; - angle = self->specialf1; - pos = parent->Vec3Angle(dist, angle, parent->Floorclip + SORC_DEFENSE_HEIGHT); - pos.Z += 15 * angle.Cos(); - // Spawn trailer - Spawn("SorcFX2T1", pos, ALLOW_REPLACE); - } - else // Clock wise - { - self->specialf1 -= 10; - angle = self->specialf1; - pos = parent->Vec3Angle(dist, angle, parent->Floorclip + SORC_DEFENSE_HEIGHT); - pos.Z += 20 * angle.Sin(); - // Spawn trailer - Spawn("SorcFX2T1", pos, ALLOW_REPLACE); - } - - self->SetOrigin (pos, true); - self->floorz = parent->floorz; - self->ceilingz = parent->ceilingz; - return 0; -} - -//============================================================================ -// -// A_SpawnBishop -// -// Green spell - spawn bishops -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SpawnBishop) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - mo = Spawn("Bishop", self->Pos(), ALLOW_REPLACE); - if (mo) - { - if (!P_TestMobjLocation(mo)) - { - mo->ClearCounters(); - mo->Destroy (); - } - else if (self->target != NULL) - { // [RH] Make the new bishops inherit the Heriarch's target - mo->CopyFriendliness (self->target, true); - mo->master = self->target; - } - } - self->Destroy (); - return 0; -} - -//============================================================================ -// -// A_SorcererBishopEntry -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SorcererBishopEntry) -{ - PARAM_SELF_PROLOGUE(AActor); - - Spawn("SorcFX3Explosion", self->Pos(), ALLOW_REPLACE); - S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_SorcFX4Check -// -// FX4 - rapid fire balls -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SorcFX4Check) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->special2-- <= 0) - { - self->SetState (self->FindState(NAME_Death)); - } - return 0; -} - -//============================================================================ -// -// A_SorcBallPop -// -// Ball death - bounce away in a random direction -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SorcBallPop) -{ - PARAM_SELF_PROLOGUE(AActor); - - S_Sound (self, CHAN_BODY, "SorcererBallPop", 1, ATTN_NONE); - self->flags &= ~MF_NOGRAVITY; - self->Gravity = 1. / 8;; - - self->Vel.X = ((pr_heresiarch()%10)-5); - self->Vel.Y = ((pr_heresiarch()%10)-5); - self->Vel.Z = (2+(pr_heresiarch()%3)); - self->args[4] = BOUNCE_TIME_UNIT; // Bounce time unit - self->args[3] = 5; // Bounce time in seconds - return 0; -} - -//============================================================================ -// -// A_DoBounceCheck -// -//============================================================================ - -void A_DoBounceCheck (AActor *self, const char *sound) -{ - if (self->args[4]-- <= 0) - { - if (self->args[3]-- <= 0) - { - self->SetState (self->FindState(NAME_Death)); - S_Sound (self, CHAN_BODY, sound, 1, ATTN_NONE); - } - else - { - self->args[4] = BOUNCE_TIME_UNIT; - } - } -} - -//============================================================================ -// -// A_BounceCheck -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_BounceCheck) -{ - PARAM_SELF_PROLOGUE(AActor); - - A_DoBounceCheck (self, "SorcererBigBallExplode"); - return 0; -} diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index e6a13317f0..2a3f392657 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -262,12 +262,12 @@ extend class Actor if (!isdefault) { - A_PlaySound(self.AttackSound, CHAN_WEAPON); + A_PlaySound(self.AttackSound, CHAN_WEAPON, 1., false, ATTN_NONE); } else { // compatibility fallback - A_PlaySound("brain/spit", CHAN_WEAPON); + A_PlaySound("brain/spit", CHAN_WEAPON, 1., false, ATTN_NONE); } } } diff --git a/wadsrc/static/zscript/hexen/heresiarch.txt b/wadsrc/static/zscript/hexen/heresiarch.txt index 7d3ba63a51..cf0b16372b 100644 --- a/wadsrc/static/zscript/hexen/heresiarch.txt +++ b/wadsrc/static/zscript/hexen/heresiarch.txt @@ -1,8 +1,52 @@ // The Heresiarch him/itself ------------------------------------------------ +//============================================================================ +// +// Sorcerer stuff +// +// Sorcerer Variables +// specialf1 Angle of ball 1 (all others relative to that) +// StopBall which ball to stop at in stop mode (MT_???) +// args[0] Defense time +// args[1] Number of full rotations since stopping mode +// args[2] Target orbit speed for acceleration/deceleration +// args[3] Movement mode (see SORC_ macros) +// args[4] Current ball orbit speed +// Sorcerer Ball Variables +// specialf1 Previous angle of ball (for woosh) +// special2 Countdown of rapid fire (FX4) +//============================================================================ + class Heresiarch native { + + const SORCBALL_INITIAL_SPEED = 7; + const SORCBALL_TERMINAL_SPEED = 25; + const SORCBALL_SPEED_ROTATIONS = 5; + const SORC_DEFENSE_TIME = 255; + const SORC_DEFENSE_HEIGHT = 45; + const BOUNCE_TIME_UNIT = (35/2); + const SORCFX4_RAPIDFIRE_TIME = (6*3); // 3 seconds + const SORCFX4_SPREAD_ANGLE = 20; + + enum ESorc + { + SORC_DECELERATE, + SORC_ACCELERATE, + SORC_STOPPING, + SORC_FIRESPELL, + SORC_STOPPED, + SORC_NORMAL, + SORC_FIRING_SPELL + } + + const BALL1_ANGLEOFFSET = 0.; + const BALL2_ANGLEOFFSET = 120.; + const BALL3_ANGLEOFFSET = 240.; + + native double BallAngle; + Default { Health 5000; @@ -27,11 +71,6 @@ class Heresiarch native Obituary "$OB_HERESIARCH"; } - native void A_SorcSpinBalls(); - native void A_SpeedBalls(); - native void A_SorcBossAttack(); - native void A_SpawnFizzle(); - States { Spawn: @@ -71,6 +110,105 @@ class Heresiarch native SORC Z -1 Bright; Stop; } + + //============================================================================ + // + // A_SorcSpinBalls + // + // Spawn spinning balls above head - actor is sorcerer + //============================================================================ + + void A_SorcSpinBalls() + { + A_SlowBalls(); + args[0] = 0; // Currently no defense + args[3] = SORC_NORMAL; + args[4] = SORCBALL_INITIAL_SPEED; // Initial orbit speed + BallAngle = 1.; + + Vector3 ballpos = (pos.xy, -Floorclip + Height); + + Actor mo = Spawn("SorcBall1", pos, NO_REPLACE); + if (mo) + { + mo.target = self; + mo.special2 = SORCFX4_RAPIDFIRE_TIME; + } + mo = Spawn("SorcBall2", pos, NO_REPLACE); + if (mo) mo.target = self; + mo = Spawn("SorcBall3", pos, NO_REPLACE); + if (mo) mo.target = self; + } + + + //============================================================================ + // + // A_SpeedBalls + // + // Set balls to speed mode - self is sorcerer + // + //============================================================================ + + void A_SpeedBalls() + { + args[3] = SORC_ACCELERATE; // speed mode + args[2] = SORCBALL_TERMINAL_SPEED; // target speed + } + + + //============================================================================ + // + // A_SlowBalls + // + // Set balls to slow mode - actor is sorcerer + // + //============================================================================ + + void A_SlowBalls() + { + args[3] = SORC_DECELERATE; // slow mode + args[2] = SORCBALL_INITIAL_SPEED; // target speed + } + + //============================================================================ + // + // A_SorcBossAttack + // + // Resume ball spinning + // + //============================================================================ + + void A_SorcBossAttack() + { + args[3] = SORC_ACCELERATE; + args[2] = SORCBALL_INITIAL_SPEED; + } + + //============================================================================ + // + // A_SpawnFizzle + // + // spell cast magic fizzle + // + //============================================================================ + + void A_SpawnFizzle() + { + Vector3 pos = Vec3Angle(5., Angle, -Floorclip + Height / 2. ); + for (int ix=0; ix<5; ix++) + { + Actor mo = Spawn("SorcSpark1", pos, ALLOW_REPLACE); + if (mo) + { + double rangle = Angle + (random[Heresiarch]() % 5) * (4096 / 360.); + mo.Vel.X = (random[Heresiarch]() % speed) * cos(rangle); + mo.Vel.Y = (random[Heresiarch]() % speed) * sin(rangle); + mo.Vel.Z = 2; + } + } + } + + } // Base class for the balls flying around the Heresiarch's head ------------- @@ -94,14 +232,56 @@ class SorcBall native } native void A_SorcBallOrbit(); - native void A_SorcBallPop(); - native void A_BounceCheck (); void A_SorcBallExplode() { - bNOBOUNCESOUND = true; + bNoBounceSound = true; A_Explode(255, 255); } + + //============================================================================ + // + // A_SorcBallPop + // + // Ball death - bounce away in a random direction + // + //============================================================================ + + void A_SorcBallPop() + { + A_PlaySound ("SorcererBallPop", CHAN_BODY, 1, false, ATTN_NONE); + bNoGravity = false; + Gravity = 1. / 8; + + Vel.X = ((random[Heresiarch]()%10)-5); + Vel.Y = ((random[Heresiarch]()%10)-5); + Vel.Z = (2+(random[Heresiarch]()%3)); + args[4] = Heresiarch.BOUNCE_TIME_UNIT; // Bounce time unit + args[3] = 5; // Bounce time in seconds + } + + //============================================================================ + // + // A_BounceCheck + // + //============================================================================ + + void A_BounceCheck () + { + if (args[4]-- <= 0) + { + if (args[3]-- <= 0) + { + SetStateLabel("Death"); + A_PlaySound ("SorcererBigBallExplode", CHAN_BODY, 1, false, ATTN_NONE); + } + else + { + args[4] = Heresiarch.BOUNCE_TIME_UNIT; + } + } + } + } // First ball (purple) - fires projectiles ---------------------------------- @@ -191,8 +371,6 @@ class SorcFX1 : Actor DeathSound "SorcererHeadScream"; } - native void A_SorcFX1Seek(); - States { Spawn: @@ -204,6 +382,32 @@ class SorcFX1 : Actor FHFX SS 6 Bright; Stop; } + + //============================================================================ + // + // A_SorcFX1Seek + // + // Yellow spell - offense + // + //============================================================================ + + void A_SorcFX1Seek() + { + if (args[4]-- <= 0) + { + if (args[3]-- <= 0) + { + SetStateLabel("Death"); + A_PlaySound ("SorcererHeadScream", CHAN_BODY, 1, false, ATTN_NONE); + } + else + { + args[4] = Heresiarch.BOUNCE_TIME_UNIT; + } + } + A_SeekerMissile(2, 6); + } + } @@ -221,9 +425,6 @@ class SorcFX2 : Actor +NOTELEPORT } - native void A_SorcFX2Split(); - native void A_SorcFX2Orbit (); - states { Spawn: @@ -237,6 +438,106 @@ class SorcFX2 : Actor SBS2 A 10; Stop; } + + //============================================================================ + // + // A_SorcFX2Split + // + // Blue spell - defense + // + //============================================================================ + // + // FX2 Variables + // specialf1 current angle + // special2 + // args[0] 0 = CW, 1 = CCW + // args[1] + //============================================================================ + + // Split ball in two + void A_SorcFX2Split() + { + Actor mo = Spawn(GetClass(), Pos, NO_REPLACE); + if (mo) + { + mo.target = target; + mo.args[0] = 0; // CW + mo.specialf1 = Angle; // Set angle + mo.SetStateLabel("Orbit"); + } + mo = Spawn(GetClass(), Pos, NO_REPLACE); + if (mo) + { + mo.target = target; + mo.args[0] = 1; // CCW + mo.specialf1 = Angle; // Set angle + mo.SetStateLabel("Orbit"); + } + Destroy (); + } + + //============================================================================ + // + // A_SorcFX2Orbit + // + // Orbit FX2 about sorcerer + // + //============================================================================ + + void A_SorcFX2Orbit () + { + Actor parent = target; + + // [RH] If no parent, then disappear + if (parent == NULL) + { + Destroy(); + return; + } + + double dist = parent.radius; + + if ((parent.health <= 0) || // Sorcerer is dead + (!parent.args[0])) // Time expired + { + SetStateLabel("Death"); + parent.args[0] = 0; + parent.bReflective = false; + parent.bInvulnerable = false; + } + + if (args[0] && (parent.args[0]-- <= 0)) // Time expired + { + SetStateLabel("Death"); + parent.args[0] = 0; + parent.bReflective = false; + } + + Vector3 posi; + // Move to new position based on angle + if (args[0]) // Counter clock-wise + { + specialf1 += 10; + angle = specialf1; + posi = parent.Vec3Angle(dist, angle, parent.Floorclip + Heresiarch.SORC_DEFENSE_HEIGHT); + posi.Z += 15 * cos(angle); + // Spawn trailer + Spawn("SorcFX2T1", pos, ALLOW_REPLACE); + } + else // Clock wise + { + specialf1 -= 10; + angle = specialf1; + posi = parent.Vec3Angle(dist, angle, parent.Floorclip + Heresiarch.SORC_DEFENSE_HEIGHT); + posi.Z += 20 * sin(angle); + // Spawn trailer + Spawn("SorcFX2T1", pos, ALLOW_REPLACE); + } + + SetOrigin (posi, true); + floorz = parent.floorz; + ceilingz = parent.ceilingz; + } } // The translucent trail behind SorcFX2 ------------------------------------- @@ -271,9 +572,6 @@ class SorcFX3 : Actor SeeSound "SorcererBishopSpawn"; } - native void A_SpawnBishop(); - native void A_SorcererBishopEntry(); - States { Spawn: @@ -287,6 +585,45 @@ class SorcFX3 : Actor BISH G 3 A_SpawnBishop; Stop; } + + //============================================================================ + // + // A_SorcererBishopEntry + // + //============================================================================ + + void A_SorcererBishopEntry() + { + Spawn("SorcFX3Explosion", Pos, ALLOW_REPLACE); + A_PlaySound (SeeSound, CHAN_VOICE); + } + + //============================================================================ + // + // A_SpawnBishop + // + // Green spell - spawn bishops + // + //============================================================================ + + void A_SpawnBishop() + { + Actor mo = Spawn("Bishop", Pos, ALLOW_REPLACE); + if (mo) + { + if (!mo.TestMobjLocation()) + { + mo.ClearCounters(); + mo.Destroy (); + } + else if (target != NULL) + { // [RH] Make the new bishops inherit the Heriarch's target + mo.CopyFriendliness (target, true); + mo.master = target; + } + } + Destroy (); + } } @@ -326,8 +663,6 @@ class SorcFX4 : Actor DeathSound "SorcererBallExplode"; } - native void A_SorcFX4Check(); - States { Spawn: @@ -339,6 +674,22 @@ class SorcFX4 : Actor SBS4 FGH 2 Bright; Stop; } + + //============================================================================ + // + // A_SorcFX4Check + // + // FX4 - rapid fire balls + // + //============================================================================ + + void A_SorcFX4Check() + { + if (special2-- <= 0) + { + SetStateLabel ("Death"); + } + } } From f17f6c30c2faa4eb464ea407332f38e189780094 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 17:17:10 +0100 Subject: [PATCH 412/471] - scriptified the Heresiarch. --- src/CMakeLists.txt | 1 - src/g_hexen/a_heresiarch.cpp | 584 --------------------- src/g_hexen/a_hexenmisc.cpp | 1 - src/scripting/thingdef_data.cpp | 10 +- src/scripting/zscript/zcc_compile.cpp | 19 + wadsrc/static/zscript/base.txt | 1 + wadsrc/static/zscript/hexen/heresiarch.txt | 441 +++++++++++++++- 7 files changed, 461 insertions(+), 596 deletions(-) delete mode 100644 src/g_hexen/a_heresiarch.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d04747948..c7228edd89 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -859,7 +859,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp g_shared/sbarinfo_commands.cpp xlat/xlat_parser.y diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp deleted file mode 100644 index 38d9160943..0000000000 --- a/src/g_hexen/a_heresiarch.cpp +++ /dev/null @@ -1,584 +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 "i_system.h" -#include "vm.h" -#include "g_level.h" -*/ - -#define SORCBALL_INITIAL_SPEED 7 -#define SORCBALL_TERMINAL_SPEED 25 -#define SORCBALL_SPEED_ROTATIONS 5 -#define SORC_DEFENSE_TIME 255 -#define SORC_DEFENSE_HEIGHT 45 -#define BOUNCE_TIME_UNIT (35/2) -#define SORCFX4_RAPIDFIRE_TIME (6*3) // 3 seconds -#define SORCFX4_SPREAD_ANGLE 20 - -#define SORC_DECELERATE 0 -#define SORC_ACCELERATE 1 -#define SORC_STOPPING 2 -#define SORC_FIRESPELL 3 -#define SORC_STOPPED 4 -#define SORC_NORMAL 5 -#define SORC_FIRING_SPELL 6 - -#define BALL1_ANGLEOFFSET 0. -#define BALL2_ANGLEOFFSET 120. -#define BALL3_ANGLEOFFSET 240. - -void A_SlowBalls (AActor *actor); -void A_StopBalls (AActor *actor); -void A_AccelBalls (AActor *actor); -void A_DecelBalls (AActor *actor); -void A_SorcOffense2 (AActor *actor); -void A_DoBounceCheck (AActor *actor, const char *sound); - -static FRandom pr_heresiarch ("Heresiarch"); - -// The Heresiarch him/itself ------------------------------------------------ - -class AHeresiarch : public AActor -{ - DECLARE_CLASS (AHeresiarch, AActor) -public: - PClassActor *StopBall; - DAngle BallAngle; - - - void Serialize(FSerializer &arc); - void Die (AActor *source, AActor *inflictor, int dmgflags); -}; - -IMPLEMENT_CLASS(AHeresiarch, false, false) - -void AHeresiarch::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - arc("stopball", StopBall) - ("ballangle", BallAngle); -} - -void AHeresiarch::Die (AActor *source, AActor *inflictor, int dmgflags) -{ - // The heresiarch just executes a script instead of a special upon death - int script = special; - special = 0; - - Super::Die (source, inflictor, dmgflags); - - if (script != 0) - { - P_StartScript (this, NULL, script, level.MapName, NULL, 0, 0); - } -} - -// Base class for the balls flying around the Heresiarch's head ------------- - -class ASorcBall : public AActor -{ - DECLARE_CLASS (ASorcBall, AActor) -public: - virtual void DoFireSpell (); - virtual void SorcUpdateBallAngle (); - virtual void CastSorcererSpell (); - DAngle AngleOffset; - DAngle OldAngle; - - - - void Serialize(FSerializer &arc) - { - Super::Serialize (arc); - arc("angleoffset", AngleOffset) - ("oldangle", OldAngle); - } - - bool SpecialBlastHandling (AActor *source, double strength) - { // don't blast sorcerer balls - return false; - } -}; - -IMPLEMENT_CLASS(ASorcBall, false, false) - -// First ball (purple) - fires projectiles ---------------------------------- - -class ASorcBall1 : public ASorcBall -{ - DECLARE_CLASS (ASorcBall1, ASorcBall) -public: - void BeginPlay () - { - Super::BeginPlay (); - AngleOffset = BALL1_ANGLEOFFSET; - } - virtual void DoFireSpell (); - virtual void SorcUpdateBallAngle (); - virtual void CastSorcererSpell (); -}; - -IMPLEMENT_CLASS(ASorcBall1, false, false) - -// Second ball (blue) - generates the shield -------------------------------- - -class ASorcBall2 : public ASorcBall -{ - DECLARE_CLASS (ASorcBall2, ASorcBall) -public: - void BeginPlay () - { - Super::BeginPlay (); - AngleOffset = BALL2_ANGLEOFFSET; - } - virtual void CastSorcererSpell (); -}; - -IMPLEMENT_CLASS(ASorcBall2, false, false) - -// Third ball (green) - summons Bishops ------------------------------------- - -class ASorcBall3 : public ASorcBall -{ - DECLARE_CLASS (ASorcBall3, ASorcBall) -public: - void BeginPlay () - { - Super::BeginPlay (); - AngleOffset = BALL3_ANGLEOFFSET; - } - virtual void CastSorcererSpell (); -}; - -IMPLEMENT_CLASS(ASorcBall3, false, false) - -// Sorcerer spell 1 (The burning, bouncing head thing) ---------------------- - -//============================================================================ -// -// SorcBall::DoFireSpell -// -//============================================================================ - -void ASorcBall::DoFireSpell () -{ - CastSorcererSpell (); - target->args[3] = SORC_STOPPED; -} - -//============================================================================ -// -// SorcBall1::DoFireSpell -// -//============================================================================ - -void ASorcBall1::DoFireSpell () -{ - if (pr_heresiarch() < 200) - { - S_Sound (target, CHAN_VOICE, "SorcererSpellCast", 1, ATTN_NONE); - special2 = SORCFX4_RAPIDFIRE_TIME; - args[4] = 128; - target->args[3] = SORC_FIRING_SPELL; - } - else - { - Super::DoFireSpell (); - } -} - -DEFINE_FIELD(AHeresiarch, BallAngle); -//============================================================================ -// -// A_SorcBallOrbit -// -// - actor is ball -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SorcBallOrbit) -{ - PARAM_SELF_PROLOGUE(ASorcBall); - - // [RH] If no parent, then die instead of crashing - if (self->target == NULL) - { - self->SetState (self->FindState(NAME_Pain)); - return 0; - } - - int mode = self->target->args[3]; - AHeresiarch *parent = barrier_cast(self->target); - double dist = parent->radius - (self->radius*2); - -#if 0 - // This cannot happen anymore because this is defined locally in SorcBall - if (!self->IsKindOf (RUNTIME_CLASS(ASorcBall))) - { - I_Error ("Corrupted sorcerer:\nTried to use a %s", self->GetClass()->TypeName.GetChars()); - } -#endif - - if (self->target->health <= 0) - { - self->SetState (self->FindState(NAME_Pain)); - return 0; - } - - DAngle prevangle = self->OldAngle; - DAngle baseangle = parent->BallAngle; - DAngle angle = baseangle + self->AngleOffset; - - self->Angles.Yaw = angle; - - switch (mode) - { - case SORC_NORMAL: // Balls rotating normally - self->SorcUpdateBallAngle (); - break; - - case SORC_DECELERATE: // Balls decelerating - A_DecelBalls(self); - self->SorcUpdateBallAngle (); - break; - - case SORC_ACCELERATE: // Balls accelerating - A_AccelBalls(self); - self->SorcUpdateBallAngle (); - break; - - case SORC_STOPPING: // Balls stopping - if ((parent->StopBall == self->GetClass()) && - (parent->args[1] > SORCBALL_SPEED_ROTATIONS) && - absangle(angle, parent->Angles.Yaw) < 42.1875) - { - // Can stop now - self->target->args[3] = SORC_FIRESPELL; - self->target->args[4] = 0; - // Set angle so self angle == sorcerer angle - parent->BallAngle = parent->Angles.Yaw - self->AngleOffset; - } - else - { - self->SorcUpdateBallAngle (); - } - break; - - case SORC_FIRESPELL: // Casting spell - if (parent->StopBall == self->GetClass()) - { - // Put sorcerer into special throw spell anim - if (parent->health > 0) - parent->SetState (parent->FindState("Attack1")); - - self->DoFireSpell (); - } - break; - - case SORC_FIRING_SPELL: - if (parent->StopBall == self->GetClass()) - { - if (self->special2-- <= 0) - { - // Done rapid firing - parent->args[3] = SORC_STOPPED; - // Back to orbit balls - if (parent->health > 0) - parent->SetState (parent->FindState("Attack2")); - } - else - { - // Do rapid fire spell - A_SorcOffense2(self); - } - } - break; - - case SORC_STOPPED: // Balls stopped - default: - break; - } - - if ( angle.BAMs() < prevangle.BAMs() && (parent->args[4]==SORCBALL_TERMINAL_SPEED)) - { - parent->args[1]++; // Bump rotation counter - // Completed full rotation - make woosh sound - S_Sound (self, CHAN_BODY, "SorcererBallWoosh", 1, ATTN_NORM); - } - self->OldAngle = angle; // Set previous angle - - DVector3 pos = parent->Vec3Angle(dist, angle, -parent->Floorclip + parent->Height); - self->SetOrigin (pos, true); - self->floorz = parent->floorz; - self->ceilingz = parent->ceilingz; - return 0; -} - -//============================================================================ -// -// A_StopBalls -// -// Instant stop when rotation gets to ball in special2 -// self is sorcerer -// -//============================================================================ - -void A_StopBalls(AActor *scary) -{ - AHeresiarch *self = static_cast (scary); - int chance = pr_heresiarch(); - self->args[3] = SORC_STOPPING; // stopping mode - self->args[1] = 0; // Reset rotation counter - - if ((self->args[0] <= 0) && (chance < 200)) - { - self->StopBall = RUNTIME_CLASS(ASorcBall2); // Blue - } - else if((self->health < (self->SpawnHealth() >> 1)) && - (chance < 200)) - { - self->StopBall = RUNTIME_CLASS(ASorcBall3); // Green - } - else - { - self->StopBall = RUNTIME_CLASS(ASorcBall1); // Yellow - } -} - -//============================================================================ -// -// A_AccelBalls -// -// Increase ball orbit speed - actor is ball -// -//============================================================================ - -void A_AccelBalls(AActor *self) -{ - AActor *sorc = self->target; - - if (sorc->args[4] < sorc->args[2]) - { - sorc->args[4]++; - } - else - { - sorc->args[3] = SORC_NORMAL; - if (sorc->args[4] >= SORCBALL_TERMINAL_SPEED) - { - // Reached terminal velocity - stop balls - A_StopBalls(sorc); - } - } -} - -//============================================================================ -// -// A_DecelBalls -// -// Decrease ball orbit speed - actor is ball -// -//============================================================================ - -void A_DecelBalls(AActor *self) -{ - AActor *sorc = self->target; - - if (sorc->args[4] > sorc->args[2]) - { - sorc->args[4]--; - } - else - { - sorc->args[3] = SORC_NORMAL; - } -} - -//============================================================================ -// -// ASorcBall1::SorcUpdateBallAngle -// -// Update angle if first ball -//============================================================================ - -void ASorcBall1::SorcUpdateBallAngle () -{ - barrier_cast(target)->BallAngle += target->args[4]; -} - -//============================================================================ -// -// ASorcBall::SorcUpdateBallAngle -// -//============================================================================ - -void ASorcBall::SorcUpdateBallAngle () -{ -} - -//============================================================================ -// -// ASorcBall::CastSorcererSpell -// -// Make noise and change the parent sorcerer's animation -// -//============================================================================ - -void ASorcBall::CastSorcererSpell () -{ - S_Sound (target, CHAN_VOICE, "SorcererSpellCast", 1, ATTN_NONE); - - // Put sorcerer into throw spell animation - if (target->health > 0) - target->SetState (target->FindState("Attack2")); -} - -//============================================================================ -// -// ASorcBall2::CastSorcererSpell -// -// Defensive -// -//============================================================================ - -void ASorcBall2::CastSorcererSpell () -{ - Super::CastSorcererSpell (); - - AActor *parent = target; - AActor *mo; - - mo = Spawn("SorcFX2", PosPlusZ(parent->Floorclip + SORC_DEFENSE_HEIGHT), ALLOW_REPLACE); - parent->flags2 |= MF2_REFLECTIVE|MF2_INVULNERABLE; - parent->args[0] = SORC_DEFENSE_TIME; - if (mo) mo->target = parent; -} - -//============================================================================ -// -// ASorcBall3::CastSorcererSpell -// -// Reinforcements -// -//============================================================================ - -void ASorcBall3::CastSorcererSpell () -{ - Super::CastSorcererSpell (); - - AActor *mo; - DAngle ang1, ang2; - AActor *parent = target; - - ang1 = Angles.Yaw.Degrees - 45; - ang2 = Angles.Yaw.Degrees + 45; - PClassActor *cls = PClass::FindActor("SorcFX3"); - if (health < (SpawnHealth()/3)) - { // Spawn 2 at a time - mo = P_SpawnMissileAngle(parent, cls, ang1, 4.); - if (mo) mo->target = parent; - mo = P_SpawnMissileAngle(parent, cls, ang2, 4.); - if (mo) mo->target = parent; - } - else - { - if (pr_heresiarch() < 128) - ang1 = ang2; - mo = P_SpawnMissileAngle(parent, cls, ang1, 4.); - if (mo) mo->target = parent; - } -} - - -/* -void A_SpawnReinforcements(AActor *actor) -{ - AActor *parent = self->target; - AActor *mo; - DAngle ang; - - ang = P_Random(); - mo = P_SpawnMissileAngle(actor, MT_SORCFX3, ang, 5.); - if (mo) mo->target = parent; -} -*/ - -//============================================================================ -// -// SorcBall1::CastSorcererSpell -// -// Offensive -// -//============================================================================ - -void ASorcBall1::CastSorcererSpell () -{ - Super::CastSorcererSpell (); - - AActor *mo; - DAngle ang1, ang2; - AActor *parent = target; - - ang1 = Angles.Yaw.Degrees + 70; - ang2 = Angles.Yaw.Degrees - 70; - PClassActor *cls = PClass::FindActor("SorcFX1"); - mo = P_SpawnMissileAngle (parent, cls, ang1, 0); - if (mo) - { - mo->target = parent; - mo->tracer = parent->target; - mo->args[4] = BOUNCE_TIME_UNIT; - mo->args[3] = 15; // Bounce time in seconds - } - mo = P_SpawnMissileAngle (parent, cls, ang2, 0); - if (mo) - { - mo->target = parent; - mo->tracer = parent->target; - mo->args[4] = BOUNCE_TIME_UNIT; - mo->args[3] = 15; // Bounce time in seconds - } -} - -//============================================================================ -// -// A_SorcOffense2 -// -// Actor is ball -// -//============================================================================ - -void A_SorcOffense2(AActor *self) -{ - DAngle ang1; - AActor *mo; - double delta; - int index; - AActor *parent = self->target; - AActor *dest = parent->target; - double dist; - - // [RH] If no enemy, then don't try to shoot. - if (dest == NULL) - { - return; - } - - index = self->args[4]; - self->args[4] = (self->args[4] + 15) & 255; - delta = DAngle(index * (360 / 256.f)).Sin() * SORCFX4_SPREAD_ANGLE; - - ang1 = self->Angles.Yaw + delta; - mo = P_SpawnMissileAngle(parent, PClass::FindActor("SorcFX4"), ang1, 0); - if (mo) - { - mo->special2 = 35*5/2; // 5 seconds - dist = mo->DistanceBySpeed(dest, mo->Speed); - mo->Vel.Z = (dest->Z() - mo->Z()) / dist; - } -} - diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index f871e82d9a..1f4aa18ebc 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -24,5 +24,4 @@ #include "a_pickups.h" // Include all the Hexen stuff here to reduce compile time -#include "a_heresiarch.cpp" #include "a_spike.cpp" diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 65a979edd6..b34157b36a 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -842,6 +842,13 @@ DEFINE_ACTION_FUNCTION(DObject, GameType) ACTION_RETURN_INT(gameinfo.gametype); } +DEFINE_ACTION_FUNCTION(DObject, BAM) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(ang); + ACTION_RETURN_INT(DAngle(ang).BAMs()); +} + DEFINE_ACTION_FUNCTION(FStringTable, Localize) { PARAM_PROLOGUE; @@ -856,4 +863,5 @@ DEFINE_ACTION_FUNCTION(FString, Replace) PARAM_STRING(s2); self->Substitute(*s1, *s2); return 0; -} \ No newline at end of file +} + diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 4eab47c1b9..ae666a2f7b 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2285,6 +2285,25 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr ? nullptr : *(afd->VMPointer), varflags, useflags); c->Type()->Symbols.ReplaceSymbol(sym); + auto cls = dyn_cast(c->Type()); + PFunction *virtsym = nullptr; + if (cls != nullptr && cls->ParentClass != nullptr) virtsym = dyn_cast(cls->ParentClass->Symbols.FindSymbol(FName(f->Name), true)); + unsigned vindex = ~0u; + if (virtsym != nullptr) vindex = virtsym->Variants[0].Implementation->VirtualIndex; + + if (vindex != ~0u || (varflags & VARF_Virtual)) + { + // Todo: Check if the declaration is legal. + + // First step: compare prototypes - if they do not match the virtual base method does not apply. + + // Second step: Check flags. Possible cases: + // 1. Base method is final: Error. + // 2. This method is override: Base virtual method must exist + // 3. This method is virtual but not override: Base may not have a virtual method with the same prototype. + } + + if (!(f->Flags & ZCC_Native)) { if (f->Body == nullptr) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 08125952d2..b5ffe3a064 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -10,6 +10,7 @@ class Object native native static int GameType(); native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM); native static void C_MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable. + native static uint BAM(double angle); /*virtual*/ native void Destroy(); } diff --git a/wadsrc/static/zscript/hexen/heresiarch.txt b/wadsrc/static/zscript/hexen/heresiarch.txt index cf0b16372b..9cfdde19d5 100644 --- a/wadsrc/static/zscript/hexen/heresiarch.txt +++ b/wadsrc/static/zscript/hexen/heresiarch.txt @@ -18,7 +18,7 @@ // special2 Countdown of rapid fire (FX4) //============================================================================ -class Heresiarch native +class Heresiarch : Actor { const SORCBALL_INITIAL_SPEED = 7; @@ -45,7 +45,8 @@ class Heresiarch native const BALL2_ANGLEOFFSET = 120.; const BALL3_ANGLEOFFSET = 240.; - native double BallAngle; + double BallAngle; + class StopBall; Default { @@ -110,7 +111,50 @@ class Heresiarch native SORC Z -1 Bright; Stop; } + + void Die (Actor source, Actor inflictor, int dmgflags) + { + // The heresiarch just executes a script instead of a special upon death + int script = special; + special = 0; + + Super.Die (source, inflictor, dmgflags); + + if (script != 0) + { + ACS_Execute(script, 0); + } + } + //============================================================================ + // + // A_StopBalls + // + // Instant stop when rotation gets to ball in special2 + // self is sorcerer + // + //============================================================================ + + void A_StopBalls() + { + int chance = random[Heresiarch](); + args[3] = SORC_STOPPING; // stopping mode + args[1] = 0; // Reset rotation counter + + if ((args[0] <= 0) && (chance < 200)) + { + StopBall = "SorcBall2"; // Blue + } + else if((health < (SpawnHealth() >> 1)) && (chance < 200)) + { + StopBall = "SorcBall3"; // Green + } + else + { + StopBall = "SorcBall1"; // Yellow + } + } + //============================================================================ // // A_SorcSpinBalls @@ -213,7 +257,7 @@ class Heresiarch native // Base class for the balls flying around the Heresiarch's head ------------- -class SorcBall native +class SorcBall : Actor { Default { @@ -231,8 +275,239 @@ class SorcBall native DeathSound "SorcererBigBallExplode"; } - native void A_SorcBallOrbit(); + double OldAngle, AngleOffset; + + //============================================================================ + // + // SorcBall::DoFireSpell + // + //============================================================================ + + virtual void DoFireSpell () + { + CastSorcererSpell (); + target.args[3] = Heresiarch.SORC_STOPPED; + } + + virtual void SorcUpdateBallAngle () + { + } + + override bool SpecialBlastHandling (Actor source, double strength) + { // don't blast sorcerer balls + return false; + } + + //============================================================================ + // + // ASorcBall::CastSorcererSpell + // + // Make noise and change the parent sorcerer's animation + // + //============================================================================ + + virtual void CastSorcererSpell () + { + target.A_PlaySound ("SorcererSpellCast", CHAN_VOICE); + + // Put sorcerer into throw spell animation + if (target.health > 0) + target.SetStateLabel ("Attack2"); + } + + //============================================================================ + // + // A_SorcBallOrbit + // + // - actor is ball + //============================================================================ + + void A_SorcBallOrbit() + { + // [RH] If no parent, then die instead of crashing + if (target == null || target.health <= 0) + { + SetStateLabel ("Pain"); + return; + } + + int mode = target.args[3]; + Heresiarch parent = Heresiarch(target); + double dist = parent.radius - (radius*2); + + double prevangle = OldAngle; + double baseangle = parent.BallAngle; + double curangle = baseangle + AngleOffset; + + angle = curangle; + + switch (mode) + { + case Heresiarch.SORC_NORMAL: // Balls rotating normally + SorcUpdateBallAngle (); + break; + + case Heresiarch.SORC_DECELERATE: // Balls decelerating + A_DecelBalls(); + SorcUpdateBallAngle (); + break; + + case Heresiarch.SORC_ACCELERATE: // Balls accelerating + A_AccelBalls(); + SorcUpdateBallAngle (); + break; + + case Heresiarch.SORC_STOPPING: // Balls stopping + if ((parent.StopBall == GetClass()) && + (parent.args[1] > Heresiarch.SORCBALL_SPEED_ROTATIONS) && + absangle(curangle, parent.angle) < 42.1875) + { + // Can stop now + target.args[3] = Heresiarch.SORC_FIRESPELL; + target.args[4] = 0; + // Set angle so self angle == sorcerer angle + parent.BallAngle = parent.angle - AngleOffset; + } + else + { + SorcUpdateBallAngle (); + } + break; + + case Heresiarch.SORC_FIRESPELL: // Casting spell + if (parent.StopBall == GetClass()) + { + // Put sorcerer into special throw spell anim + if (parent.health > 0) + parent.SetStateLabel("Attack1"); + + DoFireSpell (); + } + break; + + case Heresiarch.SORC_FIRING_SPELL: + if (parent.StopBall == GetClass()) + { + if (special2-- <= 0) + { + // Done rapid firing + parent.args[3] = Heresiarch.SORC_STOPPED; + // Back to orbit balls + if (parent.health > 0) + parent.SetStateLabel("Attack2"); + } + else + { + // Do rapid fire spell + A_SorcOffense2(); + } + } + break; + + default: + break; + } + + // The comparison here depends on binary angle semantics and cannot be done in floating point. + // It also requires very exact conversion that must be done natively. + if (BAM(curangle) < BAM(prevangle) && (parent.args[4] == Heresiarch.SORCBALL_TERMINAL_SPEED)) + { + parent.args[1]++; // Bump rotation counter + // Completed full rotation - make woosh sound + A_PlaySound ("SorcererBallWoosh", CHAN_BODY); + } + OldAngle = curangle; // Set previous angle + + Vector3 pos = parent.Vec3Angle(dist, curangle, -parent.Floorclip + parent.Height); + SetOrigin (pos, true); + floorz = parent.floorz; + ceilingz = parent.ceilingz; + } + + //============================================================================ + // + // A_SorcOffense2 + // + // Actor is ball + // + //============================================================================ + + void A_SorcOffense2() + { + Actor parent = target; + Actor dest = parent.target; + + // [RH] If no enemy, then don't try to shoot. + if (dest == null) + { + return; + } + + int index = args[4]; + args[4] = (args[4] + 15) & 255; + double delta = sin(index * (360 / 256.f)) * Heresiarch.SORCFX4_SPREAD_ANGLE; + + double ang1 = Angle + delta; + Actor mo = parent.SpawnMissileAngle("SorcFX4", ang1, 0); + if (mo) + { + mo.special2 = 35*5/2; // 5 seconds + double dist = mo.DistanceBySpeed(dest, mo.Speed); + mo.Vel.Z = (dest.pos.z - mo.pos.z) / dist; + } + } + + //============================================================================ + // + // A_AccelBalls + // + // Increase ball orbit speed - actor is ball + // + //============================================================================ + + void A_AccelBalls() + { + Heresiarch sorc = Heresiarch(target); + + if (sorc.args[4] < sorc.args[2]) + { + sorc.args[4]++; + } + else + { + sorc.args[3] = Heresiarch.SORC_NORMAL; + if (sorc.args[4] >= Heresiarch.SORCBALL_TERMINAL_SPEED) + { + // Reached terminal velocity - stop balls + sorc.A_StopBalls(); + } + } + } + + //============================================================================ + // + // A_DecelBalls + // + // Decrease ball orbit speed - actor is ball + // + //============================================================================ + + void A_DecelBalls() + { + Actor sorc = target; + + if (sorc.args[4] > sorc.args[2]) + { + sorc.args[4]--; + } + else + { + sorc.args[3] = Heresiarch.SORC_NORMAL; + } + } + + void A_SorcBallExplode() { bNoBounceSound = true; @@ -286,7 +561,7 @@ class SorcBall native // First ball (purple) - fires projectiles ---------------------------------- -class SorcBall1 : SorcBall native +class SorcBall1 : SorcBall { States { @@ -303,12 +578,90 @@ class SorcBall1 : SorcBall native SBS4 FGH 6; Stop; } + + override void BeginPlay () + { + Super.BeginPlay (); + AngleOffset = Heresiarch.BALL1_ANGLEOFFSET; + A_Log("Ball1 begins " .. AngleOffset); + } + + //============================================================================ + // + // SorcBall1::CastSorcererSpell + // + // Offensive + // + //============================================================================ + + override void CastSorcererSpell () + { + Super.CastSorcererSpell (); + + Actor parent = target; + + double ang1 = Angle + 70; + double ang2 = Angle - 70; + Class cls = "SorcFX1"; + Actor mo = parent.SpawnMissileAngle (cls, ang1, 0); + if (mo) + { + mo.target = parent; + mo.tracer = parent.target; + mo.args[4] = Heresiarch.BOUNCE_TIME_UNIT; + mo.args[3] = 15; // Bounce time in seconds + } + mo = parent.SpawnMissileAngle (cls, ang2, 0); + if (mo) + { + mo.target = parent; + mo.tracer = parent.target; + mo.args[4] = Heresiarch.BOUNCE_TIME_UNIT; + mo.args[3] = 15; // Bounce time in seconds + } + } + + + //============================================================================ + // + // ASorcBall1::SorcUpdateBallAngle + // + // Update angle if first ball + //============================================================================ + + override void SorcUpdateBallAngle () + { + (Heresiarch(target)).BallAngle += target.args[4]; + } + + //============================================================================ + // + // SorcBall1::DoFireSpell + // + //============================================================================ + + override void DoFireSpell () + { + if (random[Heresiarch]() < 200) + { + target.A_PlaySound ("SorcererSpellCast", CHAN_VOICE, 1, false, ATTN_NONE); + special2 = Heresiarch.SORCFX4_RAPIDFIRE_TIME; + args[4] = 128; + target.args[3] = Heresiarch.SORC_FIRING_SPELL; + } + else + { + Super.DoFireSpell (); + } + } + + } // Second ball (blue) - generates the shield -------------------------------- -class SorcBall2 : SorcBall native +class SorcBall2 : SorcBall { States { @@ -325,11 +678,40 @@ class SorcBall2 : SorcBall native SBS3 FGH 6; Stop; } + + override void BeginPlay () + { + Super.BeginPlay (); + AngleOffset = Heresiarch.BALL2_ANGLEOFFSET; + A_Log("Ball2 begins " .. AngleOffset); + } + + //============================================================================ + // + // ASorcBall2::CastSorcererSpell + // + // Defensive + // + //============================================================================ + + override void CastSorcererSpell () + { + Super.CastSorcererSpell (); + + Actor parent = target; + Actor mo = Spawn("SorcFX2", Pos + (0, 0, parent.Floorclip + Heresiarch.SORC_DEFENSE_HEIGHT), ALLOW_REPLACE); + bReflective = true; + bInvulnerable = true; + parent.args[0] = Heresiarch.SORC_DEFENSE_TIME; + if (mo) mo.target = parent; + } + + } // Third ball (green) - summons Bishops ------------------------------------- -class SorcBall3 : SorcBall native +class SorcBall3 : SorcBall { States { @@ -346,6 +728,47 @@ class SorcBall3 : SorcBall native SBS3 FGH 6; Stop; } + + override void BeginPlay () + { + Super.BeginPlay (); + AngleOffset = Heresiarch.BALL3_ANGLEOFFSET; + A_Log("Ball3 begins " .. AngleOffset); + } + + //============================================================================ + // + // ASorcBall3::CastSorcererSpell + // + // Reinforcements + // + //============================================================================ + + override void CastSorcererSpell () + { + Actor mo; + Super.CastSorcererSpell (); + Actor parent = target; + + double ang1 = Angle - 45; + double ang2 = Angle + 45; + Class cls = "SorcFX3"; + if (health < (SpawnHealth()/3)) + { // Spawn 2 at a time + mo = parent.SpawnMissileAngle(cls, ang1, 4.); + if (mo) mo.target = parent; + mo = parent.SpawnMissileAngle(cls, ang2, 4.); + if (mo) mo.target = parent; + } + else + { + if (random[Heresiarch]() < 128) ang1 = ang2; + mo = parent.SpawnMissileAngle(cls, ang1, 4.); + if (mo) mo.target = parent; + } + } + + } @@ -489,7 +912,7 @@ class SorcFX2 : Actor Actor parent = target; // [RH] If no parent, then disappear - if (parent == NULL) + if (parent == null) { Destroy(); return; @@ -616,7 +1039,7 @@ class SorcFX3 : Actor mo.ClearCounters(); mo.Destroy (); } - else if (target != NULL) + else if (target != null) { // [RH] Make the new bishops inherit the Heriarch's target mo.CopyFriendliness (target, true); mo.master = target; From 0c969746d07a003f581ae350f9b01372099c32b9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 18:42:48 +0100 Subject: [PATCH 413/471] - scriptified Hexen's spike, which was the last remaining item in the game directories. - added a BlockThingsIterator for scripts. --- src/CMakeLists.txt | 5 -- src/g_hexen/a_hexenmisc.cpp | 27 -------- src/g_hexen/a_spike.cpp | 90 --------------------------- src/p_map.cpp | 22 ++++--- src/p_maputl.cpp | 69 ++++++++++++++++++++ wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/base.txt | 11 ++++ wadsrc/static/zscript/hexen/spike.txt | 56 ++++++++++++++++- 8 files changed, 146 insertions(+), 136 deletions(-) delete mode 100644 src/g_hexen/a_hexenmisc.cpp delete mode 100644 src/g_hexen/a_spike.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c7228edd89..071fc5ce72 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -828,7 +828,6 @@ endif() file( GLOB HEADER_FILES ${EXTRA_HEADER_DIRS} fragglescript/*.h - g_hexen/*.h g_shared/*.h g_strife/*.h intermission/*.h @@ -859,7 +858,6 @@ set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} sc_man_scanner.h sc_man_scanner.re - g_hexen/a_spike.cpp g_shared/sbarinfo_commands.cpp xlat/xlat_parser.y xlat_parser.c @@ -1108,7 +1106,6 @@ set (PCH_SOURCES w_wad.cpp wi_stuff.cpp zstrformat.cpp - g_hexen/a_hexenmisc.cpp g_strife/strife_sbar.cpp g_shared/a_action.cpp g_shared/a_armor.cpp @@ -1258,7 +1255,6 @@ endif() target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma ) include_directories( . - g_hexen g_strife g_shared oplsynth @@ -1389,7 +1385,6 @@ source_group("External\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/m 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\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+") 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("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+") diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp deleted file mode 100644 index 1f4aa18ebc..0000000000 --- a/src/g_hexen/a_hexenmisc.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "d_player.h" -#include "info.h" -#include "p_local.h" -#include "s_sound.h" -#include "a_action.h" -#include "m_random.h" -#include "a_sharedglobal.h" -#include "i_system.h" -#include "gi.h" -#include "g_level.h" -#include "p_enemy.h" -#include "a_weaponpiece.h" -#include "doomstat.h" -#include "p_lnspec.h" -#include "p_terrain.h" -#include "m_bbox.h" -#include "v_palette.h" -#include "g_game.h" -#include "p_blockmap.h" -#include "r_utility.h" -#include "p_maputl.h" -#include "p_spec.h" -#include "serializer.h" -#include "a_pickups.h" - -// Include all the Hexen stuff here to reduce compile time -#include "a_spike.cpp" diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp deleted file mode 100644 index cd0d2e8914..0000000000 --- a/src/g_hexen/a_spike.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "p_enemy.h" -#include "p_local.h" -#include "a_sharedglobal.h" -#include "s_sound.h" -#include "m_bbox.h" -#include "vm.h" -*/ - -static FRandom pr_thrustraise ("ThrustRaise"); - -// Spike (thrust floor) ----------------------------------------------------- - -// AThrustFloor is just a container for all the spike states. -// All the real spikes subclass it. - -class AThrustFloor : public AActor -{ - DECLARE_CLASS (AThrustFloor, AActor) -public: - - void Activate (AActor *activator); - void Deactivate (AActor *activator); -}; - -IMPLEMENT_CLASS(AThrustFloor, false, false) - -void AThrustFloor::Activate (AActor *activator) -{ - if (args[0] == 0) - { - S_Sound (this, CHAN_BODY, "ThrustSpikeLower", 1, ATTN_NORM); - renderflags &= ~RF_INVISIBLE; - if (args[1]) - SetState (FindState ("BloodThrustRaise")); - else - SetState (FindState ("ThrustRaise")); - } -} - -void AThrustFloor::Deactivate (AActor *activator) -{ - if (args[0] == 1) - { - S_Sound (this, CHAN_BODY, "ThrustSpikeRaise", 1, ATTN_NORM); - if (args[1]) - SetState (FindState ("BloodThrustLower")); - else - SetState (FindState ("ThrustLower")); - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_ThrustImpale) -{ - PARAM_SELF_PROLOGUE(AActor); - - // This doesn't need to iterate through portals. - - FPortalGroupArray check; - FMultiBlockThingsIterator it(check, self); - FMultiBlockThingsIterator::CheckResult cres; - while (it.Next(&cres)) - { - double blockdist = self->radius + cres.thing->radius; - if (fabs(cres.thing->X() - cres.Position.X) >= blockdist || fabs(cres.thing->Y() - cres.Position.Y) >= blockdist) - continue; - - // Q: Make this z-aware for everything? It never was before. - if (cres.thing->Top() < self->Z() || cres.thing->Z() > self->Top()) - { - if (self->Sector->PortalGroup != cres.thing->Sector->PortalGroup) - continue; - } - - if (!(cres.thing->flags & MF_SHOOTABLE) ) - continue; - - if (cres.thing == self) - continue; // don't clip against self - - int newdam = P_DamageMobj (cres.thing, self, self, 10001, NAME_Crush); - P_TraceBleed (newdam > 0 ? newdam : 10001, cres.thing); - self->args[1] = 1; // Mark thrust thing as bloody - } - return 0; -} - diff --git a/src/p_map.cpp b/src/p_map.cpp index 367c35fd04..c5780eedcd 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4652,16 +4652,6 @@ 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; -} - //========================================================================== // // @@ -4706,6 +4696,18 @@ void P_TraceBleed(int damage, AActor *target) } } +DEFINE_ACTION_FUNCTION(AActor, TraceBleed) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(damage); + PARAM_OBJECT(missile, AActor); + + if (missile) P_TraceBleed(damage, self, missile); + else P_TraceBleed(damage, self); + return 0; +} + + //========================================================================== // // [RH] Rail gun stuffage diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 16fc790c05..aa29a1c5e7 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1152,6 +1152,75 @@ void FMultiBlockThingsIterator::Reset() startIteratorForGroup(basegroup); } +//=========================================================================== +// +// and the scriptable version +// +//=========================================================================== + +class DBlockThingsIterator : public DObject, public FMultiBlockThingsIterator +{ + DECLARE_CLASS(DBlockThingsIterator, DObject); + FPortalGroupArray check; +public: + FMultiBlockThingsIterator::CheckResult cres; + +public: + bool Next() + { + return FMultiBlockThingsIterator::Next(&cres); + } + + DBlockThingsIterator(AActor *origin = nullptr, double checkradius = -1, bool ignorerestricted = false) + : FMultiBlockThingsIterator(check, origin, checkradius, ignorerestricted) + { + cres.thing = nullptr; + cres.Position.Zero(); + cres.portalflags = 0; + } + + DBlockThingsIterator(double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec) + : FMultiBlockThingsIterator(check, checkx, checky, checkz, checkh, checkradius, ignorerestricted, newsec) + { + cres.thing = nullptr; + cres.Position.Zero(); + cres.portalflags = 0; + } +}; + +IMPLEMENT_CLASS(DBlockThingsIterator, false, false); + +DEFINE_ACTION_FUNCTION(DBlockThingsIterator, Create) +{ + PARAM_PROLOGUE; + PARAM_OBJECT(origin, AActor); + PARAM_FLOAT_DEF(radius); + PARAM_BOOL_DEF(ignore); + ACTION_RETURN_OBJECT(new DBlockThingsIterator(origin, radius, ignore)); +} + +DEFINE_ACTION_FUNCTION(DBlockThingsIterator, CreateFromPos) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_FLOAT(h); + PARAM_FLOAT(radius); + PARAM_BOOL(ignore); + ACTION_RETURN_OBJECT(new DBlockThingsIterator(x, y, z, h, radius, ignore, nullptr)); +} + +DEFINE_ACTION_FUNCTION(DBlockThingsIterator, Next) +{ + PARAM_SELF_PROLOGUE(DBlockThingsIterator); + ACTION_RETURN_BOOL(self->Next()); +} + +DEFINE_FIELD_NAMED(DBlockThingsIterator, cres.thing, thing); +DEFINE_FIELD_NAMED(DBlockThingsIterator, cres.Position, position); +DEFINE_FIELD_NAMED(DBlockThingsIterator, cres.portalflags, portalflags); + //=========================================================================== // // FPathTraverse :: Intercepts diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 37306db39a..c3dc3c1dd5 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -387,7 +387,7 @@ class Actor : Thinker native // DECORATE compatible functions native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); native double GetDistance(bool checkz, int ptr = AAPTR_TARGET); - native double GetAngle(int flags, int ptr = AAPTR_DEFAULT); + native double GetAngle(int flags, int ptr = AAPTR_TARGET); native double GetZAt(double px = 0, double py = 0, double angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); native int GetSpawnHealth(); native int GetGibHealth(); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index b5ffe3a064..73f515f71b 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -42,6 +42,17 @@ class ActorIterator : Object native native void Reinit(); } +class BlockThingsIterator : Object native +{ + native Actor thing; + native Vector3 position; + native int portalflags; + + native static BlockThingsIterator Create(Actor origin, double checkradius = -1, bool ignorerestricted = false); + native static BlockThingsIterator CreateFromPos(double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted); + native bool Next(); +} + class DropItem : Object native { native readonly DropItem Next; diff --git a/wadsrc/static/zscript/hexen/spike.txt b/wadsrc/static/zscript/hexen/spike.txt index 8d418d55a5..248c957264 100644 --- a/wadsrc/static/zscript/hexen/spike.txt +++ b/wadsrc/static/zscript/hexen/spike.txt @@ -18,7 +18,7 @@ class DirtClump : Actor // Spike (thrust floor) ----------------------------------------------------- -class ThrustFloor : Actor native +class ThrustFloor : Actor { Default { @@ -26,8 +26,6 @@ class ThrustFloor : Actor native Height 128; } - native void A_ThrustImpale(); - States { ThrustRaising: @@ -78,6 +76,31 @@ class ThrustFloor : Actor native Loop; } + override void Activate (Actor activator) + { + if (args[0] == 0) + { + A_PlaySound ("ThrustSpikeLower", CHAN_BODY); + bInvisible = false; + if (args[1]) + SetStateLabel("BloodThrustRaise"); + else + SetStateLabel("ThrustRaise"); + } + } + + override void Deactivate (Actor activator) + { + if (args[0] == 1) + { + A_PlaySound ("ThrustSpikeRaise", CHAN_BODY); + if (args[1]) + SetStateLabel("BloodThrustLower"); + else + SetStateLabel("ThrustLower"); + } + } + //=========================================================================== // // Thrust floor stuff @@ -150,6 +173,33 @@ class ThrustFloor : Actor native } + void A_ThrustImpale() + { + BlockThingsIterator it = BlockThingsIterator.Create(self); + while (it.Next()) + { + double blockdist = radius + it.thing.radius; + if (abs(it.thing.pos.x - it.Position.X) >= blockdist || abs(it.thing.pos.y - it.Position.Y) >= blockdist) + continue; + + // Q: Make this z-aware for everything? It never was before. + if (it.thing.pos.z + it.thing.height < pos.z || it.thing.pos.z > pos.z + height) + { + if (CurSector.PortalGroup != it.thing.CurSector.PortalGroup) + continue; + } + + if (!it.thing.bShootable) + continue; + + if (it.thing == self) + continue; // don't clip against self + + int newdam = it.thing.DamageMobj (self, self, 10001, 'Crush'); + it.thing.TraceBleed (newdam > 0 ? newdam : 10001, null); + args[1] = 1; // Mark thrust thing as bloody + } + } } // Spike up ----------------------------------------------------------------- From a13e23dbe65328c6e0f587d8fd3ba6d6244b4ce5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 19:50:34 +0100 Subject: [PATCH 414/471] - scriptified some trivial stuff from g_shared. --- src/CMakeLists.txt | 6 -- src/am_map.cpp | 4 +- src/dthinker.cpp | 7 ++ src/g_shared/a_action.cpp | 77 ------------------- src/g_shared/a_action.h | 29 ------- src/g_shared/a_hatetarget.cpp | 76 ------------------ src/g_shared/a_mapmarker.cpp | 69 ----------------- src/g_shared/a_randomspawner.cpp | 1 - src/g_shared/a_secrettrigger.cpp | 66 ---------------- src/g_shared/a_setcolor.cpp | 33 -------- src/g_shared/a_sharedglobal.h | 9 --- src/g_shared/a_spark.cpp | 55 ------------- src/g_shared/a_waterzone.cpp | 53 ------------- src/p_actionfunctions.cpp | 1 - src/p_effect.cpp | 10 +++ src/p_enemy.cpp | 1 - src/p_mobj.cpp | 1 - src/p_sectors.cpp | 20 +++++ src/p_spec.cpp | 9 +++ src/scripting/decorate/olddecorations.cpp | 1 - src/scripting/decorate/thingdef_states.cpp | 1 - src/scripting/thingdef.cpp | 1 - src/scripting/thingdef_properties.cpp | 1 - wadsrc/static/zscript/actor.txt | 3 +- wadsrc/static/zscript/base.txt | 58 ++++++++++++-- wadsrc/static/zscript/raven/minotaur.txt | 47 +++++++++++ wadsrc/static/zscript/shared/hatetarget.txt | 30 +++++++- wadsrc/static/zscript/shared/mapmarker.txt | 33 +++++++- .../static/zscript/shared/secrettrigger.txt | 16 +++- wadsrc/static/zscript/shared/setcolor.txt | 21 ++++- wadsrc/static/zscript/shared/sharedmisc.txt | 18 ++++- wadsrc/static/zscript/shared/spark.txt | 10 ++- wadsrc/static/zscript/shared/waterzone.txt | 11 ++- 33 files changed, 276 insertions(+), 502 deletions(-) delete mode 100644 src/g_shared/a_action.h delete mode 100644 src/g_shared/a_hatetarget.cpp delete mode 100644 src/g_shared/a_mapmarker.cpp delete mode 100644 src/g_shared/a_secrettrigger.cpp delete mode 100644 src/g_shared/a_setcolor.cpp delete mode 100644 src/g_shared/a_spark.cpp delete mode 100644 src/g_shared/a_waterzone.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 071fc5ce72..111b2663c8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1116,25 +1116,19 @@ set (PCH_SOURCES g_shared/a_fastprojectile.cpp g_shared/a_flashfader.cpp g_shared/a_fountain.cpp - g_shared/a_hatetarget.cpp g_shared/a_keys.cpp g_shared/a_lightning.cpp - g_shared/a_mapmarker.cpp g_shared/a_morph.cpp g_shared/a_movingcamera.cpp g_shared/a_pickups.cpp g_shared/a_puzzleitems.cpp g_shared/a_quake.cpp g_shared/a_randomspawner.cpp - g_shared/a_secrettrigger.cpp g_shared/a_sectoraction.cpp - g_shared/a_setcolor.cpp g_shared/a_skies.cpp g_shared/a_soundenvironment.cpp g_shared/a_soundsequence.cpp - g_shared/a_spark.cpp g_shared/a_specialspot.cpp - g_shared/a_waterzone.cpp g_shared/a_weaponpiece.cpp g_shared/a_weapons.cpp g_shared/hudmessages.cpp diff --git a/src/am_map.cpp b/src/am_map.cpp index d74927b684..99fda3bd63 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2963,8 +2963,8 @@ void AM_drawAuthorMarkers () // [RH] Draw any actors derived from AMapMarker on the automap. // If args[0] is 0, then the actor's sprite is drawn at its own location. // Otherwise, its sprite is drawn at the location of any actors whose TIDs match args[0]. - TThinkerIterator it (STAT_MAPMARKER); - AMapMarker *mark; + TThinkerIterator it ("MapMarker", STAT_MAPMARKER); + AActor *mark; while ((mark = it.Next()) != NULL) { diff --git a/src/dthinker.cpp b/src/dthinker.cpp index d214b28e99..7c8bf1bf5a 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -387,6 +387,13 @@ void DThinker::ChangeStatNum (int statnum) list->AddTail(this); } +DEFINE_ACTION_FUNCTION(DThinker, ChangeStatNum) +{ + PARAM_SELF_PROLOGUE(DThinker); + PARAM_INT(stat); + self->ChangeStatNum(stat); + return 0; +} //========================================================================== // // Mark the first thinker of each list diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index 3938a9743f..afe188019b 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -1,7 +1,6 @@ #include "actor.h" #include "p_conversation.h" #include "p_lnspec.h" -#include "a_action.h" #include "m_random.h" #include "s_sound.h" #include "d_player.h" @@ -18,39 +17,6 @@ static FRandom pr_icesettics ("IceSetTics"); static FRandom pr_freeze ("FreezeDeathChunks"); -// SwitchableDecoration: Activate and Deactivate change state --------------- - -class ASwitchableDecoration : public AActor -{ - DECLARE_CLASS (ASwitchableDecoration, AActor) -public: - void Activate (AActor *activator); - void Deactivate (AActor *activator); -}; - -IMPLEMENT_CLASS(ASwitchableDecoration, false, false) - -void ASwitchableDecoration::Activate (AActor *activator) -{ - SetState (FindState(NAME_Active)); -} - -void ASwitchableDecoration::Deactivate (AActor *activator) -{ - SetState (FindState(NAME_Inactive)); -} - -// SwitchingDecoration: Only Activate changes state ------------------------- - -class ASwitchingDecoration : public ASwitchableDecoration -{ - DECLARE_CLASS (ASwitchingDecoration, ASwitchableDecoration) -public: - void Deactivate (AActor *activator) {} -}; - -IMPLEMENT_CLASS(ASwitchingDecoration, false, false) - //---------------------------------------------------------------------------- // // PROC A_NoBlocking @@ -412,46 +378,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeQueueCorpse) return 0; } -//=========================================================================== -// -// FaceMovementDirection -// -//=========================================================================== - -void FaceMovementDirection(AActor *actor) -{ - switch (actor->movedir) - { - case DI_EAST: - actor->Angles.Yaw = 0.; - break; - case DI_NORTHEAST: - actor->Angles.Yaw = 45.; - break; - case DI_NORTH: - actor->Angles.Yaw = 90.; - break; - case DI_NORTHWEST: - actor->Angles.Yaw = 135.; - break; - case DI_WEST: - actor->Angles.Yaw = 180.; - break; - case DI_SOUTHWEST: - actor->Angles.Yaw = 225.; - break; - case DI_SOUTH: - actor->Angles.Yaw = 270.; - break; - case DI_SOUTHEAST: - actor->Angles.Yaw = 315.; - break; - } -} - -DEFINE_ACTION_FUNCTION(AActor, FaceMovementDirection) -{ - PARAM_SELF_PROLOGUE(AActor); - FaceMovementDirection(self); - return 0; -} diff --git a/src/g_shared/a_action.h b/src/g_shared/a_action.h deleted file mode 100644 index 7c5e00a79e..0000000000 --- a/src/g_shared/a_action.h +++ /dev/null @@ -1,29 +0,0 @@ -class AActor; - -/* -void A_NoBlocking (AActor *); -void A_HideThing (AActor *); -void A_UnHideThing (AActor *); -void A_FreezeDeath (AActor *); -void A_FreezeDeathChunks (AActor *); -void A_GenericFreezeDeath (AActor *); -void A_IceSetTics (AActor *); -void A_IceCheckHeadDone (AActor *); -void A_QueueCorpse (AActor *); -void A_DeQueueCorpse (AActor *); -void A_SetInvulnerable (AActor *); -void A_UnSetInvulnerable (AActor *); -void A_SetReflective (AActor *); -void A_UnSetReflective (AActor *); -void A_SetReflectiveInvulnerable (AActor *); -void A_UnSetReflectiveInvulnerable (AActor *); -void A_SetShootable (AActor *); -void A_UnSetShootable (AActor *); -void A_SetFloorClip (AActor *); -void A_UnSetFloorClip (AActor *); -void A_NoGravity (AActor *); -void A_SkullPop (AActor *); -*/ - - -void FaceMovementDirection (AActor *); diff --git a/src/g_shared/a_hatetarget.cpp b/src/g_shared/a_hatetarget.cpp deleted file mode 100644 index 8d5b0fa725..0000000000 --- a/src/g_shared/a_hatetarget.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* -** a_hatetarget.cpp -** Something for monsters to hate and shoot at -** -**--------------------------------------------------------------------------- -** Copyright 2003-2006 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 "actor.h" -#include "info.h" -#include "m_fixed.h" - -// Hate Target -------------------------------------------------------------- - -class AHateTarget : public AActor -{ - DECLARE_CLASS(AHateTarget, AActor) -public: - void BeginPlay(); - int TakeSpecialDamage(AActor *inflictor, AActor *source, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(AHateTarget, false, false) - -void AHateTarget::BeginPlay() -{ - Super::BeginPlay(); - if (SpawnAngle != 0) - { // Each degree translates into 10 units of health - health = SpawnAngle * 10; - } - else - { - special2 = 1; - health = 1000001; - } -} - -int AHateTarget::TakeSpecialDamage(AActor *inflictor, AActor *source, int damage, FName damagetype) -{ - if (special2 != 0) - { - return 0; - } - else - { - return damage; - } -} - diff --git a/src/g_shared/a_mapmarker.cpp b/src/g_shared/a_mapmarker.cpp deleted file mode 100644 index 524bfca44f..0000000000 --- a/src/g_shared/a_mapmarker.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* -** a_mapmarker.cpp -** An actor that appears on the automap instead of in the 3D view. -** -**--------------------------------------------------------------------------- -** Copyright 2006 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 "a_sharedglobal.h" -#include "statnums.h" - -// Map Marker -------------------------------------------------------------- -// -// This class uses the following argument: -// args[0] == 0, shows the sprite at this actor -// != 0, shows the sprite for all actors whose TIDs match instead -// -// args[1] == 0, show the sprite always -// == 1, show the sprite only after its sector has been drawn -// -// To enable display of the sprite, activate it. To turn off the sprite, -// deactivate it. -// -// All the code to display it is in am_map.cpp. -// -//-------------------------------------------------------------------------- - -IMPLEMENT_CLASS(AMapMarker, false, false) - -void AMapMarker::BeginPlay () -{ - ChangeStatNum (STAT_MAPMARKER); -} - -void AMapMarker::Activate (AActor *activator) -{ - flags2 |= MF2_DORMANT; -} - -void AMapMarker::Deactivate (AActor *activator) -{ - flags2 &= ~MF2_DORMANT; -} diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index 0cecfd1154..d5a396d0d9 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -13,7 +13,6 @@ #include "s_sound.h" #include "statnums.h" #include "gstrings.h" -#include "a_action.h" #include "v_text.h" #include "doomstat.h" #include "doomdata.h" diff --git a/src/g_shared/a_secrettrigger.cpp b/src/g_shared/a_secrettrigger.cpp deleted file mode 100644 index 509ec47e92..0000000000 --- a/src/g_shared/a_secrettrigger.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* -** a_secrettrigger.cpp -** A thing that counts toward the secret count when activated -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 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 "actor.h" -#include "g_level.h" -#include "c_console.h" -#include "info.h" -#include "s_sound.h" -#include "d_player.h" -#include "doomstat.h" -#include "v_font.h" -#include "p_spec.h" - -class ASecretTrigger : public AActor -{ - DECLARE_CLASS (ASecretTrigger, AActor) -public: - void PostBeginPlay (); - void Activate (AActor *activator); -}; - -IMPLEMENT_CLASS(ASecretTrigger, false, false) - -void ASecretTrigger::PostBeginPlay () -{ - Super::PostBeginPlay (); - level.total_secrets++; -} - -void ASecretTrigger::Activate (AActor *activator) -{ - P_GiveSecret(activator, args[0] <= 1, (args[0] == 0 || args[0] == 2), -1); - Destroy (); -} - diff --git a/src/g_shared/a_setcolor.cpp b/src/g_shared/a_setcolor.cpp deleted file mode 100644 index e8a11b850b..0000000000 --- a/src/g_shared/a_setcolor.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "r_defs.h" -#include "actor.h" -#include "info.h" - -class AColorSetter : public AActor -{ - DECLARE_CLASS(AColorSetter, AActor) - - void PostBeginPlay() - { - Super::PostBeginPlay(); - Sector->SetColor(args[0], args[1], args[2], args[3]); - Destroy(); - } - -}; - -IMPLEMENT_CLASS(AColorSetter, false, false) - -class AFadeSetter : public AActor -{ - DECLARE_CLASS(AFadeSetter, AActor) - - void PostBeginPlay() - { - Super::PostBeginPlay(); - Sector->SetFade(args[0], args[1], args[2]); - Destroy(); - } - -}; - -IMPLEMENT_CLASS(AFadeSetter, false, false) diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index a690107c90..0087690f71 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -214,15 +214,6 @@ public: ActorFlags FlagsSave; }; -class AMapMarker : public AActor -{ - DECLARE_CLASS(AMapMarker, AActor) -public: - void BeginPlay (); - void Activate (AActor *activator); - void Deactivate (AActor *activator); -}; - class AFastProjectile : public AActor { DECLARE_CLASS(AFastProjectile, AActor) diff --git a/src/g_shared/a_spark.cpp b/src/g_shared/a_spark.cpp deleted file mode 100644 index f13c7178f7..0000000000 --- a/src/g_shared/a_spark.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* -** a_spark.cpp -** Actor that makes a particle spark when activated -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 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 "actor.h" -#include "info.h" -#include "m_random.h" -#include "p_effect.h" -#include "s_sound.h" - -class ASpark : public AActor -{ - DECLARE_CLASS (ASpark, AActor) -public: - void Activate (AActor *activator); -}; - -IMPLEMENT_CLASS(ASpark, false, false) - -void ASpark::Activate (AActor *activator) -{ - Super::Activate (activator); - P_DrawSplash (args[0] ? args[0] : 32, Pos(), Angles.Yaw, 1); - S_Sound (this, CHAN_AUTO, "world/spark", 1, ATTN_STATIC); -} diff --git a/src/g_shared/a_waterzone.cpp b/src/g_shared/a_waterzone.cpp deleted file mode 100644 index 2245b22bd3..0000000000 --- a/src/g_shared/a_waterzone.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -** a_waterzone.cpp -** Actor that makes BOOM deep water swimmable -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 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 "info.h" -#include "r_defs.h" - -class AWaterZone : public AActor -{ - DECLARE_CLASS (AWaterZone, AActor) -public: - void PostBeginPlay (); -}; - -IMPLEMENT_CLASS(AWaterZone, false, false) - -void AWaterZone::PostBeginPlay () -{ - Super::PostBeginPlay (); - Sector->MoreFlags |= SECF_UNDERWATER; - Destroy (); -} - diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index a23e9943a6..99d38b2c1c 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -53,7 +53,6 @@ #include "p_lnspec.h" #include "p_effect.h" #include "p_enemy.h" -#include "a_action.h" #include "decallib.h" #include "m_random.h" #include "i_system.h" diff --git a/src/p_effect.cpp b/src/p_effect.cpp index ec051c2990..42e82d7405 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -574,6 +574,16 @@ void P_DrawSplash (int count, const DVector3 &pos, DAngle angle, int kind) } } +DEFINE_ACTION_FUNCTION(AActor, DrawSplash) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(count); + PARAM_FLOAT(angle); + PARAM_INT(kind); + P_DrawSplash(count, self->Pos(), angle, kind); + return 0; +} + void P_DrawSplash2 (int count, const DVector3 &pos, DAngle angle, int updown, int kind) { int color1, color2, zadd; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 3d9122930e..64e4feb4a7 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -42,7 +42,6 @@ #include "c_cvars.h" #include "p_enemy.h" #include "a_sharedglobal.h" -#include "a_action.h" #include "d_dehacked.h" #include "g_level.h" #include "r_utility.h" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5e2a9f0394..7decbe9adf 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -47,7 +47,6 @@ #include "p_acs.h" #include "cmdlib.h" #include "decallib.h" -#include "a_action.h" #include "a_keys.h" #include "p_conversation.h" #include "g_game.h" diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 2b8097e554..22ef883580 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -700,6 +700,16 @@ void sector_t::SetColor(int r, int g, int b, int desat) P_RecalculateAttachedLights(this); } +DEFINE_ACTION_FUNCTION(_Sector, SetColor) +{ + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_COLOR(color); + PARAM_INT(desat); + self->ColorMap = GetSpecialLights(color, self->ColorMap->Fade, desat); + P_RecalculateAttachedLights(self); + return 0; +} + void sector_t::SetFade(int r, int g, int b) { PalEntry fade = PalEntry (r,g,b); @@ -707,6 +717,16 @@ void sector_t::SetFade(int r, int g, int b) P_RecalculateAttachedLights(this); } +DEFINE_ACTION_FUNCTION(_Sector, SetFade) +{ + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_COLOR(fade); + self->ColorMap = GetSpecialLights(self->ColorMap->Color, fade, self->ColorMap->Desaturate); + P_RecalculateAttachedLights(self); + return 0; +} + + //=========================================================================== // // sector_t :: ClosestPoint diff --git a/src/p_spec.cpp b/src/p_spec.cpp index eb6b9bea7e..e4aea5595f 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -552,6 +552,15 @@ void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornu level.found_secrets++; } +DEFINE_ACTION_FUNCTION(AActor, GiveSecret) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL(printmessage); + PARAM_BOOL(playsound); + P_GiveSecret(self, printmessage, playsound, -1); + return 0; +} + //============================================================================ // // P_PlayerOnSpecialFlat diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 8321a8f899..400444340f 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -44,7 +44,6 @@ #include "s_sound.h" #include "cmdlib.h" #include "p_lnspec.h" -#include "a_action.h" #include "decallib.h" #include "i_system.h" #include "thingdef.h" diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 3b4abe002e..1cb0a91afd 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -45,7 +45,6 @@ #include "templates.h" #include "cmdlib.h" #include "p_lnspec.h" -#include "a_action.h" #include "p_local.h" #include "v_palette.h" #include "doomerrors.h" diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 5708f89d29..77120c9477 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -50,7 +50,6 @@ #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" diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 8586d32af2..cfadc53bf3 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -49,7 +49,6 @@ #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" diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c3dc3c1dd5..b4b4afeb1e 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -302,7 +302,6 @@ class Actor : Thinker native native void SetOrigin(vector3 newpos, bool moving); native void SetXYZ(vector3 newpos); native Actor GetPointer(int aaptr); - native void FaceMovementDirection(); native double BulletSlope(out FTranslatedLineTarget pLineTarget = null, int aimflags = 0); native Actor AimTarget(); native bool CheckMissileSpawn(double maxdist); @@ -375,6 +374,8 @@ class Actor : Thinker native native name GetSpecies(); native void PlayActiveSound(); native void Howl(); + native void DrawSplash (int count, double angle, int kind); + native void GiveSecret(bool printmsg = true, bool playsound = true); native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native Inventory FindInventory(class itemtype, bool subclass = false); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 73f515f71b..b1d9526ce7 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -17,20 +17,47 @@ class Object native class Thinker : Object native { + enum EStatnums + { + // Thinkers that don't actually think + STAT_INFO, // An info queue + STAT_DECAL, // A decal + STAT_AUTODECAL, // A decal that can be automatically deleted + STAT_CORPSEPOINTER, // An entry in Hexen's corpse queue + STAT_TRAVELLING, // An actor temporarily travelling to a new map + + // Thinkers that do think + STAT_FIRST_THINKING=32, + STAT_SCROLLER=STAT_FIRST_THINKING, // A DScroller thinker + STAT_PLAYER, // A player actor + STAT_BOSSTARGET, // A boss brain target + STAT_LIGHTNING, // The lightning thinker + STAT_DECALTHINKER, // An object that thinks for a decal + STAT_INVENTORY, // An inventory item + STAT_LIGHT, // A sector light effect + STAT_LIGHTTRANSFER, // A sector light transfer. These must be ticked after the light effects. + STAT_EARTHQUAKE, // Earthquake actors + STAT_MAPMARKER, // Map marker actors + + STAT_DEFAULT = 100, // Thinkers go here unless specified otherwise. + STAT_SECTOREFFECT, // All sector effects that cause floor and ceiling movement + STAT_ACTORMOVER, // actor movers + STAT_SCRIPTS, // The ACS thinker. This is to ensure that it can't tick before all actors called PostBeginPlay + STAT_BOT, // Bot thinker + MAX_STATNUM = 127 + } + const TICRATE = 35; virtual native void Tick(); virtual native void PostBeginPlay(); + virtual native void ChangeStatNum(int stat); } class ThinkerIterator : Object native { - enum EStatnums - { - MAX_STATNUM = 127 - } - native static ThinkerIterator Create(class type = "Actor", int statnum=MAX_STATNUM+1); + native static ThinkerIterator Create(class type = "Actor", int statnum=Thinker.MAX_STATNUM+1); native Thinker Next(bool exact = false); native void Reinit(); } @@ -87,11 +114,11 @@ struct LevelLocals native native readonly int maptype; native readonly String Music; native readonly int musicorder; - native readonly int total_secrets; + native int total_secrets; native int found_secrets; - native readonly int total_items; + native int total_items; native int found_items; - native readonly int total_monsters; + native int total_monsters; native int killed_monsters; native double gravity; native double aircontrol; @@ -225,6 +252,19 @@ struct Sector native native int16 leakydamage; native uint16 ZoneNumber; + + enum ESectorMoreFlags + { + SECMF_FAKEFLOORONLY = 2, // when used as heightsec in R_FakeFlat, only copies floor + SECMF_CLIPFAKEPLANES = 4, // as a heightsec, clip planes to target sector's planes + SECMF_NOFAKELIGHT = 8, // heightsec does not change lighting + SECMF_IGNOREHEIGHTSEC= 16, // heightsec is only for triggering sector actions + SECMF_UNDERWATER = 32, // sector is underwater + SECMF_FORCEDUNDERWATER= 64, // sector is forced to be underwater + SECMF_UNDERWATERMASK = 32+64, + SECMF_DRAWN = 128, // sector has been drawn at least once + SECMF_HIDDEN = 256, // Do not draw on textured automap + } native uint16 MoreFlags; enum ESectorFlags @@ -263,6 +303,8 @@ struct Sector native native void RemoveForceField(); native static Sector PointInSector(Vector2 pt); + native void SetColor(color c, int desat = 0); + native void SetFade(color c); } struct Wads diff --git a/wadsrc/static/zscript/raven/minotaur.txt b/wadsrc/static/zscript/raven/minotaur.txt index fa40cbec1f..5e3d0cfe37 100644 --- a/wadsrc/static/zscript/raven/minotaur.txt +++ b/wadsrc/static/zscript/raven/minotaur.txt @@ -757,3 +757,50 @@ class MinotaurSmokeExit : Actor } } +extend class Actor +{ + enum dirtype_t + { + DI_EAST, + DI_NORTHEAST, + DI_NORTH, + DI_NORTHWEST, + DI_WEST, + DI_SOUTHWEST, + DI_SOUTH, + DI_SOUTHEAST, + DI_NODIR, + NUMDIRS + }; + + void FaceMovementDirection() + { + switch (movedir) + { + case DI_EAST: + angle = 0.; + break; + case DI_NORTHEAST: + angle = 45.; + break; + case DI_NORTH: + angle = 90.; + break; + case DI_NORTHWEST: + angle = 135.; + break; + case DI_WEST: + angle = 180.; + break; + case DI_SOUTHWEST: + angle = 225.; + break; + case DI_SOUTH: + angle = 270.; + break; + case DI_SOUTHEAST: + angle = 315.; + break; + } + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/hatetarget.txt b/wadsrc/static/zscript/shared/hatetarget.txt index 6d2263f61b..e90abcdbb8 100644 --- a/wadsrc/static/zscript/shared/hatetarget.txt +++ b/wadsrc/static/zscript/shared/hatetarget.txt @@ -2,7 +2,7 @@ // Hate Target -------------------------------------------------------------- -class HateTarget : Actor native +class HateTarget : Actor { default { @@ -19,4 +19,32 @@ class HateTarget : Actor native Spawn: TNT1 A -1; } + + override void BeginPlay() + { + Super.BeginPlay(); + if (SpawnAngle != 0) + { // Each degree translates into 10 units of health + health = SpawnAngle * 10; + } + else + { + special2 = 1; + health = 1000001; + } + } + + override int TakeSpecialDamage(Actor inflictor, Actor source, int damage, Name damagetype) + { + if (special2 != 0) + { + return 0; + } + else + { + return damage; + } + } + + } \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/mapmarker.txt b/wadsrc/static/zscript/shared/mapmarker.txt index 1afa00459d..25e1973077 100644 --- a/wadsrc/static/zscript/shared/mapmarker.txt +++ b/wadsrc/static/zscript/shared/mapmarker.txt @@ -1,5 +1,20 @@ +// Map Marker -------------------------------------------------------------- +// +// This class uses the following argument: +// args[0] == 0, shows the sprite at this actor +// != 0, shows the sprite for all actors whose TIDs match instead +// +// args[1] == 0, show the sprite always +// == 1, show the sprite only after its sector has been drawn +// +// To enable display of the sprite, activate it. To turn off the sprite, +// deactivate it. +// +// All the code to display it is in am_map.cpp. +// +//-------------------------------------------------------------------------- -class MapMarker : Actor native +class MapMarker : Actor { default { @@ -15,4 +30,20 @@ class MapMarker : Actor native AMRK A -1; Stop; } + + override void BeginPlay () + { + ChangeStatNum (STAT_MAPMARKER); + } + + override void Activate (Actor activator) + { + bDormant = true; + } + + override void Deactivate (Actor activator) + { + bDormant = false; + } + } diff --git a/wadsrc/static/zscript/shared/secrettrigger.txt b/wadsrc/static/zscript/shared/secrettrigger.txt index 48c93686ea..c60399600d 100644 --- a/wadsrc/static/zscript/shared/secrettrigger.txt +++ b/wadsrc/static/zscript/shared/secrettrigger.txt @@ -1,5 +1,5 @@ -class SecretTrigger : Actor native +class SecretTrigger : Actor { default { @@ -8,5 +8,19 @@ class SecretTrigger : Actor native +NOGRAVITY +DONTSPLASH } + + override void PostBeginPlay () + { + Super.PostBeginPlay (); + level.total_secrets++; + } + + override void Activate (Actor activator) + { + activator.GiveSecret(args[0] <= 1, (args[0] == 0 || args[0] == 2)); + Destroy (); + } + + } diff --git a/wadsrc/static/zscript/shared/setcolor.txt b/wadsrc/static/zscript/shared/setcolor.txt index 8689e5fd10..18105ef543 100644 --- a/wadsrc/static/zscript/shared/setcolor.txt +++ b/wadsrc/static/zscript/shared/setcolor.txt @@ -1,4 +1,4 @@ -class ColorSetter : Actor native +class ColorSetter : Actor { default { @@ -7,10 +7,18 @@ class ColorSetter : Actor native +DONTSPLASH RenderStyle "None"; } + + override void PostBeginPlay() + { + Super.PostBeginPlay(); + CurSector.SetColor(color(args[0], args[1], args[2]), args[3]); + Destroy(); + } + } -class FadeSetter : Actor native +class FadeSetter : Actor { default { @@ -19,4 +27,13 @@ class FadeSetter : Actor native +DONTSPLASH RenderStyle "None"; } + + void PostBeginPlay() + { + Super.PostBeginPlay(); + CurSector.SetFade(color(args[0], args[1], args[2])); + Destroy(); + } + + } diff --git a/wadsrc/static/zscript/shared/sharedmisc.txt b/wadsrc/static/zscript/shared/sharedmisc.txt index 5989702fdf..6da942e393 100644 --- a/wadsrc/static/zscript/shared/sharedmisc.txt +++ b/wadsrc/static/zscript/shared/sharedmisc.txt @@ -157,13 +157,25 @@ class CustomSprite : Actor native // SwitchableDecoration: Activate and Deactivate change state -------------- -class SwitchableDecoration : Actor native +class SwitchableDecoration : Actor { + override void Activate (Actor activator) + { + SetStateLabel("Active"); + } + + override void Deactivate (Actor activator) + { + SetStateLabel("Inactive"); + } + } - -class SwitchingDecoration : SwitchableDecoration native +class SwitchingDecoration : SwitchableDecoration { + override void Deactivate (Actor activator) + { + } } // Random spawner ---------------------------------------------------------- diff --git a/wadsrc/static/zscript/shared/spark.txt b/wadsrc/static/zscript/shared/spark.txt index 5adffdfe1c..c5ae6a455c 100644 --- a/wadsrc/static/zscript/shared/spark.txt +++ b/wadsrc/static/zscript/shared/spark.txt @@ -1,5 +1,5 @@ -class Spark : Actor native +class Spark : Actor { default { @@ -8,4 +8,12 @@ class Spark : Actor native +NOGRAVITY +DONTSPLASH } + + override void Activate (Actor activator) + { + Super.Activate (activator); + DrawSplash (args[0] ? args[0] : 32, Angle, 1); + A_PlaySound ("world/spark", CHAN_AUTO, 1, false, ATTN_STATIC); + } + } \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/waterzone.txt b/wadsrc/static/zscript/shared/waterzone.txt index 975c8a473b..49d950b00d 100644 --- a/wadsrc/static/zscript/shared/waterzone.txt +++ b/wadsrc/static/zscript/shared/waterzone.txt @@ -1,4 +1,4 @@ -class WaterZone : Actor native +class WaterZone : Actor { default { @@ -7,4 +7,13 @@ class WaterZone : Actor native +NOGRAVITY +DONTSPLASH } + + override void PostBeginPlay () + { + Super.PostBeginPlay (); + CurSector.MoreFlags |= Sector.SECMF_UNDERWATER; + Destroy (); + } + + } From 91934665729693e4be7092549f885b0813fdc80e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 20:16:14 +0100 Subject: [PATCH 415/471] - scriptified ASecurityCamera and AAimingCamera. This concludes this round of script converesions of internal classes. --- src/CMakeLists.txt | 1 - src/g_shared/a_camera.cpp | 200 ------------------------ src/p_mobj.cpp | 7 + wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/shared/camera.txt | 107 ++++++++++++- 5 files changed, 110 insertions(+), 206 deletions(-) delete mode 100644 src/g_shared/a_camera.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 111b2663c8..d1e90581c7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1111,7 +1111,6 @@ set (PCH_SOURCES g_shared/a_armor.cpp g_shared/a_artifacts.cpp g_shared/a_bridge.cpp - g_shared/a_camera.cpp g_shared/a_decals.cpp g_shared/a_fastprojectile.cpp g_shared/a_flashfader.cpp diff --git a/src/g_shared/a_camera.cpp b/src/g_shared/a_camera.cpp deleted file mode 100644 index a0bc40ce33..0000000000 --- a/src/g_shared/a_camera.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* -** a_camera.cpp -** Implements the Duke Nukem 3D-ish security camera -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 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 "actor.h" -#include "info.h" -#include "a_sharedglobal.h" -#include "p_local.h" -#include "serializer.h" -#include "math/cmath.h" - -/* -== SecurityCamera -== -== args[0] = pitch -== args[1] = amount camera turns to either side of its initial position -== (in degrees) -== args[2] = octics to complete one cycle -*/ - -class ASecurityCamera : public AActor -{ - DECLARE_CLASS (ASecurityCamera, AActor) -public: - void PostBeginPlay (); - void Tick (); - - - void Serialize(FSerializer &arc); -protected: - DAngle Center; - DAngle Acc; - DAngle Delta; - DAngle Range; -}; - -IMPLEMENT_CLASS(ASecurityCamera, false, false) - -void ASecurityCamera::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - arc("center", Center) - ("acc", Acc) - ("delta", Delta) - ("range", Range); -} - -void ASecurityCamera::PostBeginPlay () -{ - Super::PostBeginPlay (); - Center = Angles.Yaw; - if (args[2]) - Delta = 360. / (args[2] * TICRATE / 8); - else - Delta = 0.; - if (args[1]) - Delta /= 2; - Acc = 0.; - Angles.Pitch = (double)clamp((signed char)args[0], -89, 89); - Range = (double)args[1]; -} - -void ASecurityCamera::Tick () -{ - Acc += Delta; - if (Range != 0) - Angles.Yaw = Center + Range * Acc.Sin(); - else if (Delta != 0) - Angles.Yaw = Acc; -} - -/* -== AimingCamera -== -== args[0] = pitch -== args[1] = max turn (in degrees) -== args[2] = max pitch turn (in degrees) -== args[3] = tid of thing to look at -== -== Also uses: -== tracer: thing to look at -*/ - -class AAimingCamera : public ASecurityCamera -{ - DECLARE_CLASS (AAimingCamera, ASecurityCamera) -public: - void PostBeginPlay (); - void Tick (); - - - void Serialize(FSerializer &arc); -protected: - DAngle MaxPitchChange; -}; - -IMPLEMENT_CLASS(AAimingCamera, false, false) - -void AAimingCamera::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - arc("maxpitchchange", MaxPitchChange); -} - -void AAimingCamera::PostBeginPlay () -{ - int changepitch = args[2]; - - args[2] = 0; - Super::PostBeginPlay (); - MaxPitchChange = double(changepitch / TICRATE); - Range /= TICRATE; - - TActorIterator iterator (args[3]); - tracer = iterator.Next (); - if (tracer == NULL) - { - //Printf ("AimingCamera %d: Can't find TID %d\n", tid, args[3]); - } - else - { // Don't try for a new target upon losing this one. - args[3] = 0; - } -} - -void AAimingCamera::Tick () -{ - if (tracer == NULL && args[3] != 0) - { // Recheck, in case something with this TID was created since the last time. - TActorIterator iterator (args[3]); - tracer = iterator.Next (); - } - if (tracer != NULL) - { - DAngle delta; - int dir = P_FaceMobj (this, tracer, &delta); - if (delta > Range) - { - delta = Range; - } - if (dir) - { - Angles.Yaw += delta; - } - else - { - Angles.Yaw -= delta; - } - if (MaxPitchChange != 0) - { // Aim camera's pitch; use floats for precision - DVector2 vect = tracer->Vec2To(this); - double dz = Z() - tracer->Z() - tracer->Height/2; - double dist = vect.Length(); - DAngle desiredPitch = dist != 0.f ? VecToAngle(dist, dz) : 0.; - DAngle diff = deltaangle(Angles.Pitch, desiredPitch); - if (fabs (diff) < MaxPitchChange) - { - Angles.Pitch = desiredPitch; - } - else if (diff < 0) - { - Angles.Pitch -= MaxPitchChange; - } - else - { - Angles.Pitch += MaxPitchChange; - } - } - } -} diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7decbe9adf..9c0f587ebb 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7539,6 +7539,13 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3To) ACTION_RETURN_VEC3(self->Vec3To(t)); } +DEFINE_ACTION_FUNCTION(AActor, Vec2To) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(t, AActor) + ACTION_RETURN_VEC2(self->Vec2To(t)); +} + DEFINE_ACTION_FUNCTION(AActor, Vec3Angle) { PARAM_SELF_PROLOGUE(AActor); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index b4b4afeb1e..15c6430477 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -356,6 +356,7 @@ class Actor : Thinker native native double AngleTo(Actor target, bool absolute = false); native void AddZ(double zadd, bool moving = true); native void SetZ(double z); + native vector2 Vec2To(Actor other); native vector3 Vec3To(Actor other); native vector3 Vec3Offset(double x, double y, double z, bool absolute = false); native vector3 Vec3Angle(double length, double angle, double z = 0, bool absolute = false); diff --git a/wadsrc/static/zscript/shared/camera.txt b/wadsrc/static/zscript/shared/camera.txt index 9420c98d5a..abb394745e 100644 --- a/wadsrc/static/zscript/shared/camera.txt +++ b/wadsrc/static/zscript/shared/camera.txt @@ -9,21 +9,118 @@ class DoomBuilderCamera : Actor } -class SecurityCamera : Actor native +class SecurityCamera : Actor { default { +NOBLOCKMAP +NOGRAVITY +DONTSPLASH - } - default - { RenderStyle "None"; CameraHeight 0; } + + double Center; + double Acc; + double Delta; + double Range; + + override void PostBeginPlay () + { + Super.PostBeginPlay (); + Center = Angle; + if (args[2]) + Delta = 360. / (args[2] * TICRATE / 8); + else + Delta = 0.; + if (args[1]) + Delta /= 2; + Acc = 0.; + Pitch = clamp(args[0], -89, 89); + Range = args[1]; + } + + override void Tick () + { + Acc += Delta; + if (Range != 0) + Angle = Center + Range * sin(Acc); + else if (Delta != 0) + Angle = Acc; + } + + } -class AimingCamera : SecurityCamera native +class AimingCamera : SecurityCamera { + double MaxPitchChange; + + override void PostBeginPlay () + { + int changepitch = args[2]; + + args[2] = 0; + Super.PostBeginPlay (); + MaxPitchChange = double(changepitch / TICRATE); + Range /= TICRATE; + + ActorIterator it = ActorIterator.Create(args[3]); + tracer = it.Next (); + if (tracer == NULL) + { + //Printf ("AimingCamera %d: Can't find TID %d\n", tid, args[3]); + } + else + { // Don't try for a new target upon losing this one. + args[3] = 0; + } + } + + override void Tick () + { + if (tracer == NULL && args[3] != 0) + { // Recheck, in case something with this TID was created since the last time. + ActorIterator it = ActorIterator.Create(args[3]); + tracer = it.Next (); + } + if (tracer != NULL) + { + double dir = deltaangle(angle, AngleTo(tracer)); + double delta = abs(dir); + if (delta > Range) + { + delta = Range; + } + if (dir > 0) + { + Angle += delta; + } + else + { + Angle -= delta; + } + if (MaxPitchChange != 0) + { // Aim camera's pitch; use floats for precision + Vector2 vect = tracer.Vec2To(self); + double dz = pos.z - tracer.pos.z - tracer.Height/2; + double dist = vect.Length(); + double desiredPitch = dist != 0.f ? VectorAngle(dist, dz) : 0.; + double diff = deltaangle(pitch, desiredPitch); + if (abs (diff) < MaxPitchChange) + { + pitch = desiredPitch; + } + else if (diff < 0) + { + pitch -= MaxPitchChange; + } + else + { + pitch += MaxPitchChange; + } + } + } + } + } From 4372a14479765b1114564587170dd1c1b782362c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 20:28:04 +0100 Subject: [PATCH 416/471] - fixed: Giving several morph items in the same tic could lead to an invalid Owner pointer in APowerupGiver::Use. --- src/g_shared/a_artifacts.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 99a4f46d84..5866e8b2ae 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -72,6 +72,7 @@ DEFINE_FIELD(APowerupGiver, Strength) bool APowerupGiver::Use (bool pickup) { if (PowerupType == NULL) return true; // item is useless + if (Owner == nullptr) return true; APowerup *power = static_cast (Spawn (PowerupType)); From bbf62132d83645557368f7abd846ec234b7d2b1f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 01:25:51 +0100 Subject: [PATCH 417/471] - added a larger batch of function exports. - cleaned up the virtual function interface of APlayerPawn which still had many virtual declarations from old times when class properties were handled through virtual overrides. None of this makes sense these days anymore. --- src/d_player.h | 39 ++--- src/info.cpp | 7 + src/p_ceiling.cpp | 16 ++ src/p_enemy.cpp | 43 +++++- src/p_interaction.cpp | 14 ++ src/p_map.cpp | 43 ++++++ src/p_mobj.cpp | 187 +++++++++++++++++++++++- src/p_user.cpp | 27 +++- src/s_sound.cpp | 11 ++ wadsrc/static/zscript/actor.txt | 47 +++++- wadsrc/static/zscript/base.txt | 92 +++++++++++- wadsrc/static/zscript/shared/player.txt | 13 ++ 12 files changed, 498 insertions(+), 41 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index d1678b6199..95a288ebdf 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -105,29 +105,36 @@ public: virtual void Serialize(FSerializer &arc); - virtual void PostBeginPlay(); - virtual void Tick(); - virtual void AddInventory (AInventory *item); - virtual void RemoveInventory (AInventory *item); - virtual bool UseInventory (AInventory *item); - virtual void MarkPrecacheSounds () const; + virtual void PostBeginPlay() override; + virtual void Tick() override; + virtual void AddInventory (AInventory *item) override; + virtual void RemoveInventory (AInventory *item) override; + virtual bool UseInventory (AInventory *item) override; + virtual void MarkPrecacheSounds () const override; + virtual void BeginPlay () override; + virtual void Die (AActor *source, AActor *inflictor, int dmgflags) override; + virtual bool UpdateWaterLevel (bool splash) override; - virtual void PlayIdle (); - virtual void PlayRunning (); - virtual void ThrowPoisonBag (); - virtual void TweakSpeeds (double &forwardmove, double &sidemove); + bool ResetAirSupply (bool playgasp = true); + int GetMaxHealth() const; + void TweakSpeeds (double &forwardmove, double &sidemove); void MorphPlayerThink (); - virtual void ActivateMorphWeapon (); + void ActivateMorphWeapon (); AWeapon *PickNewWeapon (PClassAmmo *ammotype); AWeapon *BestWeapon (PClassAmmo *ammotype); void CheckWeaponSwitch(PClassAmmo *ammotype); - virtual void GiveDeathmatchInventory (); - virtual void FilterCoopRespawnInventory (APlayerPawn *oldplayer); + void GiveDeathmatchInventory (); + void FilterCoopRespawnInventory (APlayerPawn *oldplayer); void SetupWeaponSlots (); void GiveDefaultInventory (); + + // These are virtual on the script side only. + void PlayIdle(); + void PlayRunning(); void PlayAttacking (); void PlayAttacking2 (); + const char *GetSoundClass () const; enum EInvulState @@ -138,8 +145,6 @@ public: INVUL_GetAlpha }; - void BeginPlay (); - void Die (AActor *source, AActor *inflictor, int dmgflags); int crouchsprite; int MaxHealth; @@ -171,10 +176,6 @@ public: // [SP] ViewBob Multiplier double ViewBob; - bool UpdateWaterLevel (bool splash); - bool ResetAirSupply (bool playgasp = true); - - int GetMaxHealth() const; }; class APlayerChunk : public APlayerPawn diff --git a/src/info.cpp b/src/info.cpp index 8a2842ff45..69605d454d 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -151,6 +151,13 @@ int GetSpriteIndex(const char * spritename, bool add) return (lastindex = (int)sprites.Push (temp)); } +DEFINE_ACTION_FUNCTION(AActor, GetSpriteIndex) +{ + PARAM_PROLOGUE; + PARAM_NAME(sprt); + ACTION_RETURN_INT(GetSpriteIndex(sprt.GetChars(), false)); +} + IMPLEMENT_CLASS(PClassActor, false, true) IMPLEMENT_POINTERS_START(PClassActor) diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index a38a17f9ca..932b4c6493 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -458,6 +458,22 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t return ceiling != NULL; } +DEFINE_ACTION_FUNCTION(DCeiling, CreateCeiling) +{ + PARAM_PROLOGUE; + PARAM_POINTER(sec, sector_t); + PARAM_INT(type); + PARAM_POINTER(ln, line_t); + PARAM_FLOAT(speed); + PARAM_FLOAT(speed2); + PARAM_FLOAT_DEF(height); + PARAM_INT_DEF(crush); + PARAM_INT_DEF(silent); + PARAM_INT_DEF(change); + PARAM_INT_DEF(crushmode); + ACTION_RETURN_BOOL(P_CreateCeiling(sec, (DCeiling::ECeiling)type, ln, 0, speed, speed2, height, crush, silent, change, (DCeiling::ECrushMode)crushmode)); +} + //============================================================================ // // EV_DoCeiling diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 64e4feb4a7..5b2ba6d655 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1283,6 +1283,14 @@ void P_RandomChaseDir (AActor *actor) actor->movedir = DI_NODIR; // cannot move } +DEFINE_ACTION_FUNCTION(AActor, RandomChaseDir) +{ + PARAM_SELF_PROLOGUE(AActor); + P_RandomChaseDir(self); + return 0; +} + + //--------------------------------------------------------------------------- // // P_IsVisible @@ -1335,6 +1343,15 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams return P_CheckSight(lookee, other, SF_SEEPASTSHOOTABLELINES); } +DEFINE_ACTION_FUNCTION(AActor, IsVisible) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + PARAM_BOOL(allaround); + PARAM_POINTER_DEF(params, FLookExParams); + ACTION_RETURN_BOOL(P_IsVisible(self, other, allaround, params)); +} + //--------------------------------------------------------------------------- // // FUNC P_LookForMonsters @@ -1388,6 +1405,12 @@ bool P_LookForMonsters (AActor *actor) return false; } +DEFINE_ACTION_FUNCTION(AActor, LookForMonsters) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(P_LookForMonsters(self)); +} + //============================================================================ // // LookForTIDinBlock @@ -1560,6 +1583,14 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround, FLookExParams *params) return false; } +DEFINE_ACTION_FUNCTION(AActor, LookForTID) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL(allaround); + PARAM_POINTER_DEF(params, FLookExParams); + ACTION_RETURN_BOOL(P_LookForTID(self, allaround, params)); +} + //============================================================================ // // LookForEnemiesinBlock @@ -1699,6 +1730,15 @@ bool P_LookForEnemies (AActor *actor, INTBOOL allaround, FLookExParams *params) return false; } +DEFINE_ACTION_FUNCTION(AActor, LookForEnemies) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL(allaround); + PARAM_POINTER_DEF(params, FLookExParams); + ACTION_RETURN_BOOL(P_LookForEnemies(self, allaround, params)); +} + + /* ================ = @@ -1886,7 +1926,8 @@ DEFINE_ACTION_FUNCTION(AActor, LookForPlayers) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(allaround); - ACTION_RETURN_BOOL(P_LookForPlayers(self, allaround, nullptr)); + PARAM_POINTER_DEF(params, FLookExParams); + ACTION_RETURN_BOOL(P_LookForPlayers(self, allaround, params)); } // diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index a5fcc2dda5..e0e3e62b9a 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1636,6 +1636,20 @@ void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage } +DEFINE_ACTION_FUNCTION(AActor, PoisonMobj) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(inflictor, AActor); + PARAM_OBJECT(source, AActor); + PARAM_INT(damage); + PARAM_INT(duration); + PARAM_INT(period); + PARAM_NAME(mod); + P_PoisonMobj(self, inflictor, source, damage, duration, period, mod); + return 0; +} + + bool AActor::OkayToSwitchTarget (AActor *other) { if (other == this) diff --git a/src/p_map.cpp b/src/p_map.cpp index c5780eedcd..11036d1716 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -297,6 +297,14 @@ void P_FindFloorCeiling(AActor *actor, int flags) } } +DEFINE_ACTION_FUNCTION(AActor, FindFloorCeiling) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_DEF(flags); + P_FindFloorCeiling(self, flags); + return 0; +} + // Debug CCMD for checking errors in the MultiBlockLinesIterator (needs to be removed when this code is complete) CCMD(ffcf) { @@ -661,6 +669,21 @@ double P_GetMoveFactor(const AActor *mo, double *frictionp) return movefactor; } +DEFINE_ACTION_FUNCTION(AActor, GetFriction) +{ + PARAM_SELF_PROLOGUE(AActor); + double friction, movefactor = P_GetMoveFactor(self, &friction); + if (numret > 1) + { + numret = 2; + ret[1].SetFloat(movefactor); + } + if (numret > 0) + { + ret[0].SetFloat(friction); + } + return numret; +} //========================================================================== // @@ -1885,6 +1908,26 @@ bool P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) return onmobj == NULL; } +DEFINE_ACTION_FUNCTION(AActor, TestMobjZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL_DEF(quick); + + AActor *on = nullptr;; + bool retv = P_TestMobjZ(self, quick, &on); + if (numret > 1) + { + numret = 2; + ret[1].SetPointer(on, ATAG_OBJECT); + } + if (numret > 0) + { + ret[0].SetInt(retv); + } + return numret; +} + + //============================================================================= // // P_FakeZMovement diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 9c0f587ebb..d099a8e775 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -568,6 +568,13 @@ bool AActor::InStateSequence(FState * newstate, FState * basestate) return false; } +DEFINE_ACTION_FUNCTION(AActor, InStateSequence) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER(newstate, FState); + PARAM_POINTER(basestate, FState); + ACTION_RETURN_BOOL(self->InStateSequence(newstate, basestate)); +} //========================================================================== // // AActor::GetTics @@ -736,6 +743,15 @@ void AActor::AddInventory (AInventory *item) Inventory->InventoryID = InventoryID++; } +DEFINE_ACTION_FUNCTION(AActor, AddInventory) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(item, AInventory); + self->AddInventory(item); + return 0; +} + + //============================================================================ // // AActor :: GiveInventory @@ -795,6 +811,14 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat) return result; } +DEFINE_ACTION_FUNCTION(AActor, Inventory) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(item, AInventory); + ACTION_RETURN_BOOL(self->UseInventory(item)); +} + + //============================================================================ // // AActor :: RemoveInventory @@ -822,6 +846,15 @@ void AActor::RemoveInventory(AInventory *item) } } +DEFINE_ACTION_FUNCTION(AActor, RemoveInventory) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(item, AInventory); + self->RemoveInventory(item); + return 0; +} + + //============================================================================ // // AActor :: TakeInventory @@ -1186,6 +1219,14 @@ void AActor::ClearInventory() } } +DEFINE_ACTION_FUNCTION(AActor, ClearInventory) +{ + PARAM_SELF_PROLOGUE(AActor); + self->ClearInventory(); + return 0; +} + + //============================================================================ // // AActor :: CopyFriendliness @@ -3176,6 +3217,18 @@ DEFINE_ACTION_FUNCTION(AActor, RemoveFromHash) return 0; } +DEFINE_ACTION_FUNCTION(AActor, ChangeTid) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(tid); + self->RemoveFromHash(); + self->tid = tid; + self->AddToHash(); + return 0; +} + + + //========================================================================== // // P_IsTIDUsed @@ -3258,6 +3311,17 @@ int P_FindUniqueTID(int start_tid, int limit) return 0; } +DEFINE_ACTION_FUNCTION(AActor, FindUniqueTid) +{ + PARAM_PROLOGUE; + PARAM_INT_DEF(start); + PARAM_INT_DEF(limit); + ACTION_RETURN_INT(P_FindUniqueTID(start, limit)); +} + + + + CCMD(utid) { Printf("%d\n", @@ -3537,6 +3601,14 @@ void AActor::SetShade (int r, int g, int b) fillcolor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b); } +DEFINE_ACTION_FUNCTION(AActor, SetShade) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(color); + self->SetShade(color); + return 0; +} + void AActor::SetPitch(DAngle p, bool interpolate, bool forceclamp) { if (player != NULL || forceclamp) @@ -5777,6 +5849,19 @@ void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *origina P_DrawSplash2 (40, pos, dir, 2, bloodcolor); } +DEFINE_ACTION_FUNCTION(AActor, SpawnBlood) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_ANGLE(dir); + PARAM_INT(damage); + P_SpawnBlood(DVector3(x, y, z), dir, damage, self); + return 0; +} + + //--------------------------------------------------------------------------- // // PROC P_BloodSplatter @@ -5859,6 +5944,20 @@ void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle) } } +DEFINE_ACTION_FUNCTION(AActor, BloodSplatter) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_ANGLE(dir); + PARAM_BOOL_DEF(axe); + if (axe) P_BloodSplatter2(DVector3(x, y, z), self, dir); + else P_BloodSplatter(DVector3(x, y, z), self, dir); + return 0; +} + + //--------------------------------------------------------------------------- // // PROC P_RipperBlood @@ -6078,6 +6177,20 @@ foundone: return plane == &sec->floorplane ? Terrains[terrainnum].IsLiquid : false; } +DEFINE_ACTION_FUNCTION(AActor, HitWater) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER(sec, sector_t); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_BOOL_DEF(checkabove); + PARAM_BOOL_DEF(alert); + PARAM_BOOL_DEF(force); + ACTION_RETURN_BOOL(P_HitWater(self, sec, DVector3(x, y, z), checkabove, alert, force)); +} + + //--------------------------------------------------------------------------- // // FUNC P_HitFloor @@ -6284,6 +6397,15 @@ void P_PlaySpawnSound(AActor *missile, AActor *spawner) } } +DEFINE_ACTION_FUNCTION(AActor, PlaySpawnSound) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(missile, AActor); + P_PlaySpawnSound(missile, self); + return 0; +} + + static double GetDefaultSpeed(PClassActor *type) { if (type == NULL) @@ -6911,6 +7033,14 @@ bool AActor::IsHostile (AActor *other) return true; } +DEFINE_ACTION_FUNCTION(AActor, isHostile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_BOOL(self->IsHostile(other)); +} + + //========================================================================== // // AActor :: DoSpecialDamage @@ -7179,6 +7309,13 @@ double AActor::GetCameraHeight() const return GetClass()->CameraHeight == INT_MIN ? Height / 2 : GetClass()->CameraHeight; } +DEFINE_ACTION_FUNCTION(AActor, GetCameraHeight) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_FLOAT(self->GetCameraHeight()); +} + + DDropItem *AActor::GetDropItems() const { return GetClass()->DropItems; @@ -7196,6 +7333,13 @@ double AActor::GetGravity() const return level.gravity * Sector->gravity * Gravity * 0.00125; } +DEFINE_ACTION_FUNCTION(AActor, GetGravity) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_FLOAT(self->GetGravity()); +} + + // killough 11/98: // Whether an object is "sentient" or not. Used for environmental influences. // (left precisely the same as MBF even though it doesn't make much sense.) @@ -7240,14 +7384,17 @@ DEFINE_ACTION_FUNCTION(AActor, GetTag) void AActor::SetTag(const char *def) { - if (def == NULL || *def == 0) - { - Tag = NULL; - } - else - { - Tag = mStringPropertyData.Alloc(def); - } + if (def == NULL || *def == 0) Tag = nullptr; + else Tag = mStringPropertyData.Alloc(def); +} + +DEFINE_ACTION_FUNCTION(AActor, SetTag) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(def); + if (def.IsEmpty()) self->Tag = nullptr; + else self->Tag = self->mStringPropertyData.Alloc(def); + return 0; } @@ -7392,6 +7539,13 @@ DEFINE_ACTION_FUNCTION(AActor, Distance2D) ACTION_RETURN_FLOAT(self->Distance2D(other)); } +DEFINE_ACTION_FUNCTION(AActor, Distance3D) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_FLOAT(self->Distance3D(other)); +} + DEFINE_ACTION_FUNCTION(AActor, AddZ) { PARAM_SELF_PROLOGUE(AActor); @@ -7455,6 +7609,17 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) return 0; } +// This combines all 3 variations of the internal function +DEFINE_ACTION_FUNCTION(AActor, Vel3DFromAngle) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(speed); + PARAM_ANGLE(angle); + PARAM_ANGLE(pitch); + self->Vel3DFromAngle(pitch, angle, speed); + return 0; +} + // This combines all 3 variations of the internal function DEFINE_ACTION_FUNCTION(AActor, Thrust) { @@ -7619,6 +7784,12 @@ DEFINE_ACTION_FUNCTION(AActor, AccuracyFactor) ACTION_RETURN_FLOAT(self->AccuracyFactor()); } +DEFINE_ACTION_FUNCTION(AActor, CountsAsKill) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_FLOAT(self->CountsAsKill()); +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/p_user.cpp b/src/p_user.cpp index 1ac60ba351..66437d4308 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1285,6 +1285,13 @@ bool APlayerPawn::ResetAirSupply (bool playgasp) return wasdrowning; } +DEFINE_ACTION_FUNCTION(APlayerPawn, ResetAirSupply) +{ + PARAM_SELF_PROLOGUE(APlayerPawn); + PARAM_BOOL_DEF(playgasp); + ACTION_RETURN_BOOL(self->ResetAirSupply(playgasp)); +} + //=========================================================================== // // Animations @@ -1293,14 +1300,22 @@ bool APlayerPawn::ResetAirSupply (bool playgasp) void APlayerPawn::PlayIdle () { - if (InStateSequence(state, SeeState)) - SetState (SpawnState); + IFVIRTUAL(APlayerPawn, PlayIdle) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } } void APlayerPawn::PlayRunning () { - if (InStateSequence(state, SpawnState) && SeeState != NULL) - SetState (SeeState); + IFVIRTUAL(APlayerPawn, PlayRunning) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } } void APlayerPawn::PlayAttacking () @@ -1323,10 +1338,6 @@ void APlayerPawn::PlayAttacking2 () } } -void APlayerPawn::ThrowPoisonBag () -{ -} - //=========================================================================== // // APlayerPawn :: GiveDefaultInventory diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 81b94b0f22..fd15b94910 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -2607,6 +2607,17 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) return false; } +DEFINE_ACTION_FUNCTION(DObject, S_ChangeMusic) +{ + PARAM_PROLOGUE; + PARAM_STRING(music); + PARAM_INT_DEF(order); + PARAM_BOOL(looping); + PARAM_BOOL(force); + ACTION_RETURN_BOOL(S_ChangeMusic(music, order, looping, force)); +} + + //========================================================================== // // S_RestartMusic diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 15c6430477..5eebb73504 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -33,7 +33,7 @@ class Actor : Thinker native native vector2 Scale; native TextureID picnum; native double Alpha; - native color fillcolor; + native readonly color fillcolor; // must be set with SetShade to initialize correctly. native Sector CurSector; native double CeilingZ; native double FloorZ; @@ -276,10 +276,16 @@ class Actor : Thinker native } + native static int GetSpriteIndex(name sprt); native static double GetDefaultSpeed(class type); native static class GetSpawnableType(int spawnnum); native void RemoveFromHash(); + native void ChangeTid(int newtid); + native static int FindUniqueTid(int start = 0, int limit = 0); + native void SetShade(color col); + native string GetTag(string defstr = ""); + native void SetTag(string defstr = ""); native double GetBobOffset(double frac = 0); native void ClearCounters(); native bool GiveBody (int num, int max=0); @@ -299,6 +305,7 @@ class Actor : Thinker native native int SpawnHealth(); native void SetDamage(int dmg); native double Distance2D(Actor other); + native double Distance3D(Actor other); native void SetOrigin(vector3 newpos, bool moving); native void SetXYZ(vector3 newpos); native Actor GetPointer(int aaptr); @@ -328,7 +335,12 @@ class Actor : Thinker native void A_LightInverse() { if (player) player.extralight = 0x80000000; } native Actor OldSpawnMissile(Actor dest, class type, Actor owner = null); - native Actor SpawnPuff(class pufftype, vector3 pos, double hitdir, double particledir, int updown, int flags = 0, Actor vict = null); + native Actor SpawnPuff(class pufftype, vector3 pos, double hitdir, double particledir, int updown, int flags = 0, Actor victim = null); + native void SpawnBlood (Vector3 pos1, double dir, int damage); + native void BloodSplatter (Vector3 pos, double hitangle, bool axe = false); + native bool HitWater (sector sec, Vector3 pos, bool checkabove = false, bool alert = true, bool force = false); + native void PlaySpawnSound(Actor missile); + native bool CountsAsKill(); native bool Teleport(Vector3 pos, double angle, int flags); native void TraceBleed(int damage, Actor missile); @@ -338,13 +350,32 @@ class Actor : Thinker native native bool CheckMeleeRange(); native bool CheckMeleeRange2(); native int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0); + native void PoisonMobj (Actor inflictor, Actor source, int damage, int duration, int period, Name type); 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 IsVisible(Actor other, bool allaround, LookExParams params = null); native bool HitFriend(); native bool MonsterMove(); + + native void FindFloorCeiling(int flags = 0); + native double, double GetFriction(); + native bool, Actor TestMobjZ(bool quick = false); + native bool InStateSequence(State newstate, State basestate); + + bool TryWalk () + { + if (!MonsterMove ()) + { + return false; + } + movecount = random[TryWalk]() & 15; + return true; + } + native bool TryMove(vector2 newpos, int dropoff); native void NewChaseDir(); + native void RandomChaseDir(); native bool CheckMissileRange(); native bool SetState(state st, bool nofunction = false); native state FindState(statelabel st, bool exact = false); @@ -364,12 +395,17 @@ class Actor : Thinker native native vector2 Vec2Offset(double x, double y, bool absolute = false); native vector3 Vec2OffsetZ(double x, double y, double atz, bool absolute = false); native void VelFromAngle(double speed = 0, double angle = 0); + native void Vel3DFromAngle(double speed, double angle, double pitch); native void Thrust(double speed = 0, double angle = 0); native bool isFriend(Actor other); + native bool isHostile(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 LookForMonsters(); + native bool LookForTid(bool allaround, LookExParams params = null); + native bool LookForEnemies(bool allaround, LookExParams params = null); + native bool LookForPlayers(bool allaround, LookExParams params = null); native bool TeleportMove(Vector3 pos, bool telefrag, bool modifyactor = true); native double DistanceBySpeed(Actor other, double speed); native name GetSpecies(); @@ -377,8 +413,13 @@ class Actor : Thinker native native void Howl(); native void DrawSplash (int count, double angle, int kind); native void GiveSecret(bool printmsg = true, bool playsound = true); + native void GetCameraHeight(); + native void GetGravity(); native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); + native void AddInventory(Inventory inv); + native void RemoveInventory(Inventory inv); + native void ClearInventory(); native Inventory FindInventory(class itemtype, bool subclass = false); native Inventory GiveInventoryType(class itemtype); native Inventory DropInventory (Inventory item); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index b1d9526ce7..6db88ab0ad 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -9,6 +9,7 @@ class Object native native static vector3, int G_PickPlayerStart(int pnum, int flags = 0); native static int GameType(); native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM); + native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false); native static void C_MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable. native static uint BAM(double angle); @@ -180,6 +181,40 @@ struct F3DFloor native struct Line native { + enum ELineFlags + { + ML_BLOCKING =0x00000001, // solid, is an obstacle + ML_BLOCKMONSTERS =0x00000002, // blocks monsters only + ML_TWOSIDED =0x00000004, // backside will not be present at all if not two sided + ML_DONTPEGTOP = 0x00000008, // upper texture unpegged + ML_DONTPEGBOTTOM = 0x00000010, // lower texture unpegged + ML_SECRET = 0x00000020, // don't map as two sided: IT'S A SECRET! + ML_SOUNDBLOCK = 0x00000040, // don't let sound cross two of these + ML_DONTDRAW = 0x00000080, // don't draw on the automap + ML_MAPPED = 0x00000100, // set if already drawn in automap + ML_REPEAT_SPECIAL = 0x00000200, // special is repeatable + ML_ADDTRANS = 0x00000400, // additive translucency (can only be set internally) + + // Extended flags + ML_MONSTERSCANACTIVATE = 0x00002000, // [RH] Monsters (as well as players) can activate the line + ML_BLOCK_PLAYERS = 0x00004000, + ML_BLOCKEVERYTHING = 0x00008000, // [RH] Line blocks everything + ML_ZONEBOUNDARY = 0x00010000, + ML_RAILING = 0x00020000, + ML_BLOCK_FLOATERS = 0x00040000, + ML_CLIP_MIDTEX = 0x00080000, // Automatic for every Strife line + ML_WRAP_MIDTEX = 0x00100000, + ML_3DMIDTEX = 0x00200000, + ML_CHECKSWITCHRANGE = 0x00400000, + ML_FIRSTSIDEONLY = 0x00800000, // activated only when crossed from front side + ML_BLOCKPROJECTILE = 0x01000000, + ML_BLOCKUSE = 0x02000000, // blocks all use actions through this line + ML_BLOCKSIGHT = 0x04000000, // blocks monster line of sight + ML_BLOCKHITSCAN = 0x08000000, // blocks hitscan attacks + ML_3DMIDTEX_IMPASS = 0x10000000, // [TP] if 3D midtex, behaves like a height-restricted ML_BLOCKING + }; + + //native readonly vertex v1, v2; // vertices, from v1 to v2 native readonly Vector2 delta; // precalculated v2 - v1 for side checking native uint flags; @@ -411,6 +446,59 @@ class Floor : Thinker native genFloorChg }; - native static bool CreateFloor(sector sec, EFloor floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool hexencrush = false, bool hereticlower = false); + native static bool CreateFloor(sector sec, EFloor floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false); +} + +class Ceiling : Thinker native +{ + enum ECeiling + { + ceilLowerByValue, + ceilRaiseByValue, + ceilMoveToValue, + ceilLowerToHighestFloor, + ceilLowerInstant, + ceilRaiseInstant, + ceilCrushAndRaise, + ceilLowerAndCrush, + ceil_placeholder, + ceilCrushRaiseAndStay, + ceilRaiseToNearest, + ceilLowerToLowest, + ceilLowerToFloor, + + // The following are only used by Generic_Ceiling + ceilRaiseToHighest, + ceilLowerToHighest, + ceilRaiseToLowest, + ceilLowerToNearest, + ceilRaiseToHighestFloor, + ceilRaiseToFloor, + ceilRaiseByTexture, + ceilLowerByTexture, + + genCeilingChg0, + genCeilingChgT, + genCeilingChg + } + + enum ECrushMode + { + crushDoom = 0, + crushHexen = 1, + crushSlowdown = 2 + } -} \ No newline at end of file + native bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = crushDoom); + +} + +struct LookExParams +{ + double Fov; + double minDist; + double maxDist; + double maxHeardist; + int flags; + State seestate; +}; diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index aa9b4a0669..2f6dc4bc19 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -77,6 +77,18 @@ class PlayerPawn : Actor native Obituary "$OB_MPDEFAULT"; } + virtual void PlayIdle () + { + if (InStateSequence(CurState, SeeState)) + SetState (SpawnState); + } + + virtual void PlayRunning () + { + if (InStateSequence(CurState, SpawnState) && SeeState != NULL) + SetState (SeeState); + } + virtual void PlayAttacking () { if (MissileState != null) SetState (MissileState); @@ -92,6 +104,7 @@ class PlayerPawn : Actor native } native int GetMaxHealth(); + native bool ResetAirSupply (bool playgasp = false); } class PlayerChunk : PlayerPawn native From fb3bde0e0d0554e1f4f53eec1c25fc42d4f78cec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 01:39:06 +0100 Subject: [PATCH 418/471] - cleaned up and grouped the virtual function declarations in AActor to ensure that everything has been properly exported. - removed the native parts of SpecialBlastHandling. Since this is called from the script side and the only remaining native remnant was an empty function it's now 100% scripted. --- src/actor.h | 46 ++++++++++++++++++--------------- src/p_mobj.cpp | 15 ----------- wadsrc/static/zscript/actor.txt | 8 +++++- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/actor.h b/src/actor.h index 0b6c58c19a..18b1282156 100644 --- a/src/actor.h +++ b/src/actor.h @@ -585,11 +585,13 @@ public: AActor () throw(); AActor (const AActor &other) throw(); AActor &operator= (const AActor &other); - void Destroy () override; ~AActor (); - void Serialize(FSerializer &arc); - void PostSerialize(); + virtual void Destroy() override; + virtual void Serialize(FSerializer &arc) override; + virtual void PostSerialize() override; + virtual void PostBeginPlay() override; // Called immediately before the actor's first tick + virtual void Tick() override; static AActor *StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false); @@ -614,18 +616,17 @@ public: virtual void BeginPlay(); // Called immediately after the actor is created void CallBeginPlay(); - virtual void PostBeginPlay(); // Called immediately before the actor's first tick + 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. virtual void Activate (AActor *activator); - virtual void Deactivate (AActor *activator); void CallActivate(AActor *activator); - void CallDeactivate(AActor *activator); - virtual void Tick (); + virtual void Deactivate(AActor *activator); + void CallDeactivate(AActor *activator); // Called when actor dies virtual void Die (AActor *source, AActor *inflictor, int dmgflags = 0); @@ -640,6 +641,16 @@ public: virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); int CallTakeSpecialDamage(AActor *inflictor, AActor *source, int damage, FName damagetype); + // Actor had MF_SKULLFLY set and rammed into something + // Returns false to stop moving and true to keep moving + virtual bool Slam(AActor *victim); + bool CallSlam(AActor *victim); + + // Something just touched this actor. + virtual void Touch(AActor *toucher); + void CallTouch(AActor *toucher); + + // Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed // Made a metadata property so no longer virtual void Howl (); @@ -650,32 +661,25 @@ public: // Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor bool FloorBounceMissile (secplane_t &plane); - // Called when an actor is to be reflected by a disc of repulsion. - // Returns true to continue normal blast processing. - virtual bool SpecialBlastHandling (AActor *source, double strength); - // Called by RoughBlockCheck bool IsOkayToAttack (AActor *target); // Plays the actor's ActiveSound if its voice isn't already making noise. void PlayActiveSound (); - // Actor had MF_SKULLFLY set and rammed into something - // Returns false to stop moving and true to keep moving - virtual bool Slam (AActor *victim); - bool CallSlam(AActor *victim); - // Called by PIT_CheckThing() and needed for some Hexen things. // Returns -1 for normal behavior, 0 to return false, and 1 to return true. // I'm not sure I like it this way, but it will do for now. + // (virtual on the script side only) int SpecialMissileHit (AActor *victim); // Returns true if it's okay to switch target to "other" after being attacked by it. - virtual bool OkayToSwitchTarget (AActor *other); + bool OkayToSwitchTarget (AActor *other); - // Something just touched this actor. - virtual void Touch (AActor *toucher); - void CallTouch(AActor *toucher); + // Note: Although some of the inventory functions are virtual, this + // is not exposed to scripts, as the only class overriding them is + // APlayerPawn for some specific handling for players. None of this + // should ever be overridden by custom classes. // Adds the item to this actor's inventory and sets its Owner. virtual void AddInventory (AInventory *item); @@ -760,7 +764,7 @@ public: DVector3 GetPortalTransition(double byoffset, sector_t **pSec = NULL); // What species am I? - virtual FName GetSpecies(); + FName GetSpecies(); // set translation void SetTranslation(FName trname); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d099a8e775..78487185cd 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3440,21 +3440,6 @@ bool AActor::CallSlam(AActor *thing) -bool AActor::SpecialBlastHandling (AActor *source, double strength) -{ - return true; -} - -// This only gets called from the script side so we do not need a native wrapper like for the other virtual methods. -// This will be removed, once all actors overriding this method are exported. -DEFINE_ACTION_FUNCTION(AActor, SpecialBlastHandling) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(source, AActor); - PARAM_FLOAT(strength); - ACTION_RETURN_BOOL(self->SpecialBlastHandling(source, strength)); -} - // This virtual method only exists on the script side. int AActor::SpecialMissileHit (AActor *victim) { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5eebb73504..9bf4fdcd97 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -267,9 +267,15 @@ class Actor : Thinker native virtual native int TakeSpecialDamage (Actor inflictor, Actor source, int damage, Name damagetype); virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0); virtual native bool Slam(Actor victim); - virtual native bool SpecialBlastHandling (Actor source, double strength); virtual native void Touch(Actor toucher); + // Called when an actor is to be reflected by a disc of repulsion. + // Returns true to continue normal blast processing. + virtual bool SpecialBlastHandling (Actor source, double strength) // this is entirely on the script side with no native part at all. + { + return true; + } + virtual int SpecialMissileHit (Actor victim) // for this no native version exists { return -1; From 0cd6cec5319a8f1d671899d0b455d4b184f68470 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 01:49:36 +0100 Subject: [PATCH 419/471] - scriptified the SectorFlagSetter. --- src/g_shared/a_skies.cpp | 15 --------------- wadsrc/static/zscript/shared/sharedmisc.txt | 8 +++++++- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index d42324936b..9e99d9368e 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -177,18 +177,3 @@ void ASectorSilencer::Destroy () Super::Destroy (); } -class ASectorFlagSetter : public AActor -{ - DECLARE_CLASS (ASectorFlagSetter, AActor) -public: - void BeginPlay (); -}; - -IMPLEMENT_CLASS(ASectorFlagSetter, false, false) - -void ASectorFlagSetter::BeginPlay () -{ - Super::BeginPlay (); - Sector->Flags |= args[0]; -} - diff --git a/wadsrc/static/zscript/shared/sharedmisc.txt b/wadsrc/static/zscript/shared/sharedmisc.txt index 6da942e393..1b5ad4ee98 100644 --- a/wadsrc/static/zscript/shared/sharedmisc.txt +++ b/wadsrc/static/zscript/shared/sharedmisc.txt @@ -193,7 +193,7 @@ class RandomSpawner : Actor native // Sector flag setter ------------------------------------------------------ -class SectorFlagSetter : Actor native +class SectorFlagSetter : Actor { Default { @@ -202,6 +202,12 @@ class SectorFlagSetter : Actor native +DONTSPLASH RenderStyle "None"; } + + override void BeginPlay () + { + Super.BeginPlay (); + CurSector.Flags |= args[0]; + } } // Marker for sounds : Actor ------------------------------------------------------- From 661692062d9e5faa9fb303407abf2962147af459 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 09:53:16 +0100 Subject: [PATCH 420/471] - fixed: FxIdentifier::Resolve checked all cases of what an identifier can be, even if it already found a proper match. --- src/scripting/codegeneration/codegen.cpp | 26 ++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 2eb6cfec67..42c526d0ab 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5521,6 +5521,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) self = self->Resolve(ctx); newex = ResolveMember(ctx, ctx.Function->Variants[0].SelfClass, self, ctx.Function->Variants[0].SelfClass); ABORT(newex); + goto foundit; } } @@ -5531,8 +5532,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars()); newex = FxConstant::MakeConstant(sym, ScriptPosition); - delete this; - return newex->Resolve(ctx); + goto foundit; } // 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))) @@ -5543,6 +5543,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) ABORT(newex); ScriptPosition.Message(MSG_OPTERROR, "Self pointer used in ambiguous context; VM execution may abort!"); ctx.Unsafe = true; + goto foundit; } else { @@ -5573,16 +5574,20 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global constant\n", Identifier.GetChars()); newex = FxConstant::MakeConstant(sym, ScriptPosition); + goto foundit; } 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); + goto foundit; } else { ScriptPosition.Message(MSG_ERROR, "Invalid global identifier '%s'\n", Identifier.GetChars()); + delete this; + return nullptr; } } @@ -5591,6 +5596,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) { ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num); newex = new FxConstant(num, ScriptPosition); + goto foundit; } auto cvar = FindCVar(Identifier.GetChars(), nullptr); @@ -5603,14 +5609,14 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) return nullptr; } newex = new FxCVar(cvar, ScriptPosition); + goto foundit; } - if (newex == nullptr) - { - ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); - delete this; - return nullptr; - } + ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); + delete this; + return nullptr; + +foundit: delete this; return newex? newex->Resolve(ctx) : nullptr; } @@ -5733,6 +5739,10 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) // because the resulting value type would cause problems in nearly every other place where identifiers are being used. ccls = FindStructType(static_cast(Object)->Identifier); if (ccls != nullptr) static_cast(Object)->noglobal = true; + if (ccls && ccls->TypeName == FName("Tracer")) + { + int a = 0; + } } SAFE_RESOLVE(Object, ctx); From b1910effd6070eab476b1bd22cc67d4cd341f150 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 09:54:37 +0100 Subject: [PATCH 421/471] - remove debug code. --- src/scripting/codegeneration/codegen.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 42c526d0ab..7408573a00 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5739,10 +5739,6 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) // because the resulting value type would cause problems in nearly every other place where identifiers are being used. ccls = FindStructType(static_cast(Object)->Identifier); if (ccls != nullptr) static_cast(Object)->noglobal = true; - if (ccls && ccls->TypeName == FName("Tracer")) - { - int a = 0; - } } SAFE_RESOLVE(Object, ctx); From 014e04ce820a67aae7cb925edb8917c7d7c3c450 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 10:28:02 +0100 Subject: [PATCH 422/471] - copied inventory files to their own folder. It's about time this stuff is getting cleaned up seriously. Both a_pickups.cpp and a_artifacts.cpp are so overstuffed that it has become a chore finding stuff in there. --- src/CMakeLists.txt | 17 ++++++++++------- src/{g_shared => g_inventory}/a_armor.cpp | 0 src/{g_shared => g_inventory}/a_artifacts.cpp | 0 src/{g_shared => g_inventory}/a_artifacts.h | 0 src/{g_shared => g_inventory}/a_keys.cpp | 0 src/{g_shared => g_inventory}/a_keys.h | 0 src/{g_shared => g_inventory}/a_pickups.cpp | 0 src/{g_shared => g_inventory}/a_pickups.h | 0 src/{g_shared => g_inventory}/a_puzzleitems.cpp | 0 src/{g_shared => g_inventory}/a_weaponpiece.cpp | 0 src/{g_shared => g_inventory}/a_weaponpiece.h | 0 src/{g_shared => g_inventory}/a_weapons.cpp | 0 src/p_acs.cpp | 3 +-- 13 files changed, 11 insertions(+), 9 deletions(-) rename src/{g_shared => g_inventory}/a_armor.cpp (100%) rename src/{g_shared => g_inventory}/a_artifacts.cpp (100%) rename src/{g_shared => g_inventory}/a_artifacts.h (100%) rename src/{g_shared => g_inventory}/a_keys.cpp (100%) rename src/{g_shared => g_inventory}/a_keys.h (100%) rename src/{g_shared => g_inventory}/a_pickups.cpp (100%) rename src/{g_shared => g_inventory}/a_pickups.h (100%) rename src/{g_shared => g_inventory}/a_puzzleitems.cpp (100%) rename src/{g_shared => g_inventory}/a_weaponpiece.cpp (100%) rename src/{g_shared => g_inventory}/a_weaponpiece.h (100%) rename src/{g_shared => g_inventory}/a_weapons.cpp (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d1e90581c7..be6c0ac730 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -829,6 +829,7 @@ file( GLOB HEADER_FILES ${EXTRA_HEADER_DIRS} fragglescript/*.h g_shared/*.h + g_inventory/*.h g_strife/*.h intermission/*.h menu/*.h @@ -1106,21 +1107,23 @@ set (PCH_SOURCES w_wad.cpp wi_stuff.cpp zstrformat.cpp + g_inventory/a_armor.cpp + g_inventory/a_artifacts.cpp + g_inventory/a_keys.cpp + g_inventory/a_pickups.cpp + g_inventory/a_puzzleitems.cpp + g_inventory/a_weaponpiece.cpp + g_inventory/a_weapons.cpp g_strife/strife_sbar.cpp g_shared/a_action.cpp - g_shared/a_armor.cpp - g_shared/a_artifacts.cpp g_shared/a_bridge.cpp g_shared/a_decals.cpp g_shared/a_fastprojectile.cpp g_shared/a_flashfader.cpp g_shared/a_fountain.cpp - g_shared/a_keys.cpp g_shared/a_lightning.cpp g_shared/a_morph.cpp g_shared/a_movingcamera.cpp - g_shared/a_pickups.cpp - g_shared/a_puzzleitems.cpp g_shared/a_quake.cpp g_shared/a_randomspawner.cpp g_shared/a_sectoraction.cpp @@ -1128,8 +1131,6 @@ set (PCH_SOURCES g_shared/a_soundenvironment.cpp g_shared/a_soundsequence.cpp g_shared/a_specialspot.cpp - g_shared/a_weaponpiece.cpp - g_shared/a_weapons.cpp g_shared/hudmessages.cpp g_shared/sbarinfo.cpp g_shared/sbar_mugshot.cpp @@ -1250,6 +1251,7 @@ target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma ) include_directories( . g_strife g_shared + g_inventory oplsynth sound textures @@ -1380,6 +1382,7 @@ source_group("Externak\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/s source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+") 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("Inventory" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_inventory/.+") source_group("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+") source_group("Render Core\\Render Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_.+\\.h$") source_group("Render Core\\Render Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_.+\\.cpp$") diff --git a/src/g_shared/a_armor.cpp b/src/g_inventory/a_armor.cpp similarity index 100% rename from src/g_shared/a_armor.cpp rename to src/g_inventory/a_armor.cpp diff --git a/src/g_shared/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp similarity index 100% rename from src/g_shared/a_artifacts.cpp rename to src/g_inventory/a_artifacts.cpp diff --git a/src/g_shared/a_artifacts.h b/src/g_inventory/a_artifacts.h similarity index 100% rename from src/g_shared/a_artifacts.h rename to src/g_inventory/a_artifacts.h diff --git a/src/g_shared/a_keys.cpp b/src/g_inventory/a_keys.cpp similarity index 100% rename from src/g_shared/a_keys.cpp rename to src/g_inventory/a_keys.cpp diff --git a/src/g_shared/a_keys.h b/src/g_inventory/a_keys.h similarity index 100% rename from src/g_shared/a_keys.h rename to src/g_inventory/a_keys.h diff --git a/src/g_shared/a_pickups.cpp b/src/g_inventory/a_pickups.cpp similarity index 100% rename from src/g_shared/a_pickups.cpp rename to src/g_inventory/a_pickups.cpp diff --git a/src/g_shared/a_pickups.h b/src/g_inventory/a_pickups.h similarity index 100% rename from src/g_shared/a_pickups.h rename to src/g_inventory/a_pickups.h diff --git a/src/g_shared/a_puzzleitems.cpp b/src/g_inventory/a_puzzleitems.cpp similarity index 100% rename from src/g_shared/a_puzzleitems.cpp rename to src/g_inventory/a_puzzleitems.cpp diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_inventory/a_weaponpiece.cpp similarity index 100% rename from src/g_shared/a_weaponpiece.cpp rename to src/g_inventory/a_weaponpiece.cpp diff --git a/src/g_shared/a_weaponpiece.h b/src/g_inventory/a_weaponpiece.h similarity index 100% rename from src/g_shared/a_weaponpiece.h rename to src/g_inventory/a_weaponpiece.h diff --git a/src/g_shared/a_weapons.cpp b/src/g_inventory/a_weapons.cpp similarity index 100% rename from src/g_shared/a_weapons.cpp rename to src/g_inventory/a_weapons.cpp diff --git a/src/p_acs.cpp b/src/p_acs.cpp index a711106742..96949dd965 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -82,8 +82,7 @@ #include "i_music.h" #include "serializer.h" #include "thingdef.h" - -#include "g_shared/a_pickups.h" +#include "a_pickups.h" extern FILE *Logfile; From 78fa0760797b034c885ff90fb7a3441523ed64ff Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 10:55:03 +0100 Subject: [PATCH 423/471] - moved armor class declarations to their own file and added necessary #includes only to those files actually using them. - added copyright headers to a_armor.cpp and a_keys.cpp. --- src/ct_chat.cpp | 1 + src/d_dehacked.cpp | 1 + src/g_inventory/a_armor.cpp | 69 ++++++++++++++++++++- src/g_inventory/a_armor.h | 89 +++++++++++++++++++++++++++ src/g_inventory/a_keys.cpp | 64 +++++++++++++++++++ src/g_inventory/a_pickups.h | 85 ------------------------- src/g_shared/a_morph.cpp | 1 + src/g_shared/sbarinfo.cpp | 1 + src/g_shared/shared_hud.cpp | 1 + src/g_strife/strife_sbar.cpp | 1 + src/m_cheat.cpp | 1 + src/p_acs.cpp | 1 + src/p_actionfunctions.cpp | 1 + src/p_mobj.cpp | 1 + src/p_user.cpp | 1 + src/scripting/thingdef_properties.cpp | 1 + 16 files changed, 233 insertions(+), 86 deletions(-) create mode 100644 src/g_inventory/a_armor.h diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index 3c0994a3b4..0a92a58b9c 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -31,6 +31,7 @@ #include "templates.h" #include "d_net.h" #include "d_event.h" +#include "a_armor.h" #define QUEUESIZE 128 #define MESSAGESIZE 128 diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index e9e5a58d0d..630586b0d3 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -74,6 +74,7 @@ #include "info.h" #include "v_text.h" #include "vmbuilder.h" +#include "a_armor.h" // [SO] Just the way Randy said to do it :) // [RH] Made this CVAR_SERVERINFO diff --git a/src/g_inventory/a_armor.cpp b/src/g_inventory/a_armor.cpp index 25d45d35db..ebe8f49f6b 100644 --- a/src/g_inventory/a_armor.cpp +++ b/src/g_inventory/a_armor.cpp @@ -1,8 +1,44 @@ +/* +** a_armor.cpp +** Implements all variations of armor objects +** +**--------------------------------------------------------------------------- +** Copyright 2002-2016 Randy Heit +** Copyright 2006-2016 Cheistoph 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 #include "info.h" #include "gi.h" #include "a_pickups.h" +#include "a_armor.h" #include "templates.h" #include "g_level.h" #include "d_player.h" @@ -15,6 +51,13 @@ IMPLEMENT_CLASS(ABasicArmorPickup, false, false) IMPLEMENT_CLASS(ABasicArmorBonus, false, false) IMPLEMENT_CLASS(AHexenArmor, false, false) +//=========================================================================== +// +// +// BasicArmor +// +// +//=========================================================================== DEFINE_FIELD(ABasicArmor, AbsorbCount) DEFINE_FIELD(ABasicArmor, SavePercent) @@ -198,6 +241,15 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage) } } +//=========================================================================== +// +// +// BasicArmorPickup +// +// +//=========================================================================== + + DEFINE_FIELD(ABasicArmorPickup, SavePercent) DEFINE_FIELD(ABasicArmorPickup, MaxAbsorb) DEFINE_FIELD(ABasicArmorPickup, MaxFullAbsorb) @@ -291,10 +343,13 @@ bool ABasicArmorPickup::Use (bool pickup) //=========================================================================== // -// ABasicArmorBonus +// +// BasicArmorBonus +// // //=========================================================================== + DEFINE_FIELD(ABasicArmorBonus, SavePercent) DEFINE_FIELD(ABasicArmorBonus, MaxSaveAmount) DEFINE_FIELD(ABasicArmorBonus, MaxAbsorb) @@ -406,6 +461,13 @@ bool ABasicArmorBonus::Use (bool pickup) return true; } +//=========================================================================== +// +// +// HexenArmor +// +// +//=========================================================================== DEFINE_FIELD(AHexenArmor, Slots) DEFINE_FIELD(AHexenArmor, SlotsIncrement) @@ -573,6 +635,11 @@ void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage) } } +//=========================================================================== +// +// AHexenArmor :: DepleteOrDestroy +// +//=========================================================================== void AHexenArmor::DepleteOrDestroy() { diff --git a/src/g_inventory/a_armor.h b/src/g_inventory/a_armor.h new file mode 100644 index 0000000000..b7b2dad3e1 --- /dev/null +++ b/src/g_inventory/a_armor.h @@ -0,0 +1,89 @@ +#pragma once + +#include "a_pickups.h" + +// Armor absorbs some damage for the player. +class AArmor : public AInventory +{ + DECLARE_CLASS (AArmor, AInventory) +}; + +// Basic armor absorbs a specific percent of the damage. You should +// never pickup a BasicArmor. Instead, you pickup a BasicArmorPickup +// or BasicArmorBonus and those gives you BasicArmor when it activates. +class ABasicArmor : public AArmor +{ + DECLARE_CLASS (ABasicArmor, AArmor) +public: + + virtual void Serialize(FSerializer &arc); + virtual void Tick (); + virtual AInventory *CreateCopy (AActor *other); + virtual bool HandlePickup (AInventory *item); + virtual void AbsorbDamage (int damage, FName damageType, int &newdamage); + + int AbsorbCount; + double SavePercent; + int MaxAbsorb; + int MaxFullAbsorb; + int BonusCount; + FNameNoInit ArmorType; + int ActualSaveAmount; +}; + +// BasicArmorPickup replaces the armor you have. +class ABasicArmorPickup : public AArmor +{ + DECLARE_CLASS (ABasicArmorPickup, AArmor) +public: + + virtual void Serialize(FSerializer &arc); + virtual AInventory *CreateCopy (AActor *other); + virtual bool Use (bool pickup); + + double SavePercent; + int MaxAbsorb; + int MaxFullAbsorb; + int SaveAmount; +}; + +// BasicArmorBonus adds to the armor you have. +class ABasicArmorBonus : public AArmor +{ + DECLARE_CLASS (ABasicArmorBonus, AArmor) +public: + + virtual void Serialize(FSerializer &arc); + virtual AInventory *CreateCopy (AActor *other); + virtual bool Use (bool pickup); + + double SavePercent; // The default, for when you don't already have armor + int MaxSaveAmount; + int MaxAbsorb; + int MaxFullAbsorb; + int SaveAmount; + int BonusCount; + int BonusMax; +}; + +// Hexen armor consists of four separate armor types plus a conceptual armor +// type (the player himself) that work together as a single armor. +class AHexenArmor : public AArmor +{ + DECLARE_CLASS (AHexenArmor, AArmor) +public: + + virtual void Serialize(FSerializer &arc); + virtual AInventory *CreateCopy (AActor *other); + virtual AInventory *CreateTossable (); + virtual bool HandlePickup (AInventory *item); + virtual void AbsorbDamage (int damage, FName damageType, int &newdamage); + void DepleteOrDestroy(); + + double Slots[5]; + double SlotsIncrement[4]; + +protected: + bool AddArmorToSlot (AActor *actor, int slot, int amount); +}; + diff --git a/src/g_inventory/a_keys.cpp b/src/g_inventory/a_keys.cpp index fc9363be58..a2b5b308a5 100644 --- a/src/g_inventory/a_keys.cpp +++ b/src/g_inventory/a_keys.cpp @@ -1,3 +1,36 @@ +/* +** a_keys.cpp +** Implements all keys and associated data +** +**--------------------------------------------------------------------------- +** Copyright 2005-2016 Cheistoph 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_keys.h" #include "tarray.h" #include "gi.h" @@ -12,6 +45,18 @@ #include "v_font.h" +//=========================================================================== +// +// Data for the LOCKDEFS +// +//=========================================================================== + + +//=========================================================================== +// +// +//=========================================================================== + struct OneKey { PClassActor *key; @@ -45,6 +90,11 @@ struct OneKey } }; +//=========================================================================== +// +// +//=========================================================================== + struct Keygroup { TArray anykeylist; @@ -59,6 +109,11 @@ struct Keygroup } }; +//=========================================================================== +// +// +//=========================================================================== + struct Lock { TArray keylist; @@ -100,6 +155,10 @@ struct Lock } }; +//=========================================================================== +// +// +//=========================================================================== static Lock *locks[256]; // all valid locks static bool keysdone=false; // have the locks been initialized? @@ -490,6 +549,11 @@ bool AKey::HandlePickup (AInventory *item) return false; } +//=========================================================================== +// +// +//=========================================================================== + bool AKey::ShouldStay () { return !!multiplayer; diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 48afac2268..56caabf3cb 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -458,91 +458,6 @@ public: virtual bool Use (bool pickup); }; -// Armor absorbs some damage for the player. -class AArmor : public AInventory -{ - DECLARE_CLASS (AArmor, AInventory) -}; - -// Basic armor absorbs a specific percent of the damage. You should -// never pickup a BasicArmor. Instead, you pickup a BasicArmorPickup -// or BasicArmorBonus and those gives you BasicArmor when it activates. -class ABasicArmor : public AArmor -{ - DECLARE_CLASS (ABasicArmor, AArmor) -public: - - virtual void Serialize(FSerializer &arc); - virtual void Tick (); - virtual AInventory *CreateCopy (AActor *other); - virtual bool HandlePickup (AInventory *item); - virtual void AbsorbDamage (int damage, FName damageType, int &newdamage); - - int AbsorbCount; - double SavePercent; - int MaxAbsorb; - int MaxFullAbsorb; - int BonusCount; - FNameNoInit ArmorType; - int ActualSaveAmount; -}; - -// BasicArmorPickup replaces the armor you have. -class ABasicArmorPickup : public AArmor -{ - DECLARE_CLASS (ABasicArmorPickup, AArmor) -public: - - virtual void Serialize(FSerializer &arc); - virtual AInventory *CreateCopy (AActor *other); - virtual bool Use (bool pickup); - - double SavePercent; - int MaxAbsorb; - int MaxFullAbsorb; - int SaveAmount; -}; - -// BasicArmorBonus adds to the armor you have. -class ABasicArmorBonus : public AArmor -{ - DECLARE_CLASS (ABasicArmorBonus, AArmor) -public: - - virtual void Serialize(FSerializer &arc); - virtual AInventory *CreateCopy (AActor *other); - virtual bool Use (bool pickup); - - double SavePercent; // The default, for when you don't already have armor - int MaxSaveAmount; - int MaxAbsorb; - int MaxFullAbsorb; - int SaveAmount; - int BonusCount; - int BonusMax; -}; - -// Hexen armor consists of four separate armor types plus a conceptual armor -// type (the player himself) that work together as a single armor. -class AHexenArmor : public AArmor -{ - DECLARE_CLASS (AHexenArmor, AArmor) -public: - - virtual void Serialize(FSerializer &arc); - virtual AInventory *CreateCopy (AActor *other); - virtual AInventory *CreateTossable (); - virtual bool HandlePickup (AInventory *item); - virtual void AbsorbDamage (int damage, FName damageType, int &newdamage); - void DepleteOrDestroy(); - - double Slots[5]; - double SlotsIncrement[4]; - -protected: - bool AddArmorToSlot (AActor *actor, int slot, int amount); -}; - // PuzzleItems work in conjunction with the UsePuzzleItem special class PClassPuzzleItem : public PClassInventory { diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 2f986c201b..ad15cb081c 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -14,6 +14,7 @@ #include "serializer.h" #include "p_enemy.h" #include "d_player.h" +#include "a_armor.h" #include "r_data/sprites.h" static FRandom pr_morphmonst ("MorphMonster"); diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 4bb9d5b81b..f2852919d8 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -45,6 +45,7 @@ #include "st_stuff.h" #include "m_swap.h" #include "a_keys.h" +#include "a_armor.h" #include "templates.h" #include "i_system.h" #include "sbarinfo.h" diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 4733c6e41b..c6e12918d5 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -43,6 +43,7 @@ #include "c_cvars.h" #include "w_wad.h" #include "a_keys.h" +#include "a_armor.h" #include "sbar.h" #include "sc_man.h" #include "templates.h" diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index c12c7a7237..3a242f80c3 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -12,6 +12,7 @@ #include "m_swap.h" #include "templates.h" #include "a_keys.h" +#include "a_armor.h" #include "gi.h" #include "g_level.h" #include "colormatcher.h" diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index f5cd568482..6bd6b3862a 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -47,6 +47,7 @@ #include "serializer.h" #include "r_utility.h" #include "a_morph.h" +#include "a_armor.h" // [RH] Actually handle the cheat. The cheat code in st_stuff.c now just // writes some bytes to the network data stream, and the network code diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 96949dd965..93d0cd45b3 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -83,6 +83,7 @@ #include "serializer.h" #include "thingdef.h" #include "a_pickups.h" +#include "a_armor.h" extern FILE *Logfile; diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 99d38b2c1c..8981538e77 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -78,6 +78,7 @@ #include "v_text.h" #include "thingdef.h" #include "math/cmath.h" +#include "a_armor.h" AActor *SingleActorFromTID(int tid, AActor *defactor); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 78487185cd..7c7d97cf2c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -69,6 +69,7 @@ #include "thingdef.h" #include "d_player.h" #include "virtual.h" +#include "a_armor.h" // MACROS ------------------------------------------------------------------ diff --git a/src/p_user.cpp b/src/p_user.cpp index 66437d4308..e92b560db3 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -59,6 +59,7 @@ #include "a_morph.h" #include "p_spec.h" #include "virtual.h" +#include "a_armor.h" static FRandom pr_skullpop ("SkullPop"); diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index cfadc53bf3..e85b6a1d9f 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -46,6 +46,7 @@ #include "templates.h" #include "r_defs.h" #include "a_pickups.h" +#include "a_armor.h" #include "s_sound.h" #include "cmdlib.h" #include "p_lnspec.h" From 229c55ce61b5be24fc7d2a489017d988c711d67d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 12:24:50 +0100 Subject: [PATCH 424/471] - moved ammo to its own file, including the backpack. - moved weapon declarations to their own header. --- src/CMakeLists.txt | 1 + src/b_think.cpp | 1 + src/d_dehacked.cpp | 1 + src/d_player.h | 1 + src/fragglescript/t_func.cpp | 1 + src/g_inventory/a_ammo.cpp | 381 ++++++++++++++++++++++++++ src/g_inventory/a_ammo.h | 47 ++++ src/g_inventory/a_pickups.cpp | 343 +---------------------- src/g_inventory/a_pickups.h | 268 ------------------ src/g_inventory/a_puzzleitems.cpp | 64 ++++- src/g_inventory/a_weaponpiece.cpp | 63 +++++ src/g_inventory/a_weaponpiece.h | 1 + src/g_inventory/a_weapons.cpp | 36 +++ src/g_inventory/a_weapons.h | 230 ++++++++++++++++ src/g_shared/sbarinfo.cpp | 1 + src/g_shared/shared_hud.cpp | 1 + src/g_strife/strife_sbar.cpp | 1 + src/m_cheat.cpp | 1 + src/p_acs.cpp | 1 + src/p_enemy.cpp | 1 + src/p_mobj.cpp | 1 + src/p_user.cpp | 1 + src/scripting/thingdef_properties.cpp | 1 + 23 files changed, 836 insertions(+), 611 deletions(-) create mode 100644 src/g_inventory/a_ammo.cpp create mode 100644 src/g_inventory/a_ammo.h create mode 100644 src/g_inventory/a_weapons.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be6c0ac730..1265544963 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1107,6 +1107,7 @@ set (PCH_SOURCES w_wad.cpp wi_stuff.cpp zstrformat.cpp + g_inventory/a_ammo.cpp g_inventory/a_armor.cpp g_inventory/a_artifacts.cpp g_inventory/a_keys.cpp diff --git a/src/b_think.cpp b/src/b_think.cpp index d097db8640..7dd196622b 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -21,6 +21,7 @@ #include "d_event.h" #include "d_player.h" #include "vectors.h" +#include "a_ammo.h" static FRandom pr_botmove ("BotMove"); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 630586b0d3..62daefcaa9 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -75,6 +75,7 @@ #include "v_text.h" #include "vmbuilder.h" #include "a_armor.h" +#include "a_ammo.h" // [SO] Just the way Randy said to do it :) // [RH] Made this CVAR_SERVERINFO diff --git a/src/d_player.h b/src/d_player.h index 95a288ebdf..4cdfb8b793 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -30,6 +30,7 @@ #include "doomstat.h" #include "a_artifacts.h" +#include "a_weapons.h" // The player data structure depends on a number // of other structs: items (internal inventory), diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 7266daf40a..6b0059981e 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -69,6 +69,7 @@ #include "p_setup.h" #include "p_spec.h" #include "r_utility.h" +#include "a_ammo.h" #include "math/cmath.h" static FRandom pr_script("FScript"); diff --git a/src/g_inventory/a_ammo.cpp b/src/g_inventory/a_ammo.cpp new file mode 100644 index 0000000000..23a9221874 --- /dev/null +++ b/src/g_inventory/a_ammo.cpp @@ -0,0 +1,381 @@ +/* +** a_ammo.cpp +** Implements ammo and backpack items. +** +**--------------------------------------------------------------------------- +** Copyright 2000-2016 Randy Heit +** Copyright 2006-2016 Cheistoph 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 "c_dispatch.h" +#include "d_player.h" +#include "serializer.h" + +IMPLEMENT_CLASS(PClassAmmo, false, false) + +PClassAmmo::PClassAmmo() +{ + DropAmount = 0; +} + +void PClassAmmo::DeriveData(PClass *newclass) +{ + assert(newclass->IsKindOf(RUNTIME_CLASS(PClassAmmo))); + Super::DeriveData(newclass); + PClassAmmo *newc = static_cast(newclass); + + newc->DropAmount = DropAmount; +} + +IMPLEMENT_CLASS(AAmmo, false, false) + +DEFINE_FIELD(AAmmo, BackpackAmount) +DEFINE_FIELD(AAmmo, BackpackMaxAmount) + +//=========================================================================== +// +// AAmmo :: Serialize +// +//=========================================================================== + +void AAmmo::Serialize(FSerializer &arc) +{ + Super::Serialize (arc); + auto def = (AAmmo*)GetDefault(); + arc("backpackamount", BackpackAmount, def->BackpackAmount) + ("backpackmaxamount", BackpackMaxAmount, def->BackpackMaxAmount); +} + +//=========================================================================== +// +// AAmmo :: GetParentAmmo +// +// Returns the least-derived ammo type that this ammo is a descendant of. +// That is, if this ammo is an immediate subclass of Ammo, then this ammo's +// type is returned. If this ammo's superclass is not Ammo, then this +// function travels up the inheritance chain until it finds a type that is +// an immediate subclass of Ammo and returns that. +// +// The intent of this is that all unique ammo types will be immediate +// subclasses of Ammo. To make different pickups with different ammo amounts, +// you subclass the type of ammo you want a different amount for and edit +// that. +// +//=========================================================================== + +PClassActor *AAmmo::GetParentAmmo () const +{ + PClass *type = GetClass(); + + while (type->ParentClass != RUNTIME_CLASS(AAmmo) && type->ParentClass != NULL) + { + type = type->ParentClass; + } + return static_cast(type); +} + +//=========================================================================== +// +// AAmmo :: HandlePickup +// +//=========================================================================== +EXTERN_CVAR(Bool, sv_unlimited_pickup) + +bool AAmmo::HandlePickup (AInventory *item) +{ + if (GetClass() == item->GetClass() || + (item->IsKindOf (RUNTIME_CLASS(AAmmo)) && static_cast(item)->GetParentAmmo() == GetClass())) + { + if (Amount < MaxAmount || sv_unlimited_pickup) + { + int receiving = item->Amount; + + if (!(item->ItemFlags & IF_IGNORESKILL)) + { // extra ammo in baby mode and nightmare mode + receiving = int(receiving * G_SkillProperty(SKILLP_AmmoFactor)); + } + int oldamount = Amount; + + if (Amount > 0 && Amount + receiving < 0) + { + Amount = 0x7fffffff; + } + else + { + Amount += receiving; + } + if (Amount > MaxAmount && !sv_unlimited_pickup) + { + Amount = MaxAmount; + } + item->ItemFlags |= IF_PICKUPGOOD; + + // If the player previously had this ammo but ran out, possibly switch + // to a weapon that uses it, but only if the player doesn't already + // have a weapon pending. + + assert (Owner != NULL); + + if (oldamount == 0 && Owner != NULL && Owner->player != NULL) + { + barrier_cast(Owner)->CheckWeaponSwitch(GetClass()); + } + } + return true; + } + return false; +} + +//=========================================================================== +// +// AAmmo :: CreateCopy +// +//=========================================================================== + +AInventory *AAmmo::CreateCopy (AActor *other) +{ + AInventory *copy; + int amount = Amount; + + // extra ammo in baby mode and nightmare mode + if (!(ItemFlags&IF_IGNORESKILL)) + { + amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); + } + + if (GetClass()->ParentClass != RUNTIME_CLASS(AAmmo) && GetClass() != RUNTIME_CLASS(AAmmo)) + { + PClassActor *type = GetParentAmmo(); + if (!GoAway ()) + { + Destroy (); + } + + copy = static_cast(Spawn (type)); + copy->Amount = amount; + copy->BecomeItem (); + } + else + { + copy = Super::CreateCopy (other); + copy->Amount = amount; + } + if (copy->Amount > copy->MaxAmount) + { // Don't pick up more ammo than you're supposed to be able to carry. + copy->Amount = copy->MaxAmount; + } + return copy; +} + +//=========================================================================== +// +// AAmmo :: CreateTossable +// +//=========================================================================== + +AInventory *AAmmo::CreateTossable() +{ + AInventory *copy = Super::CreateTossable(); + if (copy != NULL) + { // Do not increase ammo by dropping it and picking it back up at + // certain skill levels. + copy->ItemFlags |= IF_IGNORESKILL; + } + return copy; +} + + +// Backpack ----------------------------------------------------------------- + +IMPLEMENT_CLASS(ABackpackItem, false, false) + +DEFINE_FIELD(ABackpackItem, bDepleted) + +//=========================================================================== +// +// ABackpackItem :: Serialize +// +//=========================================================================== + +void ABackpackItem::Serialize(FSerializer &arc) +{ + Super::Serialize (arc); + auto def = (ABackpackItem*)GetDefault(); + arc("bdepleted", bDepleted, def->bDepleted); +} + +//=========================================================================== +// +// ABackpackItem :: CreateCopy +// +// A backpack is being added to a player who doesn't yet have one. Give them +// every kind of ammo, and increase their max amounts. +// +//=========================================================================== + +AInventory *ABackpackItem::CreateCopy (AActor *other) +{ + // Find every unique type of ammo. Give it to the player if + // he doesn't have it already, and double its maximum capacity. + for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) + { + PClass *type = PClassActor::AllActorClasses[i]; + + if (type->ParentClass == RUNTIME_CLASS(AAmmo)) + { + PClassActor *atype = static_cast(type); + AAmmo *ammo = static_cast(other->FindInventory(atype)); + int amount = static_cast(GetDefaultByType(type))->BackpackAmount; + // extra ammo in baby mode and nightmare mode + if (!(ItemFlags&IF_IGNORESKILL)) + { + amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); + } + if (amount < 0) amount = 0; + if (ammo == NULL) + { // The player did not have the ammo. Add it. + ammo = static_cast(Spawn(atype)); + ammo->Amount = bDepleted ? 0 : amount; + if (ammo->BackpackMaxAmount > ammo->MaxAmount) + { + ammo->MaxAmount = ammo->BackpackMaxAmount; + } + if (ammo->Amount > ammo->MaxAmount) + { + ammo->Amount = ammo->MaxAmount; + } + ammo->AttachToOwner (other); + } + else + { // The player had the ammo. Give some more. + if (ammo->MaxAmount < ammo->BackpackMaxAmount) + { + ammo->MaxAmount = ammo->BackpackMaxAmount; + } + if (!bDepleted && ammo->Amount < ammo->MaxAmount) + { + ammo->Amount += amount; + if (ammo->Amount > ammo->MaxAmount) + { + ammo->Amount = ammo->MaxAmount; + } + } + } + } + } + return Super::CreateCopy (other); +} + +//=========================================================================== +// +// ABackpackItem :: HandlePickup +// +// When the player picks up another backpack, just give them more ammo. +// +//=========================================================================== + +bool ABackpackItem::HandlePickup (AInventory *item) +{ + // Since you already have a backpack, that means you already have every + // kind of ammo in your inventory, so we don't need to look at the + // entire PClass list to discover what kinds of ammo exist, and we don't + // have to alter the MaxAmount either. + if (item->IsKindOf (RUNTIME_CLASS(ABackpackItem))) + { + for (AInventory *probe = Owner->Inventory; probe != NULL; probe = probe->Inventory) + { + if (probe->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo)) + { + if (probe->Amount < probe->MaxAmount || sv_unlimited_pickup) + { + int amount = static_cast(probe->GetDefault())->BackpackAmount; + // extra ammo in baby mode and nightmare mode + if (!(item->ItemFlags&IF_IGNORESKILL)) + { + amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); + } + probe->Amount += amount; + if (probe->Amount > probe->MaxAmount && !sv_unlimited_pickup) + { + probe->Amount = probe->MaxAmount; + } + } + } + } + // The pickup always succeeds, even if you didn't get anything + item->ItemFlags |= IF_PICKUPGOOD; + return true; + } + return false; +} + +//=========================================================================== +// +// ABackpackItem :: CreateTossable +// +// The tossed backpack must not give out any more ammo, otherwise a player +// could cheat by dropping their backpack and picking it up for more ammo. +// +//=========================================================================== + +AInventory *ABackpackItem::CreateTossable () +{ + ABackpackItem *pack = static_cast(Super::CreateTossable()); + if (pack != NULL) + { + pack->bDepleted = true; + } + return pack; +} + +//=========================================================================== +// +// ABackpackItem :: DetachFromOwner +// +//=========================================================================== + +void ABackpackItem::DetachFromOwner () +{ + // When removing a backpack, drop the player's ammo maximums to normal + AInventory *item; + + for (item = Owner->Inventory; item != NULL; item = item->Inventory) + { + if (item->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo) && + item->MaxAmount == static_cast(item)->BackpackMaxAmount) + { + item->MaxAmount = static_cast(item->GetDefault())->MaxAmount; + if (item->Amount > item->MaxAmount) + { + item->Amount = item->MaxAmount; + } + } + } +} + diff --git a/src/g_inventory/a_ammo.h b/src/g_inventory/a_ammo.h new file mode 100644 index 0000000000..fe5e1759e8 --- /dev/null +++ b/src/g_inventory/a_ammo.h @@ -0,0 +1,47 @@ +#pragma once +#include "a_pickups.h" + +// Ammo: Something a weapon needs to operate +class PClassAmmo : public PClassInventory +{ + DECLARE_CLASS(PClassAmmo, PClassInventory) +protected: + virtual void DeriveData(PClass *newclass); +public: + PClassAmmo(); + + int DropAmount; // Specifies the amount for a dropped ammo item. +}; + +class AAmmo : public AInventory +{ + DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo) +public: + + void Serialize(FSerializer &arc); + AInventory *CreateCopy (AActor *other); + bool HandlePickup (AInventory *item); + PClassActor *GetParentAmmo () const; + AInventory *CreateTossable (); + + int BackpackAmount, BackpackMaxAmount; +}; + + +// A backpack gives you one clip of each ammo and doubles your +// normal maximum ammo amounts. +class ABackpackItem : public AInventory +{ + DECLARE_CLASS (ABackpackItem, AInventory) +public: + + void Serialize(FSerializer &arc); + bool HandlePickup (AInventory *item); + AInventory *CreateCopy (AActor *other); + AInventory *CreateTossable (); + void DetachFromOwner (); + + bool bDepleted; +}; + + diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index ad843667a5..84b8b366fe 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -20,8 +20,10 @@ #include "p_spec.h" #include "serializer.h" #include "virtual.h" +#include "a_ammo.h" static FRandom pr_restore ("RestorePos"); +EXTERN_CVAR(Bool, sv_unlimited_pickup) IMPLEMENT_CLASS(PClassInventory, false, false) @@ -70,179 +72,6 @@ void PClassInventory::Finalize(FStateDefinitions &statedef) ((AActor*)Defaults)->flags |= MF_SPECIAL; } -IMPLEMENT_CLASS(PClassAmmo, false, false) - -PClassAmmo::PClassAmmo() -{ - DropAmount = 0; -} - -void PClassAmmo::DeriveData(PClass *newclass) -{ - assert(newclass->IsKindOf(RUNTIME_CLASS(PClassAmmo))); - Super::DeriveData(newclass); - PClassAmmo *newc = static_cast(newclass); - - newc->DropAmount = DropAmount; -} - -IMPLEMENT_CLASS(AAmmo, false, false) - -DEFINE_FIELD(AAmmo, BackpackAmount) -DEFINE_FIELD(AAmmo, BackpackMaxAmount) - -//=========================================================================== -// -// AAmmo :: Serialize -// -//=========================================================================== - -void AAmmo::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - auto def = (AAmmo*)GetDefault(); - arc("backpackamount", BackpackAmount, def->BackpackAmount) - ("backpackmaxamount", BackpackMaxAmount, def->BackpackMaxAmount); -} - -//=========================================================================== -// -// AAmmo :: GetParentAmmo -// -// Returns the least-derived ammo type that this ammo is a descendant of. -// That is, if this ammo is an immediate subclass of Ammo, then this ammo's -// type is returned. If this ammo's superclass is not Ammo, then this -// function travels up the inheritance chain until it finds a type that is -// an immediate subclass of Ammo and returns that. -// -// The intent of this is that all unique ammo types will be immediate -// subclasses of Ammo. To make different pickups with different ammo amounts, -// you subclass the type of ammo you want a different amount for and edit -// that. -// -//=========================================================================== - -PClassActor *AAmmo::GetParentAmmo () const -{ - PClass *type = GetClass(); - - while (type->ParentClass != RUNTIME_CLASS(AAmmo) && type->ParentClass != NULL) - { - type = type->ParentClass; - } - return static_cast(type); -} - -//=========================================================================== -// -// AAmmo :: HandlePickup -// -//=========================================================================== -EXTERN_CVAR(Bool, sv_unlimited_pickup) - -bool AAmmo::HandlePickup (AInventory *item) -{ - if (GetClass() == item->GetClass() || - (item->IsKindOf (RUNTIME_CLASS(AAmmo)) && static_cast(item)->GetParentAmmo() == GetClass())) - { - if (Amount < MaxAmount || sv_unlimited_pickup) - { - int receiving = item->Amount; - - if (!(item->ItemFlags & IF_IGNORESKILL)) - { // extra ammo in baby mode and nightmare mode - receiving = int(receiving * G_SkillProperty(SKILLP_AmmoFactor)); - } - int oldamount = Amount; - - if (Amount > 0 && Amount + receiving < 0) - { - Amount = 0x7fffffff; - } - else - { - Amount += receiving; - } - if (Amount > MaxAmount && !sv_unlimited_pickup) - { - Amount = MaxAmount; - } - item->ItemFlags |= IF_PICKUPGOOD; - - // If the player previously had this ammo but ran out, possibly switch - // to a weapon that uses it, but only if the player doesn't already - // have a weapon pending. - - assert (Owner != NULL); - - if (oldamount == 0 && Owner != NULL && Owner->player != NULL) - { - barrier_cast(Owner)->CheckWeaponSwitch(GetClass()); - } - } - return true; - } - return false; -} - -//=========================================================================== -// -// AAmmo :: CreateCopy -// -//=========================================================================== - -AInventory *AAmmo::CreateCopy (AActor *other) -{ - AInventory *copy; - int amount = Amount; - - // extra ammo in baby mode and nightmare mode - if (!(ItemFlags&IF_IGNORESKILL)) - { - amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); - } - - if (GetClass()->ParentClass != RUNTIME_CLASS(AAmmo) && GetClass() != RUNTIME_CLASS(AAmmo)) - { - PClassActor *type = GetParentAmmo(); - if (!GoAway ()) - { - Destroy (); - } - - copy = static_cast(Spawn (type)); - copy->Amount = amount; - copy->BecomeItem (); - } - else - { - copy = Super::CreateCopy (other); - copy->Amount = amount; - } - if (copy->Amount > copy->MaxAmount) - { // Don't pick up more ammo than you're supposed to be able to carry. - copy->Amount = copy->MaxAmount; - } - return copy; -} - -//=========================================================================== -// -// AAmmo :: CreateTossable -// -//=========================================================================== - -AInventory *AAmmo::CreateTossable() -{ - AInventory *copy = Super::CreateTossable(); - if (copy != NULL) - { // Do not increase ammo by dropping it and picking it back up at - // certain skill levels. - copy->ItemFlags |= IF_IGNORESKILL; - } - return copy; -} - //--------------------------------------------------------------------------- // // FUNC P_GiveBody @@ -2068,174 +1897,6 @@ void AHealthPickup::Serialize(FSerializer &arc) arc("autousemode", autousemode, def->autousemode); } -// Backpack ----------------------------------------------------------------- - -IMPLEMENT_CLASS(ABackpackItem, false, false) - -DEFINE_FIELD(ABackpackItem, bDepleted) - -//=========================================================================== -// -// ABackpackItem :: Serialize -// -//=========================================================================== - -void ABackpackItem::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - auto def = (ABackpackItem*)GetDefault(); - arc("bdepleted", bDepleted, def->bDepleted); -} - -//=========================================================================== -// -// ABackpackItem :: CreateCopy -// -// A backpack is being added to a player who doesn't yet have one. Give them -// every kind of ammo, and increase their max amounts. -// -//=========================================================================== - -AInventory *ABackpackItem::CreateCopy (AActor *other) -{ - // Find every unique type of ammo. Give it to the player if - // he doesn't have it already, and double its maximum capacity. - for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) - { - PClass *type = PClassActor::AllActorClasses[i]; - - if (type->ParentClass == RUNTIME_CLASS(AAmmo)) - { - PClassActor *atype = static_cast(type); - AAmmo *ammo = static_cast(other->FindInventory(atype)); - int amount = static_cast(GetDefaultByType(type))->BackpackAmount; - // extra ammo in baby mode and nightmare mode - if (!(ItemFlags&IF_IGNORESKILL)) - { - amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); - } - if (amount < 0) amount = 0; - if (ammo == NULL) - { // The player did not have the ammo. Add it. - ammo = static_cast(Spawn(atype)); - ammo->Amount = bDepleted ? 0 : amount; - if (ammo->BackpackMaxAmount > ammo->MaxAmount) - { - ammo->MaxAmount = ammo->BackpackMaxAmount; - } - if (ammo->Amount > ammo->MaxAmount) - { - ammo->Amount = ammo->MaxAmount; - } - ammo->AttachToOwner (other); - } - else - { // The player had the ammo. Give some more. - if (ammo->MaxAmount < ammo->BackpackMaxAmount) - { - ammo->MaxAmount = ammo->BackpackMaxAmount; - } - if (!bDepleted && ammo->Amount < ammo->MaxAmount) - { - ammo->Amount += amount; - if (ammo->Amount > ammo->MaxAmount) - { - ammo->Amount = ammo->MaxAmount; - } - } - } - } - } - return Super::CreateCopy (other); -} - -//=========================================================================== -// -// ABackpackItem :: HandlePickup -// -// When the player picks up another backpack, just give them more ammo. -// -//=========================================================================== - -bool ABackpackItem::HandlePickup (AInventory *item) -{ - // Since you already have a backpack, that means you already have every - // kind of ammo in your inventory, so we don't need to look at the - // entire PClass list to discover what kinds of ammo exist, and we don't - // have to alter the MaxAmount either. - if (item->IsKindOf (RUNTIME_CLASS(ABackpackItem))) - { - for (AInventory *probe = Owner->Inventory; probe != NULL; probe = probe->Inventory) - { - if (probe->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo)) - { - if (probe->Amount < probe->MaxAmount || sv_unlimited_pickup) - { - int amount = static_cast(probe->GetDefault())->BackpackAmount; - // extra ammo in baby mode and nightmare mode - if (!(item->ItemFlags&IF_IGNORESKILL)) - { - amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); - } - probe->Amount += amount; - if (probe->Amount > probe->MaxAmount && !sv_unlimited_pickup) - { - probe->Amount = probe->MaxAmount; - } - } - } - } - // The pickup always succeeds, even if you didn't get anything - item->ItemFlags |= IF_PICKUPGOOD; - return true; - } - return false; -} - -//=========================================================================== -// -// ABackpackItem :: CreateTossable -// -// The tossed backpack must not give out any more ammo, otherwise a player -// could cheat by dropping their backpack and picking it up for more ammo. -// -//=========================================================================== - -AInventory *ABackpackItem::CreateTossable () -{ - ABackpackItem *pack = static_cast(Super::CreateTossable()); - if (pack != NULL) - { - pack->bDepleted = true; - } - return pack; -} - -//=========================================================================== -// -// ABackpackItem :: DetachFromOwner -// -//=========================================================================== - -void ABackpackItem::DetachFromOwner () -{ - // When removing a backpack, drop the player's ammo maximums to normal - AInventory *item; - - for (item = Owner->Inventory; item != NULL; item = item->Inventory) - { - if (item->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo) && - item->MaxAmount == static_cast(item)->BackpackMaxAmount) - { - item->MaxAmount = static_cast(item->GetDefault())->MaxAmount; - if (item->Amount > item->MaxAmount) - { - item->Amount = item->MaxAmount; - } - } - } -} - //=========================================================================== // // ABackpack diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 56caabf3cb..00a8e6546d 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -9,92 +9,9 @@ class player_t; class FConfigFile; -class AWeapon; -class PClassWeapon; class PClassPlayerPawn; struct visstyle_t; -class FWeaponSlot -{ -public: - FWeaponSlot() { Clear(); } - FWeaponSlot(const FWeaponSlot &other) { Weapons = other.Weapons; } - FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; } - void Clear() { Weapons.Clear(); } - bool AddWeapon (const char *type); - bool AddWeapon (PClassWeapon *type); - void AddWeaponList (const char *list, bool clear); - AWeapon *PickWeapon (player_t *player, bool checkammo = false); - int Size () const { return (int)Weapons.Size(); } - int LocateWeapon (PClassWeapon *type); - - inline PClassWeapon *GetWeapon (int index) const - { - if ((unsigned)index < Weapons.Size()) - { - return Weapons[index].Type; - } - else - { - return NULL; - } - } - - friend struct FWeaponSlots; - -private: - struct WeaponInfo - { - PClassWeapon *Type; - int Position; - }; - void SetInitialPositions(); - void Sort(); - TArray Weapons; -}; -// FWeaponSlots::AddDefaultWeapon return codes -enum ESlotDef -{ - SLOTDEF_Exists, // Weapon was already assigned a slot - SLOTDEF_Added, // Weapon was successfully added - SLOTDEF_Full // The specifed slot was full -}; - -struct FWeaponSlots -{ - FWeaponSlots() { Clear(); } - FWeaponSlots(const FWeaponSlots &other); - - FWeaponSlot Slots[NUM_WEAPON_SLOTS]; - - AWeapon *PickNextWeapon (player_t *player); - AWeapon *PickPrevWeapon (player_t *player); - - void Clear (); - bool LocateWeapon (PClassWeapon *type, int *const slot, int *const index); - ESlotDef AddDefaultWeapon (int slot, PClassWeapon *type); - void AddExtraWeapons(); - void SetFromGameInfo(); - void SetFromPlayer(PClassPlayerPawn *type); - void StandardSetup(PClassPlayerPawn *type); - void LocalSetup(PClassActor *type); - void SendDifferences(int playernum, const FWeaponSlots &other); - int RestoreSlots (FConfigFile *config, const char *section); - void PrintSettings(); - - void AddSlot(int slot, PClassWeapon *type, bool feedback); - void AddSlotDefault(int slot, PClassWeapon *type, bool feedback); - -}; - -void P_PlaybackKeyConfWeapons(FWeaponSlots *slots); -void Net_WriteWeapon(PClassWeapon *type); -PClassWeapon *Net_ReadWeapon(BYTE **stream); - -void P_SetupWeapons_ntohton(); -void P_WriteDemoWeaponsChunk(BYTE **demo); -void P_ReadDemoWeaponsChunk(BYTE **demo); - /************************************************************************/ /* Class definitions */ /************************************************************************/ @@ -252,174 +169,6 @@ public: bool SpecialDropAction (AActor *dropper); }; -// Ammo: Something a weapon needs to operate -class PClassAmmo : public PClassInventory -{ - DECLARE_CLASS(PClassAmmo, PClassInventory) -protected: - virtual void DeriveData(PClass *newclass); -public: - PClassAmmo(); - - int DropAmount; // Specifies the amount for a dropped ammo item. -}; - -class AAmmo : public AInventory -{ - DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo) -public: - - void Serialize(FSerializer &arc); - AInventory *CreateCopy (AActor *other); - bool HandlePickup (AInventory *item); - PClassActor *GetParentAmmo () const; - AInventory *CreateTossable (); - - int BackpackAmount, BackpackMaxAmount; -}; - -// A weapon is just that. -class PClassWeapon : public PClassInventory -{ - DECLARE_CLASS(PClassWeapon, PClassInventory); -protected: - virtual void DeriveData(PClass *newclass); -public: - PClassWeapon(); - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); - void Finalize(FStateDefinitions &statedef); - - int SlotNumber; - int SlotPriority; -}; - -class AWeapon : public AStateProvider -{ - DECLARE_CLASS_WITH_META(AWeapon, AStateProvider, PClassWeapon) - HAS_OBJECT_POINTERS -public: - DWORD WeaponFlags; - PClassAmmo *AmmoType1, *AmmoType2; // Types of ammo used by this weapon - int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon - int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon - int AmmoUse1, AmmoUse2; // How much ammo to use with each shot - int Kickback; - float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) - FSoundIDNoInit UpSound, ReadySound; // Sounds when coming up and idle - PClassWeapon *SisterWeaponType; // Another weapon to pick up with this one - PClassActor *ProjectileType; // Projectile used by primary attack - PClassActor *AltProjectileType; // Projectile used by alternate attack - int SelectionOrder; // Lower-numbered weapons get picked first - int MinSelAmmo1, MinSelAmmo2; // Ignore in BestWeapon() if inadequate ammo - double MoveCombatDist; // Used by bots, but do they *really* need it? - int ReloadCounter; // For A_CheckForReload - int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double) - float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs. - float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction. - - // In-inventory instance variables - TObjPtr Ammo1, Ammo2; - TObjPtr SisterWeapon; - float FOVScale; - int Crosshair; // 0 to use player's crosshair - bool GivenAsMorphWeapon; - - bool bAltFire; // Set when this weapon's alternate fire is used. - - virtual void MarkPrecacheSounds() const; - - virtual void Serialize(FSerializer &arc); - virtual bool ShouldStay (); - virtual void AttachToOwner (AActor *other); - virtual bool HandlePickup (AInventory *item); - virtual AInventory *CreateCopy (AActor *other); - virtual AInventory *CreateTossable (); - virtual bool TryPickup (AActor *&toucher); - virtual bool TryPickupRestricted (AActor *&toucher); - virtual bool PickupForAmmo (AWeapon *ownedWeapon); - virtual bool Use (bool pickup); - virtual void Destroy() override; - - FState *GetUpState (); - FState *GetDownState (); - FState *GetReadyState (); - FState *GetAtkState (bool hold); - FState *GetAltAtkState (bool hold); - FState *GetStateForButtonName (FName button); - - virtual void PostMorphWeapon (); - virtual void EndPowerup (); - void CallEndPowerup(); - - enum - { - PrimaryFire, - AltFire, - EitherFire - }; - bool CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo=false, int ammocount = -1); - bool DepleteAmmo (bool altFire, bool checkEnough=true, int ammouse = -1); - - enum - { - BobNormal, - BobInverse, - BobAlpha, - BobInverseAlpha, - BobSmooth, - BobInverseSmooth - }; - -protected: - AAmmo *AddAmmo (AActor *other, PClassActor *ammotype, int amount); - bool AddExistingAmmo (AAmmo *ammo, int amount); - AWeapon *AddWeapon (PClassWeapon *weapon); -}; - -enum -{ - WIF_NOAUTOFIRE = 0x00000001, // weapon does not autofire - WIF_READYSNDHALF = 0x00000002, // ready sound is played ~1/2 the time - WIF_DONTBOB = 0x00000004, // don't bob the weapon - WIF_AXEBLOOD = 0x00000008, // weapon makes axe blood on impact (Hexen only) - WIF_NOALERT = 0x00000010, // weapon does not alert monsters - WIF_AMMO_OPTIONAL = 0x00000020, // weapon can use ammo but does not require it - WIF_ALT_AMMO_OPTIONAL = 0x00000040, // alternate fire can use ammo but does not require it - WIF_PRIMARY_USES_BOTH = 0x00000080, // primary fire uses both ammo - WIF_ALT_USES_BOTH = 0x00000100, // alternate fire uses both ammo - WIF_WIMPY_WEAPON = 0x00000200, // change away when ammo for another weapon is replenished - WIF_POWERED_UP = 0x00000400, // this is a tome-of-power'ed version of its sister - WIF_AMMO_CHECKBOTH = 0x00000800, // check for both primary and secondary fire before switching it off - WIF_NO_AUTO_SWITCH = 0x00001000, // never switch to this weapon when it's picked up - WIF_STAFF2_KICKBACK = 0x00002000, // the powered-up Heretic staff has special kickback - WIF_NOAUTOAIM = 0x00004000, // this weapon never uses autoaim (useful for ballistic projectiles) - WIF_MELEEWEAPON = 0x00008000, // melee weapon. Used by bots and monster AI. - WIF_DEHAMMO = 0x00010000, // Uses Doom's original amount of ammo for the respective attack functions so that old DEHACKED patches work as intended. - // AmmoUse1 will be set to the first attack's ammo use so that checking for empty weapons still works - WIF_NODEATHDESELECT = 0x00020000, // Don't jump to the Deselect state when the player dies - WIF_NODEATHINPUT = 0x00040000, // The weapon cannot be fired/reloaded/whatever when the player is dead - WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil) - - // Flags used only by bot AI: - - WIF_BOT_REACTION_SKILL_THING = 1<<31, // I don't understand this - WIF_BOT_EXPLOSIVE = 1<<30, // weapon fires an explosive - WIF_BOT_BFG = 1<<28, // this is a BFG -}; - -class AWeaponGiver : public AWeapon -{ - DECLARE_CLASS(AWeaponGiver, AWeapon) - -public: - bool TryPickup(AActor *&toucher); - - void Serialize(FSerializer &arc); - - double DropAmmoFactor; -}; - - // Health is some item that gives the player health when picked up. class PClassHealth : public PClassInventory { @@ -488,23 +237,6 @@ public: bool TryPickup (AActor *&toucher); }; -// A backpack gives you one clip of each ammo and doubles your -// normal maximum ammo amounts. -class ABackpackItem : public AInventory -{ - DECLARE_CLASS (ABackpackItem, AInventory) -public: - - void Serialize(FSerializer &arc); - bool HandlePickup (AInventory *item); - AInventory *CreateCopy (AActor *other); - AInventory *CreateTossable (); - void DetachFromOwner (); - - bool bDepleted; -}; - - // A score item is picked up without being added to the inventory. // It differs from FakeInventory by doing nothing more than increasing the player's score. class AScoreItem : public AInventory diff --git a/src/g_inventory/a_puzzleitems.cpp b/src/g_inventory/a_puzzleitems.cpp index 0d63bb00c3..e2a538387d 100644 --- a/src/g_inventory/a_puzzleitems.cpp +++ b/src/g_inventory/a_puzzleitems.cpp @@ -1,3 +1,38 @@ +/* +** a_puzzleitems.cpp +** Implements Hexen's puzzle items. +** +**--------------------------------------------------------------------------- +** Copyright 2002-2016 Randy Heit +** Copyright 2006-2016 Cheistoph 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 "info.h" #include "a_pickups.h" #include "a_artifacts.h" @@ -8,7 +43,17 @@ #include "doomstat.h" #include "v_font.h" + IMPLEMENT_CLASS(PClassPuzzleItem, false, false) +IMPLEMENT_CLASS(APuzzleItem, false, false) + +DEFINE_FIELD(APuzzleItem, PuzzleItemNumber) + +//=========================================================================== +// +// +// +//=========================================================================== void PClassPuzzleItem::DeriveData(PClass *newclass) { @@ -17,9 +62,12 @@ void PClassPuzzleItem::DeriveData(PClass *newclass) static_cast(newclass)->PuzzFailMessage = PuzzFailMessage; } -IMPLEMENT_CLASS(APuzzleItem, false, false) -DEFINE_FIELD(APuzzleItem, PuzzleItemNumber) +//=========================================================================== +// +// +// +//=========================================================================== bool APuzzleItem::HandlePickup (AInventory *item) { @@ -31,6 +79,12 @@ bool APuzzleItem::HandlePickup (AInventory *item) return Super::HandlePickup (item); } +//=========================================================================== +// +// +// +//=========================================================================== + bool APuzzleItem::Use (bool pickup) { if (P_UsePuzzleItem (Owner, PuzzleItemNumber)) @@ -49,6 +103,12 @@ bool APuzzleItem::Use (bool pickup) return false; } +//=========================================================================== +// +// +// +//=========================================================================== + bool APuzzleItem::ShouldStay () { return !!multiplayer; diff --git a/src/g_inventory/a_weaponpiece.cpp b/src/g_inventory/a_weaponpiece.cpp index bb98415fca..b504559bd1 100644 --- a/src/g_inventory/a_weaponpiece.cpp +++ b/src/g_inventory/a_weaponpiece.cpp @@ -1,3 +1,38 @@ +/* +** a_weaponpieces.cpp +** Implements generic weapon pieces +** +**--------------------------------------------------------------------------- +** Copyright 2006-2016 Cheistoph Oelckers +** Copyright 2006-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 "a_pickups.h" #include "a_weaponpiece.h" #include "doomstat.h" @@ -9,6 +44,12 @@ IMPLEMENT_CLASS(AWeaponHolder, false, false) DEFINE_FIELD(AWeaponHolder, PieceMask); DEFINE_FIELD(AWeaponHolder, PieceWeapon); +//=========================================================================== +// +// +// +//=========================================================================== + void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) { Super::ReplaceClassRef(oldclass, newclass); @@ -19,6 +60,11 @@ void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) } } +//=========================================================================== +// +// +// +//=========================================================================== void AWeaponHolder::Serialize(FSerializer &arc) { @@ -33,6 +79,11 @@ IMPLEMENT_POINTERS_START(AWeaponPiece) IMPLEMENT_POINTER(FullWeapon) IMPLEMENT_POINTERS_END +//=========================================================================== +// +// +// +//=========================================================================== void AWeaponPiece::Serialize(FSerializer &arc) { @@ -151,11 +202,23 @@ bool AWeaponPiece::TryPickup (AActor *&toucher) return true; } +//=========================================================================== +// +// +// +//=========================================================================== + bool AWeaponPiece::ShouldStay () { return PrivateShouldStay (); } +//=========================================================================== +// +// +// +//=========================================================================== + bool AWeaponPiece::PrivateShouldStay () { // We want a weapon piece to behave like a weapon, so follow the exact diff --git a/src/g_inventory/a_weaponpiece.h b/src/g_inventory/a_weaponpiece.h index e293637cf9..bcaa261cbd 100644 --- a/src/g_inventory/a_weaponpiece.h +++ b/src/g_inventory/a_weaponpiece.h @@ -1,5 +1,6 @@ #pragma once #include "a_pickups.h" +#include "a_weapons.h" // class PClassWeaponPiece : public PClassInventory diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 4f49ecd6f6..90a217495a 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -1,3 +1,38 @@ +/* +** a_weapons.cpp +** Implements weapon handling +** +**--------------------------------------------------------------------------- +** Copyright 2000-2016 Randy Heit +** Copyright 2006-2016 Cheistoph 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 #include "a_pickups.h" @@ -19,6 +54,7 @@ #include "serializer.h" #include "thingdef.h" #include "virtual.h" +#include "a_ammo.h" #define BONUSADD 6 diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h new file mode 100644 index 0000000000..786f6189b6 --- /dev/null +++ b/src/g_inventory/a_weapons.h @@ -0,0 +1,230 @@ +#pragma once + +#include "a_ammo.h" + +class PClassWeapon; +class AWeapon; + +class FWeaponSlot +{ +public: + FWeaponSlot() { Clear(); } + FWeaponSlot(const FWeaponSlot &other) { Weapons = other.Weapons; } + FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; } + void Clear() { Weapons.Clear(); } + bool AddWeapon (const char *type); + bool AddWeapon (PClassWeapon *type); + void AddWeaponList (const char *list, bool clear); + AWeapon *PickWeapon (player_t *player, bool checkammo = false); + int Size () const { return (int)Weapons.Size(); } + int LocateWeapon (PClassWeapon *type); + + inline PClassWeapon *GetWeapon (int index) const + { + if ((unsigned)index < Weapons.Size()) + { + return Weapons[index].Type; + } + else + { + return NULL; + } + } + + friend struct FWeaponSlots; + +private: + struct WeaponInfo + { + PClassWeapon *Type; + int Position; + }; + void SetInitialPositions(); + void Sort(); + TArray Weapons; +}; +// FWeaponSlots::AddDefaultWeapon return codes +enum ESlotDef +{ + SLOTDEF_Exists, // Weapon was already assigned a slot + SLOTDEF_Added, // Weapon was successfully added + SLOTDEF_Full // The specifed slot was full +}; + +struct FWeaponSlots +{ + FWeaponSlots() { Clear(); } + FWeaponSlots(const FWeaponSlots &other); + + FWeaponSlot Slots[NUM_WEAPON_SLOTS]; + + AWeapon *PickNextWeapon (player_t *player); + AWeapon *PickPrevWeapon (player_t *player); + + void Clear (); + bool LocateWeapon (PClassWeapon *type, int *const slot, int *const index); + ESlotDef AddDefaultWeapon (int slot, PClassWeapon *type); + void AddExtraWeapons(); + void SetFromGameInfo(); + void SetFromPlayer(PClassPlayerPawn *type); + void StandardSetup(PClassPlayerPawn *type); + void LocalSetup(PClassActor *type); + void SendDifferences(int playernum, const FWeaponSlots &other); + int RestoreSlots (FConfigFile *config, const char *section); + void PrintSettings(); + + void AddSlot(int slot, PClassWeapon *type, bool feedback); + void AddSlotDefault(int slot, PClassWeapon *type, bool feedback); + +}; + +void P_PlaybackKeyConfWeapons(FWeaponSlots *slots); +void Net_WriteWeapon(PClassWeapon *type); +PClassWeapon *Net_ReadWeapon(BYTE **stream); + +void P_SetupWeapons_ntohton(); +void P_WriteDemoWeaponsChunk(BYTE **demo); +void P_ReadDemoWeaponsChunk(BYTE **demo); + + +// A weapon is just that. +class PClassWeapon : public PClassInventory +{ + DECLARE_CLASS(PClassWeapon, PClassInventory); +protected: + virtual void DeriveData(PClass *newclass); +public: + PClassWeapon(); + virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); + void Finalize(FStateDefinitions &statedef); + + int SlotNumber; + int SlotPriority; +}; + +class AWeapon : public AStateProvider +{ + DECLARE_CLASS_WITH_META(AWeapon, AStateProvider, PClassWeapon) + HAS_OBJECT_POINTERS +public: + DWORD WeaponFlags; + PClassAmmo *AmmoType1, *AmmoType2; // Types of ammo used by this weapon + int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon + int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon + int AmmoUse1, AmmoUse2; // How much ammo to use with each shot + int Kickback; + float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) + FSoundIDNoInit UpSound, ReadySound; // Sounds when coming up and idle + PClassWeapon *SisterWeaponType; // Another weapon to pick up with this one + PClassActor *ProjectileType; // Projectile used by primary attack + PClassActor *AltProjectileType; // Projectile used by alternate attack + int SelectionOrder; // Lower-numbered weapons get picked first + int MinSelAmmo1, MinSelAmmo2; // Ignore in BestWeapon() if inadequate ammo + double MoveCombatDist; // Used by bots, but do they *really* need it? + int ReloadCounter; // For A_CheckForReload + int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double) + float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs. + float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction. + + // In-inventory instance variables + TObjPtr Ammo1, Ammo2; + TObjPtr SisterWeapon; + float FOVScale; + int Crosshair; // 0 to use player's crosshair + bool GivenAsMorphWeapon; + + bool bAltFire; // Set when this weapon's alternate fire is used. + + virtual void MarkPrecacheSounds() const; + + virtual void Serialize(FSerializer &arc); + virtual bool ShouldStay (); + virtual void AttachToOwner (AActor *other); + virtual bool HandlePickup (AInventory *item); + virtual AInventory *CreateCopy (AActor *other); + virtual AInventory *CreateTossable (); + virtual bool TryPickup (AActor *&toucher); + virtual bool TryPickupRestricted (AActor *&toucher); + virtual bool PickupForAmmo (AWeapon *ownedWeapon); + virtual bool Use (bool pickup); + virtual void Destroy() override; + + FState *GetUpState (); + FState *GetDownState (); + FState *GetReadyState (); + FState *GetAtkState (bool hold); + FState *GetAltAtkState (bool hold); + FState *GetStateForButtonName (FName button); + + virtual void PostMorphWeapon (); + virtual void EndPowerup (); + void CallEndPowerup(); + + enum + { + PrimaryFire, + AltFire, + EitherFire + }; + bool CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo=false, int ammocount = -1); + bool DepleteAmmo (bool altFire, bool checkEnough=true, int ammouse = -1); + + enum + { + BobNormal, + BobInverse, + BobAlpha, + BobInverseAlpha, + BobSmooth, + BobInverseSmooth + }; + +protected: + AAmmo *AddAmmo (AActor *other, PClassActor *ammotype, int amount); + bool AddExistingAmmo (AAmmo *ammo, int amount); + AWeapon *AddWeapon (PClassWeapon *weapon); +}; + +enum +{ + WIF_NOAUTOFIRE = 0x00000001, // weapon does not autofire + WIF_READYSNDHALF = 0x00000002, // ready sound is played ~1/2 the time + WIF_DONTBOB = 0x00000004, // don't bob the weapon + WIF_AXEBLOOD = 0x00000008, // weapon makes axe blood on impact (Hexen only) + WIF_NOALERT = 0x00000010, // weapon does not alert monsters + WIF_AMMO_OPTIONAL = 0x00000020, // weapon can use ammo but does not require it + WIF_ALT_AMMO_OPTIONAL = 0x00000040, // alternate fire can use ammo but does not require it + WIF_PRIMARY_USES_BOTH = 0x00000080, // primary fire uses both ammo + WIF_ALT_USES_BOTH = 0x00000100, // alternate fire uses both ammo + WIF_WIMPY_WEAPON = 0x00000200, // change away when ammo for another weapon is replenished + WIF_POWERED_UP = 0x00000400, // this is a tome-of-power'ed version of its sister + WIF_AMMO_CHECKBOTH = 0x00000800, // check for both primary and secondary fire before switching it off + WIF_NO_AUTO_SWITCH = 0x00001000, // never switch to this weapon when it's picked up + WIF_STAFF2_KICKBACK = 0x00002000, // the powered-up Heretic staff has special kickback + WIF_NOAUTOAIM = 0x00004000, // this weapon never uses autoaim (useful for ballistic projectiles) + WIF_MELEEWEAPON = 0x00008000, // melee weapon. Used by bots and monster AI. + WIF_DEHAMMO = 0x00010000, // Uses Doom's original amount of ammo for the respective attack functions so that old DEHACKED patches work as intended. + // AmmoUse1 will be set to the first attack's ammo use so that checking for empty weapons still works + WIF_NODEATHDESELECT = 0x00020000, // Don't jump to the Deselect state when the player dies + WIF_NODEATHINPUT = 0x00040000, // The weapon cannot be fired/reloaded/whatever when the player is dead + WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil) + + // Flags used only by bot AI: + + WIF_BOT_REACTION_SKILL_THING = 1<<31, // I don't understand this + WIF_BOT_EXPLOSIVE = 1<<30, // weapon fires an explosive + WIF_BOT_BFG = 1<<28, // this is a BFG +}; + +class AWeaponGiver : public AWeapon +{ + DECLARE_CLASS(AWeaponGiver, AWeapon) + +public: + bool TryPickup(AActor *&toucher); + + void Serialize(FSerializer &arc); + + double DropAmmoFactor; +}; + diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index f2852919d8..8ca8d68163 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -59,6 +59,7 @@ #include "gstrings.h" #include "version.h" #include "cmdlib.h" +#include "a_ammo.h" #define ARTIFLASH_OFFSET (statusBar->invBarOffset+6) enum diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index c6e12918d5..a061dbf59a 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -44,6 +44,7 @@ #include "w_wad.h" #include "a_keys.h" #include "a_armor.h" +#include "a_ammo.h" #include "sbar.h" #include "sc_man.h" #include "templates.h" diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 3a242f80c3..973364cf7d 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -13,6 +13,7 @@ #include "templates.h" #include "a_keys.h" #include "a_armor.h" +#include "a_ammo.h" #include "gi.h" #include "g_level.h" #include "colormatcher.h" diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 6bd6b3862a..53405017ac 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -48,6 +48,7 @@ #include "r_utility.h" #include "a_morph.h" #include "a_armor.h" +#include "a_ammo.h" // [RH] Actually handle the cheat. The cheat code in st_stuff.c now just // writes some bytes to the network data stream, and the network code diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 93d0cd45b3..ba086da3ad 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -84,6 +84,7 @@ #include "thingdef.h" #include "a_pickups.h" #include "a_armor.h" +#include "a_ammo.h" extern FILE *Logfile; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 5b2ba6d655..29128c8b71 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -51,6 +51,7 @@ #include "p_spec.h" #include "p_checkposition.h" #include "math/cmath.h" +#include "a_ammo.h" #include "gi.h" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7c7d97cf2c..2d36136f34 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -70,6 +70,7 @@ #include "d_player.h" #include "virtual.h" #include "a_armor.h" +#include "a_ammo.h" // MACROS ------------------------------------------------------------------ diff --git a/src/p_user.cpp b/src/p_user.cpp index e92b560db3..11857631ab 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -60,6 +60,7 @@ #include "p_spec.h" #include "virtual.h" #include "a_armor.h" +#include "a_ammo.h" static FRandom pr_skullpop ("SkullPop"); diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index e85b6a1d9f..e87602114b 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -70,6 +70,7 @@ #include "r_data/colormaps.h" #include "a_weaponpiece.h" #include "vmbuilder.h" +#include "a_ammo.h" extern TArray OptionalClassPtrs; From b0f3121bec0e9b265b11f002f93a18f8ffa829d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 13:36:13 +0100 Subject: [PATCH 425/471] - split up zscript/shared/inventory.txt. - moved health items to their own file. - scriptified ScoreItem and MapRevealer whose entire functionality was a small TryPickup method. - fixed: bit fields in global variables were not correctly written. This should conclude the inventory cleanup. It is now possible again to find things in there. --- src/CMakeLists.txt | 1 + src/b_think.cpp | 1 + src/d_dehacked.cpp | 1 + src/d_net.cpp | 1 + src/dobjtype.cpp | 2 + src/g_inventory/a_artifacts.cpp | 2 + src/g_inventory/a_health.cpp | 301 ++++++++++ src/g_inventory/a_health.h | 42 ++ src/g_inventory/a_keys.h | 24 + src/g_inventory/a_pickups.cpp | 311 ---------- src/g_inventory/a_pickups.h | 78 --- src/g_inventory/a_puzzleitems.cpp | 1 + src/p_actionfunctions.cpp | 1 + src/p_interaction.cpp | 1 + src/p_mobj.cpp | 1 + src/scripting/codegeneration/codegen.cpp | 16 +- src/scripting/codegeneration/codegen.h | 4 + src/scripting/thingdef_properties.cpp | 2 + wadsrc/static/zscript.txt | 6 +- wadsrc/static/zscript/shared/armor.txt | 72 +++ wadsrc/static/zscript/shared/inv_misc.txt | 87 +++ wadsrc/static/zscript/shared/inventory.txt | 560 +----------------- .../shared/{pickups.txt => itemeffects.txt} | 0 wadsrc/static/zscript/shared/powerups.txt | 282 +++++++++ wadsrc/static/zscript/shared/weapons.txt | 144 +++++ 25 files changed, 982 insertions(+), 959 deletions(-) create mode 100644 src/g_inventory/a_health.cpp create mode 100644 src/g_inventory/a_health.h create mode 100644 wadsrc/static/zscript/shared/armor.txt create mode 100644 wadsrc/static/zscript/shared/inv_misc.txt rename wadsrc/static/zscript/shared/{pickups.txt => itemeffects.txt} (100%) create mode 100644 wadsrc/static/zscript/shared/powerups.txt create mode 100644 wadsrc/static/zscript/shared/weapons.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1265544963..83dad3b9d1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1110,6 +1110,7 @@ set (PCH_SOURCES g_inventory/a_ammo.cpp g_inventory/a_armor.cpp g_inventory/a_artifacts.cpp + g_inventory/a_health.cpp g_inventory/a_keys.cpp g_inventory/a_pickups.cpp g_inventory/a_puzzleitems.cpp diff --git a/src/b_think.cpp b/src/b_think.cpp index 7dd196622b..e41433fa30 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -22,6 +22,7 @@ #include "d_player.h" #include "vectors.h" #include "a_ammo.h" +#include "a_health.h" static FRandom pr_botmove ("BotMove"); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 62daefcaa9..c0ea00f5e3 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -76,6 +76,7 @@ #include "vmbuilder.h" #include "a_armor.h" #include "a_ammo.h" +#include "a_health.h" // [SO] Just the way Randy said to do it :) // [RH] Made this CVAR_SERVERINFO diff --git a/src/d_net.cpp b/src/d_net.cpp index 2611338679..4bda255103 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -61,6 +61,7 @@ #include "p_spec.h" #include "hardware.h" #include "r_utility.h" +#include "a_keys.h" #include "intermission/intermission.h" EXTERN_CVAR (Int, disableautosave) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 7377af56b7..dba5544982 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -50,6 +50,8 @@ #include "d_player.h" #include "doomerrors.h" #include "fragglescript/t_fs.h" +#include "a_keys.h" +#include "a_health.h" // MACROS ------------------------------------------------------------------ diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 5866e8b2ae..1198b91531 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -40,6 +40,7 @@ static FRandom pr_torch ("Torch"); #define TIMEFREEZE_TICS ( 12 * TICRATE ) */ + IMPLEMENT_CLASS(APowerup, false, false) // Powerup-Giver ------------------------------------------------------------- @@ -56,6 +57,7 @@ void PClassPowerupGiver::ReplaceClassRef(PClass *oldclass, PClass *newclass) } } +IMPLEMENT_CLASS(APowerupGiver, false, false) DEFINE_FIELD(APowerupGiver, PowerupType) DEFINE_FIELD(APowerupGiver, EffectTics) diff --git a/src/g_inventory/a_health.cpp b/src/g_inventory/a_health.cpp new file mode 100644 index 0000000000..58cd86e2a5 --- /dev/null +++ b/src/g_inventory/a_health.cpp @@ -0,0 +1,301 @@ +/* +** a_health.cpp +** All health items +** +**--------------------------------------------------------------------------- +** Copyright 2000-2016 Randy Heit +** Copyright 2006-2016 Cheistoph 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 "d_player.h" +#include "a_morph.h" +#include "a_health.h" +#include "serializer.h" + +//--------------------------------------------------------------------------- +// +// FUNC P_GiveBody +// +// Returns false if the body isn't needed at all. +// +//--------------------------------------------------------------------------- + +bool P_GiveBody (AActor *actor, int num, int max) +{ + if (actor->health <= 0 || (actor->player != NULL && actor->player->playerstate == PST_DEAD)) + { // Do not heal dead things. + return false; + } + + player_t *player = actor->player; + + num = clamp(num, -65536, 65536); // prevent overflows for bad values + if (player != NULL) + { + // Max is 0 by default, preserving default behavior for P_GiveBody() + // calls while supporting AHealth. + if (max <= 0) + { + max = static_cast(actor)->GetMaxHealth() + player->mo->stamina; + // [MH] First step in predictable generic morph effects + if (player->morphTics) + { + if (player->MorphStyle & MORPH_FULLHEALTH) + { + if (!(player->MorphStyle & MORPH_ADDSTAMINA)) + { + max -= player->mo->stamina; + } + } + else // old health behaviour + { + max = MAXMORPHHEALTH; + if (player->MorphStyle & MORPH_ADDSTAMINA) + { + max += player->mo->stamina; + } + } + } + } + // [RH] For Strife: A negative body sets you up with a percentage + // of your full health. + if (num < 0) + { + num = max * -num / 100; + if (player->health < num) + { + player->health = num; + actor->health = num; + return true; + } + } + else if (num > 0) + { + if (player->health < max) + { + num = int(num * G_SkillProperty(SKILLP_HealthFactor)); + if (num < 1) num = 1; + player->health += num; + if (player->health > max) + { + player->health = max; + } + actor->health = player->health; + return true; + } + } + } + else + { + // Parameter value for max is ignored on monsters, preserving original + // behaviour on AHealth as well as on existing calls to P_GiveBody(). + max = actor->SpawnHealth(); + if (num < 0) + { + num = max * -num / 100; + if (actor->health < num) + { + actor->health = num; + return true; + } + } + else if (actor->health < max) + { + actor->health += num; + if (actor->health > max) + { + actor->health = max; + } + return true; + } + } + return false; +} + +DEFINE_ACTION_FUNCTION(AActor, GiveBody) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(num); + PARAM_INT_DEF(max); + ACTION_RETURN_BOOL(P_GiveBody(self, num, max)); +} + +//=========================================================================== +// +// Classes +// +//=========================================================================== + +IMPLEMENT_CLASS(PClassHealth, false, false) +IMPLEMENT_CLASS(AHealth, false, false) +DEFINE_FIELD(AHealth, PrevHealth) + +//=========================================================================== +// +// PClassHealth Constructor +// +//=========================================================================== + +PClassHealth::PClassHealth() +{ + LowHealth = 0; +} + +//=========================================================================== +// +// PClassHealth :: DeriveData +// +//=========================================================================== + +void PClassHealth::DeriveData(PClass *newclass) +{ + assert(newclass->IsKindOf(RUNTIME_CLASS(PClassHealth))); + Super::DeriveData(newclass); + PClassHealth *newc = static_cast(newclass); + + newc->LowHealth = LowHealth; + newc->LowHealthMessage = LowHealthMessage; +} + + +//=========================================================================== +// +// AHealth :: PickupMessage +// +//=========================================================================== +FString AHealth::PickupMessage () +{ + int threshold = GetClass()->LowHealth; + + if (PrevHealth < threshold) + { + FString message = GetClass()->LowHealthMessage; + + if (message.IsNotEmpty()) + { + return message; + } + } + return Super::PickupMessage(); +} + +//=========================================================================== +// +// AHealth :: TryPickup +// +//=========================================================================== + +bool AHealth::TryPickup (AActor *&other) +{ + PrevHealth = other->player != NULL ? other->player->health : other->health; + + // P_GiveBody adds one new feature, applied only if it is possible to pick up negative health: + // Negative values are treated as positive percentages, ie Amount -100 means 100% health, ignoring max amount. + if (P_GiveBody(other, Amount, MaxAmount)) + { + GoAwayAndDie(); + return true; + } + return false; +} + +IMPLEMENT_CLASS(AHealthPickup, false, false) + +DEFINE_FIELD(AHealthPickup, autousemode) + +//=========================================================================== +// +// AHealthPickup :: CreateCopy +// +//=========================================================================== + +AInventory *AHealthPickup::CreateCopy (AActor *other) +{ + AInventory *copy = Super::CreateCopy (other); + copy->health = health; + return copy; +} + +//=========================================================================== +// +// AHealthPickup :: CreateTossable +// +//=========================================================================== + +AInventory *AHealthPickup::CreateTossable () +{ + AInventory *copy = Super::CreateTossable (); + if (copy != NULL) + { + copy->health = health; + } + return copy; +} + +//=========================================================================== +// +// AHealthPickup :: HandlePickup +// +//=========================================================================== + +bool AHealthPickup::HandlePickup (AInventory *item) +{ + // HealthPickups that are the same type but have different health amounts + // do not count as the same item. + if (item->health == health) + { + return Super::HandlePickup (item); + } + return false; +} + +//=========================================================================== +// +// AHealthPickup :: Use +// +//=========================================================================== + +bool AHealthPickup::Use (bool pickup) +{ + return P_GiveBody (Owner, health, 0); +} + +//=========================================================================== +// +// AHealthPickup :: Serialize +// +//=========================================================================== + +void AHealthPickup::Serialize(FSerializer &arc) +{ + Super::Serialize(arc); + auto def = (AHealthPickup*)GetDefault(); + arc("autousemode", autousemode, def->autousemode); +} + diff --git a/src/g_inventory/a_health.h b/src/g_inventory/a_health.h new file mode 100644 index 0000000000..a462bbfbda --- /dev/null +++ b/src/g_inventory/a_health.h @@ -0,0 +1,42 @@ +#pragma once + +#include "a_pickups.h" + +// Health is some item that gives the player health when picked up. +class PClassHealth : public PClassInventory +{ + DECLARE_CLASS(PClassHealth, PClassInventory) +protected: +public: + PClassHealth(); + virtual void DeriveData(PClass *newclass); + + FString LowHealthMessage; + int LowHealth; +}; + +class AHealth : public AInventory +{ + DECLARE_CLASS_WITH_META(AHealth, AInventory, PClassHealth) + +public: + int PrevHealth; + virtual bool TryPickup (AActor *&other); + virtual FString PickupMessage (); +}; + +// HealthPickup is some item that gives the player health when used. +class AHealthPickup : public AInventory +{ + DECLARE_CLASS (AHealthPickup, AInventory) +public: + int autousemode; + + + virtual void Serialize(FSerializer &arc); + virtual AInventory *CreateCopy (AActor *other); + virtual AInventory *CreateTossable (); + virtual bool HandlePickup (AInventory *item); + virtual bool Use (bool pickup); +}; + diff --git a/src/g_inventory/a_keys.h b/src/g_inventory/a_keys.h index 8222aa6942..fd46b416c1 100644 --- a/src/g_inventory/a_keys.h +++ b/src/g_inventory/a_keys.h @@ -21,4 +21,28 @@ void P_DeinitKeyMessages (); int P_GetMapColorForLock (int lock); int P_GetMapColorForKey (AInventory *key); + +// PuzzleItems work in conjunction with the UsePuzzleItem special +class PClassPuzzleItem : public PClassInventory +{ + DECLARE_CLASS(PClassPuzzleItem, PClassInventory); +protected: +public: + virtual void DeriveData(PClass *newclass); + FString PuzzFailMessage; +}; + +class APuzzleItem : public AInventory +{ + DECLARE_CLASS_WITH_META(APuzzleItem, AInventory, PClassPuzzleItem) +public: + + bool ShouldStay (); + bool Use (bool pickup); + bool HandlePickup (AInventory *item); + + int PuzzleItemNumber; +}; + + #endif diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 84b8b366fe..cf5dddcf3f 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -72,114 +72,6 @@ void PClassInventory::Finalize(FStateDefinitions &statedef) ((AActor*)Defaults)->flags |= MF_SPECIAL; } -//--------------------------------------------------------------------------- -// -// FUNC P_GiveBody -// -// Returns false if the body isn't needed at all. -// -//--------------------------------------------------------------------------- - -bool P_GiveBody (AActor *actor, int num, int max) -{ - if (actor->health <= 0 || (actor->player != NULL && actor->player->playerstate == PST_DEAD)) - { // Do not heal dead things. - return false; - } - - player_t *player = actor->player; - - num = clamp(num, -65536, 65536); // prevent overflows for bad values - if (player != NULL) - { - // Max is 0 by default, preserving default behavior for P_GiveBody() - // calls while supporting AHealth. - if (max <= 0) - { - max = static_cast(actor)->GetMaxHealth() + player->mo->stamina; - // [MH] First step in predictable generic morph effects - if (player->morphTics) - { - if (player->MorphStyle & MORPH_FULLHEALTH) - { - if (!(player->MorphStyle & MORPH_ADDSTAMINA)) - { - max -= player->mo->stamina; - } - } - else // old health behaviour - { - max = MAXMORPHHEALTH; - if (player->MorphStyle & MORPH_ADDSTAMINA) - { - max += player->mo->stamina; - } - } - } - } - // [RH] For Strife: A negative body sets you up with a percentage - // of your full health. - if (num < 0) - { - num = max * -num / 100; - if (player->health < num) - { - player->health = num; - actor->health = num; - return true; - } - } - else if (num > 0) - { - if (player->health < max) - { - num = int(num * G_SkillProperty(SKILLP_HealthFactor)); - if (num < 1) num = 1; - player->health += num; - if (player->health > max) - { - player->health = max; - } - actor->health = player->health; - return true; - } - } - } - else - { - // Parameter value for max is ignored on monsters, preserving original - // behaviour on AHealth as well as on existing calls to P_GiveBody(). - max = actor->SpawnHealth(); - if (num < 0) - { - num = max * -num / 100; - if (actor->health < num) - { - actor->health = num; - return true; - } - } - else if (actor->health < max) - { - actor->health += num; - if (actor->health > max) - { - actor->health = max; - } - return true; - } - } - return false; -} - -DEFINE_ACTION_FUNCTION(AActor, GiveBody) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(num); - PARAM_INT_DEF(max); - ACTION_RETURN_BOOL(P_GiveBody(self, num, max)); -} - //--------------------------------------------------------------------------- // // PROC A_RestoreSpecialThing1 @@ -1379,12 +1271,6 @@ bool AInventory::DrawPowerup (int x, int y) return false; } -/***************************************************************************/ -/* AArtifact implementation */ -/***************************************************************************/ - -IMPLEMENT_CLASS(APowerupGiver, false, false) - //=========================================================================== // // AInventory :: DoRespawn @@ -1748,200 +1634,3 @@ bool ACustomInventory::TryPickup (AActor *&toucher) } return useok; } - -IMPLEMENT_CLASS(PClassHealth, false, false) - -//=========================================================================== -// -// PClassHealth Constructor -// -//=========================================================================== - -PClassHealth::PClassHealth() -{ - LowHealth = 0; -} - -//=========================================================================== -// -// PClassHealth :: DeriveData -// -//=========================================================================== - -void PClassHealth::DeriveData(PClass *newclass) -{ - assert(newclass->IsKindOf(RUNTIME_CLASS(PClassHealth))); - Super::DeriveData(newclass); - PClassHealth *newc = static_cast(newclass); - - newc->LowHealth = LowHealth; - newc->LowHealthMessage = LowHealthMessage; -} - -IMPLEMENT_CLASS(AHealth, false, false) - -DEFINE_FIELD(AHealth, PrevHealth) - -//=========================================================================== -// -// AHealth :: PickupMessage -// -//=========================================================================== -FString AHealth::PickupMessage () -{ - int threshold = GetClass()->LowHealth; - - if (PrevHealth < threshold) - { - FString message = GetClass()->LowHealthMessage; - - if (message.IsNotEmpty()) - { - return message; - } - } - return Super::PickupMessage(); -} - -//=========================================================================== -// -// AHealth :: TryPickup -// -//=========================================================================== - -bool AHealth::TryPickup (AActor *&other) -{ - PrevHealth = other->player != NULL ? other->player->health : other->health; - - // P_GiveBody adds one new feature, applied only if it is possible to pick up negative health: - // Negative values are treated as positive percentages, ie Amount -100 means 100% health, ignoring max amount. - if (P_GiveBody(other, Amount, MaxAmount)) - { - GoAwayAndDie(); - return true; - } - return false; -} - -IMPLEMENT_CLASS(AHealthPickup, false, false) - -DEFINE_FIELD(AHealthPickup, autousemode) - -//=========================================================================== -// -// AHealthPickup :: CreateCopy -// -//=========================================================================== - -AInventory *AHealthPickup::CreateCopy (AActor *other) -{ - AInventory *copy = Super::CreateCopy (other); - copy->health = health; - return copy; -} - -//=========================================================================== -// -// AHealthPickup :: CreateTossable -// -//=========================================================================== - -AInventory *AHealthPickup::CreateTossable () -{ - AInventory *copy = Super::CreateTossable (); - if (copy != NULL) - { - copy->health = health; - } - return copy; -} - -//=========================================================================== -// -// AHealthPickup :: HandlePickup -// -//=========================================================================== - -bool AHealthPickup::HandlePickup (AInventory *item) -{ - // HealthPickups that are the same type but have different health amounts - // do not count as the same item. - if (item->health == health) - { - return Super::HandlePickup (item); - } - return false; -} - -//=========================================================================== -// -// AHealthPickup :: Use -// -//=========================================================================== - -bool AHealthPickup::Use (bool pickup) -{ - return P_GiveBody (Owner, health); -} - -//=========================================================================== -// -// AHealthPickup :: Serialize -// -//=========================================================================== - -void AHealthPickup::Serialize(FSerializer &arc) -{ - Super::Serialize(arc); - auto def = (AHealthPickup*)GetDefault(); - arc("autousemode", autousemode, def->autousemode); -} - -//=========================================================================== -// -// ABackpack -// -//=========================================================================== - -IMPLEMENT_CLASS(AMapRevealer, false, false) - -//=========================================================================== -// -// AMapRevealer :: TryPickup -// -// The MapRevealer doesn't actually go in your inventory. Instead, it sets -// a flag on the level. -// -//=========================================================================== - -bool AMapRevealer::TryPickup (AActor *&toucher) -{ - level.flags2 |= LEVEL2_ALLMAP; - GoAwayAndDie (); - return true; -} - - -//=========================================================================== -// -// AScoreItem -// -//=========================================================================== - -IMPLEMENT_CLASS(AScoreItem, false, false) - -//=========================================================================== -// -// AScoreItem :: TryPickup -// -// Adds the value (Amount) of the item to the toucher's Score property. -// -//=========================================================================== - -bool AScoreItem::TryPickup (AActor *&toucher) -{ - toucher->Score += Amount; - GoAwayAndDie(); - return true; -} - diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 00a8e6546d..b366a60318 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -169,84 +169,6 @@ public: bool SpecialDropAction (AActor *dropper); }; -// Health is some item that gives the player health when picked up. -class PClassHealth : public PClassInventory -{ - DECLARE_CLASS(PClassHealth, PClassInventory) -protected: -public: - PClassHealth(); - virtual void DeriveData(PClass *newclass); - - FString LowHealthMessage; - int LowHealth; -}; - -class AHealth : public AInventory -{ - DECLARE_CLASS_WITH_META(AHealth, AInventory, PClassHealth) - -public: - int PrevHealth; - virtual bool TryPickup (AActor *&other); - virtual FString PickupMessage (); -}; - -// HealthPickup is some item that gives the player health when used. -class AHealthPickup : public AInventory -{ - DECLARE_CLASS (AHealthPickup, AInventory) -public: - int autousemode; - - - virtual void Serialize(FSerializer &arc); - virtual AInventory *CreateCopy (AActor *other); - virtual AInventory *CreateTossable (); - virtual bool HandlePickup (AInventory *item); - virtual bool Use (bool pickup); -}; - -// PuzzleItems work in conjunction with the UsePuzzleItem special -class PClassPuzzleItem : public PClassInventory -{ - DECLARE_CLASS(PClassPuzzleItem, PClassInventory); -protected: -public: - virtual void DeriveData(PClass *newclass); - FString PuzzFailMessage; -}; - -class APuzzleItem : public AInventory -{ - DECLARE_CLASS_WITH_META(APuzzleItem, AInventory, PClassPuzzleItem) -public: - - bool ShouldStay (); - bool Use (bool pickup); - bool HandlePickup (AInventory *item); - - int PuzzleItemNumber; -}; - -// A MapRevealer reveals the whole map for the player who picks it up. -class AMapRevealer : public AInventory -{ - DECLARE_CLASS (AMapRevealer, AInventory) -public: - bool TryPickup (AActor *&toucher); -}; - -// A score item is picked up without being added to the inventory. -// It differs from FakeInventory by doing nothing more than increasing the player's score. -class AScoreItem : public AInventory -{ - DECLARE_CLASS (AScoreItem, AInventory) - -public: - bool TryPickup(AActor *&toucher); -}; - extern PClassActor *QuestItemClasses[31]; diff --git a/src/g_inventory/a_puzzleitems.cpp b/src/g_inventory/a_puzzleitems.cpp index e2a538387d..7617f63833 100644 --- a/src/g_inventory/a_puzzleitems.cpp +++ b/src/g_inventory/a_puzzleitems.cpp @@ -42,6 +42,7 @@ #include "c_console.h" #include "doomstat.h" #include "v_font.h" +#include "a_keys.h" IMPLEMENT_CLASS(PClassPuzzleItem, false, false) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 8981538e77..bc217f4ae5 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -79,6 +79,7 @@ #include "thingdef.h" #include "math/cmath.h" #include "a_armor.h" +#include "a_health.h" AActor *SingleActorFromTID(int tid, AActor *defactor); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index e0e3e62b9a..eae7edb00e 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -59,6 +59,7 @@ #include "d_netinf.h" #include "a_morph.h" #include "virtual.h" +#include "a_health.h" static FRandom pr_obituary ("Obituary"); static FRandom pr_botrespawn ("BotRespawn"); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2d36136f34..572c7656f9 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -71,6 +71,7 @@ #include "virtual.h" #include "a_armor.h" #include "a_ammo.h" +#include "a_health.h" // MACROS ------------------------------------------------------------------ diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7408573a00..eaeca6e9d6 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2248,16 +2248,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) } // 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; - } - } - + IsBitWrite = Base->GetBitValue(); return this; } @@ -5743,6 +5734,11 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) SAFE_RESOLVE(Object, ctx); + if (Identifier == FName("allmap")) + { + int a = 2; + } + // check for class or struct constants if the left side is a type name. if (Object->ValueType == TypeError) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 5d0af0b49a..c54c8dc62a 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -318,6 +318,7 @@ public: virtual PPrototype *ReturnProto(); virtual VMFunction *GetDirectFunction(); virtual bool CheckReturn() { return false; } + virtual int GetBitValue() { return -1; } 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); } @@ -1266,6 +1267,7 @@ public: FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); + virtual int GetBitValue() { return membervar->BitValue; } }; class FxCVar : public FxExpression @@ -1296,6 +1298,7 @@ public: FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); + virtual int GetBitValue() { return membervar->BitValue; } }; //========================================================================== @@ -1349,6 +1352,7 @@ public: FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); ExpEmit Emit(VMFunctionBuilder *build); + virtual int GetBitValue() { return membervar->BitValue; } }; //========================================================================== diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index e87602114b..9bff91a805 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -71,6 +71,8 @@ #include "a_weaponpiece.h" #include "vmbuilder.h" #include "a_ammo.h" +#include "a_health.h" +#include "a_keys.h" extern TArray OptionalClassPtrs; diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 82810185a3..a2b89da013 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -4,6 +4,10 @@ zscript/actor.txt zscript/actor_checks.txt zscript/shared/inventory.txt +zscript/shared/inv_misc.txt +zscript/shared/weapons.txt +zscript/shared/armor.txt +zscript/shared/powerups.txt zscript/shared/player.txt zscript/shared/morph.txt zscript/shared/botstuff.txt @@ -12,7 +16,7 @@ zscript/shared/blood.txt zscript/shared/debris.txt zscript/shared/decal.txt zscript/shared/splashes.txt -zscript/shared/pickups.txt +zscript/shared/itemeffects.txt zscript/shared/fountain.txt zscript/shared/spark.txt zscript/shared/soundsequence.txt diff --git a/wadsrc/static/zscript/shared/armor.txt b/wadsrc/static/zscript/shared/armor.txt new file mode 100644 index 0000000000..3e7f57e21c --- /dev/null +++ b/wadsrc/static/zscript/shared/armor.txt @@ -0,0 +1,72 @@ +class Armor : Inventory native +{ + Default + { + Inventory.PickupSound "misc/armor_pkup"; + } +} + +class BasicArmor : Armor native +{ + + native int AbsorbCount; + native double SavePercent; + native int MaxAbsorb; + native int MaxFullAbsorb; + native int BonusCount; + native Name ArmorType; + native int ActualSaveAmount; + + Default + { + +Inventory.KEEPDEPLETED + } +} + +class BasicArmorBonus : Armor native +{ + native double SavePercent; // The default, for when you don't already have armor + native int MaxSaveAmount; + native int MaxAbsorb; + native int MaxFullAbsorb; + native int SaveAmount; + native int BonusCount; + native int BonusMax; + + Default + { + +Inventory.AUTOACTIVATE + +Inventory.ALWAYSPICKUP + Inventory.MaxAmount 0; + Armor.SavePercent 33.335; + } +} + +class BasicArmorPickup : Armor native +{ + + native double SavePercent; + native int MaxAbsorb; + native int MaxFullAbsorb; + native int SaveAmount; + + Default + { + +Inventory.AUTOACTIVATE; + Inventory.MaxAmount 0; + } +} + +class HexenArmor : Armor native +{ + + native double Slots[5]; + native double SlotsIncrement[4]; + + Default + { + +Inventory.KEEPDEPLETED + +Inventory.UNDROPPABLE + } +} + diff --git a/wadsrc/static/zscript/shared/inv_misc.txt b/wadsrc/static/zscript/shared/inv_misc.txt new file mode 100644 index 0000000000..032c9e8266 --- /dev/null +++ b/wadsrc/static/zscript/shared/inv_misc.txt @@ -0,0 +1,87 @@ +class ScoreItem : Inventory +{ + Default + { + Height 10; + +COUNTITEM + Inventory.Amount 1; + +Inventory.ALWAYSPICKUP + } + + override bool TryPickup (in out Actor toucher) + { + toucher.Score += Amount; + GoAwayAndDie(); + return true; + } +} + +class Health : Inventory native +{ + native int PrevHealth; + + Default + { + Inventory.Amount 1; + Inventory.MaxAmount 0; + Inventory.PickupSound "misc/health_pkup"; + } +} + +class HealthPickup : Inventory native +{ + native int autousemode; + + Default + { + Inventory.DefMaxAmount; + +INVENTORY.INVBAR + } +} + +class Key : Inventory native +{ + native uint8 KeyNumber; + + Default + { + +DONTGIB; // Don't disappear due to a crusher + Inventory.InterHubAmount 0; + Inventory.PickupSound "misc/k_pkup"; + } +} + +class MapRevealer : Inventory +{ + //=========================================================================== + // + // AMapRevealer :: TryPickup + // + // A MapRevealer reveals the whole map for the player who picks it up. + // The MapRevealer doesn't actually go in your inventory. Instead, it sets + // a flag on the level. + // + //=========================================================================== + + override bool TryPickup (in out Actor toucher) + { + level.allmap = true; + GoAwayAndDie (); + return true; + } +} + +class PuzzleItem : Inventory native +{ + native int PuzzleItemNumber; + + Default + { + +NOGRAVITY + +INVENTORY.INVBAR + Inventory.DefMaxAmount; + Inventory.UseSound "PuzzleSuccess"; + Inventory.PickupSound "misc/i_pkup"; + } +} + diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 5192b4c93b..4e5c13d888 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -87,108 +87,10 @@ class StateProvider : Inventory native action native void A_ResetReloadCounter(); } -class ScoreItem : Inventory native +class DehackedPickup : Inventory native { - Default - { - Height 10; - +COUNTITEM - Inventory.Amount 1; - +Inventory.ALWAYSPICKUP - } } -class Ammo : Inventory native -{ - native int BackpackAmount; - native int BackpackMaxAmount; - - Default - { - +INVENTORY.KEEPDEPLETED - Inventory.PickupSound "misc/ammo_pkup"; - } -} - -class BackpackItem : Inventory native -{ - native bool bDepleted; -} - -class Armor : Inventory native -{ - Default - { - Inventory.PickupSound "misc/armor_pkup"; - } -} - -class BasicArmor : Armor native -{ - - native int AbsorbCount; - native double SavePercent; - native int MaxAbsorb; - native int MaxFullAbsorb; - native int BonusCount; - native Name ArmorType; - native int ActualSaveAmount; - - Default - { - +Inventory.KEEPDEPLETED - } -} - -class BasicArmorBonus : Armor native -{ - native double SavePercent; // The default, for when you don't already have armor - native int MaxSaveAmount; - native int MaxAbsorb; - native int MaxFullAbsorb; - native int SaveAmount; - native int BonusCount; - native int BonusMax; - - Default - { - +Inventory.AUTOACTIVATE - +Inventory.ALWAYSPICKUP - Inventory.MaxAmount 0; - Armor.SavePercent 33.335; - } -} - -class BasicArmorPickup : Armor native -{ - - native double SavePercent; - native int MaxAbsorb; - native int MaxFullAbsorb; - native int SaveAmount; - - Default - { - +Inventory.AUTOACTIVATE; - Inventory.MaxAmount 0; - } -} - -class HexenArmor : Armor native -{ - - native double Slots[5]; - native double SlotsIncrement[4]; - - Default - { - +Inventory.KEEPDEPLETED - +Inventory.UNDROPPABLE - } -} - -class DehackedPickup : Inventory native {} - class FakeInventory : Inventory native { native bool Respawnable; @@ -201,463 +103,3 @@ class CustomInventory : StateProvider native DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_ITEM; } } - -class Health : Inventory native -{ - native int PrevHealth; - - Default - { - Inventory.Amount 1; - Inventory.MaxAmount 0; - Inventory.PickupSound "misc/health_pkup"; - } -} - -class HealthPickup : Inventory native -{ - native int autousemode; - - Default - { - Inventory.DefMaxAmount; - +INVENTORY.INVBAR - } -} - -class Key : Inventory native -{ - native uint8 KeyNumber; - - Default - { - +DONTGIB; // Don't disappear due to a crusher - Inventory.InterHubAmount 0; - Inventory.PickupSound "misc/k_pkup"; - } -} - -class PowerupGiver : Inventory native -{ - - native Class PowerupType; - native int EffectTics; // Non-0 to override the powerup's default tics - native color BlendColor; // Non-0 to override the powerup's default blend - native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility - native double Strength; // Meaning depends on powerup - currently used only by Invisibility - - Default - { - Inventory.DefMaxAmount; - +INVENTORY.INVBAR - +INVENTORY.FANCYPICKUPSOUND - Inventory.PickupSound "misc/p_pkup"; - } -} - -class Powerup : Inventory native -{ - native int EffectTics; - native color BlendColor; - native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility - native double Strength; // Meaning depends on powerup - currently used only by Invisibility -} - -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 -{ - native int SpeedFlags; - - Default - { - Powerup.Duration -45; - Speed 1.5; - Inventory.Icon "SPBOOT0"; - +INVENTORY.NOTELEPORTFREEZE - } -} - -// Player Speed Trail (used by the Speed Powerup) ---------------------------- - -class PlayerSpeedTrail : Actor -{ - Default - { - +NOBLOCKMAP - +NOGRAVITY - Alpha 0.6; - RenderStyle "Translucent"; - } - - override void Tick() - { - Alpha -= .6 / 8; - if (Alpha <= 0) - { - Destroy (); - } - } -} - -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 -{ - native Class PlayerClass; - native Class MorphFlash, UnMorphFlash; - native int MorphStyle; - native PlayerInfo MorphedPlayer; - native bool bInUndoMorph; - - Default - { - Powerup.Duration -40; - } -} - -class PowerInfiniteAmmo : Powerup native -{ - Default - { - Powerup.Duration -30; - } -} - -class MapRevealer : Inventory native {} - -class PuzzleItem : Inventory native -{ - native int PuzzleItemNumber; - - Default - { - +NOGRAVITY - +INVENTORY.INVBAR - Inventory.DefMaxAmount; - Inventory.UseSound "PuzzleSuccess"; - Inventory.PickupSound "misc/i_pkup"; - } -} - -class Weapon : StateProvider native -{ - enum EFireMode - { - PrimaryFire, - AltFire, - EitherFire - }; - - native uint WeaponFlags; - native class AmmoType1, AmmoType2; // Types of ammo used by this weapon - native int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon - native int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon - native int AmmoUse1, AmmoUse2; // How much ammo to use with each shot - native int Kickback; - native float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) - native sound UpSound, ReadySound; // Sounds when coming up and idle - native class SisterWeaponType; // Another weapon to pick up with this one - native class ProjectileType; // Projectile used by primary attack - native class AltProjectileType; // Projectile used by alternate attack - native int SelectionOrder; // Lower-numbered weapons get picked first - native int MinSelAmmo1, MinSelAmmo2; // Ignore in BestWeapon() if inadequate ammo - native double MoveCombatDist; // Used by bots, but do they *really* need it? - native int ReloadCounter; // For A_CheckForReload - native int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double) - native float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs. - native float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction. - native Ammo Ammo1, Ammo2; // In-inventory instance variables - native Weapon SisterWeapon; - native float FOVScale; - native int Crosshair; // 0 to use player's crosshair - native bool GivenAsMorphWeapon; - native bool bAltFire; // Set when this weapon's alternate fire is used. - native readonly bool bDehAmmo; - - 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 bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1); - native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); - native virtual void EndPowerup(); - - virtual State GetReadyState () - { - return FindState('Ready'); - } - - virtual State GetUpState () - { - return FindState('Select'); - } - - virtual State GetDownState () - { - return FindState('Deselect'); - } - - virtual State GetAtkState (bool hold) - { - State s = null; - if (hold) s = FindState('Hold'); - if (s == null) s = FindState('Fire'); - return s; - } - - virtual State GetAltAtkState (bool hold) - { - State s = null; - if (hold) s = FindState('AltHold'); - if (s == null) s = FindState('AltFire'); - return s; - } - - native action void A_ZoomFactor(double scale = 1, int flags = 0); - native action void A_SetCrosshair(int xhair); - const ZOOM_INSTANT = 1; - const ZOOM_NOSCALETURNING = 2; - -} - -class WeaponGiver : Weapon native -{ - - native double DropAmmoFactor; - - Default - { - Weapon.AmmoGive1 -1; - Weapon.AmmoGive2 -1; - } -} - -class WeaponHolder : Inventory native -{ - native int PieceMask; - native Class PieceWeapon; - - Default - { - +NOBLOCKMAP - +NOSECTOR - +INVENTORY.UNDROPPABLE - } -} - -class WeaponPiece : Inventory native -{ - Default - { - +WEAPONSPAWN; - } -} diff --git a/wadsrc/static/zscript/shared/pickups.txt b/wadsrc/static/zscript/shared/itemeffects.txt similarity index 100% rename from wadsrc/static/zscript/shared/pickups.txt rename to wadsrc/static/zscript/shared/itemeffects.txt diff --git a/wadsrc/static/zscript/shared/powerups.txt b/wadsrc/static/zscript/shared/powerups.txt new file mode 100644 index 0000000000..4c7a84efe6 --- /dev/null +++ b/wadsrc/static/zscript/shared/powerups.txt @@ -0,0 +1,282 @@ +class PowerupGiver : Inventory native +{ + + native Class PowerupType; + native int EffectTics; // Non-0 to override the powerup's default tics + native color BlendColor; // Non-0 to override the powerup's default blend + native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility + native double Strength; // Meaning depends on powerup - currently used only by Invisibility + + Default + { + Inventory.DefMaxAmount; + +INVENTORY.INVBAR + +INVENTORY.FANCYPICKUPSOUND + Inventory.PickupSound "misc/p_pkup"; + } +} + +class Powerup : Inventory native +{ + native int EffectTics; + native color BlendColor; + native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility + native double Strength; // Meaning depends on powerup - currently used only by Invisibility +} + +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 +{ + native int SpeedFlags; + + Default + { + Powerup.Duration -45; + Speed 1.5; + Inventory.Icon "SPBOOT0"; + +INVENTORY.NOTELEPORTFREEZE + } +} + +// Player Speed Trail (used by the Speed Powerup) ---------------------------- + +class PlayerSpeedTrail : Actor +{ + Default + { + +NOBLOCKMAP + +NOGRAVITY + Alpha 0.6; + RenderStyle "Translucent"; + } + + override void Tick() + { + Alpha -= .6 / 8; + if (Alpha <= 0) + { + Destroy (); + } + } +} + +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 +{ + native Class PlayerClass; + native Class MorphFlash, UnMorphFlash; + native int MorphStyle; + native PlayerInfo MorphedPlayer; + native bool bInUndoMorph; + + Default + { + Powerup.Duration -40; + } +} + +class PowerInfiniteAmmo : Powerup native +{ + Default + { + Powerup.Duration -30; + } +} + diff --git a/wadsrc/static/zscript/shared/weapons.txt b/wadsrc/static/zscript/shared/weapons.txt new file mode 100644 index 0000000000..c3ebf299dd --- /dev/null +++ b/wadsrc/static/zscript/shared/weapons.txt @@ -0,0 +1,144 @@ +class Weapon : StateProvider native +{ + enum EFireMode + { + PrimaryFire, + AltFire, + EitherFire + }; + + native uint WeaponFlags; + native class AmmoType1, AmmoType2; // Types of ammo used by this weapon + native int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon + native int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon + native int AmmoUse1, AmmoUse2; // How much ammo to use with each shot + native int Kickback; + native float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) + native sound UpSound, ReadySound; // Sounds when coming up and idle + native class SisterWeaponType; // Another weapon to pick up with this one + native class ProjectileType; // Projectile used by primary attack + native class AltProjectileType; // Projectile used by alternate attack + native int SelectionOrder; // Lower-numbered weapons get picked first + native int MinSelAmmo1, MinSelAmmo2; // Ignore in BestWeapon() if inadequate ammo + native double MoveCombatDist; // Used by bots, but do they *really* need it? + native int ReloadCounter; // For A_CheckForReload + native int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double) + native float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs. + native float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction. + native Ammo Ammo1, Ammo2; // In-inventory instance variables + native Weapon SisterWeapon; + native float FOVScale; + native int Crosshair; // 0 to use player's crosshair + native bool GivenAsMorphWeapon; + native bool bAltFire; // Set when this weapon's alternate fire is used. + native readonly bool bDehAmmo; + + 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 bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1); + native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); + native virtual void EndPowerup(); + + virtual State GetReadyState () + { + return FindState('Ready'); + } + + virtual State GetUpState () + { + return FindState('Select'); + } + + virtual State GetDownState () + { + return FindState('Deselect'); + } + + virtual State GetAtkState (bool hold) + { + State s = null; + if (hold) s = FindState('Hold'); + if (s == null) s = FindState('Fire'); + return s; + } + + virtual State GetAltAtkState (bool hold) + { + State s = null; + if (hold) s = FindState('AltHold'); + if (s == null) s = FindState('AltFire'); + return s; + } + + native action void A_ZoomFactor(double scale = 1, int flags = 0); + native action void A_SetCrosshair(int xhair); + const ZOOM_INSTANT = 1; + const ZOOM_NOSCALETURNING = 2; + +} + +class WeaponGiver : Weapon native +{ + + native double DropAmmoFactor; + + Default + { + Weapon.AmmoGive1 -1; + Weapon.AmmoGive2 -1; + } +} + +class WeaponHolder : Inventory native +{ + native int PieceMask; + native Class PieceWeapon; + + Default + { + +NOBLOCKMAP + +NOSECTOR + +INVENTORY.UNDROPPABLE + } +} + +class WeaponPiece : Inventory native +{ + Default + { + +WEAPONSPAWN; + } +} + +class Ammo : Inventory native +{ + native int BackpackAmount; + native int BackpackMaxAmount; + + Default + { + +INVENTORY.KEEPDEPLETED + Inventory.PickupSound "misc/ammo_pkup"; + } +} + +class BackpackItem : Inventory native +{ + native bool bDepleted; +} + From 8a50004f55b4524c19c9bfb576d5f7b52c4fcfb8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 15:54:01 +0100 Subject: [PATCH 426/471] - cleanup of the virtual function definitions for inventory items. Let's better use 'virtual' and 'override' everywhere to make sure that nothing gets overlooked. - added call wrappers and script hooks for all relevant virtuals in AInventory. - made GetSpeedFactor and GetNoTeleportFreeze entirely scripted because they are too trivial - also do them iteratively, just like HandlePickup, because it's just a better way to do this stuff. --- src/d_dehacked.cpp | 2 +- src/g_inventory/a_ammo.h | 18 +-- src/g_inventory/a_armor.h | 34 ++-- src/g_inventory/a_artifacts.cpp | 26 --- src/g_inventory/a_artifacts.h | 148 ++++++++--------- src/g_inventory/a_health.h | 14 +- src/g_inventory/a_keys.h | 10 +- src/g_inventory/a_pickups.cpp | 179 ++++++++++++++++++--- src/g_inventory/a_pickups.h | 119 ++++++++------ src/g_inventory/a_weaponpiece.cpp | 2 +- src/g_inventory/a_weaponpiece.h | 14 +- src/g_inventory/a_weapons.cpp | 4 +- src/g_inventory/a_weapons.h | 31 ++-- src/g_shared/a_morph.cpp | 15 +- wadsrc/static/zscript/shared/inventory.txt | 13 +- wadsrc/static/zscript/shared/powerups.txt | 6 + 16 files changed, 390 insertions(+), 245 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index c0ea00f5e3..e2c5a6ea3a 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3157,7 +3157,7 @@ FString ADehackedPickup::PickupMessage () bool ADehackedPickup::ShouldStay () { if (RealPickup != nullptr) - return RealPickup->ShouldStay (); + return RealPickup->CallShouldStay (); else return true; } diff --git a/src/g_inventory/a_ammo.h b/src/g_inventory/a_ammo.h index fe5e1759e8..643d4b9248 100644 --- a/src/g_inventory/a_ammo.h +++ b/src/g_inventory/a_ammo.h @@ -18,11 +18,11 @@ class AAmmo : public AInventory DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo) public: - void Serialize(FSerializer &arc); - AInventory *CreateCopy (AActor *other); - bool HandlePickup (AInventory *item); + virtual void Serialize(FSerializer &arc) override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual bool HandlePickup (AInventory *item) override; + virtual AInventory *CreateTossable () override; PClassActor *GetParentAmmo () const; - AInventory *CreateTossable (); int BackpackAmount, BackpackMaxAmount; }; @@ -35,11 +35,11 @@ class ABackpackItem : public AInventory DECLARE_CLASS (ABackpackItem, AInventory) public: - void Serialize(FSerializer &arc); - bool HandlePickup (AInventory *item); - AInventory *CreateCopy (AActor *other); - AInventory *CreateTossable (); - void DetachFromOwner (); + virtual void Serialize(FSerializer &arc) override; + virtual bool HandlePickup (AInventory *item) override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual AInventory *CreateTossable () override; + virtual void DetachFromOwner () override; bool bDepleted; }; diff --git a/src/g_inventory/a_armor.h b/src/g_inventory/a_armor.h index b7b2dad3e1..63febda912 100644 --- a/src/g_inventory/a_armor.h +++ b/src/g_inventory/a_armor.h @@ -16,11 +16,11 @@ class ABasicArmor : public AArmor DECLARE_CLASS (ABasicArmor, AArmor) public: - virtual void Serialize(FSerializer &arc); - virtual void Tick (); - virtual AInventory *CreateCopy (AActor *other); - virtual bool HandlePickup (AInventory *item); - virtual void AbsorbDamage (int damage, FName damageType, int &newdamage); + virtual void Serialize(FSerializer &arc) override; + virtual void Tick () override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual bool HandlePickup (AInventory *item) override; + virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override; int AbsorbCount; double SavePercent; @@ -37,9 +37,9 @@ class ABasicArmorPickup : public AArmor DECLARE_CLASS (ABasicArmorPickup, AArmor) public: - virtual void Serialize(FSerializer &arc); - virtual AInventory *CreateCopy (AActor *other); - virtual bool Use (bool pickup); + virtual void Serialize(FSerializer &arc) override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual bool Use (bool pickup) override; double SavePercent; int MaxAbsorb; @@ -53,9 +53,9 @@ class ABasicArmorBonus : public AArmor DECLARE_CLASS (ABasicArmorBonus, AArmor) public: - virtual void Serialize(FSerializer &arc); - virtual AInventory *CreateCopy (AActor *other); - virtual bool Use (bool pickup); + virtual void Serialize(FSerializer &arc) override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual bool Use (bool pickup) override; double SavePercent; // The default, for when you don't already have armor int MaxSaveAmount; @@ -73,12 +73,12 @@ class AHexenArmor : public AArmor DECLARE_CLASS (AHexenArmor, AArmor) public: - virtual void Serialize(FSerializer &arc); - virtual AInventory *CreateCopy (AActor *other); - virtual AInventory *CreateTossable (); - virtual bool HandlePickup (AInventory *item); - virtual void AbsorbDamage (int damage, FName damageType, int &newdamage); - void DepleteOrDestroy(); + virtual void Serialize(FSerializer &arc) override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual AInventory *CreateTossable () override; + virtual bool HandlePickup (AInventory *item) override; + virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override; + virtual void DepleteOrDestroy() override; double Slots[5]; double SlotsIncrement[4]; diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 1198b91531..a75b9ecd44 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -373,18 +373,6 @@ void APowerup::OwnerDied () Destroy (); } -//=========================================================================== -// -// AInventory :: GetNoTeleportFreeze -// -//=========================================================================== - -bool APowerup::GetNoTeleportFreeze () -{ - if (ItemFlags & IF_NOTELEPORTFREEZE) return true; - return Super::GetNoTeleportFreeze(); -} - // Invulnerability Powerup --------------------------------------------------- IMPLEMENT_CLASS(APowerInvulnerable, false, false) @@ -1213,20 +1201,6 @@ void APowerSpeed::Serialize(FSerializer &arc) arc("speedflags", SpeedFlags); } -//=========================================================================== -// -// APowerSpeed :: GetSpeedFactor -// -//=========================================================================== - -double APowerSpeed ::GetSpeedFactor () -{ - if (Inventory != NULL) - return Speed * Inventory->GetSpeedFactor(); - else - return Speed; -} - //=========================================================================== // // APowerSpeed :: DoEffect diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index c3a0f31f08..7e9956d73b 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -11,18 +11,15 @@ class APowerup : public AInventory { DECLARE_CLASS (APowerup, AInventory) public: - virtual void Tick (); + virtual void Tick () override; virtual void Destroy () override; - virtual bool HandlePickup (AInventory *item); - virtual AInventory *CreateCopy (AActor *other); - virtual AInventory *CreateTossable (); - - - virtual void Serialize(FSerializer &arc); - virtual void OwnerDied (); - virtual bool GetNoTeleportFreeze(); - virtual PalEntry GetBlend (); - virtual bool DrawPowerup (int x, int y); + virtual bool HandlePickup (AInventory *item) override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual AInventory *CreateTossable () override; + virtual void Serialize(FSerializer &arc) override; + virtual void OwnerDied () override; + virtual PalEntry GetBlend () override; + virtual bool DrawPowerup (int x, int y) override; int EffectTics; PalEntry BlendColor; @@ -31,7 +28,7 @@ public: protected: virtual void InitEffect (); - virtual void DoEffect (); + virtual void DoEffect () override; virtual void EndEffect (); friend void EndAllPowerupEffects(AInventory *item); @@ -52,9 +49,8 @@ class APowerupGiver : public AInventory { DECLARE_CLASS_WITH_META (APowerupGiver, AInventory, PClassPowerupGiver) public: - virtual bool Use (bool pickup); - - virtual void Serialize(FSerializer &arc); + virtual bool Use (bool pickup) override; + virtual void Serialize(FSerializer &arc) override; PClassActor *PowerupType; @@ -68,10 +64,10 @@ class APowerInvulnerable : public APowerup { DECLARE_CLASS (APowerInvulnerable, APowerup) protected: - void InitEffect (); - void DoEffect (); - void EndEffect (); - int AlterWeaponSprite (visstyle_t *vis); + virtual void InitEffect () override; + virtual void DoEffect () override; + virtual void EndEffect () override; + virtual int AlterWeaponSprite (visstyle_t *vis) override; }; class APowerStrength : public APowerup @@ -80,44 +76,44 @@ class APowerStrength : public APowerup public: PalEntry GetBlend (); protected: - void InitEffect (); - void Tick (); - bool HandlePickup (AInventory *item); + virtual void InitEffect () override; + virtual void Tick () override; + virtual bool HandlePickup (AInventory *item) override; }; class APowerInvisibility : public APowerup { DECLARE_CLASS (APowerInvisibility, APowerup) protected: - bool HandlePickup (AInventory *item); - void InitEffect (); - void DoEffect (); - void EndEffect (); - int AlterWeaponSprite (visstyle_t *vis); + virtual bool HandlePickup (AInventory *item) override; + virtual void InitEffect () override; + virtual void DoEffect () override; + virtual void EndEffect () override; + virtual int AlterWeaponSprite (visstyle_t *vis) override; }; class APowerIronFeet : public APowerup { DECLARE_CLASS (APowerIronFeet, APowerup) public: - void AbsorbDamage (int damage, FName damageType, int &newdamage); - void DoEffect (); + virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override; + virtual void DoEffect () override; }; class APowerMask : public APowerIronFeet { DECLARE_CLASS (APowerMask, APowerIronFeet) public: - void AbsorbDamage (int damage, FName damageType, int &newdamage); - void DoEffect (); + virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override; + virtual void DoEffect () override; }; class APowerLightAmp : public APowerup { DECLARE_CLASS (APowerLightAmp, APowerup) protected: - void DoEffect (); - void EndEffect (); + virtual void DoEffect () override; + virtual void EndEffect () override; }; class APowerTorch : public APowerLightAmp @@ -125,9 +121,9 @@ class APowerTorch : public APowerLightAmp DECLARE_CLASS (APowerTorch, APowerLightAmp) public: - virtual void Serialize(FSerializer &arc); + virtual void Serialize(FSerializer &arc) override; protected: - void DoEffect (); + virtual void DoEffect () override; int NewTorch, NewTorchDelta; }; @@ -135,14 +131,13 @@ class APowerFlight : public APowerup { DECLARE_CLASS (APowerFlight, APowerup) public: - bool DrawPowerup (int x, int y); - - virtual void Serialize(FSerializer &arc); + virtual bool DrawPowerup (int x, int y) override; + virtual void Serialize(FSerializer &arc) override; protected: - void InitEffect (); - void Tick (); - void EndEffect (); + virtual void InitEffect () override; + virtual void Tick () override; + virtual void EndEffect () override; private: bool HitCenterFrame; @@ -152,18 +147,17 @@ class APowerWeaponLevel2 : public APowerup { DECLARE_CLASS (APowerWeaponLevel2, APowerup) protected: - void InitEffect (); - void EndEffect (); + virtual void InitEffect () override; + virtual void EndEffect () override; }; class APowerSpeed : public APowerup { DECLARE_CLASS (APowerSpeed, APowerup) protected: - void DoEffect (); + virtual void DoEffect () override; - virtual void Serialize(FSerializer &arc); - double GetSpeedFactor(); + virtual void Serialize(FSerializer &arc) override; public: int SpeedFlags; }; @@ -184,95 +178,95 @@ class APowerTargeter : public APowerup { DECLARE_CLASS (APowerTargeter, APowerup) protected: - void InitEffect (); - void DoEffect (); - void EndEffect (); + virtual void InitEffect () override; + virtual void DoEffect () override; + virtual void EndEffect () override; void PositionAccuracy (); - void Travelled (); - void AttachToOwner(AActor *other); - bool HandlePickup(AInventory *item); + virtual void Travelled () override; + virtual void AttachToOwner(AActor *other) override; + virtual bool HandlePickup(AInventory *item) override; }; class APowerFrightener : public APowerup { DECLARE_CLASS (APowerFrightener, APowerup) protected: - void InitEffect (); - void EndEffect (); + virtual void InitEffect () override; + virtual void EndEffect () override; }; class APowerBuddha : public APowerup { DECLARE_CLASS (APowerBuddha, APowerup) protected: - void InitEffect (); - void EndEffect (); + virtual void InitEffect () override; + virtual void EndEffect () override; }; class APowerTimeFreezer : public APowerup { DECLARE_CLASS( APowerTimeFreezer, APowerup ) protected: - void InitEffect( ); - void DoEffect( ); - void EndEffect( ); + virtual void InitEffect() override; + virtual void DoEffect() override; + virtual void EndEffect() override; }; class APowerDamage : public APowerup { DECLARE_CLASS( APowerDamage, APowerup ) protected: - void InitEffect (); - void EndEffect (); - virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive); + virtual void InitEffect () override; + virtual void EndEffect () override; + virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive) override; }; class APowerProtection : public APowerup { DECLARE_CLASS( APowerProtection, APowerup ) protected: - void InitEffect (); - void EndEffect (); - virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive); + virtual void InitEffect () override; + virtual void EndEffect () override; + virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive) override; }; class APowerDrain : public APowerup { DECLARE_CLASS( APowerDrain, APowerup ) protected: - void InitEffect( ); - void EndEffect( ); + virtual void InitEffect() override; + virtual void EndEffect() override; }; class APowerRegeneration : public APowerup { DECLARE_CLASS( APowerRegeneration, APowerup ) protected: - void DoEffect(); + virtual void DoEffect() override; }; class APowerHighJump : public APowerup { DECLARE_CLASS( APowerHighJump, APowerup ) protected: - void InitEffect( ); - void EndEffect( ); + virtual void InitEffect() override; + virtual void EndEffect() override; }; class APowerDoubleFiringSpeed : public APowerup { DECLARE_CLASS( APowerDoubleFiringSpeed, APowerup ) protected: - void InitEffect( ); - void EndEffect( ); + virtual void InitEffect() override; + virtual void EndEffect() override; }; class APowerInfiniteAmmo : public APowerup { DECLARE_CLASS( APowerInfiniteAmmo, APowerup ) protected: - void InitEffect( ); - void EndEffect( ); + virtual void InitEffect() override; + virtual void EndEffect() override; }; class APowerMorph : public APowerup @@ -280,7 +274,7 @@ class APowerMorph : public APowerup DECLARE_CLASS( APowerMorph, APowerup ) public: - virtual void Serialize(FSerializer &arc); + virtual void Serialize(FSerializer &arc) override; void SetNoCallUndoMorph() { bInUndoMorph = true; } // Variables @@ -291,8 +285,8 @@ public: bool bInUndoMorph; // Because P_UndoPlayerMorph() can call EndEffect recursively protected: - void InitEffect (); - void EndEffect (); + virtual void InitEffect () override; + virtual void EndEffect () override; }; #endif //__A_ARTIFACTS_H__ diff --git a/src/g_inventory/a_health.h b/src/g_inventory/a_health.h index a462bbfbda..af282031c3 100644 --- a/src/g_inventory/a_health.h +++ b/src/g_inventory/a_health.h @@ -21,8 +21,8 @@ class AHealth : public AInventory public: int PrevHealth; - virtual bool TryPickup (AActor *&other); - virtual FString PickupMessage (); + virtual bool TryPickup (AActor *&other) override; + virtual FString PickupMessage () override; }; // HealthPickup is some item that gives the player health when used. @@ -33,10 +33,10 @@ public: int autousemode; - virtual void Serialize(FSerializer &arc); - virtual AInventory *CreateCopy (AActor *other); - virtual AInventory *CreateTossable (); - virtual bool HandlePickup (AInventory *item); - virtual bool Use (bool pickup); + virtual void Serialize(FSerializer &arc) override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual AInventory *CreateTossable () override; + virtual bool HandlePickup (AInventory *item) override; + virtual bool Use (bool pickup) override; }; diff --git a/src/g_inventory/a_keys.h b/src/g_inventory/a_keys.h index fd46b416c1..eda0473a30 100644 --- a/src/g_inventory/a_keys.h +++ b/src/g_inventory/a_keys.h @@ -7,12 +7,12 @@ class AKey : public AInventory { DECLARE_CLASS (AKey, AInventory) public: - virtual bool HandlePickup (AInventory *item); + virtual bool HandlePickup (AInventory *item) override; BYTE KeyNumber; protected: - virtual bool ShouldStay (); + virtual bool ShouldStay () override; }; bool P_CheckKeys (AActor *owner, int keynum, bool remote); @@ -37,9 +37,9 @@ class APuzzleItem : public AInventory DECLARE_CLASS_WITH_META(APuzzleItem, AInventory, PClassPuzzleItem) public: - bool ShouldStay (); - bool Use (bool pickup); - bool HandlePickup (AInventory *item); + virtual bool ShouldStay () override; + virtual bool Use (bool pickup) override; + virtual bool HandlePickup (AInventory *item) override; int PuzzleItemNumber; }; diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index cf5dddcf3f..237de2ce97 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -399,6 +399,25 @@ void AInventory::DoEffect () { } +DEFINE_ACTION_FUNCTION(AInventory, DoEffect) +{ + PARAM_SELF_PROLOGUE(AInventory); + self->DoEffect(); + return 0; +} + +void AInventory::CallDoEffect() +{ + IFVIRTUAL(AInventory, DoEffect) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } + else DoEffect(); +} + + //=========================================================================== // // AInventory :: Travelled @@ -437,7 +456,7 @@ bool AInventory::HandlePickup (AInventory *item) { if (item->GetClass() == GetClass()) { - if (Amount < MaxAmount || (sv_unlimited_pickup && !item->ShouldStay())) + if (Amount < MaxAmount || (sv_unlimited_pickup && !item->CallShouldStay())) { if (Amount > 0 && Amount + item->Amount < 0) { @@ -506,7 +525,7 @@ bool AInventory::GoAway () return false; } - if (!ShouldStay ()) + if (!CallShouldStay ()) { Hide (); if (ShouldRespawn ()) @@ -776,16 +795,25 @@ void AInventory::ModifyDamage (int damage, FName damageType, int &newdamage, boo // //=========================================================================== -double AInventory::GetSpeedFactor () +double AInventory::GetSpeedFactor() { - if (Inventory != NULL) + double factor = 1.; + auto self = this; + while (self != nullptr) { - return Inventory->GetSpeedFactor(); - } - else - { - return 1.; + IFVIRTUALPTR(self, AInventory, GetSpeedFactor) + { + VMValue params[2] = { (DObject*)self }; + VMReturn ret; + VMFrameStack stack; + double retval; + ret.FloatAt(&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + factor *= retval; + } + self = self->Inventory; } + return factor; } //=========================================================================== @@ -796,15 +824,22 @@ double AInventory::GetSpeedFactor () bool AInventory::GetNoTeleportFreeze () { - // do not check the flag here because it's only active when used on PowerUps, not on PowerupGivers. - if (Inventory != NULL) + auto self = this; + while (self != nullptr) { - return Inventory->GetNoTeleportFreeze(); - } - else - { - return false; + IFVIRTUALPTR(self, AInventory, GetNoTeleportFreeze) + { + VMValue params[2] = { (DObject*)self }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + if (retval) return true; + } + self = self->Inventory; } + return false; } //=========================================================================== @@ -953,7 +988,7 @@ void AInventory::Touch (AActor *toucher) if (!CallTryPickup (toucher, &toucher)) return; // This is the only situation when a pickup flash should ever play. - if (PickupFlash != NULL && !ShouldStay()) + if (PickupFlash != NULL && !CallShouldStay()) { Spawn(PickupFlash, Pos(), ALLOW_REPLACE); } @@ -1102,6 +1137,26 @@ void AInventory::PlayPickupSound (AActor *toucher) S_Sound (toucher, chan, PickupSound, 1, atten); } +DEFINE_ACTION_FUNCTION(AInventory, PlayPickupSound) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_OBJECT(other, AActor); + self->PlayPickupSound(other); + return 0; +} + +void AInventory::CallPlayPickupSound(AActor *other) +{ + IFVIRTUAL(AInventory, PlayPickupSound) + { + VMValue params[2] = { (DObject*)this, (DObject*)other }; + VMFrameStack stack; + stack.Call(func, params, 2, nullptr, 0, nullptr); + } + else PlayPickupSound(other); +} + + //=========================================================================== // // AInventory :: ShouldStay @@ -1115,6 +1170,28 @@ bool AInventory::ShouldStay () return false; } +DEFINE_ACTION_FUNCTION(AInventory, ShouldStay) +{ + PARAM_SELF_PROLOGUE(AInventory); + ACTION_RETURN_BOOL(self->ShouldStay()); +} + +bool AInventory::CallShouldStay() +{ + IFVIRTUAL(AInventory, ShouldStay) + { + VMValue params[1] = { (DObject*)this }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 1, &ret, 1, nullptr); + return !!retval; + } + else return ShouldStay(); +} + + //=========================================================================== // // AInventory :: Destroy @@ -1416,6 +1493,14 @@ bool AInventory::TryPickupRestricted (AActor *&toucher) return false; } +DEFINE_ACTION_FUNCTION(AInventory, TryPickupRestricted) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_POINTER(toucher, AActor*); + ACTION_RETURN_BOOL(self->TryPickupRestricted(*toucher)); +} + + //=========================================================================== // // AInventory :: CallTryPickup @@ -1445,14 +1530,27 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) else res = TryPickup(toucher); } else if (!(ItemFlags & IF_RESTRICTABSOLUTELY)) - res = TryPickupRestricted(toucher); // let an item decide for itself how it will handle this + { + // let an item decide for itself how it will handle this + IFVIRTUAL(AInventory, TryPickupRestricted) + { + VMValue params[2] = { (DObject*)this, (void*)&toucher }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + res = !!retval; + } + else res = TryPickupRestricted(toucher); + } else return false; // Morph items can change the toucher so we need an option to return this info. if (toucher_return != NULL) *toucher_return = toucher; - if (!res && (ItemFlags & IF_ALWAYSPICKUP) && !ShouldStay()) + if (!res && (ItemFlags & IF_ALWAYSPICKUP) && !CallShouldStay()) { res = true; GoAwayAndDie(); @@ -1576,6 +1674,26 @@ void AInventory::AttachToOwner (AActor *other) other->AddInventory (this); } +DEFINE_ACTION_FUNCTION(AInventory, AttachToOwner) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_OBJECT(other, AActor); + self->AttachToOwner(other); + return 0; +} + +void AInventory::CallAttachToOwner(AActor *other) +{ + IFVIRTUAL(AInventory, AttachToOwner) + { + VMValue params[2] = { (DObject*)this, (DObject*)other }; + VMFrameStack stack; + stack.Call(func, params, 2, nullptr, 0, nullptr); + } + else AttachToOwner(other); +} + + //=========================================================================== // // AInventory :: DetachFromOwner @@ -1589,6 +1707,29 @@ void AInventory::DetachFromOwner () { } +DEFINE_ACTION_FUNCTION(AInventory, DetachFromOwner) +{ + PARAM_SELF_PROLOGUE(AInventory); + self->DetachFromOwner(); + return 0; +} + +void AInventory::CallDetachFromOwner() +{ + IFVIRTUAL(AInventory, DetachFromOwner) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(func, params, 1, nullptr, 0, nullptr); + } + else DetachFromOwner(); +} + +//=========================================================================== +//=========================================================================== + + + IMPLEMENT_CLASS(AStateProvider, false, false) IMPLEMENT_CLASS(ACustomInventory, false, false) diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index b366a60318..99dad87131 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -70,31 +70,87 @@ class AInventory : public AActor DECLARE_CLASS_WITH_META(AInventory, AActor, PClassInventory) HAS_OBJECT_POINTERS public: - virtual void Touch (AActor *toucher); - virtual void Serialize(FSerializer &arc); - - virtual void MarkPrecacheSounds() const; - virtual void BeginPlay (); + virtual void Touch (AActor *toucher) override; + virtual void Serialize(FSerializer &arc) override; + virtual void MarkPrecacheSounds() const override; + virtual void BeginPlay () override; virtual void Destroy () override; + virtual void Tick() override; + virtual bool Grind(bool items) override; + + // virtual methods that only get overridden by special internal classes, like DehackedPickup. + // There is no need to expose these to scripts. virtual void DepleteOrDestroy (); - virtual void Tick (); virtual bool ShouldRespawn (); - virtual bool ShouldStay (); - virtual void Hide (); - bool CallTryPickup (AActor *toucher, AActor **toucher_return = NULL); virtual void DoPickupSpecial (AActor *toucher); + + // methods that can be overridden by scripts, plus their callers. virtual bool SpecialDropAction (AActor *dropper); bool CallSpecialDropAction(AActor *dropper); - virtual bool DrawPowerup (int x, int y); - virtual void DoEffect (); - virtual bool Grind(bool items); - virtual FString PickupMessage (); + virtual bool TryPickup(AActor *&toucher); + virtual bool TryPickupRestricted(AActor *&toucher); + bool CallTryPickup(AActor *toucher, AActor **toucher_return = NULL); // This wraps both virtual methods plus a few more checks. + + virtual AInventory *CreateCopy(AActor *other); + AInventory *CallCreateCopy(AActor *other); + + virtual AInventory *CreateTossable(); + AInventory *CallCreateTossable(); + + virtual FString PickupMessage(); FString GetPickupMessage(); - virtual void PlayPickupSound (AActor *toucher); - bool DoRespawn (); + virtual bool HandlePickup(AInventory *item); + bool CallHandlePickup(AInventory *item); + + virtual bool Use(bool pickup); + bool CallUse(bool pickup); + + virtual PalEntry GetBlend(); + PalEntry CallGetBlend(); + + virtual bool ShouldStay(); + bool CallShouldStay(); + + virtual void DoEffect(); + void CallDoEffect(); + + virtual void PlayPickupSound(AActor *toucher); + void CallPlayPickupSound(AActor *toucher); + + virtual void AttachToOwner(AActor *other); + void CallAttachToOwner(AActor *other); + + virtual void DetachFromOwner(); + void CallDetachFromOwner(); + + // still need to be done. + virtual void AbsorbDamage(int damage, FName damageType, int &newdamage); + virtual void ModifyDamage(int damage, FName damageType, int &newdamage, bool passive); + + // visual stuff is for later. Right now the VM has not yet access to the needed functionality. + virtual bool DrawPowerup(int x, int y); + virtual int AlterWeaponSprite(visstyle_t *vis); + + + // virtual on the script side only. + double GetSpeedFactor(); + bool GetNoTeleportFreeze(); + // Stuff for later when more features are exported. + virtual void Travelled(); + virtual void OwnerDied(); + + + bool GoAway(); + void GoAwayAndDie(); + + void Hide(); + void BecomeItem (); + void BecomePickup (); + + bool DoRespawn(); AInventory *PrevItem(); // Returns the item preceding this one in the list. AInventory *PrevInv(); // Returns the previous item with IF_INVBAR set. AInventory *NextInv(); // Returns the next item with IF_INVBAR set. @@ -113,34 +169,7 @@ public: FSoundIDNoInit PickupSound; - void BecomeItem (); - void BecomePickup (); - virtual void AttachToOwner (AActor *other); - virtual void DetachFromOwner (); - virtual AInventory *CreateCopy (AActor *other); - AInventory *CallCreateCopy(AActor *other); - virtual AInventory *CreateTossable (); - AInventory *CallCreateTossable(); - virtual bool GoAway (); - virtual void GoAwayAndDie (); - virtual bool HandlePickup (AInventory *item); - bool CallHandlePickup(AInventory *item); - virtual bool Use (bool pickup); - bool CallUse(bool pickup); - virtual void Travelled (); - virtual void OwnerDied (); - virtual void AbsorbDamage (int damage, FName damageType, int &newdamage); - virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive); - virtual double GetSpeedFactor(); - virtual bool GetNoTeleportFreeze(); - virtual int AlterWeaponSprite (visstyle_t *vis); - - virtual PalEntry GetBlend (); - PalEntry CallGetBlend(); - - virtual bool TryPickup (AActor *&toucher); - virtual bool TryPickupRestricted (AActor *&toucher); protected: bool CanPickup(AActor * toucher); void GiveQuest(AActor * toucher); @@ -164,9 +193,9 @@ public: // This is used when an inventory item's use state sequence is executed. bool CallStateChain (AActor *actor, FState *state); - bool TryPickup (AActor *&toucher); - bool Use (bool pickup); - bool SpecialDropAction (AActor *dropper); + virtual bool TryPickup (AActor *&toucher) override; + virtual bool Use (bool pickup) override; + virtual bool SpecialDropAction (AActor *dropper) override; }; extern PClassActor *QuestItemClasses[31]; diff --git a/src/g_inventory/a_weaponpiece.cpp b/src/g_inventory/a_weaponpiece.cpp index b504559bd1..e1a7fe33bb 100644 --- a/src/g_inventory/a_weaponpiece.cpp +++ b/src/g_inventory/a_weaponpiece.cpp @@ -103,7 +103,7 @@ void AWeaponPiece::Serialize(FSerializer &arc) bool AWeaponPiece::TryPickupRestricted (AActor *&toucher) { // Wrong class, but try to pick up for ammo - if (ShouldStay()) + if (CallShouldStay()) { // Can't pick up weapons for other classes in coop netplay return false; } diff --git a/src/g_inventory/a_weaponpiece.h b/src/g_inventory/a_weaponpiece.h index bcaa261cbd..e0db150077 100644 --- a/src/g_inventory/a_weaponpiece.h +++ b/src/g_inventory/a_weaponpiece.h @@ -19,12 +19,12 @@ protected: bool PrivateShouldStay (); public: - void Serialize(FSerializer &arc); - bool TryPickup (AActor *&toucher); - bool TryPickupRestricted (AActor *&toucher); - bool ShouldStay (); - virtual FString PickupMessage (); - virtual void PlayPickupSound (AActor *toucher); + virtual void Serialize(FSerializer &arc) override; + virtual bool TryPickup (AActor *&toucher) override; + virtual bool TryPickupRestricted (AActor *&toucher) override; + virtual bool ShouldStay () override; + virtual FString PickupMessage () override; + virtual void PlayPickupSound (AActor *toucher) override; int PieceValue; PClassActor *WeaponClass; @@ -42,5 +42,5 @@ public: PClassActor * PieceWeapon; - void Serialize(FSerializer &arc); + virtual void Serialize(FSerializer &arc) override; }; diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 90a217495a..3fd4bc939b 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -275,7 +275,7 @@ void AWeapon::MarkPrecacheSounds() const bool AWeapon::TryPickupRestricted (AActor *&toucher) { // Wrong class, but try to pick up for ammo - if (ShouldStay()) + if (CallShouldStay()) { // Can't pick up weapons for other classes in coop netplay return false; } @@ -398,7 +398,7 @@ bool AWeapon::PickupForAmmo (AWeapon *ownedWeapon) bool gotstuff = false; // Don't take ammo if the weapon sticks around. - if (!ShouldStay ()) + if (!CallShouldStay ()) { int oldamount1 = 0; int oldamount2 = 0; diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index 786f6189b6..c6424075d3 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -137,26 +137,30 @@ public: virtual void MarkPrecacheSounds() const; - virtual void Serialize(FSerializer &arc); - virtual bool ShouldStay (); - virtual void AttachToOwner (AActor *other); - virtual bool HandlePickup (AInventory *item); - virtual AInventory *CreateCopy (AActor *other); - virtual AInventory *CreateTossable (); - virtual bool TryPickup (AActor *&toucher); - virtual bool TryPickupRestricted (AActor *&toucher); - virtual bool PickupForAmmo (AWeapon *ownedWeapon); - virtual bool Use (bool pickup); + virtual void Serialize(FSerializer &arc) override; + virtual bool ShouldStay () override; + virtual void AttachToOwner (AActor *other) override; + virtual bool HandlePickup (AInventory *item) override; + virtual AInventory *CreateCopy (AActor *other) override; + virtual AInventory *CreateTossable () override; + virtual bool TryPickup (AActor *&toucher) override; + virtual bool TryPickupRestricted (AActor *&toucher) override; + virtual bool Use (bool pickup) override; virtual void Destroy() override; + bool PickupForAmmo(AWeapon *ownedWeapon); + void PostMorphWeapon(); + + // scripted virtuals. FState *GetUpState (); FState *GetDownState (); FState *GetReadyState (); FState *GetAtkState (bool hold); FState *GetAltAtkState (bool hold); + FState *GetStateForButtonName (FName button); - virtual void PostMorphWeapon (); + virtual void EndPowerup (); void CallEndPowerup(); @@ -221,9 +225,8 @@ class AWeaponGiver : public AWeapon DECLARE_CLASS(AWeaponGiver, AWeapon) public: - bool TryPickup(AActor *&toucher); - - void Serialize(FSerializer &arc); + virtual bool TryPickup(AActor *&toucher) override; + virtual void Serialize(FSerializer &arc) override; double DropAmmoFactor; }; diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index ad15cb081c..f223188396 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -138,20 +138,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp AInventory *next = item->Inventory; if (item->IsKindOf (RUNTIME_CLASS(AArmor))) { - if (item->IsKindOf (RUNTIME_CLASS(AHexenArmor))) - { - // Set the HexenArmor slots to 0, except the class slot. - AHexenArmor *hxarmor = static_cast(item); - hxarmor->Slots[0] = 0; - hxarmor->Slots[1] = 0; - hxarmor->Slots[2] = 0; - hxarmor->Slots[3] = 0; - hxarmor->Slots[4] = spawntype->HexenArmor[0]; - } - else - { - item->DepleteOrDestroy(); - } + item->DepleteOrDestroy(); } item = next; } diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 4e5c13d888..06e4d75525 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -32,7 +32,15 @@ class Inventory : Actor native virtual native Inventory CreateTossable(); virtual native bool SpecialDropAction (Actor dropper); virtual native String PickupMessage(); + virtual native bool ShouldStay(); + virtual native void DoEffect(); + virtual native void PlayPickupSound(Actor user); + virtual native void AttachToOwner(Actor user); + virtual native void DetachFromOwner(); + virtual double GetSpeedFactor() { return 1; } + virtual bool GetNoTeleportFreeze() { return false; } + native void GoAwayAndDie(); native void BecomeItem(); native void BecomePickup(); @@ -42,7 +50,10 @@ class Inventory : Actor native private native void A_RestoreSpecialThing1(); private native void A_RestoreSpecialThing2(); - virtual native bool TryPickup(in out Actor toucher); + // In this case the caller function is more than a simple wrapper around the virtual method and + // is what must be actually called to pick up an item. + virtual protected native bool TryPickup(in out Actor toucher); + virtual protected native bool TryPickupRestricted(in out Actor toucher); native bool, Actor CallTryPickup(Actor toucher); States(Actor, Overlay, Weapon, Item) diff --git a/wadsrc/static/zscript/shared/powerups.txt b/wadsrc/static/zscript/shared/powerups.txt index 4c7a84efe6..0cd735c81a 100644 --- a/wadsrc/static/zscript/shared/powerups.txt +++ b/wadsrc/static/zscript/shared/powerups.txt @@ -22,6 +22,10 @@ class Powerup : Inventory native native color BlendColor; native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility native double Strength; // Meaning depends on powerup - currently used only by Invisibility + + // Note, that while this is an inventory flag, it only has meaning on an active powerup. + virtual bool GetNoTeleportFreeze() { return bNoTeleportFreeze; } + } class PowerInvulnerable : Powerup native @@ -136,6 +140,8 @@ class PowerSpeed : Powerup native Inventory.Icon "SPBOOT0"; +INVENTORY.NOTELEPORTFREEZE } + + override double GetSpeedFactor() { return Speed; } } // Player Speed Trail (used by the Speed Powerup) ---------------------------- From 47884f8a7151ad3c3e06017039b230d7b674cd1a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 16:19:13 +0100 Subject: [PATCH 427/471] - fixed a few bad declarations. --- wadsrc/static/zscript/actor.txt | 4 ++-- wadsrc/static/zscript/shared/powerups.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 9bf4fdcd97..abcd58b50c 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -419,8 +419,8 @@ class Actor : Thinker native native void Howl(); native void DrawSplash (int count, double angle, int kind); native void GiveSecret(bool printmsg = true, bool playsound = true); - native void GetCameraHeight(); - native void GetGravity(); + native double GetCameraHeight(); + native double GetGravity(); native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native void AddInventory(Inventory inv); diff --git a/wadsrc/static/zscript/shared/powerups.txt b/wadsrc/static/zscript/shared/powerups.txt index 0cd735c81a..d28799ff23 100644 --- a/wadsrc/static/zscript/shared/powerups.txt +++ b/wadsrc/static/zscript/shared/powerups.txt @@ -24,7 +24,7 @@ class Powerup : Inventory native native double Strength; // Meaning depends on powerup - currently used only by Invisibility // Note, that while this is an inventory flag, it only has meaning on an active powerup. - virtual bool GetNoTeleportFreeze() { return bNoTeleportFreeze; } + override bool GetNoTeleportFreeze() { return bNoTeleportFreeze; } } From 86544086df642e9c29fbc58931db4208caab079d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 17:15:01 +0100 Subject: [PATCH 428/471] - allow the VM to run on one global stack per thread. It is utterly pointless to require every function that wants to make a VM call to allocate a new stack first. The allocation overhead doubles the time to set up the call. With one stack, previously allocated memory can be reused. The only important thing is, if this ever gets used in a multithreaded environment to have the stack being declared as thread_local, although for ZDoom this is of no consequence. - eliminated all cases where native code was calling other native code through the VM interface. After scriptifying the game code, only 5 places were left which were quickly eliminated. This was mostly to ensure that the native VM function parameters do not need to be propagated further than absolutely necessary. --- src/actor.h | 2 + src/d_dehacked.cpp | 2 - src/dthinker.cpp | 6 +- src/g_inventory/a_pickups.cpp | 105 ++++------------------- src/g_inventory/a_weapons.cpp | 18 ++-- src/g_shared/a_action.cpp | 30 +++---- src/g_shared/a_bridge.cpp | 20 +++-- src/g_shared/a_fastprojectile.cpp | 3 +- src/info.cpp | 5 +- src/m_cheat.cpp | 3 +- src/p_acs.cpp | 6 +- src/p_actionfunctions.cpp | 7 +- src/p_enemy.cpp | 24 ++---- src/p_enemy.h | 10 +-- src/p_interaction.cpp | 3 +- src/p_mobj.cpp | 91 ++++++++++++++++---- src/p_user.cpp | 15 ++-- src/scripting/codegeneration/codegen.cpp | 12 +-- src/scripting/vm/vm.h | 14 +-- src/scripting/vm/vmexec.cpp | 6 ++ src/scripting/vm/vmframe.cpp | 11 +-- src/scripting/zscript/zcc_compile.cpp | 6 +- wadsrc/static/zscript/actor.txt | 6 +- 23 files changed, 176 insertions(+), 229 deletions(-) diff --git a/src/actor.h b/src/actor.h index 18b1282156..6718e0931f 100644 --- a/src/actor.h +++ b/src/actor.h @@ -667,6 +667,8 @@ public: // Plays the actor's ActiveSound if its voice isn't already making noise. void PlayActiveSound (); + void RestoreSpecialPosition(); + // Called by PIT_CheckThing() and needed for some Hexen things. // Returns -1 for normal behavior, 0 to return false, and 1 to return true. // I'm not sure I like it this way, but it will do for now. diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index e2c5a6ea3a..6f9687aeac 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -174,8 +174,6 @@ struct AmmoPerAttack VMFunction *ptr; }; -DECLARE_ACTION(A_Punch) - // Default ammo use of the various weapon attacks static AmmoPerAttack AmmoPerAttacks[] = { { NAME_A_Punch, 0}, diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 7c8bf1bf5a..fd20a4e79a 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -313,8 +313,7 @@ void DThinker::CallPostBeginPlay() { // Without the type cast this picks the 'void *' assignment... VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } else { @@ -557,8 +556,7 @@ void DThinker::CallTick() { // Without the type cast this picks the 'void *' assignment... VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } else Tick(); } diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 237de2ce97..91b88a0537 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -22,7 +22,6 @@ #include "virtual.h" #include "a_ammo.h" -static FRandom pr_restore ("RestorePos"); EXTERN_CVAR(Bool, sv_unlimited_pickup) IMPLEMENT_CLASS(PClassInventory, false, false) @@ -137,63 +136,6 @@ DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialDoomThing) return 0; } -//--------------------------------------------------------------------------- -// -// PROP A_RestoreSpecialPosition -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) -{ - PARAM_SELF_PROLOGUE(AActor); - - // Move item back to its original location - DVector2 sp = self->SpawnPoint; - - self->UnlinkFromWorld(); - self->SetXY(sp); - self->LinkToWorld(true); - self->SetZ(self->Sector->floorplane.ZatPoint(sp)); - P_FindFloorCeiling(self, FFCF_ONLYSPAWNPOS | FFCF_NOPORTALS); // no portal checks here so that things get spawned in this sector. - - if (self->flags & MF_SPAWNCEILING) - { - self->SetZ(self->ceilingz - self->Height - self->SpawnPoint.Z); - } - else if (self->flags2 & MF2_SPAWNFLOAT) - { - double space = self->ceilingz - self->Height - self->floorz; - if (space > 48) - { - space -= 40; - self->SetZ((space * pr_restore()) / 256. + self->floorz + 40); - } - else - { - self->SetZ(self->floorz); - } - } - else - { - self->SetZ(self->SpawnPoint.Z + self->floorz); - } - // Redo floor/ceiling check, in case of 3D floors and portals - P_FindFloorCeiling(self, FFCF_SAMESECTOR | FFCF_ONLY3DFLOORS | FFCF_3DRESTRICT); - if (self->Z() < self->floorz) - { // Do not reappear under the floor, even if that's where we were for the - // initial spawn. - self->SetZ(self->floorz); - } - if ((self->flags & MF_SOLID) && (self->Top() > self->ceilingz)) - { // Do the same for the ceiling. - self->SetZ(self->ceilingz - self->Height); - } - // Do not interpolate from the position the actor was at when it was - // picked up, in case that is different from where it is now. - self->ClearInterpolation(); - return 0; -} - int AInventory::StaticLastMessageTic; FString AInventory::StaticLastMessage; @@ -322,10 +264,9 @@ bool AInventory::CallSpecialDropAction(AActor *dropper) { VMValue params[2] = { (DObject*)this, (DObject*)dropper }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); return !!retval; } return SpecialDropAction(dropper); @@ -412,7 +353,7 @@ void AInventory::CallDoEffect() { VMValue params[1] = { (DObject*)this }; VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } else DoEffect(); } @@ -495,10 +436,9 @@ bool AInventory::CallHandlePickup(AInventory *item) // Without the type cast this picks the 'void *' assignment... VMValue params[2] = { (DObject*)self, (DObject*)item }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); if (retval) return true; } else if (self->HandlePickup(item)) return true; @@ -604,10 +544,9 @@ AInventory *AInventory::CallCreateCopy(AActor *other) { VMValue params[2] = { (DObject*)this, (DObject*)other }; VMReturn ret; - VMFrameStack stack; AInventory *retval; ret.PointerAt((void**)&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); return retval; } else return CreateCopy(other); @@ -670,10 +609,9 @@ AInventory *AInventory::CallCreateTossable() { VMValue params[1] = { (DObject*)this }; VMReturn ret; - VMFrameStack stack; AInventory *retval; ret.PointerAt((void**)&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); return retval; } else return CreateTossable(); @@ -805,10 +743,9 @@ double AInventory::GetSpeedFactor() { VMValue params[2] = { (DObject*)self }; VMReturn ret; - VMFrameStack stack; double retval; ret.FloatAt(&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); factor *= retval; } self = self->Inventory; @@ -831,10 +768,9 @@ bool AInventory::GetNoTeleportFreeze () { VMValue params[2] = { (DObject*)self }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); if (retval) return true; } self = self->Inventory; @@ -884,10 +820,9 @@ bool AInventory::CallUse(bool pickup) { VMValue params[2] = { (DObject*)this, pickup }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); return !!retval; } @@ -1090,10 +1025,9 @@ FString AInventory::GetPickupMessage() { VMValue params[1] = { (DObject*)this }; VMReturn ret; - VMFrameStack stack; FString retval; ret.StringAt(&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); return retval; } else return PickupMessage(); @@ -1150,8 +1084,7 @@ void AInventory::CallPlayPickupSound(AActor *other) IFVIRTUAL(AInventory, PlayPickupSound) { VMValue params[2] = { (DObject*)this, (DObject*)other }; - VMFrameStack stack; - stack.Call(func, params, 2, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); } else PlayPickupSound(other); } @@ -1182,10 +1115,9 @@ bool AInventory::CallShouldStay() { VMValue params[1] = { (DObject*)this }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); return !!retval; } else return ShouldStay(); @@ -1264,10 +1196,9 @@ PalEntry AInventory::CallGetBlend() { VMValue params[1] = { (DObject*)this }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); return retval; } else return GetBlend(); @@ -1521,10 +1452,9 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) { VMValue params[2] = { (DObject*)this, (void*)&toucher }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); res = !!retval; } else res = TryPickup(toucher); @@ -1536,10 +1466,9 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) { VMValue params[2] = { (DObject*)this, (void*)&toucher }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); res = !!retval; } else res = TryPickupRestricted(toucher); @@ -1687,8 +1616,7 @@ void AInventory::CallAttachToOwner(AActor *other) IFVIRTUAL(AInventory, AttachToOwner) { VMValue params[2] = { (DObject*)this, (DObject*)other }; - VMFrameStack stack; - stack.Call(func, params, 2, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); } else AttachToOwner(other); } @@ -1719,8 +1647,7 @@ void AInventory::CallDetachFromOwner() IFVIRTUAL(AInventory, DetachFromOwner) { VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } else DetachFromOwner(); } diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 3fd4bc939b..19a30dcd89 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -845,8 +845,7 @@ void AWeapon::CallEndPowerup() { // Without the type cast this picks the 'void *' assignment... VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } else EndPowerup(); } @@ -864,10 +863,9 @@ FState *AWeapon::GetUpState () { VMValue params[1] = { (DObject*)this }; VMReturn ret; - VMFrameStack stack; FState *retval; ret.PointerAt((void**)&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); return retval; } return nullptr; @@ -885,10 +883,9 @@ FState *AWeapon::GetDownState () { VMValue params[1] = { (DObject*)this }; VMReturn ret; - VMFrameStack stack; FState *retval; ret.PointerAt((void**)&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); return retval; } return nullptr; @@ -906,10 +903,9 @@ FState *AWeapon::GetReadyState () { VMValue params[1] = { (DObject*)this }; VMReturn ret; - VMFrameStack stack; FState *retval; ret.PointerAt((void**)&retval); - stack.Call(func, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); return retval; } return nullptr; @@ -927,10 +923,9 @@ FState *AWeapon::GetAtkState (bool hold) { VMValue params[2] = { (DObject*)this, hold }; VMReturn ret; - VMFrameStack stack; FState *retval; ret.PointerAt((void**)&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); return retval; } return nullptr; @@ -948,10 +943,9 @@ FState *AWeapon::GetAltAtkState (bool hold) { VMValue params[2] = { (DObject*)this, hold }; VMReturn ret; - VMFrameStack stack; FState *retval; ret.PointerAt((void**)&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); return retval; } return nullptr; diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index afe188019b..2e4597617f 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -121,35 +121,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeath) return 0; } -//========================================================================== -// -// A_GenericFreezeDeath -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(AActor, A_GenericFreezeDeath) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Translation = TRANSLATION(TRANSLATION_Standard, 7); - CALL_ACTION(A_FreezeDeath, self); - return 0; -} - //============================================================================ // // A_IceSetTics // //============================================================================ -DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics) +void IceSetTics(AActor *self) { - PARAM_SELF_PROLOGUE(AActor); int floor; - self->tics = 70+(pr_icesettics()&63); - floor = P_GetThingFloorType (self); + self->tics = 70 + (pr_icesettics() & 63); + floor = P_GetThingFloorType(self); if (Terrains[floor].DamageMOD == NAME_Fire) { self->tics >>= 2; @@ -158,6 +142,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics) { self->tics <<= 1; } +} + +DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics) +{ + PARAM_SELF_PROLOGUE(AActor); + IceSetTics(self); return 0; } @@ -203,7 +193,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks) mo->Vel.X = pr_freeze.Random2() / 128.; mo->Vel.Y = pr_freeze.Random2() / 128.; mo->Vel.Z = (mo->Z() - self->Z()) / self->Height * 4; - CALL_ACTION(A_IceSetTics, mo); // set a random tic wait + IceSetTics(mo); // set a random tic wait mo->RenderStyle = self->RenderStyle; mo->Alpha = self->Alpha; } diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 556767f373..138210061e 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -89,24 +89,22 @@ void ACustomBridge::Destroy() // target pointer to center mobj // angle angle of ball -DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) +static void BridgeOrbit(AActor *self) { - PARAM_SELF_PROLOGUE(AActor); - if (self->target == NULL) { // Don't crash if somebody spawned this into the world // independantly of a Bridge actor. - return 0; + return; } // Set default values // Every five tics, Hexen moved the ball 3/256th of a revolution. - DAngle rotationspeed = 45./32*3/5; + DAngle rotationspeed = 45. / 32 * 3 / 5; double rotationradius = ORBIT_RADIUS; // If the bridge is custom, set non-default values if any. // Set angular speed; 1--128: counterclockwise rotation ~=1--180°; 129--255: clockwise rotation ~= 180--1° - if (self->target->args[3] > 128) rotationspeed = 45./32 * (self->target->args[3]-256) / TICRATE; - else if (self->target->args[3] > 0) rotationspeed = 45./32 * (self->target->args[3]) / TICRATE; + if (self->target->args[3] > 128) rotationspeed = 45. / 32 * (self->target->args[3] - 256) / TICRATE; + else if (self->target->args[3] > 0) rotationspeed = 45. / 32 * (self->target->args[3]) / TICRATE; // Set rotation radius if (self->target->args[4]) rotationradius = ((self->target->args[4] * self->target->radius) / 100); @@ -114,6 +112,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) self->SetOrigin(self->target->Vec3Angle(rotationradius, self->Angles.Yaw, 0), true); self->floorz = self->target->floorz; self->ceilingz = self->target->ceilingz; +} + +DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) +{ + PARAM_SELF_PROLOGUE(AActor); + BridgeOrbit(self); return 0; } @@ -140,7 +144,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeInit) ball = Spawn(balltype, self->Pos(), ALLOW_REPLACE); ball->Angles.Yaw = startangle + (45./32) * (256/ballcount) * i; ball->target = self; - CALL_ACTION(A_BridgeOrbit, ball); + BridgeOrbit(ball); } return 0; } diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index c68fa800c1..fb0faef0fc 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -139,8 +139,7 @@ void AFastProjectile::Tick () { // Without the type cast this picks the 'void *' assignment... VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } } } diff --git a/src/info.cpp b/src/info.cpp index 69605d454d..b8bf3acde9 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -75,7 +75,6 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, { ActionCycles.Clock(); - 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 @@ -92,13 +91,13 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, } if (stateret == NULL) { - stack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL); + GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL); } else { VMReturn ret; ret.PointerAt((void **)stateret); - stack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL); + GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL); } ActionCycles.Unclock(); return true; diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 53405017ac..53ae789c68 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -489,11 +489,10 @@ void cht_DoCheat (player_t *player, int cheat) if (gsp) { VMValue params[1] = { player->mo }; - VMFrameStack stack; VMReturn ret; int oldpieces = 1; ret.IntAt(&oldpieces); - stack.Call(gsp, params, 1, &ret, 1, nullptr); + GlobalVMStack.Call(gsp, params, 1, &ret, 1, nullptr); item = player->mo->FindInventory(PClass::FindActor(NAME_Sigil)); if (item != NULL) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index ba086da3ad..6a7c9d10c7 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -6116,8 +6116,7 @@ static void SetMarineWeapon(AActor *marine, int weapon) if (smw) { VMValue params[2] = { marine, weapon }; - VMFrameStack stack; - stack.Call(smw, params, 2, nullptr, 0, nullptr); + GlobalVMStack.Call(smw, params, 2, nullptr, 0, nullptr); } } @@ -6128,8 +6127,7 @@ static void SetMarineSprite(AActor *marine, PClassActor *source) if (sms) { VMValue params[2] = { marine, source }; - VMFrameStack stack; - stack.Call(sms, params, 2, nullptr, 0, nullptr); + GlobalVMStack.Call(sms, params, 2, nullptr, 0, nullptr); } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index bc217f4ae5..477ed37f24 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -148,7 +148,6 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) state->ActionFunc = nullptr; } - VMFrameStack stack; PPrototype *proto = state->ActionFunc->Proto; VMReturn *wantret; FStateParamInfo stp = { state, STATE_StateChain, PSP_WEAPON }; @@ -184,7 +183,7 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) numret = 2; } } - stack.Call(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); + GlobalVMStack.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) @@ -3802,8 +3801,6 @@ static void CheckStopped(AActor *self) // //=========================================================================== -DECLARE_ACTION(A_RestoreSpecialPosition) - enum RS_Flags { RSF_FOG=1, @@ -3822,7 +3819,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Respawn) self->flags |= MF_SOLID; self->Height = self->GetDefault()->Height; self->radius = self->GetDefault()->radius; - CALL_ACTION(A_RestoreSpecialPosition, self); + self->RestoreSpecialPosition(); if (flags & RSF_TELEFRAG) { diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 29128c8b71..751f92a30e 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2285,12 +2285,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_Wander) return 0; } -// [MC] I had to move this out from within A_Wander in order to allow flags to -// pass into it. That meant replacing the CALL_ACTION(A_Wander) functions with -// just straight up defining A_Wander in order to compile. Looking around though, -// actors from the games themselves just do a straight A_Chase call itself so -// I saw no harm in it. - void A_Wander(AActor *self, int flags) { // [RH] Strife probably clears this flag somewhere, but I couldn't find where. @@ -2403,7 +2397,7 @@ nosee: //============================================================================= #define CLASS_BOSS_STRAFE_RANGE 64*10 -void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *meleestate, FState *missilestate, bool playactive, bool nightmarefast, bool dontmove, int flags) +void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missilestate, bool playactive, bool nightmarefast, bool dontmove, int flags) { if (actor->flags5 & MF5_INCONVERSATION) @@ -2533,7 +2527,7 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele { if (actor->flags & MF_FRIENDLY) { - //CALL_ACTION(A_Look, actor); + //A_Look(actor); if (actor->target == NULL) { if (!dontmove) A_Wander(actor); @@ -2931,12 +2925,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_Chase) if ((flags & CHF_RESURRECT) && P_CheckForResurrection(self, false)) return 0; - A_DoChase(stack, self, !!(flags&CHF_FASTCHASE), melee, missile, !(flags&CHF_NOPLAYACTIVE), + A_DoChase(self, !!(flags&CHF_FASTCHASE), melee, missile, !(flags&CHF_NOPLAYACTIVE), !!(flags&CHF_NIGHTMAREFAST), !!(flags&CHF_DONTMOVE), flags); } else // this is the old default A_Chase { - A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, flags); + A_DoChase(self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, flags); } return 0; } @@ -2944,7 +2938,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Chase) DEFINE_ACTION_FUNCTION(AActor, A_FastChase) { PARAM_SELF_PROLOGUE(AActor); - A_DoChase(stack, self, true, self->MeleeState, self->MissileState, true, true, false, 0); + A_DoChase(self, true, self->MeleeState, self->MissileState, true, true, false, 0); return 0; } @@ -2953,7 +2947,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VileChase) PARAM_SELF_PROLOGUE(AActor); if (!P_CheckForResurrection(self, true)) { - A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); + A_DoChase(self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } return 0; } @@ -2967,16 +2961,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_ExtChase) PARAM_BOOL_DEF (nightmarefast); // Now that A_Chase can handle state label parameters, this function has become rather useless... - A_DoChase(stack, self, false, + A_DoChase(self, false, domelee ? self->MeleeState : NULL, domissile ? self->MissileState : NULL, playactive, nightmarefast, false, 0); return 0; } // for internal use -void A_Chase(VMFrameStack *stack, AActor *self) +void A_Chase(AActor *self) { - A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); + A_DoChase(self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } //============================================================================= diff --git a/src/p_enemy.h b/src/p_enemy.h index a9aa40dc22..a0e829c712 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -60,18 +60,10 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params); void A_Weave(AActor *self, int xyspeed, int zspeed, double xydist, double zdist); void A_Unblock(AActor *self, bool drop); -DECLARE_ACTION(A_Look) -DECLARE_ACTION(A_BossDeath) -DECLARE_ACTION(A_Pain) -DECLARE_ACTION(A_MonsterRail) -DECLARE_ACTION(A_NoBlocking) -DECLARE_ACTION(A_Scream) -DECLARE_ACTION(A_FreezeDeath) -DECLARE_ACTION(A_FreezeDeathChunks) void A_BossDeath(AActor *self); void A_Wander(AActor *self, int flags = 0); -void A_Chase(VMFrameStack *stack, AActor *self); +void A_Chase(AActor *self); void A_FaceTarget(AActor *actor); void A_Face(AActor *self, AActor *other, DAngle max_turn = 0., DAngle max_pitch = 270., DAngle ang_offset = 0., DAngle pitch_offset = 0., int flags = 0, double z_add = 0); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index eae7edb00e..e6729096cf 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -777,8 +777,7 @@ void AActor::CallDie(AActor *source, AActor *inflictor, int dmgflags) IFVIRTUAL(AActor, Die) { VMValue params[4] = { (DObject*)this, source, inflictor, dmgflags }; - VMFrameStack stack; - stack.Call(func, params, 4, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 4, nullptr, 0, nullptr); } else return Die(source, inflictor, dmgflags); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 572c7656f9..f1f33425a9 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1494,8 +1494,7 @@ void AActor::CallTouch(AActor *toucher) IFVIRTUAL(AActor, Touch) { VMValue params[2] = { (DObject*)this, toucher }; - VMFrameStack stack; - stack.Call(func, params, 2, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); } else Touch(toucher); } @@ -3360,7 +3359,6 @@ int AActor::GetMissileDamage (int mask, int add) assert(false && "No damage function found"); return 0; } - VMFrameStack stack; VMValue param = this; VMReturn result; @@ -3368,7 +3366,7 @@ int AActor::GetMissileDamage (int mask, int add) result.IntAt(&amount); - if (stack.Call(DamageFunc, ¶m, 1, &result, 1) < 1) + if (GlobalVMStack.Call(DamageFunc, ¶m, 1, &result, 1) < 1) { // No results return 0; } @@ -3431,10 +3429,9 @@ bool AActor::CallSlam(AActor *thing) { VMValue params[2] = { (DObject*)this, thing }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); return !!retval; } @@ -3451,9 +3448,8 @@ int AActor::SpecialMissileHit (AActor *victim) VMValue params[2] = { (DObject*)this, victim }; VMReturn ret; int retval; - VMFrameStack stack; ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); return retval; } else return -1; @@ -4777,8 +4773,7 @@ void AActor::CallBeginPlay() { // Without the type cast this picks the 'void *' assignment... VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } else BeginPlay(); } @@ -4859,8 +4854,7 @@ void AActor::CallActivate(AActor *activator) { // Without the type cast this picks the 'void *' assignment... VMValue params[2] = { (DObject*)this, (DObject*)activator }; - VMFrameStack stack; - stack.Call(func, params, 2, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); } else Activate(activator); } @@ -4906,8 +4900,7 @@ void AActor::CallDeactivate(AActor *activator) { // Without the type cast this picks the 'void *' assignment... VMValue params[2] = { (DObject*)this, (DObject*)activator }; - VMFrameStack stack; - stack.Call(func, params, 2, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); } else Deactivate(activator); } @@ -7076,10 +7069,9 @@ int AActor::CallDoSpecialDamage(AActor *target, int damage, FName damagetype) // Without the type cast this picks the 'void *' assignment... VMValue params[4] = { (DObject*)this, (DObject*)target, damage, damagetype.GetIndex() }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 4, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 4, &ret, 1, nullptr); return retval; } else return DoSpecialDamage(target, damage, damagetype); @@ -7142,10 +7134,9 @@ int AActor::CallTakeSpecialDamage(AActor *inflictor, AActor *source, int damage, { VMValue params[5] = { (DObject*)this, inflictor, source, damage, damagetype.GetIndex() }; VMReturn ret; - VMFrameStack stack; int retval; ret.IntAt(&retval); - stack.Call(func, params, 5, &ret, 1, nullptr); + GlobalVMStack.Call(func, params, 5, &ret, 1, nullptr); return retval; } else return TakeSpecialDamage(inflictor, source, damage, damagetype); @@ -7468,6 +7459,70 @@ void AActor::SetTranslation(FName trname) // silently ignore if the name does not exist, this would create some insane message spam otherwise. } +//--------------------------------------------------------------------------- +// +// PROP A_RestoreSpecialPosition +// +//--------------------------------------------------------------------------- +static FRandom pr_restore("RestorePos"); + +void AActor::RestoreSpecialPosition() +{ + // Move item back to its original location + DVector2 sp = SpawnPoint; + + UnlinkFromWorld(); + SetXY(sp); + LinkToWorld(true); + SetZ(Sector->floorplane.ZatPoint(sp)); + P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS | FFCF_NOPORTALS); // no portal checks here so that things get spawned in this sector. + + if (flags & MF_SPAWNCEILING) + { + SetZ(ceilingz - Height - SpawnPoint.Z); + } + else if (flags2 & MF2_SPAWNFLOAT) + { + double space = ceilingz - Height - floorz; + if (space > 48) + { + space -= 40; + SetZ((space * pr_restore()) / 256. + floorz + 40); + } + else + { + SetZ(floorz); + } + } + else + { + SetZ(SpawnPoint.Z + floorz); + } + // Redo floor/ceiling check, in case of 3D floors and portals + P_FindFloorCeiling(this, FFCF_SAMESECTOR | FFCF_ONLY3DFLOORS | FFCF_3DRESTRICT); + if (Z() < floorz) + { // Do not reappear under the floor, even if that's where we were for the + // initial spawn. + SetZ(floorz); + } + if ((flags & MF_SOLID) && (Top() > ceilingz)) + { // Do the same for the ceiling. + SetZ(ceilingz - Height); + } + // Do not interpolate from the position the actor was at when it was + // picked up, in case that is different from where it is now. + ClearInterpolation(); +} + +DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) +{ + PARAM_SELF_PROLOGUE(AActor); + self->RestoreSpecialPosition(); + return 0; +} + + + class DActorIterator : public DObject, public NActorIterator { diff --git a/src/p_user.cpp b/src/p_user.cpp index 11857631ab..74b07e0ca2 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1305,8 +1305,7 @@ void APlayerPawn::PlayIdle () IFVIRTUAL(APlayerPawn, PlayIdle) { VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } } @@ -1315,8 +1314,7 @@ void APlayerPawn::PlayRunning () IFVIRTUAL(APlayerPawn, PlayRunning) { VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } } @@ -1325,8 +1323,7 @@ void APlayerPawn::PlayAttacking () IFVIRTUAL(APlayerPawn, PlayAttacking) { VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } } @@ -1335,8 +1332,7 @@ void APlayerPawn::PlayAttacking2 () IFVIRTUAL(APlayerPawn, PlayAttacking2) { VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } } @@ -1426,8 +1422,7 @@ void APlayerPawn::MorphPlayerThink () IFVIRTUAL(APlayerPawn, MorphPlayerThink) { VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(func, params, 1, nullptr, 0, nullptr); + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } } diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index eaeca6e9d6..28b20e289b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4228,7 +4228,7 @@ PPrototype *FxTypeCheck::ReturnProto() // //========================================================================== -int BuiltinTypeCheck(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +int BuiltinTypeCheck(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 2); PARAM_POINTER_AT(0, obj, DObject); @@ -5030,7 +5030,7 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx) // //========================================================================== -int BuiltinRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +int BuiltinRandom(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam >= 1 && numparam <= 3); FRandom *rng = reinterpret_cast(param[0].a); @@ -5284,7 +5284,7 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri // //========================================================================== -int BuiltinFRandom(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +int BuiltinFRandom(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 1 || numparam == 3); FRandom *rng = reinterpret_cast(param[0].a); @@ -7558,7 +7558,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) // //========================================================================== -int BuiltinCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +int BuiltinCallLineSpecial(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam > 2 && numparam < 8); assert(param[0].Type == REGT_INT); @@ -9518,7 +9518,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) // //========================================================================== -int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +int BuiltinNameToClass(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { assert(numparam == 2); assert(numret == 1); @@ -9650,7 +9650,7 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx) // //========================================================================== -int BuiltinClassCast(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) +int BuiltinClassCast(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { PARAM_PROLOGUE; PARAM_CLASS(from, DObject); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index fdee430e12..9bd0a4bc9a 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -867,7 +867,7 @@ class VMNativeFunction : public VMFunction { DECLARE_CLASS(VMNativeFunction, VMFunction); public: - typedef int (*NativeCallType)(VMFrameStack *stack, VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret); + typedef int (*NativeCallType)(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret); VMNativeFunction() : NativeCall(NULL) { Native = true; } VMNativeFunction(NativeCallType call) : NativeCall(call) { Native = true; } @@ -930,6 +930,9 @@ enum EVMEngine VMEngine_Checked }; +extern thread_local VMFrameStack GlobalVMStack; + + void VMSelectEngine(EVMEngine engine); extern int (*VMExec)(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret); void VMFillParams(VMValue *params, VMFrame *callee, int numparam); @@ -938,8 +941,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, TArray &defaultparam, int numparam, VMReturn *ret, int numret -#define VM_ARGS_NAMES stack, param, defaultparam, numparam, ret, numret +#define VM_ARGS VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret +#define VM_ARGS_NAMES param, defaultparam, numparam, ret, numret // Use these to collect the parameters in a native function. // variable name at position

@@ -1012,7 +1015,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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)*/ +typedef int(*actionf_p)(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ struct FieldDesc { @@ -1048,7 +1051,6 @@ struct AFuncDesc // 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 *AActor_##name##_VMPtr; #define DEFINE_ACTION_FUNCTION(cls, name) \ static int AF_##cls##_##name(VM_ARGS); \ @@ -1090,8 +1092,6 @@ struct AFuncDesc MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname; class AActor; -void CallAction(VMFrameStack *stack, VMFunction *vmfunc, AActor *self); -#define CALL_ACTION(name, self) CallAction(stack, AActor_##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) diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 750c384e0d..f51038f365 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -146,6 +146,12 @@ VMExec_Checked::Exec #endif ; +// Note: If the VM is being used in multiple threads, this should be declared as thread_local. +// ZDoom doesn't need this at the moment so this is disabled. + +thread_local VMFrameStack GlobalVMStack; + + //=========================================================================== // // VMSelectEngine diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 428266d0fa..d3ce5d5f97 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -422,12 +422,13 @@ VMFrame *VMFrameStack::PopFrame() int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults, VMException **trap) { + assert(this == VMGlobalStack); // why would anyone even want to create a local stack? bool allocated = false; try { if (func->Native) { - return static_cast(func)->NativeCall(this, params, func->DefaultArgs, numparams, results, numresults); + return static_cast(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults); } else { @@ -503,11 +504,3 @@ 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/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index ae666a2f7b..2b86e58e1c 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2362,7 +2362,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { if (vindex != -1) { - Error(p, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); + Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); } sym->Variants[0].Implementation->VirtualIndex = clstype->Virtuals.Push(sym->Variants[0].Implementation); } @@ -3267,3 +3267,7 @@ FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *h } return args; } + +void func() +{ +} \ No newline at end of file diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index abcd58b50c..bd00ffc98f 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -666,7 +666,11 @@ class Actor : Thinker native native void A_FastChase(); native void A_FreezeDeath(); native void A_FreezeDeathChunks(); - native void A_GenericFreezeDeath(); + void A_GenericFreezeDeath() + { + A_SetTranslation('Ice'); + A_FreezeDeath(); + } native void A_PlayerScream(); native void A_SkullPop(class skulltype = "BloodySkull"); native void A_CheckPlayerDone(); From 83d7f63364b6f16b1cc493989b1c78c8d25cdce8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 18:43:10 +0100 Subject: [PATCH 429/471] - missed these in the last commit. --- src/scripting/vm/vmexec.h | 4 ++-- src/scripting/zscript/zcc_compile.cpp | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 06c6ade8e1..225c73cabd 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -573,7 +573,7 @@ begin: FillReturns(reg, f, returns, pc+1, C); if (call->Native) { - numret = static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->DefaultArgs, B, returns, C); + numret = static_cast(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, returns, C); } else { @@ -617,7 +617,7 @@ begin: if (call->Native) { - return static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, call->DefaultArgs, B, ret, numret); + return static_cast(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, ret, numret); } else { // FIXME: Not a true tail call diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 2b86e58e1c..6eb675b891 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -3267,7 +3267,3 @@ FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *h } return args; } - -void func() -{ -} \ No newline at end of file From a350275bdfa182a1c2e0fbae247bb435dae3a7ae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 19:03:46 +0100 Subject: [PATCH 430/471] - re-added two lost parentheses in A_FireGoldWandPL1. --- wadsrc/static/zscript/heretic/weaponwand.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/heretic/weaponwand.txt b/wadsrc/static/zscript/heretic/weaponwand.txt index bd1475adb6..9516aa76c1 100644 --- a/wadsrc/static/zscript/heretic/weaponwand.txt +++ b/wadsrc/static/zscript/heretic/weaponwand.txt @@ -59,7 +59,7 @@ class GoldWand : HereticWeapon return; } double pitch = BulletSlope(); - int damage = 7 + random[FireGoldWand]() & 7; + int damage = 7 + (random[FireGoldWand]() & 7); double ang = angle; if (player.refire) { From 3f98ba9069e1fce4676f6aff927b97f779a75c9f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 19:08:58 +0100 Subject: [PATCH 431/471] - fixed: The Raven ambient sounds lost their looping flag when they were rewritten to use A_PlaySound instead of A_PlaySoundEx. --- wadsrc/static/zscript/raven/ravenambient.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/raven/ravenambient.txt b/wadsrc/static/zscript/raven/ravenambient.txt index 3495dc4e04..e0cff04d32 100644 --- a/wadsrc/static/zscript/raven/ravenambient.txt +++ b/wadsrc/static/zscript/raven/ravenambient.txt @@ -13,7 +13,7 @@ class SoundWind : Actor States { Spawn: - TNT1 A 2 A_PlaySound("world/wind", CHAN_6); + TNT1 A 2 A_PlaySound("world/wind", CHAN_6, 1, true); Loop; } } @@ -36,7 +36,7 @@ class SoundWaterfall : Actor States { Spawn: - TNT1 A 2 A_PlaySound("world/waterfall", CHAN_6); + TNT1 A 2 A_PlaySound("world/waterfall", CHAN_6, 1, true); Loop; } } From 1895feb185cb2156a620de4a86004e456feb1026 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 19:22:56 +0100 Subject: [PATCH 432/471] - fixed two apparently bogus asserts with returning gloating point constants. --- src/scripting/vm/vmexec.h | 4 ++-- src/scripting/vm/vmframe.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 225c73cabd..f5e61b5b93 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1827,12 +1827,12 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_ case REGT_FLOAT: if (regtype & REGT_KONST) { - assert(regnum + ((regtype & REGT_KONST) ? 2u : 0u) < func->NumKonstF); + assert(regnum < func->NumKonstF); src = &func->KonstF[regnum]; } else { - assert(regnum + ((regtype & REGT_KONST) ? 2u : 0u) < frame->NumRegF); + assert(regnum < frame->NumRegF); src = ®.f[regnum]; } if (regtype & REGT_MULTIREG3) diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index d3ce5d5f97..871a46673c 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -422,7 +422,7 @@ VMFrame *VMFrameStack::PopFrame() int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults, VMException **trap) { - assert(this == VMGlobalStack); // why would anyone even want to create a local stack? + assert(this == &GlobalVMStack); // why would anyone even want to create a local stack? bool allocated = false; try { From 07c110d5f7670bbf54f05d117bbabdd43c46311d Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Wed, 30 Nov 2016 16:51:20 +0100 Subject: [PATCH 433/471] - Fixed GCC compilation error. It didn't like 'cvar' being declared between 'goto foundit' and the 'foundit' label. --- src/scripting/codegeneration/codegen.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 28b20e289b..da919e139a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5590,8 +5590,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) goto foundit; } - auto cvar = FindCVar(Identifier.GetChars(), nullptr); - if (cvar != nullptr) + if (auto *cvar = FindCVar(Identifier.GetChars(), nullptr)) { if (cvar->GetFlags() & CVAR_USERINFO) { From 0233c21e33f7458bf1d8ea28e4888831dff71377 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Nov 2016 19:48:52 +0100 Subject: [PATCH 434/471] - fixed: When a bogus class is deleted from AllActorClasses, the entry should also be removed from the array instead of leaving a null pointer behind. --- src/scripting/thingdef.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 77120c9477..cdf35283ad 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -387,8 +387,9 @@ void LoadActors () } FScriptPosition::ResetErrorCounter(); - for (auto ti : PClassActor::AllActorClasses) + for (int i = PClassActor::AllActorClasses.Size()-1; i>=0;i--) { + auto ti = PClassActor::AllActorClasses[i]; if (ti->Size == TentativeClass) { if (ti->ObjectFlags & OF_Transient) @@ -400,6 +401,7 @@ void LoadActors () { if (*op == ti) *op = nullptr; } + PClassActor::AllActorClasses.Delete(i); } else { From 87484950cf5704219db4b62649b3be8bc8a84977 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 1 Dec 2016 00:05:23 +0100 Subject: [PATCH 435/471] - removed an assert from APowerMorph::EndEffect. With some recent changes to DestroyAllInventory it appears that the asserted condition no longer is true at this point when ending a game. - fixed: When replacing a tentative class, the pointers in the morph objects were not replaced. Instead of adding more ReplaceClassRef methods I chose to integrate this part into the PointerSubstitution mechanism and delete ReplaceClassRef entirely. The code had some oversights anyway that would have caused problems, now that non-actors can be created. --- src/d_player.h | 1 - src/dobject.cpp | 16 +++++++++++- src/dobject.h | 2 +- src/dobjtype.cpp | 14 +++-------- src/g_inventory/a_artifacts.cpp | 35 +++++++++++---------------- src/g_inventory/a_artifacts.h | 13 +++------- src/g_inventory/a_pickups.cpp | 11 +++++++-- src/g_inventory/a_pickups.h | 2 +- src/g_inventory/a_weaponpiece.cpp | 18 +------------- src/g_inventory/a_weaponpiece.h | 11 +-------- src/g_inventory/a_weapons.cpp | 18 -------------- src/g_inventory/a_weapons.h | 1 - src/g_shared/a_morph.cpp | 9 ++++++- src/g_shared/a_sharedglobal.h | 1 + src/info.cpp | 13 +++++----- src/info.h | 2 +- src/p_mobj.cpp | 2 ++ src/p_user.cpp | 11 +-------- src/scripting/thingdef.cpp | 15 +++--------- src/scripting/thingdef_properties.cpp | 9 ------- 20 files changed, 72 insertions(+), 132 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 4cdfb8b793..81a1c43a69 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -81,7 +81,6 @@ public: FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); } void SetPainFlash(FName type, PalEntry color); bool GetPainFlash(FName type, PalEntry *color) const; - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); FString DisplayName; // Display name (used in menus, etc.) FString SoundClass; // Sound class diff --git a/src/dobject.cpp b/src/dobject.cpp index b05ae69acf..6b973de336 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -423,7 +423,7 @@ size_t DObject::PointerSubstitution (DObject *old, DObject *notOld) // //========================================================================== -size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld) +size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults) { DObject *probe; size_t changed = 0; @@ -438,6 +438,20 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld) last = probe; } + if (scandefaults) + { + for (auto p : PClassActor::AllActorClasses) + { + auto def = GetDefaultByType(p); + if (def != nullptr) + { + def->Class = p; + def->DObject::PointerSubstitution(old, notOld); + def->Class = nullptr; // reset pointer. Defaults should not have a valid class pointer. + } + } + } + // Go through the bodyque. for (i = 0; i < BODYQUESIZE; ++i) { diff --git a/src/dobject.h b/src/dobject.h index 7d27133dc3..ed9c0fffa9 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -482,7 +482,7 @@ public: // change any pointers from the old object to the new object, // use this method. virtual size_t PointerSubstitution (DObject *old, DObject *notOld); - static size_t StaticPointerSubstitution (DObject *old, DObject *notOld); + static size_t StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults = false); PClass *GetClass() const { diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index dba5544982..c33caf12fc 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3008,8 +3008,6 @@ PClass *ClassReg::RegisterClass() &PClassPlayerPawn::RegistrationInfo, &PClassType::RegistrationInfo, &PClassClass::RegistrationInfo, - &PClassWeaponPiece::RegistrationInfo, - &PClassPowerupGiver::RegistrationInfo, }; // Skip classes that have already been registered @@ -3332,14 +3330,10 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) } else { - PClassActor::AllActorClasses.Pop(); // remove the newly added class from the list - // todo: replace all affected fields - for (unsigned i = 0; i < PClassActor::AllActorClasses.Size(); i++) - { - PClassActor::AllActorClasses[i]->ReplaceClassRef(existclass, type); - if (PClassActor::AllActorClasses[i] == existclass) - PClassActor::AllActorClasses[i] = static_cast(type); - } + StaticPointerSubstitution(existclass, type, true); // replace the old one, also in the actor defaults. + // Delete the old class from the actor classes list, if it is in there. + auto index = PClassActor::AllActorClasses.Find(static_cast(existclass)); + if (index < PClassActor::AllActorClasses.Size()) PClassActor::AllActorClasses.Delete(index); TypeTable.ReplaceType(type, existclass, bucket); } return type; diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index a75b9ecd44..4afe74f1f0 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -45,19 +45,12 @@ IMPLEMENT_CLASS(APowerup, false, false) // Powerup-Giver ------------------------------------------------------------- -IMPLEMENT_CLASS(PClassPowerupGiver, false, false) -void PClassPowerupGiver::ReplaceClassRef(PClass *oldclass, PClass *newclass) -{ - Super::ReplaceClassRef(oldclass, newclass); - APowerupGiver *def = (APowerupGiver*)Defaults; - if (def != NULL) - { - if (def->PowerupType == oldclass) def->PowerupType = static_cast(newclass); - } -} +IMPLEMENT_CLASS(APowerupGiver, false, true) -IMPLEMENT_CLASS(APowerupGiver, false, false) +IMPLEMENT_POINTERS_START(APowerupGiver) +IMPLEMENT_POINTER(PowerupType) +IMPLEMENT_POINTERS_END DEFINE_FIELD(APowerupGiver, PowerupType) DEFINE_FIELD(APowerupGiver, EffectTics) @@ -1855,7 +1848,14 @@ void APowerDoubleFiringSpeed::EndEffect( ) // Morph powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerMorph, false, false) +IMPLEMENT_CLASS(APowerMorph, false, true) + +IMPLEMENT_POINTERS_START(APowerMorph) + IMPLEMENT_POINTER(PlayerClass) + IMPLEMENT_POINTER(MorphFlash) + IMPLEMENT_POINTER(UnMorphFlash) +IMPLEMENT_POINTERS_END + DEFINE_FIELD(APowerMorph, PlayerClass) DEFINE_FIELD(APowerMorph, MorphFlash) @@ -1916,19 +1916,12 @@ void APowerMorph::EndEffect( ) { Super::EndEffect(); - // Abort if owner already destroyed - if (Owner == NULL) + // Abort if owner already destroyed or unmorphed + if (Owner == nullptr || MorphedPlayer == nullptr) { - assert(MorphedPlayer == NULL); return; } - // Abort if owner already unmorphed - if (MorphedPlayer == NULL) - { - return; - } - // Abort if owner is dead; their Die() method will // take care of any required unmorphing on death. if (MorphedPlayer->health <= 0) diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index 7e9956d73b..bb821b5d63 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -35,19 +35,11 @@ protected: friend void InitAllPowerupEffects(AInventory *item); }; -class PClassPowerupGiver: public PClassInventory -{ - DECLARE_CLASS(PClassPowerupGiver, PClassInventory) -protected: -public: - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); -}; - - // An artifact is an item that gives the player a powerup when activated. class APowerupGiver : public AInventory { - DECLARE_CLASS_WITH_META (APowerupGiver, AInventory, PClassPowerupGiver) + DECLARE_CLASS (APowerupGiver, AInventory) + HAS_OBJECT_POINTERS public: virtual bool Use (bool pickup) override; virtual void Serialize(FSerializer &arc) override; @@ -272,6 +264,7 @@ protected: class APowerMorph : public APowerup { DECLARE_CLASS( APowerMorph, APowerup ) + HAS_OBJECT_POINTERS public: virtual void Serialize(FSerializer &arc) override; diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 91b88a0537..51072023b6 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -45,9 +45,9 @@ void PClassInventory::DeriveData(PClass *newclass) newc->RestrictedToPlayerClass = RestrictedToPlayerClass; } -void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass) +size_t PClassInventory::PointerSubstitution(DObject *oldclass, DObject *newclass) { - Super::ReplaceClassRef(oldclass, newclass); + size_t changed = Super::PointerSubstitution(oldclass, newclass); AInventory *def = (AInventory*)Defaults; if (def != NULL) { @@ -55,14 +55,21 @@ void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass) for (unsigned i = 0; i < ForbiddenToPlayerClass.Size(); i++) { if (ForbiddenToPlayerClass[i] == oldclass) + { ForbiddenToPlayerClass[i] = static_cast(newclass); + changed++; + } } for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++) { if (RestrictedToPlayerClass[i] == oldclass) + { RestrictedToPlayerClass[i] = static_cast(newclass); + changed++; + } } } + return changed; } void PClassInventory::Finalize(FStateDefinitions &statedef) diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 99dad87131..32914e3e52 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -55,7 +55,7 @@ class PClassInventory : public PClassActor public: PClassInventory(); virtual void DeriveData(PClass *newclass); - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); + virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass); void Finalize(FStateDefinitions &statedef); FString PickupMessage; diff --git a/src/g_inventory/a_weaponpiece.cpp b/src/g_inventory/a_weaponpiece.cpp index e1a7fe33bb..2fe14ae91d 100644 --- a/src/g_inventory/a_weaponpiece.cpp +++ b/src/g_inventory/a_weaponpiece.cpp @@ -38,7 +38,6 @@ #include "doomstat.h" #include "serializer.h" -IMPLEMENT_CLASS(PClassWeaponPiece, false, false) IMPLEMENT_CLASS(AWeaponHolder, false, false) DEFINE_FIELD(AWeaponHolder, PieceMask); @@ -50,22 +49,6 @@ DEFINE_FIELD(AWeaponHolder, PieceWeapon); // //=========================================================================== -void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) -{ - Super::ReplaceClassRef(oldclass, newclass); - AWeaponPiece *def = (AWeaponPiece*)Defaults; - if (def != NULL) - { - if (def->WeaponClass == oldclass) def->WeaponClass = static_cast(newclass); - } -} - -//=========================================================================== -// -// -// -//=========================================================================== - void AWeaponHolder::Serialize(FSerializer &arc) { Super::Serialize(arc); @@ -77,6 +60,7 @@ IMPLEMENT_CLASS(AWeaponPiece, false, true) IMPLEMENT_POINTERS_START(AWeaponPiece) IMPLEMENT_POINTER(FullWeapon) + IMPLEMENT_POINTER(WeaponClass) IMPLEMENT_POINTERS_END //=========================================================================== diff --git a/src/g_inventory/a_weaponpiece.h b/src/g_inventory/a_weaponpiece.h index e0db150077..a8c6a2e76d 100644 --- a/src/g_inventory/a_weaponpiece.h +++ b/src/g_inventory/a_weaponpiece.h @@ -2,18 +2,9 @@ #include "a_pickups.h" #include "a_weapons.h" -// -class PClassWeaponPiece : public PClassInventory -{ - DECLARE_CLASS(PClassWeaponPiece, PClassInventory) -protected: -public: - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); -}; - class AWeaponPiece : public AInventory { - DECLARE_CLASS_WITH_META(AWeaponPiece, AInventory, PClassWeaponPiece) + DECLARE_CLASS(AWeaponPiece, AInventory) HAS_OBJECT_POINTERS protected: bool PrivateShouldStay (); diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 19a30dcd89..c312f15b34 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -148,24 +148,6 @@ void PClassWeapon::DeriveData(PClass *newclass) } -//=========================================================================== -// -// -// -//=========================================================================== - -void PClassWeapon::ReplaceClassRef(PClass *oldclass, PClass *newclass) -{ - Super::ReplaceClassRef(oldclass, newclass); - AWeapon *def = (AWeapon*)Defaults; - if (def != NULL) - { - if (def->AmmoType1 == oldclass) def->AmmoType1 = static_cast(newclass); - if (def->AmmoType2 == oldclass) def->AmmoType2 = static_cast(newclass); - if (def->SisterWeaponType == oldclass) def->SisterWeaponType = static_cast(newclass); - } -} - //=========================================================================== // // diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index c6424075d3..1b12584012 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -95,7 +95,6 @@ protected: virtual void DeriveData(PClass *newclass); public: PClassWeapon(); - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); void Finalize(FStateDefinitions &statedef); int SlotNumber; diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index f223188396..03f76c0c05 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -613,7 +613,14 @@ void InitAllPowerupEffects(AInventory *item) // Base class for morphing projectiles -------------------------------------- -IMPLEMENT_CLASS(AMorphProjectile, false, false) +IMPLEMENT_CLASS(AMorphProjectile, false, true) + +IMPLEMENT_POINTERS_START(AMorphProjectile) + IMPLEMENT_POINTER(PlayerClass) + IMPLEMENT_POINTER(MonsterClass) + IMPLEMENT_POINTER(MorphFlash) + IMPLEMENT_POINTER(UnMorphFlash) +IMPLEMENT_POINTERS_END DEFINE_FIELD(AMorphProjectile, PlayerClass) DEFINE_FIELD(AMorphProjectile, MonsterClass) diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 0087690f71..001df5488e 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -187,6 +187,7 @@ private: class AMorphProjectile : public AActor { DECLARE_CLASS (AMorphProjectile, AActor) + HAS_OBJECT_POINTERS; public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); diff --git a/src/info.cpp b/src/info.cpp index b8bf3acde9..a0117a71f0 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -619,19 +619,18 @@ void PClassActor::SetPainChance(FName type, int chance) // //========================================================================== -void PClassActor::ReplaceClassRef(PClass *oldclass, PClass *newclass) +size_t PClassActor::PointerSubstitution(DObject *oldclass, DObject *newclass) { + auto changed = Super::PointerSubstitution(oldclass, newclass); for (unsigned i = 0; i < VisibleToPlayerClass.Size(); i++) { if (VisibleToPlayerClass[i] == oldclass) + { VisibleToPlayerClass[i] = static_cast(newclass); + changed++; + } } - AActor *def = (AActor*)Defaults; - if (def != NULL) - { - if (def->TeleFogSourceType == oldclass) def->TeleFogSourceType = static_cast(newclass); - if (def->TeleFogDestType == oldclass) def->TeleFogDestType = static_cast(newclass); - } + return changed; } //========================================================================== diff --git a/src/info.h b/src/info.h index bb21524a52..54aac3e3c4 100644 --- a/src/info.h +++ b/src/info.h @@ -248,7 +248,7 @@ public: PClassActor(); ~PClassActor(); - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); + virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass); void BuildDefaults(); void ApplyDefaults(BYTE *defaults); void RegisterIDs(); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f1f33425a9..5a37561c94 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -145,6 +145,8 @@ IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(Poisoner) IMPLEMENT_POINTER(DamageFunc) IMPLEMENT_POINTER(alternative) + IMPLEMENT_POINTER(TeleFogSourceType) + IMPLEMENT_POINTER(TeleFogDestType) IMPLEMENT_POINTERS_END AActor::~AActor () diff --git a/src/p_user.cpp b/src/p_user.cpp index 74b07e0ca2..b808dd9c3d 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -607,16 +607,6 @@ bool PClassPlayerPawn::GetPainFlash(FName type, PalEntry *color) const return false; } -void PClassPlayerPawn::ReplaceClassRef(PClass *oldclass, PClass *newclass) -{ - Super::ReplaceClassRef(oldclass, newclass); - APlayerPawn *def = (APlayerPawn*)Defaults; - if (def != NULL) - { - if (def->FlechetteType == oldclass) def->FlechetteType = static_cast(newclass); - } -} - //=========================================================================== // // player_t :: SendPitchLimits @@ -648,6 +638,7 @@ IMPLEMENT_CLASS(APlayerPawn, false, true) IMPLEMENT_POINTERS_START(APlayerPawn) IMPLEMENT_POINTER(InvFirst) IMPLEMENT_POINTER(InvSel) + IMPLEMENT_POINTER(FlechetteType) IMPLEMENT_POINTERS_END IMPLEMENT_CLASS(APlayerChunk, false, false) diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index cdf35283ad..e1d5f9b270 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -68,7 +68,6 @@ // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void InitThingdef(); -TArray OptionalClassPtrs; // STATIC FUNCTION PROTOTYPES -------------------------------------------- PClassActor *QuestItemClasses[31]; @@ -365,7 +364,7 @@ static void CheckStates(PClassActor *obj) void ParseScripts(); void ParseAllDecorate(); -void LoadActors () +void LoadActors() { cycle_t timer; @@ -387,7 +386,7 @@ void LoadActors () } FScriptPosition::ResetErrorCounter(); - for (int i = PClassActor::AllActorClasses.Size()-1; i>=0;i--) + for (int i = PClassActor::AllActorClasses.Size() - 1; i >= 0; i--) { auto ti = PClassActor::AllActorClasses[i]; if (ti->Size == TentativeClass) @@ -397,10 +396,6 @@ void LoadActors () Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars()); FScriptPosition::WarnCounter++; DObject::StaticPointerSubstitution(ti, nullptr); - for (auto op : OptionalClassPtrs) - { - if (*op == ti) *op = nullptr; - } PClassActor::AllActorClasses.Delete(i); } else @@ -420,7 +415,7 @@ void LoadActors () CheckStates(ti); - + if (ti->bDecorateClass && ti->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) { // either a DECORATE based weapon or CustomInventory. @@ -429,7 +424,7 @@ void LoadActors () // 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) { @@ -447,6 +442,4 @@ void LoadActors () QuestItemClasses[i] = PClass::FindActor(fmt); } StateSourceLines.Clear(); - OptionalClassPtrs.Clear(); - OptionalClassPtrs.ShrinkToFit(); } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 9bff91a805..2eb5f67812 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -74,8 +74,6 @@ #include "a_health.h" #include "a_keys.h" -extern TArray OptionalClassPtrs; - //========================================================================== // // Gets a class pointer and performs an error check for correct type @@ -2998,7 +2996,6 @@ DEFINE_CLASS_PROPERTY(playerclass, S, MorphProjectile) { PROP_STRING_PARM(str, 0); defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push((PClassActor**)&defaults->PlayerClass); } //========================================================================== @@ -3008,7 +3005,6 @@ DEFINE_CLASS_PROPERTY(monsterclass, S, MorphProjectile) { PROP_STRING_PARM(str, 0); defaults->MonsterClass = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MonsterClass); } //========================================================================== @@ -3036,7 +3032,6 @@ DEFINE_CLASS_PROPERTY(morphflash, S, MorphProjectile) { PROP_STRING_PARM(str, 0); defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MorphFlash); } //========================================================================== @@ -3046,7 +3041,6 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, MorphProjectile) { PROP_STRING_PARM(str, 0); defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->UnMorphFlash); } //========================================================================== @@ -3056,7 +3050,6 @@ DEFINE_CLASS_PROPERTY(playerclass, S, PowerMorph) { PROP_STRING_PARM(str, 0); defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push((PClassActor**)&defaults->PlayerClass); } //========================================================================== @@ -3075,7 +3068,6 @@ DEFINE_CLASS_PROPERTY(morphflash, S, PowerMorph) { PROP_STRING_PARM(str, 0); defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MorphFlash); } //========================================================================== @@ -3085,7 +3077,6 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, PowerMorph) { PROP_STRING_PARM(str, 0); defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->UnMorphFlash); } From 7688e14becbe5f1aa13e5825c2dc90897377c9b1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 1 Dec 2016 01:13:53 +0100 Subject: [PATCH 436/471] - added a boolean cast VM instruction. Although this already helps a lot with the messed up code generated for comparisons it's not really a solution for this - it still needs a proper implementation to generate efficient code. --- src/scripting/codegeneration/codegen.cpp | 20 +----------------- src/scripting/vm/vm.h | 5 +++++ src/scripting/vm/vmdisasm.cpp | 11 ++++++++++ src/scripting/vm/vmexec.h | 27 ++++++++++++++++++++++-- src/scripting/vm/vmops.h | 1 + 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index da919e139a..df9d2bb463 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -758,25 +758,7 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) 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); + build->Emit(OP_CASTB, to.RegNum, from.RegNum, from.RegType == REGT_INT ? CASTB_I : from.RegType == REGT_FLOAT ? CASTB_F : CASTB_A); return to; } else diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 9bd0a4bc9a..0ccde006f0 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -130,6 +130,11 @@ enum CAST_V32S, CAST_SID2S, CAST_TID2S, + + CASTB_I, + CASTB_F, + CASTB_A, + CASTB_S }; // Register types for VMParam diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 2158139abb..d21e38d207 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -90,6 +90,7 @@ #define THROW MODE_AIMMZ | MODE_BCTHROW #define CATCH MODE_AIMMZ | MODE_BCCATCH #define CAST MODE_AX | MODE_BX | MODE_CIMMZ | MODE_BCCAST +#define CASTB MODE_AI | MODE_BX | MODE_CIMMZ | MODE_BCCAST #define RSRSRS MODE_AS | MODE_BS | MODE_CS #define RIRS MODE_AI | MODE_BS | MODE_CUNUSED @@ -381,10 +382,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction break; default: + + if ((mode & MODE_BCTYPE) == MODE_BCCAST) { switch (code[i].c) { + case CASTB_I: + mode = MODE_AI | MODE_BI | MODE_CUNUSED; + break; + case CASTB_A: + mode = MODE_AI | MODE_BP | MODE_CUNUSED; + break; case CAST_I2F: case CAST_U2F: mode = MODE_AF | MODE_BI | MODE_CUNUSED; @@ -398,6 +407,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction break; case CAST_F2I: case CAST_F2U: + case CASTB_F: mode = MODE_AI | MODE_BF | MODE_CUNUSED; break; case CAST_F2S: @@ -412,6 +422,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction case CAST_S2So: case CAST_S2N: case CAST_S2I: + case CASTB_S: mode = MODE_AI | MODE_BS | MODE_CUNUSED; break; case CAST_S2F: diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index f5e61b5b93..d19850554e 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -419,12 +419,12 @@ begin: if (C == CAST_I2F) { ASSERTF(a); ASSERTD(B); - reg.f[A] = reg.d[B]; + reg.f[a] = reg.d[B]; } else if (C == CAST_F2I) { ASSERTD(a); ASSERTF(B); - reg.d[A] = (int)reg.f[B]; + reg.d[a] = (int)reg.f[B]; } else { @@ -432,6 +432,29 @@ begin: } NEXTOP; + OP(CASTB): + if (C == CASTB_I) + { + ASSERTD(a); ASSERTD(B); + reg.f[a] = !!reg.d[B]; + } + else if (C == CASTB_F) + { + ASSERTD(a); ASSERTF(B); + reg.d[a] = reg.f[B] != 0; + } + else if (c == CASTB_A) + { + ASSERTD(a); ASSERTA(B); + reg.d[a] = reg.a[B] != nullptr; + } + else + { + ASSERTD(a); ASSERTS(B); + reg.d[a] = reg.s[B].Len() > 0; + } + NEXTOP; + OP(TEST): ASSERTD(a); if (reg.d[a] != BC) diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index e5b6d34ebb..826bdb4e3e 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -83,6 +83,7 @@ xx(MOVEA, mov, RPRP, NOP, 0, 0), // aA = aB xx(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements) xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements) xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C +xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C // Control flow. xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++ From 44d7d0b5f6b345c43f8f2053dccb634e6bd940a4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 1 Dec 2016 09:44:52 +0100 Subject: [PATCH 437/471] - fixed a typo in the bool cast. - fixed a few places for unsigned values. --- src/scripting/codegeneration/codegen.cpp | 5 +++-- src/scripting/vm/vmexec.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index df9d2bb463..b6de3a6643 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -584,7 +584,7 @@ static ExpEmit EmitKonst(VMFunctionBuilder *build, ExpEmit &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) + // no const handling here. Ultimately 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); @@ -1770,10 +1770,11 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx) { int result = ~static_cast(Operand)->GetValue().GetInt(); FxExpression *e = new FxConstant(result, ScriptPosition); + e->ValueType = Operand->ValueType == TypeUInt32 ? TypeUInt32 : TypeSInt32; delete this; return e; } - ValueType = TypeSInt32; + ValueType = Operand->ValueType == TypeUInt32? TypeUInt32 : TypeSInt32; return this; } diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index d19850554e..65e2e756c0 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -443,7 +443,7 @@ begin: ASSERTD(a); ASSERTF(B); reg.d[a] = reg.f[B] != 0; } - else if (c == CASTB_A) + else if (C == CASTB_A) { ASSERTD(a); ASSERTA(B); reg.d[a] = reg.a[B] != nullptr; From 96df8f6729eae0bde91efafeed19587458c92f13 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 1 Dec 2016 10:38:43 +0100 Subject: [PATCH 438/471] - another typo... --- src/scripting/vm/vmexec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 65e2e756c0..8f79bd90bc 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -436,7 +436,7 @@ begin: if (C == CASTB_I) { ASSERTD(a); ASSERTD(B); - reg.f[a] = !!reg.d[B]; + reg.d[a] = !!reg.d[B]; } else if (C == CASTB_F) { From cbd61d963f829729465ee2c39ea8eaa8be2e0c7f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 00:29:32 +0100 Subject: [PATCH 439/471] - removed test messages. --- wadsrc/static/zscript/hexen/heresiarch.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/wadsrc/static/zscript/hexen/heresiarch.txt b/wadsrc/static/zscript/hexen/heresiarch.txt index 9cfdde19d5..db4860c349 100644 --- a/wadsrc/static/zscript/hexen/heresiarch.txt +++ b/wadsrc/static/zscript/hexen/heresiarch.txt @@ -583,7 +583,6 @@ class SorcBall1 : SorcBall { Super.BeginPlay (); AngleOffset = Heresiarch.BALL1_ANGLEOFFSET; - A_Log("Ball1 begins " .. AngleOffset); } //============================================================================ @@ -683,7 +682,6 @@ class SorcBall2 : SorcBall { Super.BeginPlay (); AngleOffset = Heresiarch.BALL2_ANGLEOFFSET; - A_Log("Ball2 begins " .. AngleOffset); } //============================================================================ @@ -733,7 +731,6 @@ class SorcBall3 : SorcBall { Super.BeginPlay (); AngleOffset = Heresiarch.BALL3_ANGLEOFFSET; - A_Log("Ball3 begins " .. AngleOffset); } //============================================================================ From 17d9a152e74c420ecee65772682f35eb1ae1f2f6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 1 Dec 2016 23:44:23 +0100 Subject: [PATCH 440/471] - added missing THINGSPEC constants --- wadsrc/static/zscript/constants.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 2ccfb70481..c199258997 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -368,6 +368,9 @@ enum EActivationFlags THINGSPEC_ClearSpecial = 32, THINGSPEC_NoDeathSpecial = 64, THINGSPEC_TriggerActs = 128, + THINGSPEC_Activate = 1<<8, // The thing is activated when triggered + THINGSPEC_Deactivate = 1<<9, // The thing is deactivated when triggered + THINGSPEC_Switch = 1<<10, // The thing is alternatively activated and deactivated when triggered // Shorter aliases for same AF_Default = 0, @@ -379,6 +382,9 @@ enum EActivationFlags AF_ClearSpecial = 32, AF_NoDeathSpecial = 64, AF_TriggerActs = 128, + AF_Activate = 1<<8, // The thing is activated when triggered + AF_Deactivate = 1<<9, // The thing is deactivated when triggered + AF_Switch = 1<<10, // The thing is alternatively activated and deactivated when triggered }; From 77192fa9dd4d0021790b95c1c672fe4658056408 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 00:51:29 +0100 Subject: [PATCH 441/471] - branch optimization. --- src/scripting/codegeneration/codegen.cpp | 241 ++++++++++++++--------- src/scripting/codegeneration/codegen.h | 7 + src/scripting/vm/vmbuilder.cpp | 13 ++ src/scripting/vm/vmbuilder.h | 2 + 4 files changed, 166 insertions(+), 97 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index b6de3a6643..2d93dc8663 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -288,6 +288,45 @@ ExpEmit FxExpression::Emit (VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +void FxExpression::EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no) +{ + ExpEmit op = Emit(build); + ExpEmit i; + assert(op.RegType != REGT_NIL && op.RegCount == 1 && !op.Konst); + switch (op.RegType) + { + case REGT_INT: + build->Emit(OP_EQ_K, !invert, op.RegNum, build->GetConstantInt(0)); + break; + + case REGT_FLOAT: + build->Emit(OP_EQF_K, !invert, op.RegNum, build->GetConstantFloat(0)); + break; + + case REGT_POINTER: + build->Emit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0, ATAG_GENERIC)); + break; + + case REGT_STRING: + i = ExpEmit(build, REGT_INT); + build->Emit(OP_LENS, i.RegNum, op.RegNum); + build->Emit(OP_EQ_K, !invert, i.RegNum, build->GetConstantInt(0)); + i.Free(build); + break; + + default: + break; + } + patchspots_no.Push(build->Emit(OP_JMP, 0)); + op.Free(build); +} + //========================================================================== // // @@ -757,7 +796,6 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) { ExpEmit to(build, REGT_INT); from.Free(build); - // Preload result with 0. build->Emit(OP_CASTB, to.RegNum, from.RegNum, from.RegType == REGT_INT ? CASTB_I : from.RegType == REGT_FLOAT ? CASTB_F : CASTB_A); return to; } @@ -773,6 +811,17 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) // //========================================================================== +void FxBoolCast::EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no) +{ + basex->EmitCompare(build, invert, patchspots_yes, patchspots_no); +} + +//========================================================================== +// +// +// +//========================================================================== + FxIntCast::FxIntCast(FxExpression *x, bool nowarn, bool explicitly) : FxExpression(EFX_IntCast, x->ScriptPosition) { @@ -1872,6 +1921,17 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) // //========================================================================== +void FxUnaryNotBoolean::EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no) +{ + Operand->EmitCompare(build, !invert, patchspots_yes, patchspots_no); +} + +//========================================================================== +// +// +// +//========================================================================== + FxSizeAlign::FxSizeAlign(FxExpression *operand, int which) : FxExpression(EFX_SizeAlign, operand->ScriptPosition) { @@ -3124,7 +3184,7 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) // //========================================================================== -ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build) +ExpEmit FxCompareRel::EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert) { ExpEmit op1 = left->Emit(build); ExpEmit op2 = right->Emit(build); @@ -3154,11 +3214,15 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build) { op2.Free(build); } + if (invert) a ^= CMP_CHECK; - build->Emit(OP_LI, to.RegNum, 0, 0); + if (!forcompare) 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); + if (!forcompare) + { + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + } return to; } else @@ -3197,16 +3261,32 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build) { op1.Free(build); } + if (invert) check ^= 1; // See FxBoolCast for comments, since it's the same thing. - build->Emit(OP_LI, to.RegNum, 0, 0); + if (!forcompare) 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); + if (!forcompare) + { + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + } return to; } } +ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build) +{ + return EmitCommon(build, false, false); +} + +void FxCompareRel::EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no) +{ + ExpEmit emit = EmitCommon(build, true, invert); + emit.Free(build); + patchspots_no.Push(build->Emit(OP_JMP, 0)); +} + //========================================================================== // // @@ -3404,7 +3484,7 @@ error: // //========================================================================== -ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) +ExpEmit FxCompareEq::EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert) { ExpEmit op1 = left->Emit(build); ExpEmit op2 = right->Emit(build); @@ -3418,13 +3498,17 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) 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 (op1.Konst) a |= CMP_BK; if (op2.Konst) a |= CMP_CK; + if (invert) a ^= CMP_CHECK; - build->Emit(OP_LI, to.RegNum, 0, 0); + if (!forcompare) 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); + if (!forcompare) + { + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + } op1.Free(build); op2.Free(build); return to; @@ -3457,14 +3541,29 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) } // 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); + if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0); + build->Emit(instr, int(invert) ^ (Operator == TK_ApproxEq ? CMP_APPROX : ((Operator != TK_Eq) ? CMP_CHECK : 0)), op1.RegNum, op2.RegNum); + if (!forcompare) + { + build->Emit(OP_JMP, 1); + build->Emit(OP_LI, to.RegNum, 1); + } return to; } } +ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build) +{ + return EmitCommon(build, false, false); +} + +void FxCompareEq::EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no) +{ + ExpEmit emit = EmitCommon(build, true, invert); + emit.Free(build); + patchspots_no.Push(build->Emit(OP_JMP, 0)); +} + //========================================================================== // // @@ -4447,21 +4546,17 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) ExpEmit FxConditional::Emit(VMFunctionBuilder *build) { - size_t truejump, falsejump; - ExpEmit out; + size_t truejump; + ExpEmit out, falseout; // 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); + TArray yes, no; + condition->EmitCompare(build, false, yes, no); - // Test condition. - build->Emit(OP_EQ_K, 1, cond.RegNum, build->GetConstantInt(0)); - falsejump = build->Emit(OP_JMP, 0); - cond.Free(build); + build->BackpatchListToHere(yes); - // Evaluate true expression. if (truex->isConstant() && truex->ValueType->GetRegType() == REGT_INT) { out = ExpEmit(build, REGT_INT); @@ -4501,7 +4596,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build) truejump = build->Emit(OP_JMP, 0); // Evaluate false expression. - build->BackpatchToHere(falsejump); + build->BackpatchListToHere(no); if (falsex->isConstant() && falsex->ValueType->GetRegType() == REGT_INT) { build->EmitLoadInt(out.RegNum, static_cast(falsex)->GetValue().GetInt()); @@ -8858,68 +8953,28 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) { ExpEmit v; - size_t jumpspot; - FxExpression *path1, *path2; - int condcheck; + size_t jumpspot = ~0u; - // 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); + TArray yes, no; + Condition->EmitCompare(build, false, yes, no); if (WhenTrue != nullptr) { - path1 = WhenTrue; - path2 = WhenFalse; - condcheck = 1; + build->BackpatchListToHere(yes); + WhenTrue->Emit(build); + } + if (WhenFalse != nullptr) + { + if (!WhenTrue->CheckReturn()) jumpspot = build->Emit(OP_JMP, 0); // no need to emit a jump if the block returns. + build->BackpatchListToHere(no); + WhenFalse->Emit(build); + if (jumpspot != ~0u) build->BackpatchToHere(jumpspot); + if (WhenTrue == nullptr) build->BackpatchListToHere(yes); } 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; + build->BackpatchListToHere(no); } - - // 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(); } @@ -9027,19 +9082,17 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) assert(Condition->ValueType == TypeBool); size_t loopstart, loopend; - size_t jumpspot; + TArray yes, no; // 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); + Condition->EmitCompare(build, false, yes, no); } else assert(static_cast(Condition)->GetValue().GetBool() == true); + build->BackpatchListToHere(yes); // Execute the loop's content. if (Code != nullptr) { @@ -9049,13 +9102,8 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) // Loop back. build->Backpatch(build->Emit(OP_JMP, 0), loopstart); + build->BackpatchListToHere(no); loopend = build->GetAddress(); - - if (!Condition->isConstant()) - { - build->Backpatch(jumpspot, loopend); - } - Backpatch(build, loopstart, loopend); return ExpEmit(); } @@ -9132,17 +9180,16 @@ ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) 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); + TArray yes, no; + Condition->EmitCompare(build, true, yes, no); + build->BackpatchList(no, codestart); + build->BackpatchListToHere(yes); } 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(); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index c54c8dc62a..c5e6f4e68d 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -328,6 +328,7 @@ public: bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); } virtual ExpEmit Emit(VMFunctionBuilder *build); + virtual void EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no); FScriptPosition ScriptPosition; PType *ValueType = nullptr; @@ -565,6 +566,7 @@ public: FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); + void EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no); }; class FxIntCast : public FxExpression @@ -734,6 +736,7 @@ public: ~FxUnaryNotBoolean(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); + void EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no); }; //========================================================================== @@ -934,7 +937,9 @@ public: FxCompareRel(int, FxExpression*, FxExpression*); FxExpression *Resolve(FCompileContext&); + ExpEmit EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert); ExpEmit Emit(VMFunctionBuilder *build); + void EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no); }; //========================================================================== @@ -949,7 +954,9 @@ public: FxCompareEq(int, FxExpression*, FxExpression*); FxExpression *Resolve(FCompileContext&); + ExpEmit EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert); ExpEmit Emit(VMFunctionBuilder *build); + void EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no); }; //========================================================================== diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index f358fce7b6..9b399ad609 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -734,6 +734,13 @@ void VMFunctionBuilder::Backpatch(size_t loc, size_t target) Code[loc].i24 = offset; } +void VMFunctionBuilder::BackpatchList(TArray &locs, size_t target) +{ + for (auto loc : locs) + Backpatch(loc, target); +} + + //========================================================================== // // VMFunctionBuilder :: BackpatchToHere @@ -748,6 +755,12 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc) Backpatch(loc, Code.Size()); } +void VMFunctionBuilder::BackpatchListToHere(TArray &locs) +{ + for (auto loc : locs) + Backpatch(loc, Code.Size()); +} + //========================================================================== // // FFunctionBuildList diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index d533935183..7434f3a211 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -69,6 +69,8 @@ public: void Backpatch(size_t addr, size_t target); void BackpatchToHere(size_t addr); + void BackpatchList(TArray &addrs, size_t target); + void BackpatchListToHere(TArray &addrs); // Write out complete constant tables. void FillIntConstants(int *konst); From 719be058e5db54d95325fe029cc800494fb9308c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 00:54:40 +0100 Subject: [PATCH 442/471] - use the immediate versions for loading integer constants when possible. --- src/scripting/codegeneration/codegen.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 2d93dc8663..1629c8135c 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -2304,14 +2304,29 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) ExpEmit pointer = Base->Emit(build); Address = pointer; - ExpEmit result = Right->Emit(build); + ExpEmit result; + bool intconst = false; + int intconstval; + + if (Right->isConstant() && Right->ValueType->GetRegType() == REGT_INT) + { + intconst = true; + intconstval = static_cast(Right)->GetValue().GetInt(); + result.Konst = true; + result.RegType = REGT_INT; + } + else + { + result = Right->Emit(build); + } assert(result.RegType <= REGT_TYPE); if (pointer.Target) { if (result.Konst) { - build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum); + if (intconst) build->EmitLoadInt(pointer.RegNum, intconstval); + else build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum); } else { @@ -2323,7 +2338,8 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) if (result.Konst) { ExpEmit temp(build, result.RegType); - build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum); + if (intconst) build->EmitLoadInt(temp.RegNum, intconstval); + else build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum); result.Free(build); result = temp; } From fb7a8fb553a185c0cfca20fe2487025de2b66ae9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 00:56:54 +0100 Subject: [PATCH 443/471] - branch optimization for for loops. --- src/scripting/codegeneration/codegen.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 1629c8135c..7900f7262d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -9279,7 +9279,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) size_t loopstart, loopend; size_t codestart; - size_t jumpspot; + TArray yes, no; // 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) @@ -9292,12 +9292,10 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) 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); + Condition->EmitCompare(build, false, yes, no); } + build->BackpatchListToHere(yes); // Execute the loop's content. if (Code != nullptr) { @@ -9316,10 +9314,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) // End of loop. loopend = build->GetAddress(); - if (Condition != nullptr) - { - build->Backpatch(jumpspot, loopend); - } + build->BackpatchListToHere(no); Backpatch(build, loopstart, loopend); return ExpEmit(); From 4dd22d74dd672ff2adf5465757527b3af6da1b99 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 01:16:32 +0100 Subject: [PATCH 444/471] - partial optimization of chained comparisons. --- src/scripting/codegeneration/codegen.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7900f7262d..20c98acbec 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4176,23 +4176,19 @@ void FxBinaryLogical::Flatten() ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) { - TArray patchspots; + TArray yes, no; + bool invert = Operator == TK_OrOr; - 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)); + list[i]->EmitCompare(build, invert, yes, no); } + build->BackpatchListToHere(yes); ExpEmit to(build, REGT_INT); build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 1 : 0); build->Emit(OP_JMP, 1); + build->BackpatchListToHere(no); auto ctarget = build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1); - for (auto addr : patchspots) build->Backpatch(addr, ctarget); list.DeleteAndClear(); list.ShrinkToFit(); return to; @@ -4685,7 +4681,13 @@ FxExpression *FxAbs::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(val, ctx); - + if (val->ValueType == TypeBool) // abs of a boolean is always the same as the operand + { + auto v = val; + val = nullptr; + delete this; + return v; + } if (!val->IsNumeric()) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); From 05cc3dde72fd135db1fd9f74e2527a58dfa5d4ab Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 01:33:18 +0100 Subject: [PATCH 445/471] - fixed: Dehacked did not copy the defaults for DehackedPickup replacements anymore. --- src/d_dehacked.cpp | 1 + src/p_mobj.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 6f9687aeac..ed2310d459 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3020,6 +3020,7 @@ 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/p_mobj.cpp b/src/p_mobj.cpp index 5a37561c94..26e362d8f7 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7913,5 +7913,6 @@ void PrintMiscActorInfo(AActor *query) query->floorz, query->ceilingz); Printf("\nSpeed= %f, velocity= x:%f, y:%f, z:%f, combined:%f.\n", query->Speed, query->Vel.X, query->Vel.Y, query->Vel.Z, query->Vel.Length()); + Printf("Scale: x:%f, y:%f\n", query->Scale.X, query->Scale.Y); } } From 82c26706171f411a4e75c6a1f8c00ab1b39133f3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 11:42:33 +0100 Subject: [PATCH 446/471] - removed redundant DoDropItem function. A_DropItem already exists and can be used instead. --- wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/strife/strifestuff.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index bd00ffc98f..ee4c92adde 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -303,7 +303,6 @@ class Actor : Thinker native native void DaggerAlert(Actor target); native void ClearBounce(); native TerrainDef GetFloorTerrain(); - native Inventory DoDropItem(Class type, int dropamount, int chance); native bool CheckLocalView(int consoleplayer); native void ExplodeMissile(line lin = null, Actor target = null); diff --git a/wadsrc/static/zscript/strife/strifestuff.txt b/wadsrc/static/zscript/strife/strifestuff.txt index 20bee61d01..37918aa964 100644 --- a/wadsrc/static/zscript/strife/strifestuff.txt +++ b/wadsrc/static/zscript/strife/strifestuff.txt @@ -1864,7 +1864,7 @@ class PowerCoupling : Actor players[i].mo.GiveInventoryType ("QuestItem6"); S_Sound ("svox/voc13", CHAN_VOICE); players[i].SetLogNumber (13); - DoDropItem ("BrokenPowerCoupling", -1, 256); + A_DropItem ("BrokenPowerCoupling", -1, 256); Destroy (); } From f9441cd9d98684d2db56ab8082f3ce9de02c541e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 12:06:49 +0100 Subject: [PATCH 447/471] - added null pointer validation to any relevant exported function. In most cases null pointers were already being treated as 'do nothing', but there's several places where this can make the code silently fail so in these cases a VM exception will be raised, once the VM's exception handling has been repaired to provide useful diagnostics. (Right now all it does is catch the exception, print a useless message and return to the caller as if nothing has happened.) --- src/g_inventory/a_pickups.cpp | 10 +- src/g_shared/a_morph.cpp | 2 +- src/g_shared/a_specialspot.cpp | 3 +- src/p_actionfunctions.cpp | 2 +- src/p_ceiling.cpp | 2 +- src/p_enemy.cpp | 16 +-- src/p_floor.cpp | 2 +- src/p_interaction.cpp | 2 +- src/p_map.cpp | 3 +- src/p_maputl.cpp | 2 +- src/p_mobj.cpp | 162 ++++++++++++----------- src/p_pspr.cpp | 58 ++++---- src/p_sight.cpp | 2 +- src/p_states.cpp | 13 +- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/vm/vm.h | 11 ++ src/scripting/vm/vmexec.cpp | 4 + 17 files changed, 160 insertions(+), 136 deletions(-) diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 51072023b6..bdd1b6dc66 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -261,7 +261,7 @@ bool AInventory::SpecialDropAction (AActor *dropper) DEFINE_ACTION_FUNCTION(AInventory, SpecialDropAction) { PARAM_SELF_PROLOGUE(AInventory); - PARAM_OBJECT(dropper, AActor); + PARAM_OBJECT_NOT_NULL(dropper, AActor); ACTION_RETURN_BOOL(self->SpecialDropAction(dropper)); } @@ -429,7 +429,7 @@ bool AInventory::HandlePickup (AInventory *item) DEFINE_ACTION_FUNCTION(AInventory, HandlePickup) { PARAM_SELF_PROLOGUE(AInventory); - PARAM_OBJECT(item, AInventory); + PARAM_OBJECT_NOT_NULL(item, AInventory); ACTION_RETURN_BOOL(self->HandlePickup(item)); } @@ -1416,7 +1416,7 @@ bool AInventory::TryPickup (AActor *&toucher) DEFINE_ACTION_FUNCTION(AInventory, TryPickup) { PARAM_SELF_PROLOGUE(AInventory); - PARAM_POINTER(toucher, AActor*); + PARAM_POINTER_NOT_NULL(toucher, AActor*); ACTION_RETURN_BOOL(self->TryPickup(*toucher)); } @@ -1434,7 +1434,7 @@ bool AInventory::TryPickupRestricted (AActor *&toucher) DEFINE_ACTION_FUNCTION(AInventory, TryPickupRestricted) { PARAM_SELF_PROLOGUE(AInventory); - PARAM_POINTER(toucher, AActor*); + PARAM_POINTER_NOT_NULL(toucher, AActor*); ACTION_RETURN_BOOL(self->TryPickupRestricted(*toucher)); } @@ -1613,7 +1613,7 @@ void AInventory::AttachToOwner (AActor *other) DEFINE_ACTION_FUNCTION(AInventory, AttachToOwner) { PARAM_SELF_PROLOGUE(AInventory); - PARAM_OBJECT(other, AActor); + PARAM_OBJECT_NOT_NULL(other, AActor); self->AttachToOwner(other); return 0; } diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 03f76c0c05..136c096a31 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -363,7 +363,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, DEFINE_ACTION_FUNCTION(_PlayerInfo, UndoPlayerMorph) { PARAM_SELF_STRUCT_PROLOGUE(player_t); - PARAM_POINTER(player, player_t); + PARAM_POINTER_NOT_NULL(player, player_t); PARAM_INT_DEF(unmorphflag); PARAM_BOOL_DEF(force); ACTION_RETURN_BOOL(P_UndoPlayerMorph(self, player, unmorphflag, force)); diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 026185d07a..b5debf2df4 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -265,6 +265,7 @@ DEFINE_ACTION_FUNCTION(DSpotState, GetSpotState) FSpotList *DSpotState::FindSpotList(PClassActor *type) { + if (type == nullptr) return nullptr; for(unsigned i = 0; i < SpotLists.Size(); i++) { if (SpotLists[i].Type == type) return &SpotLists[i]; @@ -404,7 +405,7 @@ void ASpecialSpot::Destroy() DEFINE_ACTION_FUNCTION(AActor, A_SpawnSingleItem) { PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS (cls, AActor); + PARAM_CLASS_NOT_NULL(cls, AActor); PARAM_INT_DEF (fail_sp) PARAM_INT_DEF (fail_co) PARAM_INT_DEF (fail_dm) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 477ed37f24..115bc1f54e 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -247,7 +247,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckClass) PARAM_BOOL_DEF (match_superclass); self = COPY_AAPTR(self, pick_pointer); - if (self == NULL) + if (self == nullptr || checktype == nullptr) { ret->SetInt(false); } diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 932b4c6493..4da81db46d 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -461,7 +461,7 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t DEFINE_ACTION_FUNCTION(DCeiling, CreateCeiling) { PARAM_PROLOGUE; - PARAM_POINTER(sec, sector_t); + PARAM_POINTER_NOT_NULL(sec, sector_t); PARAM_INT(type); PARAM_POINTER(ln, line_t); PARAM_FLOAT(speed); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 751f92a30e..beaa1548fc 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1307,6 +1307,11 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams double mindist; DAngle fov; + if (other == nullptr) + { + return false; + } + if (params != NULL) { maxdist = params->maxDist; @@ -3095,7 +3100,7 @@ void A_FaceTarget(AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_Face) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(faceto, AActor) + PARAM_OBJECT_NOT_NULL(faceto, AActor) PARAM_ANGLE_DEF(max_turn) PARAM_ANGLE_DEF(max_pitch) PARAM_ANGLE_DEF(ang_offset) @@ -3323,15 +3328,6 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c return NULL; } -DEFINE_ACTION_FUNCTION(AActor, DoDropItem) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS(cls, AActor); - PARAM_INT(amt); - PARAM_INT(chance); - ACTION_RETURN_OBJECT(P_DropItem(self, cls, amt, chance)); -} - //============================================================================ // // P_TossItem diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 8fd5ad038c..4b1f243d5b 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -495,7 +495,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line, DEFINE_ACTION_FUNCTION(DFloor, CreateFloor) { PARAM_PROLOGUE; - PARAM_POINTER(sec, sector_t); + PARAM_POINTER_NOT_NULL(sec, sector_t); PARAM_INT(floortype); PARAM_POINTER(ln, line_t); PARAM_FLOAT(speed); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index e6729096cf..9aa178e64d 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1639,7 +1639,7 @@ void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage DEFINE_ACTION_FUNCTION(AActor, PoisonMobj) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(inflictor, AActor); + PARAM_OBJECT_NOT_NULL(inflictor, AActor); PARAM_OBJECT(source, AActor); PARAM_INT(damage); PARAM_INT(duration); diff --git a/src/p_map.cpp b/src/p_map.cpp index 11036d1716..f25c336126 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4513,6 +4513,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack) PARAM_POINTER_DEF(victim, FTranslatedLineTarget); int acdmg; + if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from. 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; @@ -4716,7 +4717,7 @@ DEFINE_ACTION_FUNCTION(_FTranslatedLineTarget, TraceBleed) { PARAM_SELF_STRUCT_PROLOGUE(FTranslatedLineTarget); PARAM_INT(damage); - PARAM_OBJECT(missile, AActor); + PARAM_OBJECT_NOT_NULL(missile, AActor); P_TraceBleed(damage, self, missile); return 0; diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index aa29a1c5e7..31b4125988 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1193,7 +1193,7 @@ IMPLEMENT_CLASS(DBlockThingsIterator, false, false); DEFINE_ACTION_FUNCTION(DBlockThingsIterator, Create) { PARAM_PROLOGUE; - PARAM_OBJECT(origin, AActor); + PARAM_OBJECT_NOT_NULL(origin, AActor); PARAM_FLOAT_DEF(radius); PARAM_BOOL_DEF(ignore); ACTION_RETURN_OBJECT(new DBlockThingsIterator(origin, radius, ignore)); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 26e362d8f7..88653fca9a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -751,7 +751,7 @@ void AActor::AddInventory (AInventory *item) DEFINE_ACTION_FUNCTION(AActor, AddInventory) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(item, AInventory); + PARAM_OBJECT_NOT_NULL(item, AInventory); self->AddInventory(item); return 0; } @@ -819,7 +819,7 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat) DEFINE_ACTION_FUNCTION(AActor, Inventory) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(item, AInventory); + PARAM_OBJECT_NOT_NULL(item, AInventory); ACTION_RETURN_BOOL(self->UseInventory(item)); } @@ -854,7 +854,7 @@ void AActor::RemoveInventory(AInventory *item) DEFINE_ACTION_FUNCTION(AActor, RemoveInventory) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(item, AInventory); + PARAM_OBJECT_NOT_NULL(item, AInventory); self->RemoveInventory(item); return 0; } @@ -1009,7 +1009,7 @@ bool AActor::UseInventory (AInventory *item) DEFINE_ACTION_FUNCTION(AActor, UseInventory) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(item, AInventory); + PARAM_OBJECT_NOT_NULL(item, AInventory); ACTION_RETURN_BOOL(self->UseInventory(item)); } @@ -1042,7 +1042,7 @@ AInventory *AActor::DropInventory (AInventory *item) DEFINE_ACTION_FUNCTION(AActor, DropInventory) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(item, AInventory); + PARAM_OBJECT_NOT_NULL(item, AInventory); ACTION_RETURN_OBJECT(self->DropInventory(item)); } @@ -1263,7 +1263,7 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealt DEFINE_ACTION_FUNCTION(AActor, CopyFriendliness) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(other, AActor); + PARAM_OBJECT_NOT_NULL(other, AActor); PARAM_BOOL_DEF(changetarget); PARAM_BOOL_DEF(resethealth); self->CopyFriendliness(other, changetarget, resethealth); @@ -1486,7 +1486,7 @@ void AActor::Touch (AActor *toucher) DEFINE_ACTION_FUNCTION(AActor, Touch) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(toucher, AActor); + PARAM_OBJECT_NOT_NULL(toucher, AActor); self->Touch(toucher); return 0; } @@ -2000,7 +2000,7 @@ bool AActor::CanSeek(AActor *target) const DEFINE_ACTION_FUNCTION(AActor, CanSeek) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(target, AActor); + PARAM_OBJECT_NOT_NULL(target, AActor); ACTION_RETURN_BOOL(self->CanSeek(target)); } @@ -4669,7 +4669,7 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a DEFINE_ACTION_FUNCTION(AActor, Spawn) { PARAM_PROLOGUE; - PARAM_CLASS(type, AActor); + PARAM_CLASS_NOT_NULL(type, AActor); PARAM_FLOAT_DEF(x); PARAM_FLOAT_DEF(y); PARAM_FLOAT_DEF(z); @@ -5656,6 +5656,8 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos1 AActor *puff; DVector3 pos = pos1; + if (pufftype == nullptr) return nullptr; + if (!(flags & PF_NORANDOMZ)) pos.Z += pr_spawnpuff.Random2() / 64.; puff = Spawn(pufftype, pos, ALLOW_REPLACE); if (puff == NULL) return NULL; @@ -6163,7 +6165,7 @@ foundone: DEFINE_ACTION_FUNCTION(AActor, HitWater) { PARAM_SELF_PROLOGUE(AActor); - PARAM_POINTER(sec, sector_t); + PARAM_POINTER_NOT_NULL(sec, sector_t); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); @@ -6383,7 +6385,7 @@ void P_PlaySpawnSound(AActor *missile, AActor *spawner) DEFINE_ACTION_FUNCTION(AActor, PlaySpawnSound) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(missile, AActor); + PARAM_OBJECT_NOT_NULL(missile, AActor); P_PlaySpawnSound(missile, self); return 0; } @@ -6415,47 +6417,11 @@ DEFINE_ACTION_FUNCTION(AActor, GetDefaultSpeed) // //--------------------------------------------------------------------------- -AActor *P_SpawnMissile (AActor *source, AActor *dest, PClassActor *type, AActor *owner) -{ - if (source == NULL) - { - return NULL; - } - 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) - { - return NULL; - } - 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) + if (source == nullptr || type == nullptr) { - return NULL; + return nullptr; } if (dest == NULL) @@ -6530,19 +6496,56 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissileXYZ) PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); - PARAM_OBJECT(dest, AActor); + PARAM_OBJECT_NOT_NULL(dest, AActor); PARAM_CLASS(type, AActor); PARAM_BOOL_DEF(check); PARAM_OBJECT_DEF(owner, AActor); ACTION_RETURN_OBJECT(P_SpawnMissileXYZ(DVector3(x,y,z), self, dest, type, check, owner)); } +AActor *P_SpawnMissile(AActor *source, AActor *dest, PClassActor *type, AActor *owner) +{ + if (source == nullptr) + { + return nullptr; + } + return P_SpawnMissileXYZ(source->PosPlusZ(32 + source->GetBobOffset()), source, dest, type, true, owner); +} + +DEFINE_ACTION_FUNCTION(AActor, SpawnMissile) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT_NOT_NULL(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 == nullptr) + { + return nullptr; + } + return P_SpawnMissileXYZ(source->PosAtZ(z), source, dest, type); +} + +DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(z); + PARAM_OBJECT_NOT_NULL(dest, AActor); + PARAM_CLASS(type, AActor); + ACTION_RETURN_OBJECT(P_SpawnMissileZ(self, z, dest, type)); +} + + AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassActor *type) { - if (source == NULL) + if (source == nullptr || type == nullptr) { - return NULL; + return nullptr; } AActor *th = Spawn (type, source->PosPlusZ(32.), ALLOW_REPLACE); @@ -6568,7 +6571,7 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct DEFINE_ACTION_FUNCTION(AActor, OldSpawnMissile) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(dest, AActor); + PARAM_OBJECT_NOT_NULL(dest, AActor); PARAM_CLASS(type, AActor); PARAM_OBJECT_DEF(owner, AActor); ACTION_RETURN_OBJECT(P_OldSpawnMissile(self, owner, dest, type)); @@ -6586,7 +6589,7 @@ DEFINE_ACTION_FUNCTION(AActor, OldSpawnMissile) AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type, DAngle angle, double vz) { - if (source == NULL) + if (source == nullptr || type == nullptr) { return NULL; } @@ -6595,14 +6598,18 @@ AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type, DAngle angle, do AActor *P_SpawnMissileAngleZ (AActor *source, double z, PClassActor *type, DAngle angle, double vz) { + if (type == nullptr) + { + return nullptr; + } return P_SpawnMissileAngleZSpeed (source, z, type, angle, vz, GetDefaultSpeed (type)); } AActor *P_SpawnMissileZAimed (AActor *source, double z, AActor *dest, PClassActor *type) { - if (source == NULL) + if (source == nullptr || type == nullptr) { - return NULL; + return nullptr; } DAngle an; double dist; @@ -6626,7 +6633,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZAimed) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(z); - PARAM_OBJECT(dest, AActor); + PARAM_OBJECT_NOT_NULL(dest, AActor); PARAM_CLASS(type, AActor); ACTION_RETURN_OBJECT(P_SpawnMissileZAimed(self, z, dest, type)); } @@ -6643,9 +6650,9 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnMissileZAimed) AActor *P_SpawnMissileAngleZSpeed (AActor *source, double z, PClassActor *type, DAngle angle, double vz, double speed, AActor *owner, bool checkspawn) { - if (source == NULL) + if (source == nullptr || type == nullptr) { - return NULL; + return nullptr; } AActor *mo; @@ -6689,9 +6696,9 @@ AActor *P_SpawnSubMissile(AActor *source, PClassActor *type, AActor *target) { AActor *other = Spawn(type, source->Pos(), ALLOW_REPLACE); - if (other == NULL) + if (source == nullptr || type == nullptr) { - return NULL; + return nullptr; } other->target = target; @@ -6723,7 +6730,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnSubMissile) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(cls, AActor); - PARAM_OBJECT(target, AActor); + PARAM_OBJECT_NOT_NULL(target, AActor); ACTION_RETURN_OBJECT(P_SpawnSubMissile(self, cls, target)); } /* @@ -6753,6 +6760,11 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z, PClassActor *type, DAngle angle, FTranslatedLineTarget *pLineTarget, AActor **pMissileActor, bool nofreeaim, bool noautoaim, int aimflags) { + if (source == nullptr || type == nullptr) + { + return nullptr; + } + static const double angdiff[3] = { -5.625, 5.625, 0 }; DAngle an = angle; DAngle pitch; @@ -6760,10 +6772,6 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z, AActor *defaultobject = GetDefaultByType(type); DAngle vrange = nofreeaim ? 35. : 0.; - if (source == NULL) - { - return NULL; - } if (!pLineTarget) pLineTarget = &scratch; if (source->player && source->player->ReadyWeapon && ((source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM) || noautoaim)) { @@ -6910,7 +6918,7 @@ bool AActor::IsTeammate (AActor *other) DEFINE_ACTION_FUNCTION(AActor, isTeammate) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(other, AActor); + PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_BOOL(self->IsTeammate(other)); } @@ -6982,7 +6990,7 @@ bool AActor::IsFriend (AActor *other) DEFINE_ACTION_FUNCTION(AActor, isFriend) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(other, AActor); + PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_BOOL(self->IsFriend(other)); } @@ -7019,7 +7027,7 @@ bool AActor::IsHostile (AActor *other) DEFINE_ACTION_FUNCTION(AActor, isHostile) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(other, AActor); + PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_BOOL(self->IsHostile(other)); } @@ -7058,7 +7066,7 @@ int AActor::DoSpecialDamage (AActor *target, int damage, FName damagetype) DEFINE_ACTION_FUNCTION(AActor, DoSpecialDamage) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(target, AActor); + PARAM_OBJECT_NOT_NULL(target, AActor); PARAM_INT(damage); PARAM_NAME(damagetype); ACTION_RETURN_INT(self->DoSpecialDamage(target, damage, damagetype)); @@ -7580,14 +7588,14 @@ DEFINE_ACTION_FUNCTION(AActor, absangle) // should this be global? DEFINE_ACTION_FUNCTION(AActor, Distance2D) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(other, AActor); + PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_FLOAT(self->Distance2D(other)); } DEFINE_ACTION_FUNCTION(AActor, Distance3D) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(other, AActor); + PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_FLOAT(self->Distance3D(other)); } @@ -7620,7 +7628,7 @@ DEFINE_ACTION_FUNCTION(AActor, GetDefaultByType) { PARAM_PROLOGUE; PARAM_CLASS(cls, AActor); - ACTION_RETURN_OBJECT(GetDefaultByType(cls)); + ACTION_RETURN_OBJECT(cls == nullptr? nullptr : GetDefaultByType(cls)); } DEFINE_ACTION_FUNCTION(AActor, GetBobOffset) @@ -7692,7 +7700,7 @@ DEFINE_ACTION_FUNCTION(AActor, Thrust) DEFINE_ACTION_FUNCTION(AActor, AngleTo) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(targ, AActor); + PARAM_OBJECT_NOT_NULL(targ, AActor); PARAM_BOOL_DEF(absolute); ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees); } @@ -7717,7 +7725,7 @@ DEFINE_ACTION_FUNCTION(AActor, RotateVector) DEFINE_ACTION_FUNCTION(AActor, DistanceBySpeed) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(targ, AActor); + PARAM_OBJECT_NOT_NULL(targ, AActor); PARAM_FLOAT(speed); ACTION_RETURN_FLOAT(self->DistanceBySpeed(targ, speed)); } @@ -7745,14 +7753,14 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2Angle) DEFINE_ACTION_FUNCTION(AActor, Vec3To) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(t, AActor) + PARAM_OBJECT_NOT_NULL(t, AActor) ACTION_RETURN_VEC3(self->Vec3To(t)); } DEFINE_ACTION_FUNCTION(AActor, Vec2To) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(t, AActor) + PARAM_OBJECT_NOT_NULL(t, AActor) ACTION_RETURN_VEC2(self->Vec2To(t)); } diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 610ade35a2..733741cb29 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1605,38 +1605,40 @@ void player_t::DestroyPSprites() void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int index) { - - PClassActor *cls = weapon->GetClass(); - while (cls != RUNTIME_CLASS(AWeapon)) + if (flashstate != nullptr) { - if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates) + PClassActor *cls = weapon->GetClass(); + while (cls != RUNTIME_CLASS(AWeapon)) { - // The flash state belongs to this class. - // Now let's check if the actually wanted state does also - if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates) + if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates) { - // we're ok so set the state - P_SetPsprite(player, PSP_FLASH, flashstate + index, true); - return; - } - else - { - // oh, no! The state is beyond the end of the state table so use the original flash state. - P_SetPsprite(player, PSP_FLASH, flashstate, true); - return; + // The flash state belongs to this class. + // Now let's check if the actually wanted state does also + if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates) + { + // we're ok so set the state + P_SetPsprite(player, PSP_FLASH, flashstate + index, true); + return; + } + else + { + // oh, no! The state is beyond the end of the state table so use the original flash state. + P_SetPsprite(player, PSP_FLASH, flashstate, true); + return; + } } + // try again with parent class + cls = static_cast(cls->ParentClass); + } + // if we get here the state doesn't seem to belong to any class in the inheritance chain + // This can happen with Dehacked if the flash states are remapped. + // The only way to check this would be to go through all Dehacked modifiable actors, convert + // their states into a single flat array and find the correct one. + // Rather than that, just check to make sure it belongs to something. + if (FState::StaticFindStateOwner(flashstate + index) == NULL) + { // Invalid state. With no index offset, it should at least be valid. + index = 0; } - // try again with parent class - cls = static_cast(cls->ParentClass); - } - // if we get here the state doesn't seem to belong to any class in the inheritance chain - // This can happen with Dehacked if the flash states are remapped. - // The only way to check this would be to go through all Dehacked modifiable actors, convert - // their states into a single flat array and find the correct one. - // Rather than that, just check to make sure it belongs to something. - if (FState::StaticFindStateOwner(flashstate + index) == NULL) - { // Invalid state. With no index offset, it should at least be valid. - index = 0; } P_SetPsprite(player, PSP_FLASH, flashstate + index, true); } @@ -1644,7 +1646,7 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i DEFINE_ACTION_FUNCTION(_PlayerInfo, SetSafeFlash) { PARAM_SELF_STRUCT_PROLOGUE(player_t); - PARAM_OBJECT(weapon, AWeapon); + PARAM_OBJECT_NOT_NULL(weapon, AWeapon); PARAM_POINTER(state, FState); PARAM_INT(index); P_SetSafeFlash(weapon, self, state, index); diff --git a/src/p_sight.cpp b/src/p_sight.cpp index 319d5b3ecc..21aa1bbe3d 100644 --- a/src/p_sight.cpp +++ b/src/p_sight.cpp @@ -908,7 +908,7 @@ done: DEFINE_ACTION_FUNCTION(AActor, CheckSight) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(target, AActor); + PARAM_OBJECT_NOT_NULL(target, AActor); PARAM_INT_DEF(flags); ACTION_RETURN_BOOL(P_CheckSight(self, target, flags)); } diff --git a/src/p_states.cpp b/src/p_states.cpp index 7daaa5e41c..87a1bae2fe 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -1083,11 +1083,12 @@ DEFINE_ACTION_FUNCTION(FState, DistanceTo) { PARAM_SELF_STRUCT_PROLOGUE(FState); PARAM_POINTER(other, FState); - - // Safely calculate the distance between two states. - auto o1 = FState::StaticFindStateOwner(self); - int retv; - if (other < o1->OwnedStates || other >= o1->OwnedStates + o1->NumOwnedStates) retv = INT_MIN; - else retv = int(other - self); + int retv = INT_MIN; + if (other != nullptr) + { + // Safely calculate the distance between two states. + auto o1 = FState::StaticFindStateOwner(self); + if (other >= o1->OwnedStates && other < o1->OwnedStates + o1->NumOwnedStates) retv = int(other - self); + } ACTION_RETURN_INT(retv); } diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 20c98acbec..3a2dc6034f 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -9697,7 +9697,7 @@ int BuiltinClassCast(VMValue *param, TArray &defaultparam, int numparam PARAM_PROLOGUE; PARAM_CLASS(from, DObject); PARAM_CLASS(to, DObject); - ACTION_RETURN_OBJECT(from->IsDescendantOf(to) ? from : nullptr); + ACTION_RETURN_OBJECT(from && to && from->IsDescendantOf(to) ? from : nullptr); } ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 0ccde006f0..d105d396cc 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -951,6 +951,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction // Use these to collect the parameters in a native function. // variable name at position

+void NullParam(const char *varname); + +#define PARAM_NULLCHECK(ptr, var) (ptr == nullptr? NullParam(#var), ptr : ptr) // For required parameters. #define PARAM_INT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); int x = param[p].i; @@ -966,6 +969,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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))); +#define PARAM_POINTER_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x); +#define PARAM_OBJECT_NOT_NULL_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_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type))); +#define PARAM_CLASS_NOT_NULL_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_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base))); #define PARAM_EXISTS(p) ((p) < numparam) #define ASSERTINT(p) assert((p).Type == REGT_INT) @@ -988,6 +994,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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; } +#define PARAM_CLASS_DEF_NOT_NULL_AT(p,x,t) t::MetaClass *x; if (PARAM_EXISTS(p)) { ASSERTOBJECT(param[p]); x = (t::MetaClass*)PARAM_NULLCHECK(param[p].a, #x); } else { ASSERTOBJECT(defaultparam[p]); x = (t::MetaClass*)PARAM_NULLCHECK(defaultparam[p].a, #x); } // The above, but with an automatically increasing position index. #define PARAM_PROLOGUE int paramnum = -1; @@ -1005,6 +1012,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #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_POINTER_NOT_NULL(x,type) ++paramnum; PARAM_POINTER_NOT_NULL_AT(paramnum,x,type) +#define PARAM_OBJECT_NOT_NULL(x,type) ++paramnum; PARAM_OBJECT_NOT_NULL_AT(paramnum,x,type) +#define PARAM_CLASS_NOT_NULL(x,base) ++paramnum; PARAM_CLASS_NOT_NULL_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) @@ -1019,6 +1029,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_POINTER_DEF(x,type) ++paramnum; PARAM_POINTER_DEF_AT(paramnum,x,type) #define PARAM_OBJECT_DEF(x,type) ++paramnum; PARAM_OBJECT_DEF_AT(paramnum,x,type) #define PARAM_CLASS_DEF(x,base) ++paramnum; PARAM_CLASS_DEF_AT(paramnum,x,base) +#define PARAM_CLASS_DEF_NOT_NULL(x,base) ++paramnum; PARAM_CLASS_DEF_NOT_NULL_AT(paramnum,x,base) typedef int(*actionf_p)(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/ diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index f51038f365..183cc728c3 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -228,3 +228,7 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) } } } + +void NullParam(const char *varname) +{ +} \ No newline at end of file From 967f6c0269e090cc42468c8c31f20b27895553c5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 16:56:50 +0100 Subject: [PATCH 448/471] - use a separate exception type for reporting errors from FraggleScript. CRecoverableError is used in other parts as well and it might create interference. --- src/fragglescript/t_func.cpp | 4 ++-- src/fragglescript/t_parse.cpp | 16 ++++++++++++++-- src/fragglescript/t_script.cpp | 2 +- src/fragglescript/t_script.h | 10 ++++++++++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 6b0059981e..7cd599b11d 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -2014,13 +2014,13 @@ void FParser::SF_CeilingTexture(void) void FParser::SF_ChangeHubLevel(void) { - I_Error("FS hub system permanently disabled\n"); + script_error("FS hub system permanently disabled\n"); } // for start map: start new game on a particular skill void FParser::SF_StartSkill(void) { - I_Error("startskill is not supported by this implementation!\n"); + script_error("startskill is not supported by this implementation!\n"); } //========================================================================== diff --git a/src/fragglescript/t_parse.cpp b/src/fragglescript/t_parse.cpp index 0b2f27680e..28330e9e98 100644 --- a/src/fragglescript/t_parse.cpp +++ b/src/fragglescript/t_parse.cpp @@ -113,7 +113,7 @@ void FParser::NextToken() } if(!Section) { - I_Error("section not found!\n"); + script_error("section not found!\n"); return; } } @@ -708,6 +708,18 @@ void FParser::EvaluateExpression(svalue_t &result, int start, int stop) // //========================================================================== +void FS_Error(const char *error, ...) +{ + va_list argptr; + char errortext[MAX_ERRORTEXT]; + + va_start(argptr, error); + myvsnprintf(errortext, MAX_ERRORTEXT, error, argptr); + va_end(argptr); + throw CFraggleScriptError(errortext); +} + + void FParser::ErrorMessage(FString msg) { int linenum = 0; @@ -721,7 +733,7 @@ void FParser::ErrorMessage(FString msg) } //lineinfo.Format("Script %d, line %d: ", Script->scriptnum, linenum); - I_Error("Script %d, line %d: %s", Script->scriptnum, linenum, msg.GetChars()); + FS_Error("Script %d, line %d: %s", Script->scriptnum, linenum, msg.GetChars()); } //========================================================================== diff --git a/src/fragglescript/t_script.cpp b/src/fragglescript/t_script.cpp index b852607b3c..81b2ce21ec 100644 --- a/src/fragglescript/t_script.cpp +++ b/src/fragglescript/t_script.cpp @@ -251,7 +251,7 @@ void DFsScript::ParseScript(char *position) FParser parse(this); parse.Run(position, data, data + len); } - catch (CRecoverableError &err) + catch (CFraggleScriptError &err) { Printf ("%s\n", err.GetMessage()); } diff --git a/src/fragglescript/t_script.h b/src/fragglescript/t_script.h index 50829e0008..f0409a3f0b 100644 --- a/src/fragglescript/t_script.h +++ b/src/fragglescript/t_script.h @@ -41,12 +41,22 @@ #include "p_lnspec.h" #include "m_fixed.h" #include "actor.h" +#include "doomerrors.h" #ifdef _MSC_VER // This pragma saves 8kb of wasted code. #pragma pointers_to_members( full_generality, single_inheritance ) #endif + +class CFraggleScriptError : public CDoomError +{ +public: + CFraggleScriptError() : CDoomError() {} + CFraggleScriptError(const char *message) : CDoomError(message) {} +}; + + class DRunningScript; From 1e01e6e4df263992b7c5550dcd88fefa833e02ca Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 17:36:29 +0100 Subject: [PATCH 449/471] - record all line numbers during function generation. This is useful for error reporting and eventually debugging. - throw a useful exception when a VM abort occurs, the simple enum was incapable of reporting anything more than the barest minimum, which at least for array index out of bounds errors was insufficient. The current exception mechanism is still insufficient. It really has to report a proper crash location and print a stack trace to the maximum extent possible. Instead it just prints a message and happily goes on. This is not a good solution. --- src/doomerrors.h | 8 +++- src/sc_man.cpp | 2 +- src/scripting/codegeneration/codegen.cpp | 34 +++++++++----- src/scripting/codegeneration/codegen.h | 1 + src/scripting/vm/vm.h | 9 ++++ src/scripting/vm/vmbuilder.cpp | 33 +++++++++++++- src/scripting/vm/vmbuilder.h | 12 +++++ src/scripting/vm/vmexec.cpp | 57 ++++++++++++++++++++++-- src/scripting/vm/vmexec.h | 49 +++++++++----------- src/scripting/vm/vmframe.cpp | 32 +------------ 10 files changed, 159 insertions(+), 78 deletions(-) diff --git a/src/doomerrors.h b/src/doomerrors.h index f4b0c9566e..c389c6b052 100644 --- a/src/doomerrors.h +++ b/src/doomerrors.h @@ -56,6 +56,12 @@ public: strncpy (m_Message, message, MAX_ERRORTEXT-1); m_Message[MAX_ERRORTEXT-1] = '\0'; } + void AppendMessage(const char *message) + { + size_t len = strlen(m_Message); + strncpy(m_Message + len, message, MAX_ERRORTEXT - 1 - len); + m_Message[MAX_ERRORTEXT - 1] = '\0'; + } const char *GetMessage (void) const { if (m_Message[0] != '\0') @@ -64,7 +70,7 @@ public: return NULL; } -private: +protected: char m_Message[MAX_ERRORTEXT]; }; diff --git a/src/sc_man.cpp b/src/sc_man.cpp index 254caed625..ccfb01ac52 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -1007,7 +1007,7 @@ void FScanner::CheckOpen() //========================================================================== int FScriptPosition::ErrorCounter; int FScriptPosition::WarnCounter; -bool FScriptPosition::StrictErrors; // makes all OPTERRPR messages real errors. +bool FScriptPosition::StrictErrors; // makes all OPTERROR messages real errors. FScriptPosition::FScriptPosition(const FScriptPosition &other) { diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 3a2dc6034f..6a0f840a56 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -288,6 +288,21 @@ ExpEmit FxExpression::Emit (VMFunctionBuilder *build) } +//========================================================================== +// +// Emits a statement and records its position in the source. +// +//========================================================================== + +void FxExpression::EmitStatement(VMFunctionBuilder *build) +{ + build->BeginStatement(this); + ExpEmit exp = Emit(build); + exp.Free(build); + build->EndStatement(); +} + + //========================================================================== // // @@ -8519,9 +8534,7 @@ 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); + Expressions[i]->EmitStatement(build); } return ExpEmit(); } @@ -8817,7 +8830,7 @@ ExpEmit FxSwitchStatement::Emit(VMFunctionBuilder *build) break; default: - line->Emit(build); + line->EmitStatement(build); break; } } @@ -8979,13 +8992,13 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) if (WhenTrue != nullptr) { build->BackpatchListToHere(yes); - WhenTrue->Emit(build); + WhenTrue->EmitStatement(build); } if (WhenFalse != nullptr) { if (!WhenTrue->CheckReturn()) jumpspot = build->Emit(OP_JMP, 0); // no need to emit a jump if the block returns. build->BackpatchListToHere(no); - WhenFalse->Emit(build); + WhenFalse->EmitStatement(build); if (jumpspot != ~0u) build->BackpatchToHere(jumpspot); if (WhenTrue == nullptr) build->BackpatchListToHere(yes); } @@ -9114,8 +9127,7 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) // Execute the loop's content. if (Code != nullptr) { - ExpEmit code = Code->Emit(build); - code.Free(build); + Code->EmitStatement(build); } // Loop back. @@ -9190,8 +9202,7 @@ ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) codestart = build->GetAddress(); if (Code != nullptr) { - ExpEmit code = Code->Emit(build); - code.Free(build); + Code->EmitStatement(build); } // Evaluate the condition and execute/break out of the loop. @@ -9301,8 +9312,7 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) // Execute the loop's content. if (Code != nullptr) { - ExpEmit code = Code->Emit(build); - code.Free(build); + Code->EmitStatement(build); } // Iteration statement. diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index c5e6f4e68d..49999206d4 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -328,6 +328,7 @@ public: bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); } virtual ExpEmit Emit(VMFunctionBuilder *build); + void EmitStatement(VMFunctionBuilder *build); virtual void EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no); FScriptPosition ScriptPosition; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index d105d396cc..7285fb48d4 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -5,6 +5,7 @@ #include "autosegs.h" #include "vectors.h" #include "cmdlib.h" +#include "doomerrors.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 @@ -189,6 +190,13 @@ enum EVMAbortException X_BAD_SELF, }; +class CVMAbortException : public CDoomError +{ +public: + static FString stacktrace; + CVMAbortException(EVMAbortException reason, const char *moreinfo, ...); +}; + enum EVMOpMode { MODE_ASHIFT = 0, @@ -813,6 +821,7 @@ public: const VM_ATAG *KonstATags() const { return (VM_UBYTE *)(KonstA + NumKonstA); } VMOP *Code; + FString SourceFileName; int *KonstD; double *KonstF; FString *KonstS; diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 9b399ad609..65ec0bb26b 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -75,12 +75,38 @@ VMFunctionBuilder::~VMFunctionBuilder() //========================================================================== // -// VMFunctionBuilder :: MakeFunction +// VMFunctionBuilder :: BeginStatement // -// Creates a new VMScriptFunction out of the data passed to this class. +// Records the start of a new statement. // //========================================================================== +void VMFunctionBuilder::BeginStatement(FxExpression *stmt) +{ + // pop empty statement records. + while (LineNumbers.Size() > 0 && LineNumbers.Last().InstructionIndex == Code.Size()) LineNumbers.Pop(); + // only add a new entry if the line number differs. + if (LineNumbers.Size() == 0 || stmt->ScriptPosition.ScriptLine != LineNumbers.Last().LineNumber) + { + StatementInfo si = { (uint16_t)Code.Size(), (uint16_t)stmt->ScriptPosition.ScriptLine }; + LineNumbers.Push(si); + } + StatementStack.Push(stmt); +} + +void VMFunctionBuilder::EndStatement() +{ + // pop empty statement records. + while (LineNumbers.Size() > 0 && LineNumbers.Last().InstructionIndex == Code.Size()) LineNumbers.Pop(); + StatementStack.Pop(); + // Re-enter the previous statement. + if (StatementStack.Size() > 0) + { + StatementInfo si = { (uint16_t)Code.Size(), (uint16_t)StatementStack.Last()->ScriptPosition.ScriptLine }; + LineNumbers.Push(si); + } +} + void VMFunctionBuilder::MakeFunction(VMScriptFunction *func) { func->Alloc(Code.Size(), IntConstantList.Size(), FloatConstantList.Size(), StringConstantList.Size(), AddressConstantList.Size()); @@ -880,7 +906,10 @@ void FFunctionBuildList::Build() // Emit code try { + sfunc->SourceFileName = item.Code->ScriptPosition.FileName; // remember the file name for printing error messages if something goes wrong in the VM. + buildit.BeginStatement(item.Code); item.Code->Emit(&buildit); + buildit.EndStatement(); 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. diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 7434f3a211..d319b22805 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -4,6 +4,7 @@ #include "dobject.h" class VMFunctionBuilder; +class FxExpression; struct ExpEmit { @@ -42,6 +43,8 @@ public: VMFunctionBuilder(int numimplicits); ~VMFunctionBuilder(); + void BeginStatement(FxExpression *stmt); + void EndStatement(); void MakeFunction(VMScriptFunction *func); // Returns the constant register holding the value. @@ -97,6 +100,15 @@ private: VM_ATAG Tag; }; + struct StatementInfo + { + uint16_t InstructionIndex; + uint16_t LineNumber; + }; + + TArray LineNumbers; + TArray StatementStack; + TArray IntConstantList; TArray FloatConstantList; TArray AddressConstantList; diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 183cc728c3..1984108647 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -82,8 +82,6 @@ #define ASSERTKA(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstA) #define ASSERTKS(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstS) -#define THROW(x) throw(EVMAbortException(x)) - #define CMPJMP(test) \ if ((test) == (a & CMP_CHECK)) { \ assert(pc[1].op == OP_JMP); \ @@ -93,7 +91,7 @@ } #define GETADDR(a,o,x) \ - if (a == NULL) { THROW(x); } \ + if (a == NULL) { throw CVMAbortException(x, nullptr); } \ ptr = (VM_SBYTE *)a + o static const VM_UWORD ZapTable[16] = @@ -231,4 +229,55 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) void NullParam(const char *varname) { -} \ No newline at end of file + throw CVMAbortException(X_READ_NIL, "In function parameter %s", varname); +} + +FString CVMAbortException::stacktrace; + +CVMAbortException::CVMAbortException(EVMAbortException reason, const char *moreinfo, ...) +{ + SetMessage("VM execution aborted: "); + switch (reason) + { + case X_READ_NIL: + AppendMessage("tried to read from address zero."); + break; + + case X_WRITE_NIL: + AppendMessage("tried to write to address zero."); + break; + + case X_TOO_MANY_TRIES: + AppendMessage("too many try-catch blocks."); + break; + + case X_ARRAY_OUT_OF_BOUNDS: + AppendMessage("array access out of bounds."); + break; + + case X_DIVISION_BY_ZERO: + AppendMessage("division by zero."); + break; + + case X_BAD_SELF: + AppendMessage("invalid self pointer."); + break; + + default: + { + size_t len = strlen(m_Message); + mysnprintf(m_Message + len, MAX_ERRORTEXT - len, "Unknown reason %d", reason); + break; + } + } + if (moreinfo != nullptr) + { + AppendMessage(" "); + va_list ap; + va_start(ap, moreinfo); + size_t len = strlen(m_Message); + myvsnprintf(m_Message + len, MAX_ERRORTEXT - len, moreinfo, ap); + va_end(ap); + } +} + diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 8f79bd90bc..1e688365d6 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -704,7 +704,7 @@ begin: assert(try_depth < MAX_TRY_DEPTH); if (try_depth >= MAX_TRY_DEPTH) { - THROW(X_TOO_MANY_TRIES); + throw CVMAbortException(X_TOO_MANY_TRIES, nullptr); } assert((pc + JMPOFS(pc) + 1)->op == OP_CATCH); exception_frames[try_depth++] = pc + JMPOFS(pc) + 1; @@ -727,7 +727,7 @@ begin: } else { - THROW(BC); + throw CVMAbortException(EVMAbortException(BC), nullptr); } NEXTOP; OP(CATCH): @@ -736,13 +736,10 @@ begin: assert(0); NEXTOP; - // Fixme: This really needs to throw something more informative than a number. Printing the message here instead of passing it to the exception is not sufficient. OP(BOUND): if (reg.d[a] >= BC) { - assert(false); - Printf("Array access out of bounds: Max. index = %u, current index = %u\n", BC, reg.d[a]); - THROW(X_ARRAY_OUT_OF_BOUNDS); + throw CVMAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", BC, reg.d[a]); } NEXTOP; @@ -750,9 +747,7 @@ begin: ASSERTKD(BC); if (reg.d[a] >= konstd[BC]) { - assert(false); - Printf("Array access out of bounds: Max. index = %u, current index = %u\n", konstd[BC], reg.d[a]); - THROW(X_ARRAY_OUT_OF_BOUNDS); + throw CVMAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", konstd[BC], reg.d[a]); } NEXTOP; @@ -760,9 +755,7 @@ begin: ASSERTD(B); if (reg.d[a] >= reg.d[B]) { - assert(false); - Printf("Array access out of bounds: Max. index = %u, current index = %u\n", reg.d[B], reg.d[a]); - THROW(X_ARRAY_OUT_OF_BOUNDS); + throw CVMAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", reg.d[B], reg.d[a]); } NEXTOP; @@ -909,7 +902,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = reg.d[B] / reg.d[C]; NEXTOP; @@ -917,7 +910,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTKD(C); if (konstd[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = reg.d[B] / konstd[C]; NEXTOP; @@ -925,7 +918,7 @@ begin: ASSERTD(a); ASSERTKD(B); ASSERTD(C); if (reg.d[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = konstd[B] / reg.d[C]; NEXTOP; @@ -934,7 +927,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)reg.d[B] / (unsigned)reg.d[C]); NEXTOP; @@ -942,7 +935,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTKD(C); if (konstd[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)reg.d[B] / (unsigned)konstd[C]); NEXTOP; @@ -950,7 +943,7 @@ begin: ASSERTD(a); ASSERTKD(B); ASSERTD(C); if (reg.d[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)konstd[B] / (unsigned)reg.d[C]); NEXTOP; @@ -959,7 +952,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = reg.d[B] % reg.d[C]; NEXTOP; @@ -967,7 +960,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTKD(C); if (konstd[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = reg.d[B] % konstd[C]; NEXTOP; @@ -975,7 +968,7 @@ begin: ASSERTD(a); ASSERTKD(B); ASSERTD(C); if (reg.d[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = konstd[B] % reg.d[C]; NEXTOP; @@ -984,7 +977,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)reg.d[B] % (unsigned)reg.d[C]); NEXTOP; @@ -992,7 +985,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTKD(C); if (konstd[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)reg.d[B] % (unsigned)konstd[C]); NEXTOP; @@ -1000,7 +993,7 @@ begin: ASSERTD(a); ASSERTKD(B); ASSERTD(C); if (reg.d[C] == 0) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)konstd[B] % (unsigned)reg.d[C]); NEXTOP; @@ -1178,7 +1171,7 @@ begin: ASSERTF(a); ASSERTF(B); ASSERTF(C); if (reg.f[C] == 0.) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.f[a] = reg.f[B] / reg.f[C]; NEXTOP; @@ -1186,7 +1179,7 @@ begin: ASSERTF(a); ASSERTF(B); ASSERTKF(C); if (konstf[C] == 0.) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.f[a] = reg.f[B] / konstf[C]; NEXTOP; @@ -1194,7 +1187,7 @@ begin: ASSERTF(a); ASSERTKF(B); ASSERTF(C); if (reg.f[C] == 0.) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.f[a] = konstf[B] / reg.f[C]; NEXTOP; @@ -1205,7 +1198,7 @@ begin: Do_MODF: if (fc == 0.) { - THROW(X_DIVISION_BY_ZERO); + throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.f[a] = luai_nummod(fb, fc); NEXTOP; diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 871a46673c..3a7d9b3bf1 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -453,7 +453,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur } throw; } - catch (EVMAbortException exception) + catch (CVMAbortException &exception) { if (allocated) { @@ -464,35 +464,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur *trap = nullptr; } - Printf("VM execution aborted: "); - switch (exception) - { - case X_READ_NIL: - Printf("tried to read from address zero."); - break; - - case X_WRITE_NIL: - Printf("tried to write to address zero."); - break; - - case X_TOO_MANY_TRIES: - Printf("too many try-catch blocks."); - break; - - case X_ARRAY_OUT_OF_BOUNDS: - Printf("array access out of bounds."); - break; - - case X_DIVISION_BY_ZERO: - Printf("division by zero."); - break; - - case X_BAD_SELF: - Printf("invalid self pointer."); - break; - } - Printf("\n"); - + Printf("%s\n", exception.GetMessage()); return -1; } catch (...) From fbf80849995724d5907da4eea2c732f3d68fe8e8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 18:52:58 +0100 Subject: [PATCH 450/471] - corrected the export signatures of several script exports to contain the correct classes, so that the fudging in FindFunction could be removed. - fixed PARAM_ACTION_PROLOGUE to assign correct types to the implicit pointers. It gave the actual class to the wrong one, which until now did not matter because all functions were using 'Actor', regardless of actual class association. - fixed the definition of IceChunk and removed some redundant code here. Since A_FreezeDeathChunks already calls SetState, which in turn calls the state's action function, there is no need to call it again explicitly. --- src/g_shared/a_action.cpp | 32 ----------------------- src/g_shared/a_bridge.cpp | 4 +-- src/g_shared/a_specialspot.cpp | 4 +-- src/p_actionfunctions.cpp | 28 ++++++++++---------- src/p_pspr.cpp | 16 ++++++------ src/scripting/thingdef_data.cpp | 39 ++++++++++------------------ src/scripting/vm/vm.h | 4 +-- wadsrc/static/zscript/shared/ice.txt | 16 ++++++++++-- 8 files changed, 56 insertions(+), 87 deletions(-) diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index 2e4597617f..187b215b8f 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -13,7 +13,6 @@ #include "r_data/r_translate.h" static FRandom pr_freezedeath ("FreezeDeath"); -static FRandom pr_icesettics ("IceSetTics"); static FRandom pr_freeze ("FreezeDeathChunks"); @@ -121,36 +120,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeath) return 0; } -//============================================================================ -// -// A_IceSetTics -// -//============================================================================ - -void IceSetTics(AActor *self) -{ - - int floor; - - self->tics = 70 + (pr_icesettics() & 63); - floor = P_GetThingFloorType(self); - if (Terrains[floor].DamageMOD == NAME_Fire) - { - self->tics >>= 2; - } - else if (Terrains[floor].DamageMOD == NAME_Ice) - { - self->tics <<= 1; - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_IceSetTics) -{ - PARAM_SELF_PROLOGUE(AActor); - IceSetTics(self); - return 0; -} - //============================================================================ // // A_FreezeDeathChunks @@ -193,7 +162,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks) mo->Vel.X = pr_freeze.Random2() / 128.; mo->Vel.Y = pr_freeze.Random2() / 128.; mo->Vel.Z = (mo->Z() - self->Z()) / self->Height * 4; - IceSetTics(mo); // set a random tic wait mo->RenderStyle = self->RenderStyle; mo->Alpha = self->Alpha; } diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 138210061e..cb66577967 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -114,7 +114,7 @@ static void BridgeOrbit(AActor *self) self->ceilingz = self->target->ceilingz; } -DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) +DEFINE_ACTION_FUNCTION(ABridgeBall, A_BridgeOrbit) { PARAM_SELF_PROLOGUE(AActor); BridgeOrbit(self); @@ -122,7 +122,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit) } -DEFINE_ACTION_FUNCTION(AActor, A_BridgeInit) +DEFINE_ACTION_FUNCTION(ACustomBridge, A_BridgeInit) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_DEF(balltype, AActor); diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index b5debf2df4..335f10aced 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -402,9 +402,9 @@ void ASpecialSpot::Destroy() // will build a list of all mace spots in the level and spawn a // mace. The rest of the spots will do nothing. -DEFINE_ACTION_FUNCTION(AActor, A_SpawnSingleItem) +DEFINE_ACTION_FUNCTION(ASpecialSpot, A_SpawnSingleItem) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_SELF_PROLOGUE(ASpecialSpot); PARAM_CLASS_NOT_NULL(cls, AActor); PARAM_INT_DEF (fail_sp) PARAM_INT_DEF (fail_co) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 115bc1f54e..83844ffd76 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1773,9 +1773,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomComboAttack) // State jump function // //========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_JumpIfNoAmmo) +DEFINE_ACTION_FUNCTION(AStateProvider, A_JumpIfNoAmmo) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_STATE_ACTION(jump); if (!ACTION_CALL_FROM_PSPRITE() || self->player->ReadyWeapon == nullptr) @@ -1844,9 +1844,9 @@ static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, b } } -DEFINE_ACTION_FUNCTION(AActor, A_FireBullets) +DEFINE_ACTION_FUNCTION(AStateProvider, A_FireBullets) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_ANGLE (spread_xy); PARAM_ANGLE (spread_z); PARAM_INT (numbullets); @@ -1974,9 +1974,9 @@ enum FP_Flags FPF_TRANSFERTRANSLATION = 2, FPF_NOAUTOAIM = 4, }; -DEFINE_ACTION_FUNCTION(AActor, A_FireCustomMissile) +DEFINE_ACTION_FUNCTION(AStateProvider, A_FireCustomMissile) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_CLASS (ti, AActor); PARAM_ANGLE_DEF (angle); PARAM_BOOL_DEF (useammo); @@ -2051,9 +2051,9 @@ enum CPF_STEALARMOR = 32, }; -DEFINE_ACTION_FUNCTION(AActor, A_CustomPunch) +DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_INT (damage); PARAM_BOOL_DEF (norandom); PARAM_INT_DEF (flags); @@ -2155,9 +2155,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomPunch) // customizable railgun attack function // //========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_RailAttack) +DEFINE_ACTION_FUNCTION(AStateProvider, A_RailAttack) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_INT (damage); PARAM_INT_DEF (spawnofs_xy); PARAM_BOOL_DEF (useammo); @@ -4443,9 +4443,9 @@ DEFINE_ACTION_FUNCTION(AActor, CheckIfInTargetLOS) // //=========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_CheckForReload) +DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckForReload) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); if ( self->player == NULL || self->player->ReadyWeapon == NULL ) { @@ -4496,9 +4496,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckForReload) // //=========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_ResetReloadCounter) +DEFINE_ACTION_FUNCTION(AStateProvider, A_ResetReloadCounter) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); if (self->player == NULL || self->player->ReadyWeapon == NULL) return 0; diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 733741cb29..2bd3696d42 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -828,7 +828,7 @@ void DoReadyWeapon(AActor *self) DEFINE_ACTION_FUNCTION(AStateProvider, A_WeaponReady) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_INT_DEF(flags); DoReadyWeaponToSwitch(self, !(flags & WRF_NoSwitch)); @@ -960,7 +960,7 @@ static void P_CheckWeaponButtons (player_t *player) DEFINE_ACTION_FUNCTION(AStateProvider, A_ReFire) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_STATE_ACTION_DEF(state); A_ReFire(self, state); return 0; @@ -998,7 +998,7 @@ void A_ReFire(AActor *self, FState *state) DEFINE_ACTION_FUNCTION(AStateProvider, A_ClearReFire) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); player_t *player = self->player; if (NULL != player) @@ -1020,7 +1020,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_ClearReFire) DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckReload) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); if (self->player != NULL) { @@ -1208,7 +1208,7 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayID) DEFINE_ACTION_FUNCTION(AStateProvider, A_Lower) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); player_t *player = self->player; DPSprite *psp; @@ -1254,9 +1254,9 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_Lower) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AActor, A_Raise) +DEFINE_ACTION_FUNCTION(AStateProvider, A_Raise) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); if (self == nullptr) { @@ -1368,7 +1368,7 @@ enum GF_Flags DEFINE_ACTION_FUNCTION(AStateProvider, A_GunFlash) { - PARAM_ACTION_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE(AStateProvider); PARAM_STATE_ACTION_DEF(flash); PARAM_INT_DEF(flags); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index b34157b36a..18962fbca0 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -583,35 +583,24 @@ FPropertyInfo *FindProperty(const char * string) AFuncDesc *FindFunction(PStruct *cls, const char * string) { - for (int i = 0; i < 2; i++) + int min = 0, max = AFTable.Size() - 1; + + while (min <= max) { - // Since many functions have been declared with Actor as owning class, despite being members of something else, let's hack around this until they have been fixed or exported. - // Since most of these are expected to be scriptified anyway, there's no point fixing them all before they get exported. - if (i == 1) + int mid = (min + max) / 2; + int lexval = stricmp(cls->TypeName.GetChars(), AFTable[mid].ClassName + 1); + if (lexval == 0) lexval = stricmp(string, AFTable[mid].FuncName); + if (lexval == 0) { - if (!cls->IsKindOf(RUNTIME_CLASS(PClassActor))) break; - cls = RUNTIME_CLASS(AActor); + return &AFTable[mid]; } - - int min = 0, max = AFTable.Size() - 1; - - while (min <= max) + else if (lexval > 0) { - int mid = (min + max) / 2; - int lexval = stricmp(cls->TypeName.GetChars(), AFTable[mid].ClassName + 1); - if (lexval == 0) lexval = stricmp(string, AFTable[mid].FuncName); - if (lexval == 0) - { - return &AFTable[mid]; - } - else if (lexval > 0) - { - min = mid + 1; - } - else - { - max = mid - 1; - } + min = mid + 1; + } + else + { + max = mid - 1; } } return nullptr; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 7285fb48d4..aeb52dabb3 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1140,8 +1140,8 @@ class AActor; // callingstate - State this action was called from #define PARAM_ACTION_PROLOGUE(type) \ PARAM_PROLOGUE; \ - PARAM_OBJECT (self, type); \ - PARAM_OBJECT (stateowner, AActor) \ + PARAM_OBJECT (self, AActor); \ + PARAM_OBJECT (stateowner, type) \ PARAM_POINTER (stateinfo, FStateParamInfo) \ // Number of action paramaters diff --git a/wadsrc/static/zscript/shared/ice.txt b/wadsrc/static/zscript/shared/ice.txt index 5341137855..9b72e2455d 100644 --- a/wadsrc/static/zscript/shared/ice.txt +++ b/wadsrc/static/zscript/shared/ice.txt @@ -21,12 +21,24 @@ class IceChunk : Actor +NOBLOCKMAP +MOVEWITHSECTOR } - native void A_IceSetTics (); + + void A_IceSetTics () + { + tics = 70 + (random[IceTics]() & 63); + Name dtype = GetFloorTerrain().DamageMOD; + if (dtype == 'Fire') + { + tics >>= 2; + } + else if (dtype == 'Ice') + { + tics <<= 1; + } + } States { Spawn: - ICEC A 1; ICEC ABCD 10 A_IceSetTics; Stop; } From 91c3ddf6920d3f043eff9e724c6b69f593e3ca7c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 19:30:58 +0100 Subject: [PATCH 451/471] - fixed: When a tentative class is being replaced, the old one should be removed entirely so that it cannot cause any problems later. --- src/dobjtype.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index c33caf12fc..5e1316d71b 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3330,11 +3330,15 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) } else { + TypeTable.ReplaceType(type, existclass, bucket); StaticPointerSubstitution(existclass, type, true); // replace the old one, also in the actor defaults. - // Delete the old class from the actor classes list, if it is in there. + // Delete the old class from the class lists, both the full one and the actor list. auto index = PClassActor::AllActorClasses.Find(static_cast(existclass)); if (index < PClassActor::AllActorClasses.Size()) PClassActor::AllActorClasses.Delete(index); - TypeTable.ReplaceType(type, existclass, bucket); + index = PClass::AllClasses.Find(existclass); + if (index < PClass::AllClasses.Size()) PClass::AllClasses.Delete(index); + // Now we can destroy the old class as nothing should reference it anymore + existclass->Destroy(); } return type; } From d93b6e31d6df1e6c9d6baee590f18c536e9ab000 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2016 22:10:15 +0100 Subject: [PATCH 452/471] - fixed: The ammo and sister weapon type pointers were not properly declared as pointers to the type system. --- src/g_inventory/a_weapons.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index c312f15b34..3b3b765d6d 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -66,6 +66,9 @@ IMPLEMENT_POINTERS_START(AWeapon) IMPLEMENT_POINTER(Ammo1) IMPLEMENT_POINTER(Ammo2) IMPLEMENT_POINTER(SisterWeapon) + IMPLEMENT_POINTER(AmmoType1) + IMPLEMENT_POINTER(AmmoType2) + IMPLEMENT_POINTER(SisterWeaponType) IMPLEMENT_POINTERS_END DEFINE_FIELD(AWeapon, WeaponFlags) From b3783a3850891233906d6f5aab9393cebbcf76ec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 12:23:13 +0100 Subject: [PATCH 453/471] redid the exception mechanism for script-side access violations to be of more use for diagnosing problems. The original implementation just printed a mostly information-free message and then went on as if nothing has happened, making it ridiculously easy to write broken code and release it. Changed it to: * Any VMAbortException will now terminate the game session and go back to the console. * It will also print a VM stack trace with all open functions, including source file and line numbers pointing to the problem spots. For this the relevant information had to be added to the VMScriptFunction class. An interesting effect here was that just throwing the exception object increased the VM's Exec function's stack size from 900 bytes to 70kb, because the compiler allocates a separate local buffer for every single instance of the exception object. The obvious solution was to put this part into a subfunction so that it won't pollute the Exec function's own stack frame. Interesting side effect of this: Exec's stack requirement went down from 900 bytes to 600 bytes. This is still on the high side but already a lot better. --- src/d_main.cpp | 6 ++ src/info.cpp | 31 ++++++-- src/p_actionfunctions.cpp | 14 +++- src/scripting/vm/vm.h | 14 +++- src/scripting/vm/vmbuilder.cpp | 7 +- src/scripting/vm/vmbuilder.h | 8 +- src/scripting/vm/vmexec.cpp | 60 ++------------- src/scripting/vm/vmexec.h | 78 +++++++++++++------- src/scripting/vm/vmframe.cpp | 129 +++++++++++++++++++++++++++++---- 9 files changed, 232 insertions(+), 115 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index dad2b86d95..bffb4136de 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1027,6 +1027,12 @@ void D_DoomLoop () } D_ErrorCleanup (); } + catch (CVMAbortException &error) + { + error.MaybePrintMessage(); + Printf("%s", error.stacktrace); + D_ErrorCleanup(); + } } } diff --git a/src/info.cpp b/src/info.cpp index a0117a71f0..d3cb4e2743 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -89,16 +89,35 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, stateret = NULL; } } - if (stateret == NULL) + try { - GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL); + if (stateret == NULL) + { + GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL); + } + else + { + VMReturn ret; + ret.PointerAt((void **)stateret); + GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL); + } } - else + catch (CVMAbortException &err) { - VMReturn ret; - ret.PointerAt((void **)stateret); - GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL); + err.MaybePrintMessage(); + auto owner = FState::StaticFindStateOwner(this); + int offs = int(this - owner->OwnedStates); + const char *callinfo = ""; + if (info != nullptr && info->mStateType == STATE_Psprite) + { + if (stateowner->IsKindOf(RUNTIME_CLASS(AWeapon)) && stateowner != self) callinfo = "weapon "; + else callinfo = "overlay "; + } + err.stacktrace.AppendFormat("Called from %sstate %s.%d in %s\n", callinfo, owner->TypeName.GetChars(), offs, stateowner->GetClass()->TypeName.GetChars()); + throw; + throw; } + ActionCycles.Unclock(); return true; } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 83844ffd76..12645561bb 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -183,7 +183,19 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state) numret = 2; } } - GlobalVMStack.Call(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); + try + { + GlobalVMStack.Call(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); + } + catch (CVMAbortException &err) + { + err.MaybePrintMessage(); + auto owner = FState::StaticFindStateOwner(state); + int offs = int(state - owner->OwnedStates); + err.stacktrace.AppendFormat("Called from state %s.%d in inventory state chain in %s\n", owner->TypeName.GetChars(), offs, GetClass()->TypeName.GetChars()); + throw; + } + // 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) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index aeb52dabb3..1869c410b3 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -194,7 +194,8 @@ class CVMAbortException : public CDoomError { public: static FString stacktrace; - CVMAbortException(EVMAbortException reason, const char *moreinfo, ...); + CVMAbortException(EVMAbortException reason, const char *moreinfo, va_list ap); + void MaybePrintMessage(); }; enum EVMOpMode @@ -808,6 +809,12 @@ union FVoidObj void *v; }; +struct FStatementInfo +{ + uint16_t InstructionIndex; + uint16_t LineNumber; +}; + class VMScriptFunction : public VMFunction { DECLARE_CLASS(VMScriptFunction, VMFunction); @@ -815,12 +822,13 @@ public: VMScriptFunction(FName name=NAME_None); ~VMScriptFunction(); size_t PropagateMark(); - void Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta); + void Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta, int numlinenumbers); VM_ATAG *KonstATags() { return (VM_UBYTE *)(KonstA + NumKonstA); } const VM_ATAG *KonstATags() const { return (VM_UBYTE *)(KonstA + NumKonstA); } VMOP *Code; + FStatementInfo *LineInfo; FString SourceFileName; int *KonstD; double *KonstF; @@ -828,6 +836,7 @@ public: FVoidObj *KonstA; int ExtraSpace; int CodeSize; // Size of code in instructions (not bytes) + unsigned LineInfoCount; VM_UBYTE NumRegD; VM_UBYTE NumRegF; VM_UBYTE NumRegS; @@ -843,6 +852,7 @@ public: void InitExtra(void *addr); void DestroyExtra(void *addr); int AllocExtraStack(PType *type); + int PCToLine(const VMOP *pc); }; class VMFrameStack diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 65ec0bb26b..3e833af79c 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -88,7 +88,7 @@ void VMFunctionBuilder::BeginStatement(FxExpression *stmt) // only add a new entry if the line number differs. if (LineNumbers.Size() == 0 || stmt->ScriptPosition.ScriptLine != LineNumbers.Last().LineNumber) { - StatementInfo si = { (uint16_t)Code.Size(), (uint16_t)stmt->ScriptPosition.ScriptLine }; + FStatementInfo si = { (uint16_t)Code.Size(), (uint16_t)stmt->ScriptPosition.ScriptLine }; LineNumbers.Push(si); } StatementStack.Push(stmt); @@ -102,17 +102,18 @@ void VMFunctionBuilder::EndStatement() // Re-enter the previous statement. if (StatementStack.Size() > 0) { - StatementInfo si = { (uint16_t)Code.Size(), (uint16_t)StatementStack.Last()->ScriptPosition.ScriptLine }; + FStatementInfo si = { (uint16_t)Code.Size(), (uint16_t)StatementStack.Last()->ScriptPosition.ScriptLine }; LineNumbers.Push(si); } } void VMFunctionBuilder::MakeFunction(VMScriptFunction *func) { - func->Alloc(Code.Size(), IntConstantList.Size(), FloatConstantList.Size(), StringConstantList.Size(), AddressConstantList.Size()); + func->Alloc(Code.Size(), IntConstantList.Size(), FloatConstantList.Size(), StringConstantList.Size(), AddressConstantList.Size(), LineNumbers.Size()); // Copy code block. memcpy(func->Code, &Code[0], Code.Size() * sizeof(VMOP)); + memcpy(func->LineInfo, &LineNumbers[0], LineNumbers.Size() * sizeof(LineNumbers[0])); // Create constant tables. if (IntConstantList.Size() > 0) diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index d319b22805..7c086ac0c8 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -100,13 +100,7 @@ private: VM_ATAG Tag; }; - struct StatementInfo - { - uint16_t InstructionIndex; - uint16_t LineNumber; - }; - - TArray LineNumbers; + TArray LineNumbers; TArray StatementStack; TArray IntConstantList; diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 1984108647..79d0b7fe6b 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -40,6 +40,11 @@ #include "textures/textures.h" #include "math/cmath.h" +// This must be a separate function because the VC compiler would otherwise allocate memory on the stack for every separate instance of the exception object that may get thrown. +void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...); +// intentionally implemented in a different source file tp prevent inlining. +void ThrowVMException(VMException *x); + #define IMPLEMENT_VMEXEC #if !defined(COMPGOTO) && defined(__GNUC__) @@ -91,7 +96,7 @@ } #define GETADDR(a,o,x) \ - if (a == NULL) { throw CVMAbortException(x, nullptr); } \ + if (a == NULL) { ThrowAbortException(x, nullptr); } \ ptr = (VM_SBYTE *)a + o static const VM_UWORD ZapTable[16] = @@ -227,57 +232,4 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) } } -void NullParam(const char *varname) -{ - throw CVMAbortException(X_READ_NIL, "In function parameter %s", varname); -} - -FString CVMAbortException::stacktrace; - -CVMAbortException::CVMAbortException(EVMAbortException reason, const char *moreinfo, ...) -{ - SetMessage("VM execution aborted: "); - switch (reason) - { - case X_READ_NIL: - AppendMessage("tried to read from address zero."); - break; - - case X_WRITE_NIL: - AppendMessage("tried to write to address zero."); - break; - - case X_TOO_MANY_TRIES: - AppendMessage("too many try-catch blocks."); - break; - - case X_ARRAY_OUT_OF_BOUNDS: - AppendMessage("array access out of bounds."); - break; - - case X_DIVISION_BY_ZERO: - AppendMessage("division by zero."); - break; - - case X_BAD_SELF: - AppendMessage("invalid self pointer."); - break; - - default: - { - size_t len = strlen(m_Message); - mysnprintf(m_Message + len, MAX_ERRORTEXT - len, "Unknown reason %d", reason); - break; - } - } - if (moreinfo != nullptr) - { - AppendMessage(" "); - va_list ap; - va_start(ap, moreinfo); - size_t len = strlen(m_Message); - myvsnprintf(m_Message + len, MAX_ERRORTEXT - len, moreinfo, ap); - va_end(ap); - } -} diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 1e688365d6..4152facc18 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -2,7 +2,6 @@ #error vmexec.h must not be #included outside vmexec.cpp. Use vm.h instead. #endif - static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) { #if COMPGOTO @@ -596,7 +595,17 @@ begin: FillReturns(reg, f, returns, pc+1, C); if (call->Native) { - numret = static_cast(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, returns, C); + try + { + numret = static_cast(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, returns, C); + } + catch (CVMAbortException &err) + { + err.MaybePrintMessage(); + err.stacktrace.AppendFormat("Called from %s\n", call->PrintableName.GetChars()); + // PrintParameters(reg.param + f->NumParam - B, B); + throw; + } } else { @@ -640,7 +649,17 @@ begin: if (call->Native) { - return static_cast(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, ret, numret); + try + { + return static_cast(call)->NativeCall(reg.param + f->NumParam - B, call->DefaultArgs, B, ret, numret); + } + catch (CVMAbortException &err) + { + err.MaybePrintMessage(); + err.stacktrace.AppendFormat("Called from %s\n", call->PrintableName.GetChars()); + // PrintParameters(reg.param + f->NumParam - B, B); + throw; + } } else { // FIXME: Not a true tail call @@ -704,7 +723,7 @@ begin: assert(try_depth < MAX_TRY_DEPTH); if (try_depth >= MAX_TRY_DEPTH) { - throw CVMAbortException(X_TOO_MANY_TRIES, nullptr); + ThrowAbortException(X_TOO_MANY_TRIES, nullptr); } assert((pc + JMPOFS(pc) + 1)->op == OP_CATCH); exception_frames[try_depth++] = pc + JMPOFS(pc) + 1; @@ -717,17 +736,17 @@ begin: if (a == 0) { ASSERTA(B); - throw((VMException *)reg.a[B]); + ThrowVMException((VMException *)reg.a[B]); } else if (a == 1) { ASSERTKA(B); assert(konstatag[B] == ATAG_OBJECT); - throw((VMException *)konsta[B].o); + ThrowVMException((VMException *)konsta[B].o); } else { - throw CVMAbortException(EVMAbortException(BC), nullptr); + ThrowAbortException(EVMAbortException(BC), nullptr); } NEXTOP; OP(CATCH): @@ -739,7 +758,7 @@ begin: OP(BOUND): if (reg.d[a] >= BC) { - throw CVMAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", BC, reg.d[a]); + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", BC, reg.d[a]); } NEXTOP; @@ -747,7 +766,7 @@ begin: ASSERTKD(BC); if (reg.d[a] >= konstd[BC]) { - throw CVMAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", konstd[BC], reg.d[a]); + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", konstd[BC], reg.d[a]); } NEXTOP; @@ -755,7 +774,7 @@ begin: ASSERTD(B); if (reg.d[a] >= reg.d[B]) { - throw CVMAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", reg.d[B], reg.d[a]); + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", reg.d[B], reg.d[a]); } NEXTOP; @@ -902,7 +921,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = reg.d[B] / reg.d[C]; NEXTOP; @@ -910,7 +929,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTKD(C); if (konstd[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = reg.d[B] / konstd[C]; NEXTOP; @@ -918,7 +937,7 @@ begin: ASSERTD(a); ASSERTKD(B); ASSERTD(C); if (reg.d[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = konstd[B] / reg.d[C]; NEXTOP; @@ -927,7 +946,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)reg.d[B] / (unsigned)reg.d[C]); NEXTOP; @@ -935,7 +954,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTKD(C); if (konstd[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)reg.d[B] / (unsigned)konstd[C]); NEXTOP; @@ -943,7 +962,7 @@ begin: ASSERTD(a); ASSERTKD(B); ASSERTD(C); if (reg.d[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)konstd[B] / (unsigned)reg.d[C]); NEXTOP; @@ -952,7 +971,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = reg.d[B] % reg.d[C]; NEXTOP; @@ -960,7 +979,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTKD(C); if (konstd[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = reg.d[B] % konstd[C]; NEXTOP; @@ -968,7 +987,7 @@ begin: ASSERTD(a); ASSERTKD(B); ASSERTD(C); if (reg.d[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = konstd[B] % reg.d[C]; NEXTOP; @@ -977,7 +996,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTD(C); if (reg.d[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)reg.d[B] % (unsigned)reg.d[C]); NEXTOP; @@ -985,7 +1004,7 @@ begin: ASSERTD(a); ASSERTD(B); ASSERTKD(C); if (konstd[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)reg.d[B] % (unsigned)konstd[C]); NEXTOP; @@ -993,7 +1012,7 @@ begin: ASSERTD(a); ASSERTKD(B); ASSERTD(C); if (reg.d[C] == 0) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.d[a] = int((unsigned)konstd[B] % (unsigned)reg.d[C]); NEXTOP; @@ -1171,7 +1190,7 @@ begin: ASSERTF(a); ASSERTF(B); ASSERTF(C); if (reg.f[C] == 0.) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.f[a] = reg.f[B] / reg.f[C]; NEXTOP; @@ -1179,7 +1198,7 @@ begin: ASSERTF(a); ASSERTF(B); ASSERTKF(C); if (konstf[C] == 0.) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.f[a] = reg.f[B] / konstf[C]; NEXTOP; @@ -1187,7 +1206,7 @@ begin: ASSERTF(a); ASSERTKF(B); ASSERTF(C); if (reg.f[C] == 0.) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.f[a] = konstf[B] / reg.f[C]; NEXTOP; @@ -1198,7 +1217,7 @@ begin: Do_MODF: if (fc == 0.) { - throw CVMAbortException(X_DIVISION_BY_ZERO, nullptr); + ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); } reg.f[a] = luai_nummod(fb, fc); NEXTOP; @@ -1611,6 +1630,13 @@ begin: // Nothing caught it. Rethrow and let somebody else deal with it. throw; } + catch (CVMAbortException &err) + { + err.MaybePrintMessage(); + err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars(), sfunc->PCToLine(pc)); + // PrintParameters(reg.param + f->NumParam - B, B); + throw; + } return 0; } diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 3a7d9b3bf1..f9f04e4258 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -3,6 +3,7 @@ ** **--------------------------------------------------------------------------- ** Copyright -2016 Randy Heit +** Copyright 2016 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -33,6 +34,7 @@ #include #include "dobject.h" +#include "v_text.h" IMPLEMENT_CLASS(VMException, false, false) IMPLEMENT_CLASS(VMFunction, true, true) @@ -48,11 +50,13 @@ VMScriptFunction::VMScriptFunction(FName name) { Native = false; Name = name; + LineInfo = nullptr; Code = NULL; KonstD = NULL; KonstF = NULL; KonstS = NULL; KonstA = NULL; + LineInfoCount = 0; ExtraSpace = 0; CodeSize = 0; NumRegD = 0; @@ -82,7 +86,7 @@ VMScriptFunction::~VMScriptFunction() } } -void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta) +void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta, int numlinenumbers) { assert(Code == NULL); assert(numops > 0); @@ -90,14 +94,27 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko assert(numkonstf >= 0 && numkonstf <= 65535); assert(numkonsts >= 0 && numkonsts <= 65535); assert(numkonsta >= 0 && numkonsta <= 65535); + assert(numlinenumbers >= 0 && numlinenumbers <= 65535); void *mem = M_Malloc(numops * sizeof(VMOP) + numkonstd * sizeof(int) + numkonstf * sizeof(double) + numkonsts * sizeof(FString) + - numkonsta * (sizeof(FVoidObj) + 1)); + numkonsta * (sizeof(FVoidObj) + 1) + + numlinenumbers * sizeof(FStatementInfo)); Code = (VMOP *)mem; mem = (void *)((VMOP *)mem + numops); + if (numlinenumbers > 0) + { + LineInfo = (FStatementInfo*)mem; + LineInfoCount = numlinenumbers; + mem = LineInfo + numlinenumbers; + } + else + { + LineInfo = nullptr; + LineInfoCount = 0; + } if (numkonstd > 0) { KonstD = (int *)mem; @@ -190,6 +207,20 @@ int VMScriptFunction::AllocExtraStack(PType *type) return address; } +int VMScriptFunction::PCToLine(const VMOP *pc) +{ + int PCIndex = int(pc - Code); + if (LineInfoCount == 1) return LineInfo[0].LineNumber; + for (unsigned i = 1; i < LineInfoCount; i++) + { + if (LineInfo[i].InstructionIndex > PCIndex) + { + return LineInfo[i - 1].LineNumber; + } + } + return -1; +} + //=========================================================================== // // VMFrame :: InitRegS @@ -453,20 +484,6 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur } throw; } - catch (CVMAbortException &exception) - { - if (allocated) - { - PopFrame(); - } - if (trap != nullptr) - { - *trap = nullptr; - } - - Printf("%s\n", exception.GetMessage()); - return -1; - } catch (...) { if (allocated) @@ -476,3 +493,83 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur throw; } } + +// Exception stuff for the VM is intentionally placed there, because having this in vmexec.cpp would subject it to inlining +// which we do not want because it increases the local stack requirements of Exec which are already too high. +FString CVMAbortException::stacktrace; + +CVMAbortException::CVMAbortException(EVMAbortException reason, const char *moreinfo, va_list ap) +{ + SetMessage("VM execution aborted: "); + switch (reason) + { + case X_READ_NIL: + AppendMessage("tried to read from address zero."); + break; + + case X_WRITE_NIL: + AppendMessage("tried to write to address zero."); + break; + + case X_TOO_MANY_TRIES: + AppendMessage("too many try-catch blocks."); + break; + + case X_ARRAY_OUT_OF_BOUNDS: + AppendMessage("array access out of bounds."); + break; + + case X_DIVISION_BY_ZERO: + AppendMessage("division by zero."); + break; + + case X_BAD_SELF: + AppendMessage("invalid self pointer."); + break; + + default: + { + size_t len = strlen(m_Message); + mysnprintf(m_Message + len, MAX_ERRORTEXT - len, "Unknown reason %d", reason); + break; + } + } + if (moreinfo != nullptr) + { + AppendMessage(" "); + size_t len = strlen(m_Message); + myvsnprintf(m_Message + len, MAX_ERRORTEXT - len, moreinfo, ap); + } + stacktrace = ""; +} + +// Print this only once on the first catch block. +void CVMAbortException::MaybePrintMessage() +{ + auto m = GetMessage(); + if (m != nullptr) + { + Printf(TEXTCOLOR_RED); + Printf("%s\n", m); + SetMessage(""); + } +} + + +void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...) +{ + va_list ap; + va_start(ap, moreinfo); + throw CVMAbortException(reason, moreinfo, ap); + va_end(ap); +} + +void NullParam(const char *varname) +{ + ThrowAbortException(X_READ_NIL, "In function parameter %s", varname); +} + +void ThrowVMException(VMException *x) +{ + throw x; +} From 136e976b2a99ff56df81f46410c81e8fb74b141a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 12:33:58 +0100 Subject: [PATCH 454/471] - added an error check for duplicate local variable definitions. Note that this only applies if both are in the same block. Just like in C++, it is perfectly legal to have the same variable name in two different nested scopes. --- src/scripting/codegeneration/codegen.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 6a0f840a56..c392d97d32 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -9975,6 +9975,19 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) if (Init) Init = new FxTypeCast(Init, ValueType, false); SAFE_RESOLVE_OPT(Init, ctx); } + if (Name != NAME_None) + { + for (auto l : ctx.Block->LocalVars) + { + if (l->Name == Name) + { + ScriptPosition.Message(MSG_ERROR, "Local variable %s already defined", Name.GetChars()); + l->ScriptPosition.Message(MSG_ERROR, "Original definition is here "); + delete this; + return nullptr; + } + } + } ctx.Block->LocalVars.Push(this); return this; } From 0da233a6646a3e726cd51878ed958b125ff9c27f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 13:16:09 +0100 Subject: [PATCH 455/471] changed ZScript include mechanism. * It will now use #include, just like most other definition formats and can be mixed with regular definitions. However, due to how the Lemon-generated parser works this will not recursively pull in all files, but store them in a list and process them sequentially. Functionally this shouldn't make a difference, because ZScript is mostly order-independent - the only thing where order is important is native classes, but these are completely internal to zdoom.pk3 where proper order is observed. --- src/namedef.h | 1 + src/scripting/zscript/zcc-parse.lemon | 6 + src/scripting/zscript/zcc_parser.cpp | 61 ++-- src/zstring.h | 67 ++++- wadsrc/static/zscript.txt | 406 +++++++++++++------------- 5 files changed, 297 insertions(+), 244 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index 9cb4e8d231..c3866a0be8 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -715,6 +715,7 @@ xx(String) xx(Vector) xx(Map) xx(Array) +xx(Include) xx(Sound) xx(State) xx(Fixed) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 685c401e78..5ba5a204ea 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -140,6 +140,7 @@ external_declaration(X) ::= class_definition(A). { X = A; /*X-overwrites-A* external_declaration(X) ::= struct_def(A). { X = A; /*X-overwrites-A*/ } external_declaration(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ } external_declaration(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ } +external_declaration(X) ::= include_def. { X = nullptr; } /* Optional bits. */ opt_semicolon ::= . @@ -156,6 +157,11 @@ opt_expr(X) ::= . opt_expr(X) ::= expr(X). +include_def ::= INCLUDE string_constant(A). +{ + AddInclude(A); +} + /************ Class Definition ************/ /* Can only occur at global scope. */ diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 64ac2c86d2..8a16181273 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -44,7 +44,19 @@ #include "zcc_parser.h" #include "zcc_compile.h" +TArray Includes; +TArray IncludeLocs; + static FString ZCCTokenName(int terminal); +void AddInclude(ZCC_ExprConstant *node) +{ + assert(node->Type == TypeString); + if (Includes.Find(*node->StringVal) >= Includes.Size()) + { + Includes.Push(*node->StringVal); + IncludeLocs.Push(*node); + } +} #include "zcc-parse.h" #include "zcc-parse.c" @@ -152,6 +164,7 @@ static void InitTokenMap() TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name); TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map); TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array); + TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include); TOKENDEF (TK_Void, ZCC_VOID); TOKENDEF (TK_True, ZCC_TRUE); TOKENDEF (TK_False, ZCC_FALSE); @@ -316,42 +329,24 @@ static void DoParse(int lumpnum) 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); - } - } -#ifndef NDEBUG - if (f) fprintf(f, "Starting parsing %s\n", sc.String); -#endif - ParseSingleFile(sc.String, 0, parser, state); + ParseSingleFile(nullptr, lumpnum, parser, state); + for (unsigned i = 0; i < Includes.Size(); i++) + { + lumpnum = Wads.CheckNumForFullName(Includes[i], true); + if (lumpnum == -1) + { + IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars()); + } + else + { + ParseSingleFile(nullptr, lumpnum, parser, state); } } + Includes.Clear(); + Includes.ShrinkToFit(); + IncludeLocs.Clear(); + IncludeLocs.ShrinkToFit(); value.Int = -1; value.SourceLoc = sc.GetMessageLine(); diff --git a/src/zstring.h b/src/zstring.h index fba61884f5..128197fd5e 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -298,17 +298,68 @@ protected: friend struct FStringData; +public: + bool operator == (const FString &other) const + { + return Compare(other) == 0; + } + + bool operator != (const FString &other) const + { + return Compare(other) != 0; + } + + bool operator < (const FString &other) const + { + return Compare(other) < 0; + } + + bool operator > (const FString &other) const + { + return Compare(other) > 0; + } + + bool operator <= (const FString &other) const + { + return Compare(other) <= 0; + } + + bool operator >= (const FString &other) const + { + return Compare(other) >= 0; + } + + bool operator == (const char *) const = delete; + bool operator != (const char *) const = delete; + bool operator < (const char *) const = delete; + bool operator > (const char *) const = delete; + bool operator <= (const char *) const = delete; + bool operator >= (const char *) const = delete; + + bool operator == (FName) const = delete; + bool operator != (FName) const = delete; + bool operator < (FName) const = delete; + bool operator > (FName) const = delete; + bool operator <= (FName) const = delete; + bool operator >= (FName) const = delete; + private: - // Prevent these from being called as current practices are to use Compare. - // Without this FStrings will be accidentally compared against char* ptrs. - bool operator == (const FString &illegal) const; - bool operator != (const FString &illegal) const; - bool operator < (const FString &illegal) const; - bool operator > (const FString &illegal) const; - bool operator <= (const FString &illegal) const; - bool operator >= (const FString &illegal) const; }; +bool operator == (const char *, const FString &) = delete; +bool operator != (const char *, const FString &) = delete; +bool operator < (const char *, const FString &) = delete; +bool operator > (const char *, const FString &) = delete; +bool operator <= (const char *, const FString &) = delete; +bool operator >= (const char *, const FString &) = delete; + +bool operator == (FName, const FString &) = delete; +bool operator != (FName, const FString &) = delete; +bool operator < (FName, const FString &) = delete; +bool operator > (FName, const FString &) = delete; +bool operator <= (FName, const FString &) = delete; +bool operator >= (FName, const FString &) = delete; + class FStringf : public FString { public: diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index a2b89da013..341fdc9fbe 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,211 +1,211 @@ -zscript/base.txt -zscript/constants.txt -zscript/actor.txt -zscript/actor_checks.txt +#include "zscript/base.txt" +#include "zscript/constants.txt" +#include "zscript/actor.txt" +#include "zscript/actor_checks.txt" -zscript/shared/inventory.txt -zscript/shared/inv_misc.txt -zscript/shared/weapons.txt -zscript/shared/armor.txt -zscript/shared/powerups.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/itemeffects.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/shared/fastprojectile.txt +#include "zscript/shared/inventory.txt" +#include "zscript/shared/inv_misc.txt" +#include "zscript/shared/weapons.txt" +#include "zscript/shared/armor.txt" +#include "zscript/shared/powerups.txt" +#include "zscript/shared/player.txt" +#include "zscript/shared/morph.txt" +#include "zscript/shared/botstuff.txt" +#include "zscript/shared/sharedmisc.txt" +#include "zscript/shared/blood.txt" +#include "zscript/shared/debris.txt" +#include "zscript/shared/decal.txt" +#include "zscript/shared/splashes.txt" +#include "zscript/shared/itemeffects.txt" +#include "zscript/shared/fountain.txt" +#include "zscript/shared/spark.txt" +#include "zscript/shared/soundsequence.txt" +#include "zscript/shared/soundenvironment.txt" +#include "zscript/shared/bridge.txt" +#include "zscript/shared/specialspot.txt" +#include "zscript/shared/teleport.txt" +#include "zscript/shared/camera.txt" +#include "zscript/shared/movingcamera.txt" +#include "zscript/shared/mapmarker.txt" +#include "zscript/shared/waterzone.txt" +#include "zscript/shared/skies.txt" +#include "zscript/shared/hatetarget.txt" +#include "zscript/shared/secrettrigger.txt" +#include "zscript/shared/setcolor.txt" +#include "zscript/shared/sectoraction.txt" +#include "zscript/shared/ice.txt" +#include "zscript/shared/dog.txt" +#include "zscript/shared/fastprojectile.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/weaponfist.txt -zscript/doom/weaponpistol.txt -zscript/doom/weaponshotgun.txt -zscript/doom/weaponssg.txt -zscript/doom/weaponchaingun.txt -zscript/doom/weaponchainsaw.txt -zscript/doom/weaponrlaunch.txt -zscript/doom/weaponplasma.txt -zscript/doom/weaponbfg.txt +#include "zscript/doom/doomplayer.txt" +#include "zscript/doom/possessed.txt" +#include "zscript/doom/doomimp.txt" +#include "zscript/doom/demon.txt" +#include "zscript/doom/lostsoul.txt" +#include "zscript/doom/cacodemon.txt" +#include "zscript/doom/bruiser.txt" +#include "zscript/doom/revenant.txt" +#include "zscript/doom/arachnotron.txt" +#include "zscript/doom/fatso.txt" +#include "zscript/doom/painelemental.txt" +#include "zscript/doom/archvile.txt" +#include "zscript/doom/cyberdemon.txt" +#include "zscript/doom/spidermaster.txt" +#include "zscript/doom/keen.txt" +#include "zscript/doom/bossbrain.txt" +#include "zscript/doom/weaponfist.txt" +#include "zscript/doom/weaponpistol.txt" +#include "zscript/doom/weaponshotgun.txt" +#include "zscript/doom/weaponssg.txt" +#include "zscript/doom/weaponchaingun.txt" +#include "zscript/doom/weaponchainsaw.txt" +#include "zscript/doom/weaponrlaunch.txt" +#include "zscript/doom/weaponplasma.txt" +#include "zscript/doom/weaponbfg.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 +#include "zscript/doom/deadthings.txt" +#include "zscript/doom/doomammo.txt" +#include "zscript/doom/doomarmor.txt" +#include "zscript/doom/doomartifacts.txt" +#include "zscript/doom/doomhealth.txt" +#include "zscript/doom/doomkeys.txt" +#include "zscript/doom/doommisc.txt" +#include "zscript/doom/doomdecorations.txt" +#include "zscript/doom/doomweapons.txt" +#include "zscript/doom/stealthmonsters.txt" +#include "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 +#include "zscript/raven/artiegg.txt" +#include "zscript/raven/artitele.txt" +#include "zscript/raven/ravenartifacts.txt" +#include "zscript/raven/ravenhealth.txt" +#include "zscript/raven/ravenambient.txt" +#include "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/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/heretic/weaponstaff.txt -zscript/heretic/weaponwand.txt -zscript/heretic/weaponcrossbow.txt -zscript/heretic/weapongauntlets.txt -zscript/heretic/weaponmace.txt -zscript/heretic/weaponblaster.txt -zscript/heretic/weaponskullrod.txt -zscript/heretic/weaponphoenix.txt +#include "zscript/heretic/hereticplayer.txt" +#include "zscript/heretic/hereticammo.txt" +#include "zscript/heretic/hereticarmor.txt" +#include "zscript/heretic/hereticartifacts.txt" +#include "zscript/heretic/heretickeys.txt" +#include "zscript/heretic/hereticdecorations.txt" +#include "zscript/heretic/hereticmisc.txt" +#include "zscript/heretic/mummy.txt" +#include "zscript/heretic/clink.txt" +#include "zscript/heretic/beast.txt" +#include "zscript/heretic/snake.txt" +#include "zscript/heretic/hereticimp.txt" +#include "zscript/heretic/knight.txt" +#include "zscript/heretic/wizard.txt" +#include "zscript/heretic/ironlich.txt" +#include "zscript/heretic/dsparil.txt" +#include "zscript/heretic/chicken.txt" +#include "zscript/heretic/weaponstaff.txt" +#include "zscript/heretic/weaponwand.txt" +#include "zscript/heretic/weaponcrossbow.txt" +#include "zscript/heretic/weapongauntlets.txt" +#include "zscript/heretic/weaponmace.txt" +#include "zscript/heretic/weaponblaster.txt" +#include "zscript/heretic/weaponskullrod.txt" +#include "zscript/heretic/weaponphoenix.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 +#include "zscript/hexen/baseweapons.txt" +#include "zscript/hexen/korax.txt" +#include "zscript/hexen/fighterplayer.txt" +#include "zscript/hexen/clericplayer.txt" +#include "zscript/hexen/mageplayer.txt" +#include "zscript/hexen/pig.txt" +#include "zscript/hexen/flame.txt" +#include "zscript/hexen/flies.txt" +#include "zscript/hexen/hexenarmor.txt" +#include "zscript/hexen/hexendecorations.txt" +#include "zscript/hexen/hexenkeys.txt" +#include "zscript/hexen/hexenspecialdecs.txt" +#include "zscript/hexen/mana.txt" +#include "zscript/hexen/puzzleitems.txt" +#include "zscript/hexen/scriptprojectiles.txt" +#include "zscript/hexen/speedboots.txt" +#include "zscript/hexen/ettin.txt" +#include "zscript/hexen/centaur.txt" +#include "zscript/hexen/demons.txt" +#include "zscript/hexen/firedemon.txt" +#include "zscript/hexen/fog.txt" +#include "zscript/hexen/summon.txt" +#include "zscript/hexen/flechette.txt" +#include "zscript/hexen/clericboss.txt" +#include "zscript/hexen/fighterboss.txt" +#include "zscript/hexen/mageboss.txt" +#include "zscript/hexen/bats.txt" +#include "zscript/hexen/bishop.txt" +#include "zscript/hexen/blastradius.txt" +#include "zscript/hexen/boostarmor.txt" +#include "zscript/hexen/clericmace.txt" +#include "zscript/hexen/clericflame.txt" +#include "zscript/hexen/clericholy.txt" +#include "zscript/hexen/clericstaff.txt" +#include "zscript/hexen/magewand.txt" +#include "zscript/hexen/magecone.txt" +#include "zscript/hexen/magelightning.txt" +#include "zscript/hexen/magestaff.txt" +#include "zscript/hexen/fighterfist.txt" +#include "zscript/hexen/fighteraxe.txt" +#include "zscript/hexen/fighterhammer.txt" +#include "zscript/hexen/fighterquietus.txt" +#include "zscript/hexen/dragon.txt" +#include "zscript/hexen/healingradius.txt" +#include "zscript/hexen/teleportother.txt" +#include "zscript/hexen/iceguy.txt" +#include "zscript/hexen/serpent.txt" +#include "zscript/hexen/spike.txt" +#include "zscript/hexen/wraith.txt" +#include "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/klaxon.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/strifefunctions.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/weapondagger.txt -zscript/strife/weaponcrossbow.txt -zscript/strife/weaponassault.txt -zscript/strife/weaponmissile.txt -zscript/strife/weaponflamer.txt -zscript/strife/weapongrenade.txt -zscript/strife/weaponmauler.txt -zscript/strife/sigil.txt +#include "zscript/strife/strifehumanoid.txt" +#include "zscript/strife/strifeplayer.txt" +#include "zscript/strife/strifeweapons.txt" +#include "zscript/strife/spectral.txt" +#include "zscript/strife/acolyte.txt" +#include "zscript/strife/alienspectres.txt" +#include "zscript/strife/beggars.txt" +#include "zscript/strife/coin.txt" +#include "zscript/strife/crusader.txt" +#include "zscript/strife/entityboss.txt" +#include "zscript/strife/inquisitor.txt" +#include "zscript/strife/klaxon.txt" +#include "zscript/strife/loremaster.txt" +#include "zscript/strife/macil.txt" +#include "zscript/strife/merchants.txt" +#include "zscript/strife/peasants.txt" +#include "zscript/strife/strifebishop.txt" +#include "zscript/strife/oracle.txt" +#include "zscript/strife/programmer.txt" +#include "zscript/strife/questitems.txt" +#include "zscript/strife/ratbuddy.txt" +#include "zscript/strife/rebels.txt" +#include "zscript/strife/reaver.txt" +#include "zscript/strife/sentinel.txt" +#include "zscript/strife/stalker.txt" +#include "zscript/strife/strifeammo.txt" +#include "zscript/strife/strifearmor.txt" +#include "zscript/strife/strifefunctions.txt" +#include "zscript/strife/strifeitems.txt" +#include "zscript/strife/strifekeys.txt" +#include "zscript/strife/strifestuff.txt" +#include "zscript/strife/thingstoblowup.txt" +#include "zscript/strife/templar.txt" +#include "zscript/strife/zombie.txt" +#include "zscript/strife/weapondagger.txt" +#include "zscript/strife/weaponcrossbow.txt" +#include "zscript/strife/weaponassault.txt" +#include "zscript/strife/weaponmissile.txt" +#include "zscript/strife/weaponflamer.txt" +#include "zscript/strife/weapongrenade.txt" +#include "zscript/strife/weaponmauler.txt" +#include "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 +#include "zscript/chex/chexmonsters.txt" +#include "zscript/chex/chexkeys.txt" +#include "zscript/chex/chexammo.txt" +#include "zscript/chex/chexweapons.txt" +#include "zscript/chex/chexitems.txt" +#include "zscript/chex/chexdecorations.txt" +#include "zscript/chex/chexplayer.txt" From 1fc90b1ba9762aa606ebf857b8621e5035ca7839 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 15:59:02 +0100 Subject: [PATCH 456/471] - fixed: A_Face* should not require the target to be non-null. --- src/p_enemy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index beaa1548fc..da4e3cc45a 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3100,7 +3100,7 @@ void A_FaceTarget(AActor *self) DEFINE_ACTION_FUNCTION(AActor, A_Face) { PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT_NOT_NULL(faceto, AActor) + PARAM_OBJECT(faceto, AActor) PARAM_ANGLE_DEF(max_turn) PARAM_ANGLE_DEF(max_pitch) PARAM_ANGLE_DEF(ang_offset) From 21e3aba1c7cd9f539ab02160671efb5ae40d8ecc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 16:27:53 +0100 Subject: [PATCH 457/471] - optionally allow passing a script position object to V_GetColor and subfunctions for better error output. Implemented this for all occurences where this info was available. --- src/cmdlib.cpp | 21 +++------------ src/cmdlib.h | 4 +-- src/d_iwad.cpp | 4 +-- src/d_main.cpp | 4 +-- src/decallib.cpp | 8 +++--- src/g_mapinfo.cpp | 4 +-- src/menu/menudef.cpp | 4 +-- src/scripting/codegeneration/codegen.cpp | 2 +- src/scripting/decorate/thingdef_parse.cpp | 2 +- src/scripting/thingdef_properties.cpp | 3 +-- src/teaminfo.cpp | 2 +- src/textures/multipatchtexture.cpp | 2 +- src/v_font.cpp | 6 ++--- src/v_video.cpp | 31 +++++++++++++++-------- src/v_video.h | 8 +++--- 15 files changed, 51 insertions(+), 54 deletions(-) diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index 5799a23423..266ef47beb 100644 --- a/src/cmdlib.cpp +++ b/src/cmdlib.cpp @@ -15,6 +15,7 @@ #include "cmdlib.h" #include "i_system.h" #include "v_text.h" +#include "sc_man.h" #include #include @@ -324,7 +325,7 @@ FString ExtractFileBase (const char *path, bool include_extension) // //========================================================================== -int ParseHex (const char *hex) +int ParseHex (const char *hex, FScriptPosition *sc) { const char *str; int num; @@ -342,7 +343,8 @@ int ParseHex (const char *hex) else if (*str >= 'A' && *str <= 'F') num += 10 + *str-'A'; else { - Printf ("Bad hex number: %s\n",hex); + if (!sc) Printf ("Bad hex number: %s\n",hex); + else sc->Message(MSG_WARNING, "Bad hex number: %s", hex); return 0; } str++; @@ -351,21 +353,6 @@ int ParseHex (const char *hex) return num; } -//========================================================================== -// -// ParseNum -// -//========================================================================== - -int ParseNum (const char *str) -{ - if (str[0] == '$') - return ParseHex (str+1); - if (str[0] == '0' && str[1] == 'x') - return ParseHex (str+2); - return atol (str); -} - //========================================================================== // // IsNum diff --git a/src/cmdlib.h b/src/cmdlib.h index b035842cdf..6e9fcd622f 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -33,8 +33,8 @@ void DefaultExtension (FString &path, const char *extension); FString ExtractFilePath (const char *path); FString ExtractFileBase (const char *path, bool keep_extension=false); -int ParseHex (const char *str); -int ParseNum (const char *str); +struct FScriptPosition; +int ParseHex(const char *str, FScriptPosition *sc = nullptr); bool IsNum (const char *str); // [RH] added char *copystring(const char *s); diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 1fc63e03d3..b80cbaf988 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -193,10 +193,10 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize) { sc.MustGetStringName("="); sc.MustGetString(); - iwad->FgColor = V_GetColor(NULL, sc.String); + iwad->FgColor = V_GetColor(NULL, sc); sc.MustGetStringName(","); sc.MustGetString(); - iwad->BkColor = V_GetColor(NULL, sc.String); + iwad->BkColor = V_GetColor(NULL, sc); } else if (sc.Compare("Load")) { diff --git a/src/d_main.cpp b/src/d_main.cpp index 7cc40cc058..a2cb181f18 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1844,10 +1844,10 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char else if (!nextKey.CompareNoCase("STARTUPCOLORS")) { sc.MustGetString(); - DoomStartupInfo.FgColor = V_GetColor(NULL, sc.String); + DoomStartupInfo.FgColor = V_GetColor(NULL, sc); sc.MustGetStringName(","); sc.MustGetString(); - DoomStartupInfo.BkColor = V_GetColor(NULL, sc.String); + DoomStartupInfo.BkColor = V_GetColor(NULL, sc); } else if (!nextKey.CompareNoCase("STARTUPTYPE")) { diff --git a/src/decallib.cpp b/src/decallib.cpp index 9fe2966eb4..5d24e44d51 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -532,7 +532,7 @@ void FDecalLib::ParseDecal (FScanner &sc) sc.MustGetString (); if (!sc.Compare("BloodDefault")) { - newdecal.ShadeColor = V_GetColor (NULL, sc.String); + newdecal.ShadeColor = V_GetColor (NULL, sc); } else { @@ -547,8 +547,8 @@ void FDecalLib::ParseDecal (FScanner &sc) case DECAL_COLORS: DWORD startcolor, endcolor; - sc.MustGetString (); startcolor = V_GetColor (NULL, sc.String); - sc.MustGetString (); endcolor = V_GetColor (NULL, sc.String); + sc.MustGetString (); startcolor = V_GetColor (NULL, sc); + sc.MustGetString (); endcolor = V_GetColor (NULL, sc); newdecal.Translation = GenerateTranslation (startcolor, endcolor)->Index; break; @@ -819,7 +819,7 @@ void FDecalLib::ParseColorchanger (FScanner &sc) else if (sc.Compare ("Color")) { sc.MustGetString (); - goal = V_GetColor (NULL, sc.String); + goal = V_GetColor (NULL, sc); } else { diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index b839059014..5ffb04732b 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -860,14 +860,14 @@ DEFINE_MAP_OPTION(fade, true) { parse.ParseAssign(); parse.sc.MustGetString(); - info->fadeto = V_GetColor(NULL, parse.sc.String); + info->fadeto = V_GetColor(NULL, parse.sc); } DEFINE_MAP_OPTION(outsidefog, true) { parse.ParseAssign(); parse.sc.MustGetString(); - info->outsidefog = V_GetColor(NULL, parse.sc.String); + info->outsidefog = V_GetColor(NULL, parse.sc); } DEFINE_MAP_OPTION(titlepatch, true) diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 0fcf4e4d5a..d09cb40b6e 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -400,10 +400,10 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) int y = sc.Number; sc.MustGetStringName(","); sc.MustGetString(); - PalEntry c1 = V_GetColor(NULL, sc.String); + PalEntry c1 = V_GetColor(NULL, sc); sc.MustGetStringName(","); sc.MustGetString(); - PalEntry c2 = V_GetColor(NULL, sc.String); + PalEntry c2 = V_GetColor(NULL, sc); if (sc.CheckString(",")) { sc.MustGetNumber(); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c392d97d32..a0491f69d8 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1256,7 +1256,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx) } else { - FxExpression *x = new FxConstant(V_GetColor(nullptr, constval.GetString()), ScriptPosition); + FxExpression *x = new FxConstant(V_GetColor(nullptr, constval.GetString(), &ScriptPosition), ScriptPosition); delete this; return x; } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 442e52884f..f53b970067 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -165,7 +165,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c } else { - int c = V_GetColor (NULL, sc.String); + int c = V_GetColor (NULL, sc); // 0 needs to be the default so we have to mark the color. v = MAKEARGB(1, RPART(c), GPART(c), BPART(c)); } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 2eb5f67812..ef6309d4bd 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -2305,8 +2305,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory) *pBlendColor = MakeSpecialColormap(65535); return; } - - color = V_GetColor(NULL, name); + color = V_GetColor(NULL, name, &bag.ScriptPosition); } if (PROP_PARM_COUNT > 2) { diff --git a/src/teaminfo.cpp b/src/teaminfo.cpp index bf0ef8a40b..38ba56f4cd 100644 --- a/src/teaminfo.cpp +++ b/src/teaminfo.cpp @@ -182,7 +182,7 @@ void FTeam::ParseTeamDefinition (FScanner &Scan) case TEAMINFO_PlayerColor: Scan.MustGetString (); - Team.m_iPlayerColor = V_GetColor (NULL, Scan.String); + Team.m_iPlayerColor = V_GetColor (NULL, Scan); break; case TEAMINFO_TextColor: diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index de3dd2f131..e68c4e20f2 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -1097,7 +1097,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, TexInit &init) if (!sc.CheckNumber()) { sc.MustGetString(); - part.Blend = V_GetColor(NULL, sc.String); + part.Blend = V_GetColor(NULL, sc); } else { diff --git a/src/v_font.cpp b/src/v_font.cpp index 0eb28a67c3..f024e2d2ba 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -2300,19 +2300,19 @@ void V_InitFontColors () else if (sc.Compare ("Flat:")) { sc.MustGetString(); - logcolor = V_GetColor (NULL, sc.String); + logcolor = V_GetColor (NULL, sc); } else { // Get first color - c = V_GetColor (NULL, sc.String); + c = V_GetColor (NULL, sc); tparm.Start[0] = RPART(c); tparm.Start[1] = GPART(c); tparm.Start[2] = BPART(c); // Get second color sc.MustGetString(); - c = V_GetColor (NULL, sc.String); + c = V_GetColor (NULL, sc); tparm.End[0] = RPART(c); tparm.End[1] = GPART(c); tparm.End[2] = BPART(c); diff --git a/src/v_video.cpp b/src/v_video.cpp index 7192c5d033..efe93aa04a 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -44,6 +44,7 @@ #include "i_video.h" #include "v_video.h" #include "v_text.h" +#include "sc_man.h" #include "w_wad.h" @@ -437,7 +438,7 @@ void DCanvas::ReleaseScreenshotBuffer() // //========================================================================== -int V_GetColorFromString (const DWORD *palette, const char *cstr) +int V_GetColorFromString (const DWORD *palette, const char *cstr, FScriptPosition *sc) { int c[3], i, p; char val[3]; @@ -456,7 +457,7 @@ int V_GetColorFromString (const DWORD *palette, const char *cstr) { val[0] = cstr[1 + i*2]; val[1] = cstr[2 + i*2]; - c[i] = ParseHex (val); + c[i] = ParseHex (val, sc); } } else if (len == 4) @@ -465,7 +466,7 @@ int V_GetColorFromString (const DWORD *palette, const char *cstr) for (i = 0; i < 3; ++i) { val[1] = val[0] = cstr[1 + i]; - c[i] = ParseHex (val); + c[i] = ParseHex (val, sc); } } else @@ -518,7 +519,7 @@ normal: { val[1] = val[0]; } - c[i] = ParseHex (val); + c[i] = ParseHex (val, sc); } } } @@ -538,7 +539,7 @@ normal: // //========================================================================== -FString V_GetColorStringByName (const char *name) +FString V_GetColorStringByName (const char *name, FScriptPosition *sc) { FMemLump rgbNames; char *rgbEnd; @@ -552,7 +553,8 @@ FString V_GetColorStringByName (const char *name) rgblump = Wads.CheckNumForName ("X11R6RGB"); if (rgblump == -1) { - Printf ("X11R6RGB lump not found\n"); + if (!sc) Printf ("X11R6RGB lump not found\n"); + else sc->Message(MSG_WARNING, "X11R6RGB lump not found"); return FString(); } @@ -614,7 +616,8 @@ FString V_GetColorStringByName (const char *name) } if (rgb < rgbEnd) { - Printf ("X11R6RGB lump is corrupt\n"); + if (!sc) Printf ("X11R6RGB lump is corrupt\n"); + else sc->Message(MSG_WARNING, "X11R6RGB lump is corrupt"); } return FString(); } @@ -627,22 +630,28 @@ FString V_GetColorStringByName (const char *name) // //========================================================================== -int V_GetColor (const DWORD *palette, const char *str) +int V_GetColor (const DWORD *palette, const char *str, FScriptPosition *sc) { - FString string = V_GetColorStringByName (str); + FString string = V_GetColorStringByName (str, sc); int res; if (!string.IsEmpty()) { - res = V_GetColorFromString (palette, string); + res = V_GetColorFromString (palette, string, sc); } else { - res = V_GetColorFromString (palette, str); + res = V_GetColorFromString (palette, str, sc); } return res; } +int V_GetColor(const DWORD *palette, FScanner &sc) +{ + FScriptPosition scc = sc; + return V_GetColor(palette, sc.String, &scc); +} + //========================================================================== // // BuildTransTable diff --git a/src/v_video.h b/src/v_video.h index 890ab6d638..971aa6c13d 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -497,15 +497,17 @@ void V_Shutdown (); void V_MarkRect (int x, int y, int width, int height); +class FScanner; // Returns the closest color to the one desired. String // should be of the form "rr gg bb". -int V_GetColorFromString (const DWORD *palette, const char *colorstring); +int V_GetColorFromString (const DWORD *palette, const char *colorstring, FScriptPosition *sc = nullptr); // Scans through the X11R6RGB lump for a matching color // and returns a color string suitable for V_GetColorFromString. -FString V_GetColorStringByName (const char *name); +FString V_GetColorStringByName (const char *name, FScriptPosition *sc = nullptr); // Tries to get color by name, then by string -int V_GetColor (const DWORD *palette, const char *str); +int V_GetColor (const DWORD *palette, const char *str, FScriptPosition *sc = nullptr); +int V_GetColor(const DWORD *palette, FScanner &sc); void V_DrawFrame (int left, int top, int width, int height); // If the view size is not full screen, draws a border around it. From 71bda99c3b7da3f1816e988d59793b9579c79f2d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 18:14:07 +0100 Subject: [PATCH 458/471] - fixed: DECORATE didn't pass all needed arguments to FunctionBuildList.AddFunction. Removed the default parameter values from this function's declaration to prevent it from happening again. --- src/scripting/decorate/thingdef_states.cpp | 2 +- src/scripting/thingdef.cpp | 4 ++-- src/scripting/thingdef.h | 2 +- src/scripting/thingdef_properties.cpp | 2 +- src/scripting/vm/vmbuilder.h | 2 +- src/scripting/zscript/zcc_compile.cpp | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 1cb0a91afd..671481de13 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -343,7 +343,7 @@ endofstate: 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); + state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true, bag.statedef.GetStateCount(), int(statestring.Len()), sc.LumpNum); } int count = bag.statedef.AddStates(&state, statestring, scp); if (count < 0) diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index e1d5f9b270..5d2d251a9f 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -219,7 +219,7 @@ PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName nam // //========================================================================== -void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate) +void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum) { if (id == nullptr) { @@ -229,7 +229,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, { 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); + defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate, -1, 0, lumpnum); } } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index dd8529252f..9d41b5265b 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -160,7 +160,7 @@ FName CheckCastKludges(FName in); void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PStruct *cls, DWORD funcflags, int useflags); PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error); -void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate); +void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum); //========================================================================== // diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index ef6309d4bd..9eb050a83e 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -664,7 +664,7 @@ DEFINE_PROPERTY(damage, X, Actor) defaults->DamageVal = dmgval; // Only DECORATE can get here with a valid expression. - CreateDamageFunction(bag.Info, defaults, id, true); + CreateDamageFunction(bag.Info, defaults, id, true, bag.Lumpnum); } //========================================================================== diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 7c086ac0c8..da099256ed 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -149,7 +149,7 @@ class FFunctionBuildList TArray mItems; public: - VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate = -1, int statecnt = 0, int lumpnum = -1); + VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate, int statecnt, int lumpnum); void Build(); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6eb675b891..5f7ff836ad 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1842,7 +1842,7 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro if (namenode->Id == NAME_DamageFunction) { auto x = ConvertNode(prop->Values); - CreateDamageFunction(cls, (AActor *)bag.Info->Defaults, x, false); + CreateDamageFunction(cls, (AActor *)bag.Info->Defaults, x, false, Lump); ((AActor *)bag.Info->Defaults)->DamageVal = -1; return; } From 34970c9b9cb68db1385f84307bdea29748ea8ec7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 18:49:52 +0100 Subject: [PATCH 459/471] - removed hexenglobal include from GL files. --- src/gl/renderer/gl_postprocess.cpp | 1 - src/gl/scene/gl_scene.cpp | 1 - src/gl/system/gl_framebuffer.cpp | 2 +- src/win32/win32gliface.cpp | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 52339e5870..6d080434dc 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -40,7 +40,6 @@ #include "sbar.h" #include "po_man.h" #include "r_utility.h" -#include "a_hexenglobal.h" #include "p_local.h" #include "colormatcher.h" #include "gl/gl_functions.h" diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 1437d3fd5d..0cf0fa0a1e 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -40,7 +40,6 @@ #include "sbar.h" #include "po_man.h" #include "r_utility.h" -#include "a_hexenglobal.h" #include "p_local.h" #include "gl/gl_functions.h" #include "serializer.h" diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 259cef5e0e..7102df72ea 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -53,7 +53,7 @@ #include "gl/renderer/gl_2ddrawer.h" #include "gl_debug.h" -IMPLEMENT_CLASS(OpenGLFrameBuffer, false, false, false, false) +IMPLEMENT_CLASS(OpenGLFrameBuffer, false, false) EXTERN_CVAR (Float, vid_brightness) EXTERN_CVAR (Float, vid_contrast) EXTERN_CVAR (Bool, vid_vsync) diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index 6b9e413af5..aa4755e483 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -854,7 +854,7 @@ bool Win32GLVideo::SetFullscreen(const char *devicename, int w, int h, int bits, // //========================================================================== -IMPLEMENT_CLASS(Win32GLFrameBuffer, true, false, false, false) +IMPLEMENT_CLASS(Win32GLFrameBuffer, true, false) //========================================================================== // From 5dd63a86cf2b585972fd994fa6cc9eac5ac9aa01 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 18:59:28 +0100 Subject: [PATCH 460/471] - removed excess arguments for IMPLEMENT_CLASS. --- src/gl/dynlights/a_dynlight.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp index 5c85fce85c..f705a4d5b6 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -106,10 +106,10 @@ DEFINE_CLASS_PROPERTY(type, S, DynamicLight) // which is controlled by flags // //========================================================================== -IMPLEMENT_CLASS (ADynamicLight, false, false, false, false) -IMPLEMENT_CLASS (AVavoomLight, false, false, false, false) -IMPLEMENT_CLASS (AVavoomLightWhite, false, false, false, false) -IMPLEMENT_CLASS (AVavoomLightColor, false, false, false, false) +IMPLEMENT_CLASS (ADynamicLight, false, false) +IMPLEMENT_CLASS (AVavoomLight, false, false) +IMPLEMENT_CLASS (AVavoomLightWhite, false, false) +IMPLEMENT_CLASS (AVavoomLightColor, false, false) void AVavoomLight::BeginPlay () { From 04f5be624985694b0fb7360afbeb103264767f21 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 19:14:20 +0100 Subject: [PATCH 461/471] - zcc_compile.cpp needs to include version.h for the DYNLIGHT #define. --- src/scripting/zscript/zcc_compile.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 5f7ff836ad..98a1a5ff3f 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -50,6 +50,7 @@ #include "gdtoa.h" #include "codegeneration/codegen.h" #include "vmbuilder.h" +#include "version.h" //========================================================================== // From 834802def36d59ed34a76cdb83817a68546ee917 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 19:49:32 +0100 Subject: [PATCH 462/471] - sanitized the old sprite offset adjustment feature and used it to redefine offsets for some sprites that have really bad ones. --- src/gl/data/gl_data.cpp | 27 +- wadsrc/static/filter/doom.doom1/sprofs.txt | 164 +++++++++ wadsrc/static/filter/doom.doom2/sprofs.txt | 164 +++++++++ wadsrc/static/filter/heretic/sprofs.txt | 97 ++++++ wadsrc/static/filter/hexen/sprofs.txt | 377 +++++++++++++++++++++ wadsrc/static/filter/strife/sprofs.txt | 364 ++++++++++++++++++++ 6 files changed, 1180 insertions(+), 13 deletions(-) create mode 100644 wadsrc/static/filter/doom.doom1/sprofs.txt create mode 100644 wadsrc/static/filter/doom.doom2/sprofs.txt create mode 100644 wadsrc/static/filter/heretic/sprofs.txt create mode 100644 wadsrc/static/filter/hexen/sprofs.txt create mode 100644 wadsrc/static/filter/strife/sprofs.txt diff --git a/src/gl/data/gl_data.cpp b/src/gl/data/gl_data.cpp index ad9c824bbd..c3516499b1 100644 --- a/src/gl/data/gl_data.cpp +++ b/src/gl/data/gl_data.cpp @@ -85,29 +85,30 @@ void gl_CreateSections(); void AdjustSpriteOffsets() { - static bool done=false; - char name[30]; - - if (done) return; - done=true; - - mysnprintf(name, countof(name), "sprofs/%s.sprofs", GameNames[gameinfo.gametype]); - int lump = Wads.CheckNumForFullName(name); - if (lump>=0) + int lump, lastlump = 0; + while ((lump = Wads.FindLump("SPROFS", &lastlump, false)) != -1) { FScanner sc; sc.OpenLumpNum(lump); + sc.SetCMode(true); GLRenderer->FlushTextures(); int ofslumpno = Wads.GetLumpFile(lump); while (sc.GetString()) { int x,y; + bool iwadonly = false; FTextureID texno = TexMan.CheckForTexture(sc.String, FTexture::TEX_Sprite); - sc.GetNumber(); + sc.MustGetStringName(","); + sc.MustGetNumber(); x=sc.Number; - sc.GetNumber(); + sc.MustGetStringName(","); + sc.MustGetNumber(); y=sc.Number; - + if (sc.CheckString(",")) + { + sc.MustGetString(); + if (sc.Compare("iwad")) iwadonly = true; + } if (texno.isValid()) { FTexture * tex = TexMan[texno]; @@ -117,7 +118,7 @@ void AdjustSpriteOffsets() if (lumpnum >= 0 && lumpnum < Wads.GetNumLumps()) { int wadno = Wads.GetLumpFile(lumpnum); - if (wadno==FWadCollection::IWAD_FILENUM || wadno == ofslumpno) + if ((iwadonly && wadno==FWadCollection::IWAD_FILENUM) || (!iwadonly && wadno == ofslumpno)) { tex->LeftOffset=x; tex->TopOffset=y; diff --git a/wadsrc/static/filter/doom.doom1/sprofs.txt b/wadsrc/static/filter/doom.doom1/sprofs.txt new file mode 100644 index 0000000000..eab3dc4ef0 --- /dev/null +++ b/wadsrc/static/filter/doom.doom1/sprofs.txt @@ -0,0 +1,164 @@ +BAR1A0, 10, 32, iwad +BAR1B0, 10, 32, iwad +BEXPA0, 10, 32, iwad +BEXPB0, 10, 31, iwad +BEXPC0, 19, 36, iwad +BEXPD0, 27, 49, iwad +BEXPE0, 29, 52, iwad +BOS2I0, 20, 71, iwad +BOS2J0, 26, 62, iwad +BOS2K0, 26, 52, iwad +BOS2L0, 29, 33, iwad +BOS2M0, 30, 29, iwad +BOS2N0, 30, 29, iwad +BOS2O0, 30, 29, iwad +BOSSI0, 20, 72, iwad +BOSSJ0, 26, 63, iwad +BOSSK0, 26, 51, iwad +BOSSL0, 29, 33, iwad +BOSSM0, 30, 29, iwad +BOSSN0, 30, 29, iwad +BOSSO0, 30, 29, iwad +BRS1A0, 13, 8, iwad +BSPIJ0, 50, 54, iwad +BSPIK0, 50, 57, iwad +BSPIL0, 47, 52, iwad +BSPIM0, 45, 44, iwad +BSPIN0, 45, 42, iwad +BSPIO0, 45, 30, iwad +BSPIP0, 45, 28, iwad +CBRAA0, 15, 60, iwad +CEYEA0, 21, 59, iwad +CEYEB0, 21, 58, iwad +CEYEC0, 21, 59, iwad +COL1A0, 16, 51, iwad +COL2A0, 16, 39, iwad +COL3A0, 16, 52, iwad +COL4A0, 17, 39, iwad +COL5A0, 16, 44, iwad +COL5B0, 16, 45, iwad +COL6A0, 17, 47, iwad +COLUA0, 9, 45, iwad +CPOSH0, 20, 61, iwad +CPOSI0, 23, 64, iwad +CPOSJ0, 28, 59, iwad +CPOSK0, 30, 48, iwad +CPOSL0, 31, 34, iwad +CPOSM0, 32, 22, iwad +CPOSN0, 32, 18, iwad +CPOSO0, 26, 59, iwad +CPOSP0, 28, 59, iwad +CPOSQ0, 30, 48, iwad +CPOSR0, 32, 40, iwad +CPOSS0, 32, 31, iwad +CPOST0, 32, 19, iwad +CYBRH0, 60, 108, iwad +CYBRI0, 55, 110, iwad +CYBRJ0, 49, 113, iwad +CYBRK0, 56, 114, iwad +CYBRL0, 62, 121, iwad +CYBRM0, 67, 128, iwad +CYBRN0, 70, 132, iwad +CYBRO0, 69, 132, iwad +CYBRP0, 60, 28, iwad +ELECA0, 19, 125, iwad +FATTO0, 35, 43, iwad +FATTP0, 36, 41, iwad +FATTQ0, 36, 40, iwad +FATTR0, 36, 40, iwad +FATTS0, 36, 40, iwad +FATTT0, 36, 39, iwad +FCANA0, 19, 52, iwad +FCANB0, 19, 52, iwad +FCANC0, 19, 50, iwad +PLAYH0, 16, 50, iwad +PLAYI0, 11, 42, iwad +PLAYJ0, 12, 45, iwad +PLAYK0, 17, 37, iwad +PLAYL0, 27, 14, iwad +PLAYM0, 27, 14, iwad +PLAYN0, 27, 14, iwad +POB1A0, 16, 6, iwad +POB2A0, 14, 3, iwad +POL1A0, 22, 65, iwad +POL2A0, 19, 66, iwad +POL3A0, 19, 42, iwad +POL3B0, 19, 42, iwad +POL4A0, 19, 55, iwad +POL5A0, 27, 8, iwad +POL6A0, 17, 65, iwad +POL6B0, 19, 65, iwad +POSSH0, 19, 55, iwad +POSSL0, 22, 14, iwad +SARGI0, 25, 56, iwad +SARGM0, 33, 43, iwad +SARGN0, 33, 29, iwad +SKELM0, 27, 78, iwad +SKELN0, 38, 69, iwad +SKELO0, 28, 55, iwad +SKELP0, 28, 35, iwad +SKELQ0, 40, 20, iwad +SMITA0, 22, 44, iwad +SPIDJ0, 79, 102, iwad +SPIDK0, 95, 95, iwad +SPIDL0, 94, 88, iwad +SPIDM0, 94, 76, iwad +SPIDN0, 98, 71, iwad +SPIDO0, 101, 68, iwad +SPIDP0, 104, 85, iwad +SPIDQ0, 109, 90, iwad +SPIDR0, 110, 111, iwad +SPIDS0, 98, 35, iwad +SPOSH0, 14, 60, iwad +SPOSL0, 24, 15, iwad +SSWVG0, 17, 55, iwad +SSWVH0, 17, 52, iwad +SSWVI0, 18, 54, iwad +SSWVJ0, 15, 44, iwad +SSWVK0, 15, 40, iwad +SSWVL0, 15, 25, iwad +SSWVM0, 24, 13, iwad +SSWVN0, 15, 57, iwad +SSWVO0, 22, 59, iwad +SSWVP0, 25, 58, iwad +TBLUA0, 14, 94, iwad +TBLUB0, 14, 94, iwad +TBLUC0, 14, 94, iwad +TBLUD0, 14, 95, iwad +TGRNA0, 14, 94, iwad +TGRNB0, 14, 89, iwad +TGRNC0, 14, 89, iwad +TGRND0, 14, 95, iwad +TLMPA0, 11, 78, iwad +TLMPB0, 11, 78, iwad +TLMPC0, 11, 78, iwad +TLMPD0, 11, 78, iwad +TLP2A0, 10, 58, iwad +TLP2B0, 10, 58, iwad +TLP2C0, 10, 58, iwad +TLP2D0, 10, 58, iwad +TRE1A0, 25, 67, iwad +TREDA0, 14, 94, iwad +TREDB0, 14, 89, iwad +TREDC0, 14, 89, iwad +TREDD0, 14, 95, iwad +TROOI0, 22, 62, iwad +TROOJ0, 21, 59, iwad +TROOM0, 29, 20, iwad +TROON0, 24, 59, iwad +TROOO0, 20, 61, iwad +TROOP0, 24, 61, iwad +TROOQ0, 24, 61, iwad +TROOR0, 24, 44, iwad +TROOS0, 27, 34, iwad +TROOT0, 27, 31, iwad +TROOU0, 27, 18, iwad +VILER0, 18, 80, iwad +VILES0, 23, 76, iwad +VILET0, 27, 69, iwad +VILEU0, 35, 56, iwad +VILEV0, 34, 45, iwad +VILEW0, 34, 35, iwad +VILEX0, 34, 23, iwad +VILEY0, 34, 20, iwad +VILEZ0, 34, 20, iwad diff --git a/wadsrc/static/filter/doom.doom2/sprofs.txt b/wadsrc/static/filter/doom.doom2/sprofs.txt new file mode 100644 index 0000000000..eab3dc4ef0 --- /dev/null +++ b/wadsrc/static/filter/doom.doom2/sprofs.txt @@ -0,0 +1,164 @@ +BAR1A0, 10, 32, iwad +BAR1B0, 10, 32, iwad +BEXPA0, 10, 32, iwad +BEXPB0, 10, 31, iwad +BEXPC0, 19, 36, iwad +BEXPD0, 27, 49, iwad +BEXPE0, 29, 52, iwad +BOS2I0, 20, 71, iwad +BOS2J0, 26, 62, iwad +BOS2K0, 26, 52, iwad +BOS2L0, 29, 33, iwad +BOS2M0, 30, 29, iwad +BOS2N0, 30, 29, iwad +BOS2O0, 30, 29, iwad +BOSSI0, 20, 72, iwad +BOSSJ0, 26, 63, iwad +BOSSK0, 26, 51, iwad +BOSSL0, 29, 33, iwad +BOSSM0, 30, 29, iwad +BOSSN0, 30, 29, iwad +BOSSO0, 30, 29, iwad +BRS1A0, 13, 8, iwad +BSPIJ0, 50, 54, iwad +BSPIK0, 50, 57, iwad +BSPIL0, 47, 52, iwad +BSPIM0, 45, 44, iwad +BSPIN0, 45, 42, iwad +BSPIO0, 45, 30, iwad +BSPIP0, 45, 28, iwad +CBRAA0, 15, 60, iwad +CEYEA0, 21, 59, iwad +CEYEB0, 21, 58, iwad +CEYEC0, 21, 59, iwad +COL1A0, 16, 51, iwad +COL2A0, 16, 39, iwad +COL3A0, 16, 52, iwad +COL4A0, 17, 39, iwad +COL5A0, 16, 44, iwad +COL5B0, 16, 45, iwad +COL6A0, 17, 47, iwad +COLUA0, 9, 45, iwad +CPOSH0, 20, 61, iwad +CPOSI0, 23, 64, iwad +CPOSJ0, 28, 59, iwad +CPOSK0, 30, 48, iwad +CPOSL0, 31, 34, iwad +CPOSM0, 32, 22, iwad +CPOSN0, 32, 18, iwad +CPOSO0, 26, 59, iwad +CPOSP0, 28, 59, iwad +CPOSQ0, 30, 48, iwad +CPOSR0, 32, 40, iwad +CPOSS0, 32, 31, iwad +CPOST0, 32, 19, iwad +CYBRH0, 60, 108, iwad +CYBRI0, 55, 110, iwad +CYBRJ0, 49, 113, iwad +CYBRK0, 56, 114, iwad +CYBRL0, 62, 121, iwad +CYBRM0, 67, 128, iwad +CYBRN0, 70, 132, iwad +CYBRO0, 69, 132, iwad +CYBRP0, 60, 28, iwad +ELECA0, 19, 125, iwad +FATTO0, 35, 43, iwad +FATTP0, 36, 41, iwad +FATTQ0, 36, 40, iwad +FATTR0, 36, 40, iwad +FATTS0, 36, 40, iwad +FATTT0, 36, 39, iwad +FCANA0, 19, 52, iwad +FCANB0, 19, 52, iwad +FCANC0, 19, 50, iwad +PLAYH0, 16, 50, iwad +PLAYI0, 11, 42, iwad +PLAYJ0, 12, 45, iwad +PLAYK0, 17, 37, iwad +PLAYL0, 27, 14, iwad +PLAYM0, 27, 14, iwad +PLAYN0, 27, 14, iwad +POB1A0, 16, 6, iwad +POB2A0, 14, 3, iwad +POL1A0, 22, 65, iwad +POL2A0, 19, 66, iwad +POL3A0, 19, 42, iwad +POL3B0, 19, 42, iwad +POL4A0, 19, 55, iwad +POL5A0, 27, 8, iwad +POL6A0, 17, 65, iwad +POL6B0, 19, 65, iwad +POSSH0, 19, 55, iwad +POSSL0, 22, 14, iwad +SARGI0, 25, 56, iwad +SARGM0, 33, 43, iwad +SARGN0, 33, 29, iwad +SKELM0, 27, 78, iwad +SKELN0, 38, 69, iwad +SKELO0, 28, 55, iwad +SKELP0, 28, 35, iwad +SKELQ0, 40, 20, iwad +SMITA0, 22, 44, iwad +SPIDJ0, 79, 102, iwad +SPIDK0, 95, 95, iwad +SPIDL0, 94, 88, iwad +SPIDM0, 94, 76, iwad +SPIDN0, 98, 71, iwad +SPIDO0, 101, 68, iwad +SPIDP0, 104, 85, iwad +SPIDQ0, 109, 90, iwad +SPIDR0, 110, 111, iwad +SPIDS0, 98, 35, iwad +SPOSH0, 14, 60, iwad +SPOSL0, 24, 15, iwad +SSWVG0, 17, 55, iwad +SSWVH0, 17, 52, iwad +SSWVI0, 18, 54, iwad +SSWVJ0, 15, 44, iwad +SSWVK0, 15, 40, iwad +SSWVL0, 15, 25, iwad +SSWVM0, 24, 13, iwad +SSWVN0, 15, 57, iwad +SSWVO0, 22, 59, iwad +SSWVP0, 25, 58, iwad +TBLUA0, 14, 94, iwad +TBLUB0, 14, 94, iwad +TBLUC0, 14, 94, iwad +TBLUD0, 14, 95, iwad +TGRNA0, 14, 94, iwad +TGRNB0, 14, 89, iwad +TGRNC0, 14, 89, iwad +TGRND0, 14, 95, iwad +TLMPA0, 11, 78, iwad +TLMPB0, 11, 78, iwad +TLMPC0, 11, 78, iwad +TLMPD0, 11, 78, iwad +TLP2A0, 10, 58, iwad +TLP2B0, 10, 58, iwad +TLP2C0, 10, 58, iwad +TLP2D0, 10, 58, iwad +TRE1A0, 25, 67, iwad +TREDA0, 14, 94, iwad +TREDB0, 14, 89, iwad +TREDC0, 14, 89, iwad +TREDD0, 14, 95, iwad +TROOI0, 22, 62, iwad +TROOJ0, 21, 59, iwad +TROOM0, 29, 20, iwad +TROON0, 24, 59, iwad +TROOO0, 20, 61, iwad +TROOP0, 24, 61, iwad +TROOQ0, 24, 61, iwad +TROOR0, 24, 44, iwad +TROOS0, 27, 34, iwad +TROOT0, 27, 31, iwad +TROOU0, 27, 18, iwad +VILER0, 18, 80, iwad +VILES0, 23, 76, iwad +VILET0, 27, 69, iwad +VILEU0, 35, 56, iwad +VILEV0, 34, 45, iwad +VILEW0, 34, 35, iwad +VILEX0, 34, 23, iwad +VILEY0, 34, 20, iwad +VILEZ0, 34, 20, iwad diff --git a/wadsrc/static/filter/heretic/sprofs.txt b/wadsrc/static/filter/heretic/sprofs.txt new file mode 100644 index 0000000000..5f51dcde1f --- /dev/null +++ b/wadsrc/static/filter/heretic/sprofs.txt @@ -0,0 +1,97 @@ +BARLA0, 14, 35, iwad +BEASK0, 37, 77, iwad +BEASM0, 42, 74, iwad +BEASQ0, 29, 11, iwad +BEASU0, 44, 91, iwad +BEASV0, 49, 79, iwad +BEASW0, 51, 68, iwad +BEASX0, 52, 56, iwad +BEASY0, 41, 41, iwad +BEASZ0, 41, 30, iwad +BRPLA0, 28, 128, iwad +CHKNF0, 18, 25, iwad +CHKNG0, 17, 27, iwad +CHKNH0, 18, 30, iwad +CHKNI0, 20, 29, iwad +CHKNJ0, 20, 25, iwad +CHKNK0, 17, 9, iwad +CHKNL0, 13, 4, iwad +CLNKO0, 23, 16, iwad +FDTHA0, 21, 55, iwad +FDTHB0, 21, 60, iwad +FDTHC0, 29, 80, iwad +FDTHD0, 21, 76, iwad +FDTHE0, 22, 75, iwad +FDTHF0, 23, 59, iwad +FDTHG0, 24, 51, iwad +FDTHH0, 23, 48, iwad +FDTHI0, 23, 53, iwad +FDTHJ0, 22, 53, iwad +FDTHK0, 22, 55, iwad +FDTHL0, 23, 56, iwad +FDTHM0, 25, 58, iwad +FDTHN0, 26, 58, iwad +FDTHO0, 24, 59, iwad +IMPXI0, 22, 24, iwad +IMPXJ0, 22, 34, iwad +IMPXK0, 21, 34, iwad +IMPXL0, 22, 9, iwad +IMPXW0, 32, 49, iwad +IMPXX0, 33, 41, iwad +IMPXY0, 33, 25, iwad +IMPXZ0, 33, 11, iwad +KFR1A0, 20, 77, iwad +KFR1B0, 20, 78, iwad +KFR1C0, 20, 81, iwad +KFR1D0, 20, 81, iwad +KFR1E0, 20, 76, iwad +KFR1F0, 20, 78, iwad +KFR1G0, 20, 80, iwad +KFR1H0, 20, 78, iwad +KGZ1A0, 18, 52, iwad +MUMMI0, 33, 64, iwad +MUMMJ0, 34, 66, iwad +MUMMK0, 39, 71, iwad +MUMML0, 40, 66, iwad +MUMMM0, 36, 55, iwad +MUMMN0, 37, 37, iwad +MUMMO0, 38, 19, iwad +MUMMP0, 31, 10, iwad +PLAYS0, 34, 71, iwad +PLAYT0, 35, 68, iwad +PLAYU0, 30, 44, iwad +PLAYV0, 30, 24, iwad +PLAYW0, 30, 23, iwad +PLAYX0, 30, 17, iwad +PLAYY0, 30, 14, iwad +SFFIA0, 5, 20, iwad +SFFIB0, 6, 15, iwad +SFFIC0, 6, 11, iwad +SFFID0, 5, 8, iwad +SFFIE0, 4, 5, iwad +SMPLA0, 14, 37, iwad +SNKEM0, 54, 48, iwad +SNKEN0, 49, 35, iwad +SNKEO0, 48, 23, iwad +SNKEP0, 46, 13, iwad +SRCRE0, 59, 131, iwad +SRCRF0, 52, 120, iwad +SRCRG0, 68, 122, iwad +SRCRH0, 60, 114, iwad +SRCRI0, 63, 105, iwad +SRCRJ0, 67, 76, iwad +SRCRK0, 67, 32, iwad +SRCRL0, 67, 23, iwad +SRCRM0, 67, 28, iwad +SRCRN0, 67, 29, iwad +SRCRO0, 67, 23, iwad +SRCRP0, 67, 17, iwad +SRTCA0, 5, 63, iwad +SRTCB0, 5, 63, iwad +SRTCC0, 5, 61, iwad +STGLA0, 18, 69, iwad +STGSA0, 9, 37, iwad +WZRDJ0, 34, 59, iwad +WZRDK0, 30, 49, iwad +WZRDL0, 29, 26, iwad +WZRDM0, 27, 12, iwad diff --git a/wadsrc/static/filter/hexen/sprofs.txt b/wadsrc/static/filter/hexen/sprofs.txt new file mode 100644 index 0000000000..a8d614ca07 --- /dev/null +++ b/wadsrc/static/filter/hexen/sprofs.txt @@ -0,0 +1,377 @@ +ZBARA0, 12, 33, iwad +BDPLA0, 7, 2, iwad +BDSHA0, 8, 6, iwad +BDSHB0, 8, 7, iwad +BDSHC0, 8, 7, iwad +BDSHD0, 9, 5, iwad +BISHK0, 43, 74, iwad +BISHL0, 45, 74, iwad +BISHM0, 45, 65, iwad +BISHN0, 43, 22, iwad +BISHO0, 40, 12, iwad +BISHP0, 30, 9, iwad +BRTRA0, 13, 61, iwad +BRTRB0, 13, 59, iwad +BRTRC0, 13, 57, iwad +BRTRD0, 13, 60, iwad +BRTRE0, 13, 59, iwad +BRTRF0, 13, 54, iwad +BRTRG0, 13, 54, iwad +BRTRH0, 13, 57, iwad +BRTRI0, 13, 60, iwad +BRTRJ0, 13, 62, iwad +BRTRK0, 13, 62, iwad +BRTRL0, 13, 58, iwad +BRTRM0, 13, 59, iwad +BCANA0, 10, 38, iwad +BCANB0, 10, 36, iwad +BCANC0, 10, 35, iwad +BCAND0, 10, 35, iwad +BCANE0, 10, 35, iwad +CDRNA0, 14, 24, iwad +CDRNB0, 14, 24, iwad +CDRNC0, 14, 24, iwad +CDRND0, 14, 24, iwad +CDRNE0, 14, 24, iwad +CDRNF0, 14, 24, iwad +CDRNG0, 14, 24, iwad +CDRNH0, 14, 24, iwad +CENTK0, 42, 73, iwad +CENTN0, 49, 76, iwad +CENTO0, 45, 83, iwad +CENTP0, 47, 80, iwad +CENTQ0, 55, 63, iwad +CENTR0, 53, 38, iwad +CENTS0, 43, 27, iwad +CENTT0, 43, 27, iwad +CLERM0, 28, 51, iwad +CLERN0, 26, 42, iwad +CLERO0, 26, 34, iwad +CLERQ0, 26, 16, iwad +CLERR0, 23, 67, iwad +CLERS0, 30, 67, iwad +CLERT0, 35, 68, iwad +CLERU0, 34, 64, iwad +CLERV0, 35, 61, iwad +CLERW0, 37, 53, iwad +CLERX0, 37, 43, iwad +CLERY0, 38, 30, iwad +CLERZ0, 38, 18, iwad +CLER[0, 38, 12, iwad +CPB1A0, 8, 7, iwad +CPB2A0, 7, 6, iwad +CPB3A0, 12, 4, iwad +CPB4A0, 5, 10, iwad +CPS2A0, 24, 13, iwad +CPS6A0, 22, 36, iwad +CTDPJ0, 21, 9, iwad +DEM2H0, 50, 92, iwad +DEM2I0, 67, 124, iwad +DEM2J0, 60, 121, iwad +DEM2K0, 76, 123, iwad +DEM2L0, 68, 115, iwad +DEM2M0, 71, 105, iwad +DEM2N0, 75, 76, iwad +DEM2O0, 75, 32, iwad +DEM2P0, 75, 17, iwad +DEMNH0, 50, 92, iwad +DEMNI0, 67, 124, iwad +DEMNJ0, 60, 121, iwad +DEMNK0, 76, 123, iwad +DEMNL0, 68, 115, iwad +DEMNM0, 71, 105, iwad +DEMNN0, 75, 76, iwad +DEMNO0, 75, 32, iwad +DEMNP0, 75, 17, iwad +DRAGM0, 45, 22, iwad +ETTBB0, 45, 73, iwad +ETTBC0, 39, 80, iwad +ETTBD0, 45, 87, iwad +ETTBE0, 51, 84, iwad +ETTBF0, 53, 74, iwad +ETTBG0, 48, 70, iwad +ETTBH0, 49, 64, iwad +ETTBI0, 50, 52, iwad +ETTBJ0, 50, 31, iwad +ETTBK0, 50, 22, iwad +ETTBL0, 50, 22, iwad +ETTBM0, 14, 20, iwad +ETTNO0, 42, 46, iwad +ETTNP0, 42, 56, iwad +ETTNQ0, 36, 34, iwad +FDTHA0, 29, 64, iwad +FDTHB0, 29, 64, iwad +FDTHE0, 28, 62, iwad +FDTHF0, 28, 62, iwad +FDTHG0, 29, 80, iwad +FDTHH0, 17, 76, iwad +FDTHI0, 19, 76, iwad +FDTHJ0, 20, 56, iwad +FDTHK0, 21, 51, iwad +FDTHL0, 21, 47, iwad +FDTHM0, 21, 46, iwad +FDTHN0, 21, 47, iwad +FDTHO0, 20, 49, iwad +FDTHP0, 21, 49, iwad +FDTHQ0, 19, 50, iwad +FDTHR0, 20, 51, iwad +FFLGA0, 4, 4, iwad +FFLGB0, 4, 11, iwad +FFLGC0, 6, 24, iwad +FFLGD0, 10, 28, iwad +FFLGE0, 6, 35, iwad +FFLGF0, 7, 40, iwad +FFLGG0, 7, 40, iwad +FFLGH0, 7, 34, iwad +FFLGI0, 7, 33, iwad +FFLGJ0, 7, 28, iwad +FFLGK0, 7, 28, iwad +FFLGL0, 7, 31, iwad +FFLGM0, 7, 34, iwad +FFLGN0, 7, 37, iwad +FFLGO0, 7, 39, iwad +FFLGP0, 7, 40, iwad +FFLGQ0, 7, 33, iwad +FFSMA0, 2, 20, iwad +FFSMB0, 2, 20, iwad +FFSMC0, 2, 18, iwad +FFSMD0, 2, 16, iwad +FFSME0, 2, 17, iwad +FSKLA0, 11, 54, iwad +FSKLB0, 11, 52, iwad +FSKLC0, 11, 50, iwad +FSKLD0, 11, 53, iwad +FSKLE0, 11, 47, iwad +FSKLF0, 11, 47, iwad +FSKLG0, 11, 53, iwad +FSKLH0, 11, 48, iwad +FSKLI0, 11, 51, iwad +GAR1A0, 25, 121, iwad +GAR2A0, 25, 121, iwad +GAR3A0, 25, 121, iwad +GAR4A0, 25, 121, iwad +GAR5A0, 25, 121, iwad +GAR6A0, 25, 75, iwad +GAR7A0, 25, 75, iwad +GAR8A0, 24, 75, iwad +GAR9A0, 25, 75, iwad +GMPDA0, 14, 46, iwad +GMPDB0, 14, 53, iwad +ICM4A0, 2, 23, iwad +IRONA0, 23, 62, iwad +LOGGA0, 20, 55, iwad +MAGEK0, 41, 42, iwad +MAGEL0, 43, 33, iwad +MAGEM0, 43, 21, iwad +MAGEN0, 31, 12, iwad +MAGEO0, 26, 71, iwad +MAGEP0, 30, 72, iwad +MAGEQ0, 33, 66, iwad +MAGER0, 34, 60, iwad +MAGES0, 36, 57, iwad +MAGET0, 37, 50, iwad +MAGEU0, 35, 39, iwad +MAGEV0, 36, 30, iwad +MAGEW0, 35, 18, iwad +MAGEX0, 35, 9, iwad +MSH1A0, 15, 25, iwad +MSH2A0, 13, 25, iwad +MSH3A0, 11, 21, iwad +MSH4A0, 7, 15, iwad +MSH5A0, 7, 11, iwad +MSH6A0, 6, 11, iwad +MSH7A0, 7, 12, iwad +MSH8A0, 5, 16, iwad +PIGYE0, 12, 24, iwad +PIGYF0, 17, 29, iwad +PIGYG0, 22, 41, iwad +PLAYL0, 36, 42, iwad +PLAYM0, 36, 31, iwad +PLAYN0, 40, 17, iwad +PLAYO0, 24, 72, iwad +PLAYP0, 31, 74, iwad +PLAYQ0, 35, 70, iwad +PLAYR0, 38, 64, iwad +PLAYS0, 38, 55, iwad +PLAYT0, 40, 44, iwad +PLAYU0, 40, 34, iwad +PLAYV0, 41, 28, iwad +PLAYW0, 39, 13, iwad +POT1A0, 10, 37, iwad +POT2A0, 10, 30, iwad +POT3A0, 12, 24, iwad +RBL1A0, 21, 9, iwad +RBL2A0, 14, 8, iwad +RBL3A0, 15, 10, iwad +RCK1A0, 7, 7, iwad +RCK2A0, 10, 11, iwad +RCK3A0, 14, 18, iwad +RCK4A0, 24, 22, iwad +RKBKA0, 30, 40, iwad +RKBSA0, 18, 50, iwad +ROKKA0, 11, 16, iwad +ROKKB0, 8, 11, iwad +ROKKC0, 4, 6, iwad +ROKKD0, 6, 6, iwad +ROKKE0, 4, 5, iwad +ROKKG0, 3, 5, iwad +ROKKH0, 3, 3, iwad +SGM1A0, 17, 69, iwad +SGM2A0, 12, 54, iwad +SGM3A0, 14, 44, iwad +SGMPA0, 18, 126, iwad +SHRMA0, 13, 25, iwad +SHRMB0, 15, 26, iwad +SHRMC0, 21, 36, iwad +SHRMD0, 23, 40, iwad +SHRME0, 17, 26, iwad +SHRMF0, 19, 15, iwad +SLTRA0, 23, 52, iwad +SORCH0, 29, 92, iwad +SORCI0, 34, 97, iwad +SORCJ0, 36, 98, iwad +SORCK0, 41, 101, iwad +SORCL0, 48, 97, iwad +SORCM0, 50, 97, iwad +SORCN0, 47, 97, iwad +SORCO0, 46, 97, iwad +SORCP0, 46, 95, iwad +SORCQ0, 34, 95, iwad +SORCR0, 34, 86, iwad +SORCS0, 34, 72, iwad +SORCT0, 34, 50, iwad +SORCU0, 34, 29, iwad +SORCV0, 40, 31, iwad +SORCW0, 52, 41, iwad +SORCX0, 54, 46, iwad +SORCY0, 48, 33, iwad +SORCZ0, 34, 12, iwad +SSPTO0, 36, 66, iwad +SSPTP0, 38, 73, iwad +SSPTQ0, 35, 69, iwad +SSPTR0, 33, 53, iwad +SSPTS0, 34, 52, iwad +SSPTT0, 44, 43, iwad +SSPTU0, 47, 30, iwad +SSPTV0, 41, 35, iwad +SSPTW0, 35, 43, iwad +SSPTX0, 29, 47, iwad +SSPTY0, 24, 33, iwad +SSPTZ0, 27, 17, iwad +SSXDA0, 36, 66, iwad +SSXDB0, 37, 68, iwad +SSXDC0, 52, 68, iwad +SSXDD0, 58, 54, iwad +SSXDE0, 59, 37, iwad +SSXDF0, 61, 22, iwad +SSXDG0, 57, 18, iwad +SSXDH0, 52, 13, iwad +STM1A0, 24, 39, iwad +STM2A0, 25, 32, iwad +STM3A0, 13, 25, iwad +STM4A0, 12, 34, iwad +STT2A0, 25, 121, iwad +STT3A0, 25, 121, iwad +STT4A0, 25, 75, iwad +STT5A0, 25, 75, iwad +STTWA0, 29, 83, iwad +STWNA0, 29, 83, iwad +STWNB0, 29, 83, iwad +ZSUIA0, 18, 80, iwad +ZSUIB0, 8, 8, iwad +ZSUIC0, 6, 11, iwad +ZSUID0, 6, 9, iwad +ZSUIE0, 9, 11, iwad +ZSUIF0, 6, 10, iwad +ZSUIG0, 4, 7, iwad +ZSUIH0, 12, 14, iwad +ZSUII0, 11, 7, iwad +ZSUIJ0, 7, 3, iwad +ZSUIK0, 13, 3, iwad +SWMVA0, 22, 68, iwad +TMS1A0, 19, 52, iwad +TMS2A0, 19, 52, iwad +TMS3A0, 20, 52, iwad +TMS4A0, 16, 58, iwad +TMS5A0, 18, 58, iwad +TMS6A0, 14, 54, iwad +TMS7A0, 15, 54, iwad +TRDTA0, 57, 187, iwad +TRDTB0, 76, 181, iwad +TRDTC0, 88, 153, iwad +TRDTD0, 84, 85, iwad +TRDTE0, 81, 52, iwad +TRDTF0, 61, 31, iwad +TRDTG0, 23, 31, iwad +TRDTH0, 58, 187, iwad +TRDTI0, 77, 183, iwad +TRDTJ0, 89, 191, iwad +TRDTK0, 85, 191, iwad +TRDTL0, 82, 156, iwad +TRDTM0, 62, 141, iwad +TRDTN0, 48, 140, iwad +TRDTO0, 48, 82, iwad +TRDTP0, 38, 39, iwad +TRDTQ0, 26, 39, iwad +ZTREA0, 43, 134, iwad +TRESA0, 51, 179, iwad +TRE4A0, 73, 187, iwad +TRE5A0, 72, 187, iwad +TRE6A0, 56, 122, iwad +TRE7A0, 55, 122, iwad +TSPKB0, 26, 131, iwad +TSPKD0, 22, 9, iwad +TST0A0, 12, 22, iwad +TST1A0, 6, 20, iwad +TST2A0, 6, 16, iwad +TST3A0, 9, 25, iwad +TST4A0, 6, 21, iwad +TST5A0, 6, 25, iwad +TST6A0, 8, 10, iwad +TST7A0, 6, 13, iwad +TST8A0, 6, 10, iwad +TST9A0, 6, 10, iwad +TWTRA0, 14, 79, iwad +TWTRB0, 14, 81, iwad +TWTRC0, 14, 83, iwad +TWTRD0, 14, 83, iwad +TWTRE0, 14, 79, iwad +TWTRF0, 14, 80, iwad +TWTRG0, 14, 82, iwad +TWTRH0, 14, 80, iwad +TWTRI0, 14, 65, iwad +VASEA0, 11, 53, iwad +XMASA0, 23, 150, iwad +XMASB0, 25, 151, iwad +XMASC0, 25, 151, iwad +XMASD0, 30, 151, iwad +XMASE0, 20, 151, iwad +XMASF0, 14, 156, iwad +XMASG0, 5, 163, iwad +XMASH0, 5, 152, iwad +XMASI0, 8, 132, iwad +XMASJ0, 10, 72, iwad +XMASK0, 13, 17, iwad +FHFXN0, 26, 21, iwad +CTDPG0, 15, 15, iwad +CTDPH0, 21, 7, iwad +CTDPI0, 17, 12, iwad +CTDPJ0, 21, 11, iwad +CTDPR0, 18, 12, iwad +CTDPS0, 21, 6, iwad +CTDPT0, 23, 3, iwad +ETTBM0, 14, 15, iwad +ETTBN0, 18, 8, iwad +ETTBO0, 15, 5, iwad +ETTBP0, 13, 8, iwad +ETTBQ0, 9, 16, iwad +ETTBR0, 18, 18, iwad +ETTBS0, 20, 15, iwad +THRWA0, 10, 15, iwad +THRWB0, 10, 18, iwad +THRWC0, 8, 20, iwad +THRWD0, 6, 18, iwad +THRWE0, 6, 16, iwad +THRWF0, 8, 19, iwad +THRWG0, 8, 19, iwad +THRWH0, 11, 19, iwad diff --git a/wadsrc/static/filter/strife/sprofs.txt b/wadsrc/static/filter/strife/sprofs.txt new file mode 100644 index 0000000000..d7118297bc --- /dev/null +++ b/wadsrc/static/filter/strife/sprofs.txt @@ -0,0 +1,364 @@ +TWAVA0, 47, 20, iwad +TWAVB0, 20, 15, iwad +ZAP5A0, 13, 6, iwad +ZAP5B0, 15, 6, iwad +ZAP5C0, 13, 6, iwad +ZAP5D0, 14, 6, iwad +BARTB0, 11, 31, iwad +BARTC0, 14, 31, iwad +BARTD0, 19, 34, iwad +BARTE0, 23, 36, iwad +BARTF0, 26, 40, iwad +BARTG0, 27, 43, iwad +BARTH0, 27, 44, iwad +BARTI0, 27, 45, iwad +BARTJ0, 27, 46, iwad +BARTK0, 27, 50, iwad +BARTL0, 27, 7, iwad +BARWB0, 12, 30, iwad +BARWC0, 14, 30, iwad +BARWD0, 15, 29, iwad +BARWE0, 15, 26, iwad +BARWF0, 18, 23, iwad +BARWG0, 19, 18, iwad +BARWH0, 19, 11, iwad +FLBEC0, 21, 51, iwad +FLBED0, 24, 77, iwad +DIE1A0, 27, 7, iwad +DEADA0, 31, 11, iwad +SACRA0, 31, 13, iwad +RGIBD0, 27, 48, iwad +RGIBE0, 27, 30, iwad +RGIBF0, 27, 17, iwad +RGIBG0, 27, 12, iwad +RGIBH0, 27, 10, iwad +GIBSM0, 18, 54, iwad +GIBSN0, 23, 58, iwad +GIBSO0, 23, 60, iwad +GIBSP0, 26, 54, iwad +GIBSQ0, 27, 42, iwad +GIBSR0, 27, 29, iwad +GIBSS0, 27, 19, iwad +GIBST0, 27, 11, iwad +GIBSU0, 27, 8, iwad +GIBSV0, 27, 7, iwad +GIBSA0, 28, 58, iwad +GIBSB0, 31, 62, iwad +GIBSC0, 31, 62, iwad +GIBSD0, 31, 60, iwad +GIBSE0, 31, 54, iwad +GIBSF0, 31, 38, iwad +GIBSG0, 31, 22, iwad +GIBSH0, 31, 13, iwad +GIBSI0, 31, 10, iwad +GIBSJ0, 31, 10, iwad +GIBSK0, 31, 10, iwad +GIBSL0, 31, 10, iwad +PLAYG0, 26, 54, iwad +PLAYN0, 24, 28, iwad +PLAYO0, 27, 22, iwad +PLAYP0, 27, 13, iwad +BURNA0, 15, 55, iwad +BURNB0, 23, 58, iwad +BURNC0, 23, 61, iwad +BURND0, 22, 67, iwad +BURNE0, 20, 65, iwad +BURNF0, 18, 69, iwad +BURNQ0, 23, 54, iwad +BURNR0, 23, 22, iwad +BURNS0, 23, 30, iwad +BURNT0, 23, 21, iwad +BURNU0, 23, 13, iwad +BURNV0, 23, 11, iwad +MRSTA0, 11, 59, iwad +MRLKA0, 11, 59, iwad +MRLKB0, 11, 59, iwad +MRBDA0, 11, 59, iwad +MRBDB0, 8, 59, iwad +MRBDC0, 8, 59, iwad +MRBDD0, 8, 59, iwad +MRBDE0, 8, 60, iwad +MRBDF0, 11, 59, iwad +MRYSA0, 16, 55, iwad +MRPNA0, 16, 50, iwad +MRPNB0, 11, 47, iwad +MRPNC0, 11, 43, iwad +MRPND0, 10, 41, iwad +MRGTA0, 17, 59, iwad +MRGTB0, 17, 59, iwad +MRGTC0, 19, 59, iwad +MRGTD0, 17, 59, iwad +MRGTE0, 17, 59, iwad +MRGTF0, 18, 59, iwad +MRGTG0, 16, 59, iwad +MRGTH0, 13, 59, iwad +MRGTI0, 14, 59, iwad +MRNOA0, 11, 59, iwad +MRNOB0, 11, 59, iwad +MRNOC0, 11, 58, iwad +ARMRA0, 31, 68, iwad +PEASG0, 14, 49, iwad +PEASH0, 11, 42, iwad +PEASI0, 12, 45, iwad +PEASJ0, 11, 43, iwad +PEASK0, 14, 37, iwad +PEASL0, 26, 16, iwad +PEASM0, 27, 13, iwad +PEASN0, 27, 13, iwad +BEGRF0, 10, 54, iwad +BEGRG0, 14, 58, iwad +BEGRH0, 18, 60, iwad +BEGRL0, 15, 37, iwad +BEGRM0, 17, 21, iwad +BEGRN0, 19, 10, iwad +HMN1G0, 23, 53, iwad +HMN1H0, 22, 50, iwad +HMN1J0, 20, 49, iwad +HMN1K0, 20, 45, iwad +HMN1L0, 20, 39, iwad +HMN1M0, 20, 24, iwad +HMN1N0, 20, 16, iwad +LEADG0, 26, 52, iwad +LEADH0, 24, 51, iwad +LEADI0, 23, 53, iwad +LEADJ0, 22, 51, iwad +LEADK0, 22, 49, iwad +LEADL0, 22, 47, iwad +LEADM0, 22, 49, iwad +LEADN0, 22, 53, iwad +LEADO0, 22, 50, iwad +LEADP0, 22, 43, iwad +LEADQ0, 31, 40, iwad +LEADR0, 31, 33, iwad +LEADS0, 31, 30, iwad +LEADT0, 31, 27, iwad +LEADU0, 31, 23, iwad +LEADV0, 31, 18, iwad +LEADW0, 31, 13, iwad +LEADX0, 31, 10, iwad +ROB2G0, 40, 67, iwad +ROB2H0, 48, 70, iwad +ROB2I0, 54, 92, iwad +ROB2J0, 48, 92, iwad +ROB2K0, 52, 79, iwad +ROB2L0, 58, 85, iwad +ROB2M0, 55, 92, iwad +ROB2N0, 51, 93, iwad +ROB2O0, 47, 98, iwad +SEWRI0, 46, 48, iwad +SEWRJ0, 29, 30, iwad +DISRA0, 23, 55, iwad +DISRB0, 23, 57, iwad +DISRC0, 22, 57, iwad +DISRD0, 16, 62, iwad +DISRE0, 19, 61, iwad +DISRF0, 19, 59, iwad +DISRG0, 22, 55, iwad +DISRH0, 23, 44, iwad +DISRI0, 23, 38, iwad +DISRJ0, 23, 32, iwad +PRGRA0, 51, 69, iwad +PRGRS0, 51, 28, iwad +PRGRT0, 51, 21, iwad +PRGRU0, 51, 20, iwad +PRGRV0, 51, 19, iwad +PRGRW0, 51, 19, iwad +PRGRX0, 51, 18, iwad +BASEG0, 35, 23, iwad +BASEH0, 35, 23, iwad +SPIDB1, 30, 34, iwad +SPIDB2, 37, 33, iwad +SPIDB3, 26, 34, iwad +SPIDB4, 37, 34, iwad +SPIDB5, 33, 32, iwad +SPIDB6, 37, 34, iwad +SPIDB7, 27, 34, iwad +SPIDB8, 37, 32, iwad +ROB3L0, 60, 122, iwad +ROB3M0, 65, 121, iwad +ROB3N0, 98, 114, iwad +ROB3O0, 94, 105, iwad +RBB3D0, 43, 43, iwad +RBB3E0, 43, 29, iwad +RBB3G0, 33, 46, iwad +RBB3H0, 37, 36, iwad +PGRDI0, 27, 56, iwad +PGRDJ0, 31, 56, iwad +PGRDK0, 35, 60, iwad +PGRDL0, 31, 61, iwad +PGRDM0, 27, 60, iwad +PGRDN0, 27, 63, iwad +PGRDO0, 31, 60, iwad +PGRDP0, 39, 53, iwad +PGRDQ0, 43, 39, iwad +PGRDR0, 43, 32, iwad +PGRDS0, 39, 26, iwad +PGRDT0, 35, 28, iwad +PGRDU0, 35, 28, iwad +PGRDV0, 35, 28, iwad +PGRDW0, 35, 28, iwad +PGRDX0, 35, 28, iwad +PGRDY0, 35, 28, iwad +PGRDZ0, 35, 28, iwad +PGRD[0, 35, 28, iwad +PGRD\0, 35, 28, iwad +PDEDE0, 22, 20, iwad +PDEDF0, 23, 16, iwad +PDEDG0, 23, 15, iwad +PDEDH0, 23, 15, iwad +PDEDI0, 23, 15, iwad +PDEDJ0, 23, 17, iwad +PDEDK0, 23, 20, iwad +PDEDL0, 23, 22, iwad +PDEDM0, 22, 23, iwad +PDEDN0, 22, 26, iwad +PDEDO0, 23, 26, iwad +PDEDP0, 23, 24, iwad +PDEDQ0, 23, 21, iwad +PDEDR0, 23, 15, iwad +PDEDS0, 23, 11, iwad +PDEDT0, 23, 5, iwad +ORCLB0, 23, 77, iwad +ORCLC0, 23, 70, iwad +ORCLD0, 23, 70, iwad +ORCLE0, 23, 70, iwad +ORCLF0, 23, 70, iwad +ORCLG0, 23, 70, iwad +ORCLH0, 23, 70, iwad +ORCLI0, 23, 71, iwad +ORCLJ0, 23, 68, iwad +ORCLK0, 23, 61, iwad +ORCLL0, 23, 53, iwad +ORCLM0, 23, 50, iwad +ORCLN0, 23, 45, iwad +ORCLO0, 23, 42, iwad +ORCLP0, 23, 42, iwad +ORCLQ0, 23, 42, iwad +NEALD0, 14, 48, iwad +NEALE0, 10, 43, iwad +NEALF0, 7, 38, iwad +NEALG0, 4, 35, iwad +NEALH0, 3, 32, iwad +NEALI0, 3, 28, iwad +NEALJ0, 3, 11, iwad +MLDRH0, 41, 131, iwad +MLDRI0, 54, 122, iwad +MLDRJ0, 57, 115, iwad +MLDRK0, 59, 127, iwad +MLDRL0, 72, 126, iwad +MLDRM0, 72, 134, iwad +MLDRN0, 63, 102, iwad +MLDRQ0, 38, 85, iwad +MLDRR0, 59, 61, iwad +MLDRT0, 55, 44, iwad +MLDRU0, 55, 44, iwad +MLDRV0, 55, 46, iwad +TRAYA0, 11, 39, iwad +RUB1A0, 4, 9, iwad +RUB2A0, 4, 10, iwad +RUB5A0, 2, 12, iwad +RUB7A0, 3, 12, iwad +RUB8A0, 4, 11, iwad +SPLHA0, 4, 8, iwad +SPLHB0, 4, 8, iwad +SPLHC0, 4, 8, iwad +SPLHD0, 4, 8, iwad +SPLHE0, 4, 8, iwad +SPLHF0, 4, 8, iwad +SPLHG0, 4, 7, iwad +CNDLA0, 4, 16, iwad +BARLA0, 12, 41, iwad +BARLB0, 12, 41, iwad +BARLC0, 12, 41, iwad +BARLD0, 12, 41, iwad +MUGGA0, 7, 11, iwad +VASEA0, 11, 22, iwad +STATA0, 19, 64, iwad +LTRHA0, 10, 70, iwad +LTRHB0, 10, 65, iwad +LTRHC0, 10, 69, iwad +LTRHD0, 10, 68, iwad +HERTA0, 15, 56, iwad +HERTB0, 15, 56, iwad +HERTC0, 15, 56, iwad +MONIA0, 19, 125, iwad +STELA0, 15, 127, iwad +STLEA0, 15, 40, iwad +VASEB0, 11, 31, iwad +STOLA0, 7, 23, iwad +POT1A0, 7, 13, iwad +LAMPA0, 11, 79, iwad +TUB1A0, 11, 14, iwad +TREEC0, 14, 63, iwad +BUSHA0, 15, 47, iwad +SHRBA0, 23, 63, iwad +BAR1A0, 15, 57, iwad +HUGEA0, 23, 190, iwad +HUGEB0, 23, 190, iwad +HUGEC0, 23, 190, iwad +HUGED0, 23, 190, iwad +STLGB0, 16, 60, iwad +STLGE0, 16, 100, iwad +STLGF0, 6, 31, iwad +TNK1A0, 15, 192, iwad +TNK1B0, 15, 192, iwad +TNK1C0, 15, 192, iwad +TNK2A0, 15, 192, iwad +TNK2B0, 15, 192, iwad +TNK2C0, 15, 192, iwad +TNK4A0, 15, 56, iwad +TNK4B0, 15, 56, iwad +TNK4C0, 15, 56, iwad +TNK3A0, 15, 192, iwad +TNK3B0, 15, 192, iwad +TNK3C0, 15, 192, iwad +TNK5A0, 15, 56, iwad +TNK5B0, 15, 56, iwad +TNK5C0, 15, 56, iwad +TNK6A0, 15, 56, iwad +TNK6B0, 15, 56, iwad +TNK6C0, 15, 56, iwad +APOWA0, 27, 198, iwad +LANTA0, 8, 79, iwad +LMPCA0, 11, 78, iwad +LMPCB0, 11, 78, iwad +LMPCC0, 11, 74, iwad +LMPCD0, 11, 78, iwad +LMPCE0, 11, 78, iwad +STLAA0, 15, 78, iwad +TLMPA0, 10, 63, iwad +TLMPB0, 11, 78, iwad +LOGSA0, 14, 91, iwad +LOGSB0, 14, 93, iwad +LOGSC0, 14, 93, iwad +LOGSD0, 14, 93, iwad +LOGSE0, 14, 93, iwad +HOGNA0, 23, 80, iwad +HOGNB0, 11, 80, iwad +HOGNC0, 2, 80, iwad +PSTNA0, 23, 128, iwad +PSTNB0, 23, 128, iwad +PSTNC0, 23, 128, iwad +PSTND0, 23, 128, iwad +PSTNE0, 23, 128, iwad +FLGRA0, 8, 39, iwad +FLGBA0, 8, 39, iwad +FLGGA0, 8, 39, iwad +PSTNF0, 23, 126, iwad +PSTNG0, 23, 94, iwad +PSTNH0, 23, 63, iwad +PSTNI0, 23, 15, iwad +STAKA0, 17, 127, iwad +COUPA0, 11, 22, iwad +COUPB0, 11, 22, iwad +COUPC0, 11, 22, iwad +AFEDA0, 11, 24, iwad +BOTRA0, 8, 16, iwad +HATRA0, 4, 13, iwad +TOPRA0, 12, 11, iwad +BUBBA0, 15, 127, iwad +BUBFA0, 15, 65, iwad +ASPRA0, 23, 127, iwad +SPDLA0, 30, 52, iwad +SPDLB0, 30, 52, iwad +SPDLC0, 30, 51, iwad From daf1a40521f51ccab5f9188b458b3a41abb0bbf4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Dec 2016 20:09:25 +0100 Subject: [PATCH 463/471] - allow swapping the order of gl_finish and SwapBuffers calls, because some cards do not seem to like the correct order. --- src/gl/system/gl_framebuffer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 7102df72ea..f20c9e5024 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -207,17 +207,20 @@ void OpenGLFrameBuffer::Update() // //========================================================================== +CVAR(Bool, gl_finishbeforeswap, false, 0); + void OpenGLFrameBuffer::Swap() { Finish.Reset(); Finish.Clock(); - if (needsetgamma) + if (gl_finishbeforeswap) glFinish(); + if (needsetgamma) { //DoSetGamma(); needsetgamma = false; } SwapBuffers(); - glFinish(); + if (!gl_finishbeforeswap) glFinish(); Finish.Unclock(); swapped = true; FHardwareTexture::UnbindAll(); From 94287518e011b13e08177784a8dae052c80e3f16 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 4 Dec 2016 10:13:36 +0100 Subject: [PATCH 464/471] - added a virtual CanCollideWith script method that can be overridden to do class specific collision checks. This will get called for both actors taking part in a collision, if one of the two calls returns false it will immediately abort PIT_CheckThing with no collision taking place at all. --- src/actor.h | 1 - src/p_map.cpp | 57 ++++++++++++++++++++++++++++++--- wadsrc/static/zscript/actor.txt | 1 + 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/actor.h b/src/actor.h index 6718e0931f..25669dfeca 100644 --- a/src/actor.h +++ b/src/actor.h @@ -650,7 +650,6 @@ public: virtual void Touch(AActor *toucher); void CallTouch(AActor *toucher); - // Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed // Made a metadata property so no longer virtual void Howl (); diff --git a/src/p_map.cpp b/src/p_map.cpp index f25c336126..5e5d2cfe9b 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -46,6 +46,7 @@ #include "r_utility.h" #include "p_blockmap.h" #include "p_3dmidtex.h" +#include "virtual.h" #include "s_sound.h" #include "decallib.h" @@ -1134,6 +1135,12 @@ static bool CanAttackHurt(AActor *victim, AActor *shooter) // //========================================================================== +DEFINE_ACTION_FUNCTION(AActor, CanCollideWith) +{ + // No need to check the parameters, as they are not even used. + ACTION_RETURN_BOOL(true); +} + bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm) { AActor *thing = cres.thing; @@ -1222,15 +1229,55 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch (thing->flags5 & MF5_DONTRIP) || ((tm.thing->flags6 & MF6_NOBOSSRIP) && (thing->flags2 & MF2_BOSS))) { - if (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP) - { // Some things prefer not to overlap each other, if possible - return unblocking; + // Some things prefer not to overlap each other, if possible (Q: Is this even needed anymore? It was just for dealing with some deficiencies in the code below in Heretic.) + if (!(tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP)) + { + if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z())) + return true; } - if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z())) - return true; + // If they are not allowed to overlap, the rest of this function still needs to be executed. } } + // Call the script callback. This must be done before any other checks that perform some actual action or may already return a 'block'. + // The checks here are to do this only for conditions that would later result in an action, calling this for everything would be too much of a drag if + // too many scripted overrides were being used, as PIT_CheckThing is even called for touching all the monster corpses lying around. + if (((thing->flags & MF_SOLID) || (thing->flags6 & (MF6_TOUCHY | MF6_BUMPSPECIAL))) && + ((tm.thing->flags & (MF_SOLID|MF_MISSILE)) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS) || (tm.thing->BounceFlags & BOUNCE_MBF))) + { + static unsigned VIndex = ~0u; + if (VIndex == ~0u) + { + VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanCollideWith"); + assert(VIndex != ~0u); + } + + VMValue params[3] = { tm.thing, thing, false }; + VMReturn ret; + int retval; + ret.IntAt(&retval); + + auto clss = tm.thing->GetClass(); + VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr; + if (func != nullptr) + { + GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr); + if (!retval) return true; + } + std::swap(params[0].a, params[1].a); + params[2].i = true; + + // re-get for the other actor. + clss = thing->GetClass(); + func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr; + if (func != nullptr) + { + GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr); + if (!retval) return true; + } + } + + if (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING)) { // touchy object is alive, toucher is solid diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index ee4c92adde..1e5c394160 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -268,6 +268,7 @@ class Actor : Thinker native virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0); virtual native bool Slam(Actor victim); virtual native void Touch(Actor toucher); + virtual native bool CanCollideWith(Actor other, bool passive); // This is an empty native function, it's native for the sole reason of performance as this is in a performance critical spot. // Called when an actor is to be reflected by a disc of repulsion. // Returns true to continue normal blast processing. From 18b953dd5004e65e5a3340a54b93ab520b97b0e1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 4 Dec 2016 10:34:36 +0100 Subject: [PATCH 465/471] - fixed: Blasted objects should also be subject to being checked with CanCollideWith. --- src/p_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index 5e5d2cfe9b..8cbe38f0e6 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1243,7 +1243,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch // The checks here are to do this only for conditions that would later result in an action, calling this for everything would be too much of a drag if // too many scripted overrides were being used, as PIT_CheckThing is even called for touching all the monster corpses lying around. if (((thing->flags & MF_SOLID) || (thing->flags6 & (MF6_TOUCHY | MF6_BUMPSPECIAL))) && - ((tm.thing->flags & (MF_SOLID|MF_MISSILE)) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS) || (tm.thing->BounceFlags & BOUNCE_MBF))) + ((tm.thing->flags & (MF_SOLID|MF_MISSILE)) || (tm.thing->flags2 & MF2_BLASTED) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS) || (tm.thing->BounceFlags & BOUNCE_MBF))) { static unsigned VIndex = ~0u; if (VIndex == ~0u) From ebdc672985061681a7fcb5d79271809efbc6d8ce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 4 Dec 2016 10:45:20 +0100 Subject: [PATCH 466/471] - fixed: A_Saw was using the wrong angle for adjusting the facing direction at the end. --- wadsrc/static/zscript/doom/weaponchainsaw.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/doom/weaponchainsaw.txt b/wadsrc/static/zscript/doom/weaponchainsaw.txt index 0653bc16d7..88a8c87cdf 100644 --- a/wadsrc/static/zscript/doom/weaponchainsaw.txt +++ b/wadsrc/static/zscript/doom/weaponchainsaw.txt @@ -148,14 +148,14 @@ extend class StateProvider if (anglediff < 0.0) { if (anglediff < -4.5) - angle = ang + 90.0 / 21; + angle = t.angleFromSource + 90.0 / 21; else angle -= 4.5; } else { if (anglediff > 4.5) - angle = ang - 90.0 / 21; + angle = t.angleFromSource - 90.0 / 21; else angle += 4.5; } From 5a08768eaffe0b5559645bfe2cef5cbd53aed064 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 4 Dec 2016 14:29:03 +0100 Subject: [PATCH 467/471] - removed unused label. --- src/d_main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index a2cb181f18..0f2d5af92b 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2653,7 +2653,6 @@ void D_DoomMain (void) } D_DoomLoop (); // this only returns if a 'restart' CCMD is given. -maxberestart: // // Clean up after a restart // From f722967abe036476c8aaca5e01f787308a881f13 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Dec 2016 13:24:42 +0100 Subject: [PATCH 468/471] - added automatic type deduction capabilities for local variables. If you type 'let variable = value;' the type of 'variable' will be deduced from the given value. This is mostly of interest for type casting pointers, because 'let p = Classtype(objectvar);' does not require writing the class type name twice. --- src/dobjtype.cpp | 2 ++ src/dobjtype.h | 3 ++- src/namedef.h | 1 + src/sc_man_scanner.re | 1 + src/sc_man_tokens.h | 1 + src/scripting/codegeneration/codegen.cpp | 30 ++++++++++++++++++++++-- src/scripting/zscript/zcc-parse.lemon | 1 + src/scripting/zscript/zcc_compile.cpp | 4 ++++ src/scripting/zscript/zcc_parser.cpp | 1 + src/scripting/zscript/zcc_parser.h | 1 + 10 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 5e1316d71b..ae26bc37dc 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -74,6 +74,7 @@ TArray PClass::AllClasses; bool PClass::bShutdown; PErrorType *TypeError; +PErrorType *TypeAuto; PVoidType *TypeVoid; PInt *TypeSInt8, *TypeUInt8; PInt *TypeSInt16, *TypeUInt16; @@ -570,6 +571,7 @@ void PType::StaticInit() // Create types and add them type the type table. TypeTable.AddType(TypeError = new PErrorType); + TypeTable.AddType(TypeAuto = new PErrorType(2)); TypeTable.AddType(TypeVoid = new PVoidType); TypeTable.AddType(TypeSInt8 = new PInt(1, false)); TypeTable.AddType(TypeUInt8 = new PInt(1, true)); diff --git a/src/dobjtype.h b/src/dobjtype.h index ad626ee8bb..c310f9863b 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -370,7 +370,7 @@ class PErrorType : public PType { DECLARE_CLASS(PErrorType, PType); public: - PErrorType() : PType(0, 1) {} + PErrorType(int which = 1) : PType(0, which) {} }; class PVoidType : public PType @@ -930,6 +930,7 @@ PPrototype *NewPrototype(const TArray &rettypes, const TArray // Built-in types ----------------------------------------------------------- extern PErrorType *TypeError; +extern PErrorType *TypeAuto; extern PVoidType *TypeVoid; extern PInt *TypeSInt8, *TypeUInt8; extern PInt *TypeSInt16, *TypeUInt16; diff --git a/src/namedef.h b/src/namedef.h index c3866a0be8..62d513437c 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -721,6 +721,7 @@ xx(State) xx(Fixed) xx(Vector2) xx(Vector3) +xx(let) xx(Min) xx(Max) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index a57cc34adc..8e4b42f690 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -183,6 +183,7 @@ std2: 'deprecated' { RET(TK_Deprecated); } 'action' { RET(TK_Action); } 'readonly' { RET(TK_ReadOnly); } + 'let' { RET(TK_Let); } /* Actor state options */ 'bright' { RET(StateOptions ? TK_Bright : TK_Identifier); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index c1ba10044d..efa479cf37 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -142,4 +142,5 @@ xx(TK_NoDelay, "'nodelay'") xx(TK_Offset, "'offset'") xx(TK_Slow, "'slow'") xx(TK_Bright, "'bright'") +xx(TK_Let, "'let'") #undef xx diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index a0491f69d8..0402ed9ab1 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -9964,17 +9964,43 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (ValueType->RegType == REGT_NIL) + if (ValueType->RegType == REGT_NIL && ValueType != TypeAuto) { auto sfunc = static_cast(ctx.Function->Variants[0].Implementation); StackOffset = sfunc->AllocExtraStack(ValueType); // Todo: Process the compound initializer once implemented. + if (Init != nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars()); + delete this; + return nullptr; + } } - else + else if (ValueType !=TypeAuto) { if (Init) Init = new FxTypeCast(Init, ValueType, false); SAFE_RESOLVE_OPT(Init, ctx); } + else + { + if (Init == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Automatic type deduction requires an initializer for variable %s", Name.GetChars()); + delete this; + return nullptr; + } + SAFE_RESOLVE_OPT(Init, ctx); + if (Init->ValueType->RegType == REGT_NIL) + { + ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars()); + delete this; + return nullptr; + } + ValueType = Init->ValueType; + // check for undersized ints and floats. These are not allowed as local variables. + if (IsInteger() && ValueType->Align < sizeof(int)) ValueType = TypeSInt32; + else if (IsFloat() && ValueType->Align < sizeof(double)) ValueType = TypeFloat64; + } if (Name != NAME_None) { for (auto l : ctx.Block->LocalVars) diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 5ba5a204ea..9305b9f71a 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -704,6 +704,7 @@ 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_name1(X) ::= LET(T). { X.Int = ZCC_Let; X.SourceLoc = T.SourceLoc; } type_name(X) ::= type_name1(A). { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 98a1a5ff3f..856802a97f 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1449,6 +1449,10 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n retval = TypeSound; break; + case ZCC_Let: + retval = TypeAuto; + break; + case ZCC_UserType: // statelabel et.al. are not tokens - 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? switch (btype->UserType->Id) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 8a16181273..44f72da283 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -201,6 +201,7 @@ static void InitTokenMap() TOKENDEF2(TK_State, ZCC_STATE, NAME_State); TOKENDEF2(TK_Color, ZCC_COLOR, NAME_Color); TOKENDEF2(TK_Sound, ZCC_SOUND, NAME_Sound); + TOKENDEF2(TK_Let, ZCC_LET, NAME_let); TOKENDEF (TK_Identifier, ZCC_IDENTIFIER); TOKENDEF (TK_StringConst, ZCC_STRCONST); diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 7a763b2c18..d02b1a12f2 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -131,6 +131,7 @@ enum EZCCBuiltinType ZCC_Sound, ZCC_UserType, + ZCC_Let, ZCC_NUM_BUILT_IN_TYPES }; From 092461ed34024ebb8899f757e04e3890c22f4b76 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Dec 2016 14:52:34 +0100 Subject: [PATCH 469/471] - make dynamic object casts a dedicated VM instruction instead of a builtin function. This can see some heavy use in iterators where saving several hundreds of function calls can be achieved. In these cases, using a function to do the job will become a significant time waster. --- src/scripting/codegeneration/codegen.cpp | 95 +++++++----------------- src/scripting/codegeneration/codegen.h | 3 +- src/scripting/vm/vmexec.h | 12 +++ src/scripting/vm/vmops.h | 2 + wadsrc/static/zscript/doom/bossbrain.txt | 2 +- wadsrc/static/zscript/raven/minotaur.txt | 4 +- 6 files changed, 45 insertions(+), 73 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 0402ed9ab1..3895441d80 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4324,58 +4324,32 @@ FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx) // //========================================================================== -PPrototype *FxTypeCheck::ReturnProto() +ExpEmit FxTypeCheck::EmitCommon(VMFunctionBuilder *build) { - EmitTail = true; - return FxExpression::ReturnProto(); + ExpEmit castee = left->Emit(build); + ExpEmit casttype = right->Emit(build); + castee.Free(build); + casttype.Free(build); + ExpEmit ares(build, REGT_POINTER); + build->Emit(casttype.Konst ? OP_DYNCAST_K : OP_DYNCAST_R, ares.RegNum, castee.RegNum, casttype.RegNum); + return ares; } - -//========================================================================== -// -// -// -//========================================================================== - -int BuiltinTypeCheck(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) { - EmitParameter(build, left, ScriptPosition); - EmitParameter(build, right, ScriptPosition); + ExpEmit ares = EmitCommon(build); + ares.Free(build); + ExpEmit bres(build, REGT_INT); + build->Emit(OP_CASTB, bres.RegNum, ares.RegNum, CASTB_A); + return bres; +} - - 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; - } - - ExpEmit out(build, REGT_INT); - build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); - return out; +void FxTypeCheck::EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no) +{ + ExpEmit ares = EmitCommon(build); + ares.Free(build); + build->Emit(OP_EQA_K, !invert, ares.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT)); + patchspots_no.Push(build->Emit(OP_JMP, 0)); } //========================================================================== @@ -4443,27 +4417,11 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx) ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build) { - ExpEmit in = expr->Emit(build); - ExpEmit out = in.Fixed ? ExpEmit(build, in.RegType) : in; - ExpEmit check(build, REGT_INT); - assert(out.RegType == REGT_POINTER); - - if (in.Fixed) build->Emit(OP_MOVEA, out.RegNum, in.RegNum); - build->Emit(OP_PARAM, 0, REGT_POINTER, in.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; + ExpEmit castee = expr->Emit(build); + castee.Free(build); + ExpEmit ares(build, REGT_POINTER); + build->Emit(OP_DYNCAST_K, ares.RegNum, castee.RegNum, build->GetConstantAddress(CastType, ATAG_OBJECT)); + return ares; } //========================================================================== @@ -9586,8 +9544,7 @@ int BuiltinNameToClass(VMValue *param, TArray &defaultparam, int numpar if (!cls->IsDescendantOf(desttype)) { - // Let the caller check this. The message can be enabled for diagnostic purposes. - DPrintf(DMSG_SPAMMY, "class '%s' is not compatible with '%s'\n", clsname.GetChars(), desttype->TypeName.GetChars()); + // Let the caller check this. Making this an error with a message is only taking away options from the user. cls = nullptr; } ret->SetPointer(const_cast(cls), ATAG_OBJECT); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 49999206d4..c18754cb85 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -1078,9 +1078,10 @@ public: FxTypeCheck(FxExpression*, FxExpression*); ~FxTypeCheck(); FxExpression *Resolve(FCompileContext&); - PPrototype *ReturnProto(); + ExpEmit EmitCommon(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build); + void EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no); }; //========================================================================== diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 4152facc18..76a7156cb8 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -414,6 +414,18 @@ begin: reg.f[a+1] = reg.f[B+1]; reg.f[a+2] = reg.f[B+2]; NEXTOP; + OP(DYNCAST_R) : + ASSERTA(a); ASSERTA(B); ASSERTA(C); + b = B; + reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(reg.a[C]))) ? reg.a[b] : nullptr; + reg.atag[a] = ATAG_OBJECT; + NEXTOP; + OP(DYNCAST_K) : + ASSERTA(a); ASSERTA(B); ASSERTKA(C); + b = B; + reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr; + reg.atag[a] = ATAG_OBJECT; + NEXTOP; OP(CAST): if (C == CAST_I2F) { diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 826bdb4e3e..889706726c 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -84,6 +84,8 @@ xx(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements) xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements) xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C +xx(DYNCAST_R, dyncast, RPRPRP, NOP, 0, 0), // aA = dyn_cast(aB); +xx(DYNCAST_K, dyncast, RPRPKP, NOP, 0, 0), // aA = dyn_cast(aB); // Control flow. xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++ diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 2a3f392657..f22e4dd2b0 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -193,7 +193,7 @@ extend class Actor if (sv_killbossmonst) { int count; // Repeat until we have no more boss-spawned monsters. - ThinkerIterator it = ThinkerIterator.Create(); + ThinkerIterator it = ThinkerIterator.Create("Actor"); do // (e.g. Pain Elementals can spawn more to kill upon death.) { Actor mo; diff --git a/wadsrc/static/zscript/raven/minotaur.txt b/wadsrc/static/zscript/raven/minotaur.txt index 5e3d0cfe37..01cd635410 100644 --- a/wadsrc/static/zscript/raven/minotaur.txt +++ b/wadsrc/static/zscript/raven/minotaur.txt @@ -388,7 +388,7 @@ class Minotaur : Actor // In case pain caused him to skip his fade in. A_SetRenderStyle(1, STYLE_Normal); - MinotaurFriend mf = MinotaurFriend(self); + let mf = MinotaurFriend(self); if (mf) { if (mf.StartTime >= 0 && (level.maptime - mf.StartTime) >= MAULATORTICS) @@ -501,7 +501,7 @@ class Minotaur : Actor void A_MinotaurChase() { - MinotaurFriend mf = MinotaurFriend(self); + let mf = MinotaurFriend(self); if (!mf) { A_Chase(); From daaa6e7831b0c4c0424e530d763e653b97af459c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Dec 2016 00:00:56 +0100 Subject: [PATCH 470/471] - fixed bad parameter in AActor::ModifyDamage. --- src/p_mobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 88653fca9a..b527bf6813 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7418,7 +7418,7 @@ DEFINE_ACTION_FUNCTION(AActor, ClearCounters) int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive) { if (Inventory != nullptr) - Inventory->ModifyDamage(damage, damagetype, damage, false); + Inventory->ModifyDamage(damage, damagetype, damage, passive); return damage; } From b2d1b0d7a6dd7c459050db7a0c092359370fbb35 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Dec 2016 11:04:54 +0100 Subject: [PATCH 471/471] - fixed: FTranslatedLineTarget::angleFromSource returned the attack angle, not the angle between actors when returned from P_LineAttack. For most attack functions this is wrong, it's only the Hexen fighter attack needing this particular value, so it has been split up into two return values now. --- src/actor.h | 1 + src/p_map.cpp | 5 ++++- wadsrc/static/zscript/constants.txt | 1 + wadsrc/static/zscript/hexen/baseweapons.txt | 6 +----- wadsrc/static/zscript/hexen/fighteraxe.txt | 2 +- wadsrc/static/zscript/hexen/fighterfist.txt | 2 +- wadsrc/static/zscript/hexen/fighterhammer.txt | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/actor.h b/src/actor.h index 25669dfeca..12bb4dc281 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1540,6 +1540,7 @@ struct FTranslatedLineTarget { AActor *linetarget; DAngle angleFromSource; + DAngle attackAngleFromSource; bool unlinked; // found by a trace that went through an unlinked portal. }; diff --git a/src/p_map.cpp b/src/p_map.cpp index 8cbe38f0e6..16a5933d5a 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3588,6 +3588,7 @@ struct aim_t res.linetarget = th; res.pitch = pitch; res.angleFromSource = (th->Pos() - startpos).Angle(); + res.attackAngleFromSource = res.angleFromSource; // at this point we do not have an attack angle so it's the same as the actual angle between actors. res.unlinked = unlinked; res.frac = frac; } @@ -4506,7 +4507,9 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (victim != NULL) { victim->linetarget = trace.Actor; - victim->angleFromSource = trace.SrcAngleFromTarget; + victim->attackAngleFromSource = trace.SrcAngleFromTarget; + // With arbitrary portals this cannot be calculated so using the actual attack angle is the only option. + victim->angleFromSource = trace.unlinked? victim->attackAngleFromSource : t1->AngleTo(trace.Actor); victim->unlinked = trace.unlinked; } } diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index c199258997..147b23e4ef 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -846,6 +846,7 @@ struct FTranslatedLineTarget { Actor linetarget; double angleFromSource; + double attackAngleFromSource; bool unlinked; // found by a trace that went through an unlinked portal. native void TraceBleed(int damage, Actor missile); diff --git a/wadsrc/static/zscript/hexen/baseweapons.txt b/wadsrc/static/zscript/hexen/baseweapons.txt index a1e1af9bd6..f087946485 100644 --- a/wadsrc/static/zscript/hexen/baseweapons.txt +++ b/wadsrc/static/zscript/hexen/baseweapons.txt @@ -40,11 +40,7 @@ extend class Actor void AdjustPlayerAngle(FTranslatedLineTarget t) { - // normally this will adjust relative to the actual direction to the target, - // but with arbitrary portals that cannot be calculated so using the actual - // attack angle is the only option. - double atkangle = t.unlinked ? t.angleFromSource : AngleTo(t.linetarget); - double difference = deltaangle(Angle, atkangle); + double difference = t.angleFromSource; if (abs(difference) > MAX_ANGLE_ADJUST) { if (difference > 0) diff --git a/wadsrc/static/zscript/hexen/fighteraxe.txt b/wadsrc/static/zscript/hexen/fighteraxe.txt index a0d1deba1a..1ff44a52f6 100644 --- a/wadsrc/static/zscript/hexen/fighteraxe.txt +++ b/wadsrc/static/zscript/hexen/fighteraxe.txt @@ -253,7 +253,7 @@ class FWeapAxe : FighterWeapon { if (t.linetarget.bIsMonster || t.linetarget.player) { - t.linetarget.Thrust(power, t.angleFromSource); + t.linetarget.Thrust(power, t.attackAngleFromSource); } AdjustPlayerAngle(t); diff --git a/wadsrc/static/zscript/hexen/fighterfist.txt b/wadsrc/static/zscript/hexen/fighterfist.txt index 712055e6e7..2898227896 100644 --- a/wadsrc/static/zscript/hexen/fighterfist.txt +++ b/wadsrc/static/zscript/hexen/fighterfist.txt @@ -77,7 +77,7 @@ class FWeapFist : FighterWeapon (t.linetarget.Mass < 10000000 && (t.linetarget.bIsMonster))) { if (!t.linetarget.bDontThrust) - t.linetarget.Thrust(power, t.angleFromSource); + t.linetarget.Thrust(power, t.attackAngleFromSource); } AdjustPlayerAngle(t); return true; diff --git a/wadsrc/static/zscript/hexen/fighterhammer.txt b/wadsrc/static/zscript/hexen/fighterhammer.txt index 655e59379c..f1b06b75ce 100644 --- a/wadsrc/static/zscript/hexen/fighterhammer.txt +++ b/wadsrc/static/zscript/hexen/fighterhammer.txt @@ -80,7 +80,7 @@ class FWeapHammer : FighterWeapon AdjustPlayerAngle(t); if (t.linetarget.bIsMonster || t.linetarget.player) { - t.linetarget.Thrust(10, t.angleFromSource); + t.linetarget.Thrust(10, t.attackAngleFromSource); } weaponspecial = false; // Don't throw a hammer return;